public void LogEvent_WithCustomAppVersionType_UsesCustomAppVersion()
        {
            // Arrange
            var    spy        = new InMemoryLogSink();
            var    appVersion = new AssemblyAppVersion();
            string expected   = appVersion.GetVersion();
            var    services   = new ServiceCollection();

            services.AddAppVersion <AssemblyAppVersion>();
            IServiceProvider serviceProvider = services.BuildServiceProvider();

            ILogger logger =
                new LoggerConfiguration()
                .WriteTo.Sink(spy)
                .Enrich.WithVersion(serviceProvider)
                .CreateLogger();

            // Act
            logger.Information("This log event will be enriched by the registered app version");

            // Assert
            LogEvent emit = Assert.Single(spy.CurrentLogEmits);

            Assert.NotNull(emit);
            (string key, LogEventPropertyValue value) = Assert.Single(emit.Properties);
            Assert.Equal(VersionEnricher.DefaultPropertyName, key);
            Assert.Equal(expected, value.ToDecentString());
        }
示例#2
0
        public void LogInformationWithMachineName_Without_CreatesTraceTelemetryWithPodNameAsRoleInstance()
        {
            // Arrange
            var     spySink     = new InMemoryLogSink();
            string  operationId = $"operation-id-{Guid.NewGuid()}";
            ILogger logger      = CreateLogger(spySink, config =>
            {
                return(config.Enrich.WithProperty(ContextProperties.Correlation.OperationId, operationId)
                       .Enrich.WithProperty(General.ComponentName, "component")
                       .Enrich.WithProperty(General.MachineName, "machine"));
            });

            logger.LogInformation("trace message");
            LogEvent logEvent = Assert.Single(spySink.CurrentLogEmits);

            Assert.NotNull(logEvent);

            var converter = ApplicationInsightsTelemetryConverter.Create();

            // Act
            IEnumerable <ITelemetry> telemetries = converter.Convert(logEvent, formatProvider: null);

            // Assert
            Assert.Collection(telemetries, telemetry =>
            {
                var traceTelemetry = Assert.IsType <TraceTelemetry>(telemetry);
                Assert.Equal("trace message", traceTelemetry.Message);
                Assert.Equal(logEvent.Timestamp, traceTelemetry.Timestamp);
                Assert.Equal(SeverityLevel.Information, traceTelemetry.SeverityLevel);
                Assert.Equal("component", traceTelemetry.Context.Cloud.RoleName);
                Assert.Equal("machine", traceTelemetry.Context.Cloud.RoleInstance);
                AssertOperationContext(traceTelemetry, operationId);
            });
        }
示例#3
0
        public void LogEvent_WithEvent_CreatesEventTelemetry()
        {
            // Arrange
            const string eventName   = "Order Invoiced";
            var          spySink     = new InMemoryLogSink();
            string       operationId = $"operation-id-{Guid.NewGuid()}";
            ILogger      logger      = CreateLogger(spySink, config => config.Enrich.WithProperty(ContextProperties.Correlation.OperationId, operationId));

            var telemetryContext = new Dictionary <string, object>
            {
                ["OrderId"] = "ABC",
                ["Vendor"]  = "Contoso"
            };

            logger.LogEvent(eventName, telemetryContext);
            LogEvent logEvent = Assert.Single(spySink.CurrentLogEmits);

            Assert.NotNull(logEvent);

            var converter = ApplicationInsightsTelemetryConverter.Create();

            // Act
            IEnumerable <ITelemetry> telemetries = converter.Convert(logEvent, formatProvider: null);

            // Assert
            AssertDoesNotContainLogProperty(logEvent, EventTracking.EventLogEntry);
            Assert.Collection(telemetries, telemetry =>
            {
                var eventTelemetry = Assert.IsType <EventTelemetry>(telemetry);
                Assert.Equal(eventName, eventTelemetry.Name);
                AssertOperationContext(eventTelemetry, operationId);
                AssertContainsTelemetryProperty(eventTelemetry, "OrderId", "ABC");
                AssertContainsTelemetryProperty(eventTelemetry, "Vendor", "Contoso");
            });
        }
示例#4
0
        public void LogException_WithException_CreatesExceptionTelemetry()
        {
            // Arrange
            string  platform    = $"platform-id-{Guid.NewGuid()}";
            var     exception   = new PlatformNotSupportedException(platform);
            var     spySink     = new InMemoryLogSink();
            string  operationId = $"operation-id-{Guid.NewGuid()}";
            ILogger logger      = CreateLogger(spySink, config => config.Enrich.WithProperty(ContextProperties.Correlation.OperationId, operationId));

            logger.LogCritical(exception, exception.Message);
            LogEvent logEvent = Assert.Single(spySink.CurrentLogEmits);

            Assert.NotNull(logEvent);

            var converter = ApplicationInsightsTelemetryConverter.Create();

            // Act
            IEnumerable <ITelemetry> telemetries = converter.Convert(logEvent, formatProvider: null);

            // Assert
            Assert.Collection(telemetries, telemetry =>
            {
                var exceptionTelemetryType = Assert.IsType <ExceptionTelemetry>(telemetry);
                Assert.NotNull(exceptionTelemetryType);
                Assert.NotNull(exceptionTelemetryType.Exception);
                Assert.Equal(exception.Message, exceptionTelemetryType.Exception.Message);
                AssertOperationContext(exceptionTelemetryType, operationId);
            });
        }
        public void LogEvent_WithCustomConsumerTypeWithoutAssemblyVersion_SkipsApplicationVersionEnrichment()
        {
            // Arrange
            var spy      = new InMemoryLogSink();
            var services = new ServiceCollection();

            var stubbedType = new Mock <Type>();

            stubbedType.Setup(t => t.Assembly).Returns(Mock.Of <Assembly>());
            services.AddAssemblyAppVersion(stubbedType.Object);
            IServiceProvider serviceProvider = services.BuildServiceProvider();

            ILogger logger =
                new LoggerConfiguration()
                .WriteTo.Sink(spy)
                .Enrich.WithVersion(serviceProvider)
                .CreateLogger();

            // Act
            logger.Information("This log event will not be enriched with a assembly version because custom consumer type doesn't have a assembly version attribute");

            // Assert
            LogEvent emit = Assert.Single(spy.CurrentLogEmits);

            Assert.NotNull(emit);
            Assert.Empty(emit.Properties);
        }
        public void LogEvent_WithCustomConsumerType_UsesConsumerTypeForAssemblyAppVersion()
        {
            // Arrange
            var spy      = new InMemoryLogSink();
            var services = new ServiceCollection();

            services.AddAssemblyAppVersion(typeof(VersionEnricherTests));
            IServiceProvider serviceProvider = services.BuildServiceProvider();

            ILogger logger =
                new LoggerConfiguration()
                .WriteTo.Sink(spy)
                .Enrich.WithVersion(serviceProvider)
                .CreateLogger();

            // Act
            logger.Information("This log event will be enriched with a assembly version from a custom consumer type");

            // Assert
            LogEvent emit = Assert.Single(spy.CurrentLogEmits);

            Assert.NotNull(emit);
            (string key, LogEventPropertyValue value) = Assert.Single(emit.Properties);
            Assert.Equal(VersionEnricher.DefaultPropertyName, key);
            Assert.Equal(AssemblyVersion, value.ToDecentString());
        }
        public void LogEvent_WithCustomAppVersionAndCustomPropertyName_HasCustomVersion()
        {
            // Arrange
            var    spy            = new InMemoryLogSink();
            string propertyName   = $"version-name-{Guid.NewGuid()}";
            string expected       = $"version-{Guid.NewGuid()}";
            var    stubAppVersion = new Mock <IAppVersion>();

            stubAppVersion.Setup(v => v.GetVersion()).Returns(expected);
            ILogger logger =
                new LoggerConfiguration()
                .WriteTo.Sink(spy)
                .Enrich.WithVersion(stubAppVersion.Object, propertyName)
                .CreateLogger();

            // Act
            logger.Information("This log event will be enriched with a custom application version on a custom property");

            // Assert
            LogEvent emit = Assert.Single(spy.CurrentLogEmits);

            Assert.NotNull(emit);
            (string key, LogEventPropertyValue value) = Assert.Single(emit.Properties);
            Assert.Equal(propertyName, key);
            Assert.Equal(expected, value.ToDecentString());
        }
        public void LogEvent_WithCustomRegisteredAppVersionAndCustomPropertyName_UsesCustomAppVersion()
        {
            // Arrange
            var spy          = new InMemoryLogSink();
            var propertyName = $"property-name-{Guid.NewGuid()}";
            var expected     = $"version-{Guid.NewGuid()}";
            var services     = new ServiceCollection();

            services.AddAppVersion(provider => new StubAppVersion(expected));
            IServiceProvider serviceProvider = services.BuildServiceProvider();

            ILogger logger =
                new LoggerConfiguration()
                .WriteTo.Sink(spy)
                .Enrich.WithVersion(serviceProvider, propertyName)
                .CreateLogger();

            // Act
            logger.Information("This log event will be enriched by the registered stubbed app version on the custom property name");

            // Assert
            LogEvent emit = Assert.Single(spy.CurrentLogEmits);

            Assert.NotNull(emit);
            (string key, LogEventPropertyValue value) = Assert.Single(emit.Properties);
            Assert.Equal(propertyName, key);
            Assert.Equal(expected, value.ToDecentString());
        }
示例#9
0
        public void LogEvent_WithKubernetesEnricher_HasEnvironmentInformation()
        {
            // Arrange
            string nodeName   = $"node-{Guid.NewGuid()}";
            string podName    = $"pod-{Guid.NewGuid()}";
            string @namespace = $"namespace-{Guid.NewGuid()}";

            var     spy    = new InMemoryLogSink();
            ILogger logger = new LoggerConfiguration()
                             .Enrich.With <KubernetesEnricher>()
                             .WriteTo.Sink(spy)
                             .CreateLogger();

            using (TemporaryEnvironmentVariable.Create(NodeNameVariable, nodeName))
                using (TemporaryEnvironmentVariable.Create(PodNameVariable, podName))
                    using (TemporaryEnvironmentVariable.Create(NamespaceVariable, @namespace))
                    {
                        // Act
                        logger.Information("This log event should be enriched with Kubernetes information");
                    }

            // Assert
            LogEvent logEvent = Assert.Single(spy.CurrentLogEmits);

            Assert.NotNull(logEvent);

            Assert.True(logEvent.ContainsProperty(ContextProperties.Kubernetes.NodeName, nodeName), "Log event should contain node name property");
            Assert.True(logEvent.ContainsProperty(ContextProperties.Kubernetes.PodName, podName), "Log event should contain pod name property");
            Assert.True(logEvent.ContainsProperty(ContextProperties.Kubernetes.Namespace, @namespace), "Log event should contain namespace property");
        }
示例#10
0
        public void LogEventWithPodNameProperty_WithKubernetesEnricher_HasEnvironmentInformation()
        {
            // Arrange
            string expectedPodName = $"pod-{Guid.NewGuid()}";
            string ignoredPodName  = $"pod-{Guid.NewGuid()}";

            var     spy    = new InMemoryLogSink();
            ILogger logger = new LoggerConfiguration()
                             .Enrich.With <KubernetesEnricher>()
                             .WriteTo.Sink(spy)
                             .CreateLogger();

            using (TemporaryEnvironmentVariable.Create(PodNameVariable, ignoredPodName))
            {
                // Act
                logger.Information("This log even already has a Kubernetes PodName {PodName}", expectedPodName);
            }

            // Assert
            LogEvent logEvent = Assert.Single(spy.CurrentLogEmits);

            Assert.NotNull(logEvent);

            Assert.True(logEvent.ContainsProperty(ContextProperties.Kubernetes.PodName, expectedPodName), "Log event should contain pod name property");
            Assert.DoesNotContain(logEvent.Properties, prop => prop.Key == ContextProperties.Kubernetes.NodeName);
            Assert.DoesNotContain(logEvent.Properties, prop => prop.Key == ContextProperties.Kubernetes.Namespace);
        }
        public void LogEvent_WithStaticDefaultCorrelationInfoAccessorWithCustomOperationIdProperty_HasOperationIdAndTransactionId()
        {
            // Arrange
            string operationIdPropertyName = $"operation-name-{Guid.NewGuid():N}";
            string expectedOperationId     = $"operation-{Guid.NewGuid()}";
            string expectedTransactionId   = $"transaction-{Guid.NewGuid()}";

            var spySink = new InMemoryLogSink();
            var correlationInfoAccessor = DefaultCorrelationInfoAccessor.Instance;

            correlationInfoAccessor.SetCorrelationInfo(new CorrelationInfo(expectedOperationId, expectedTransactionId));

            ILogger logger = new LoggerConfiguration()
                             .Enrich.WithCorrelationInfo(operationIdPropertyName: operationIdPropertyName)
                             .WriteTo.Sink(spySink)
                             .CreateLogger();

            // Act
            logger.Information("This message will be enriched with correlation information");

            // Assert
            LogEvent logEvent = Assert.Single(spySink.CurrentLogEmits);

            Assert.True(
                logEvent.ContainsProperty(operationIdPropertyName, expectedOperationId),
                $"Expected to have a log property operation ID '{operationIdPropertyName}' with the value '{expectedOperationId}'");
            Assert.True(
                logEvent.ContainsProperty(ContextProperties.Correlation.TransactionId, expectedTransactionId),
                $"Expected to have a log property transaction ID '{ContextProperties.Correlation.TransactionId}' with the value '{expectedTransactionId}'");
        }
        public void LogEvent_WithCustomCorrelationInfoEnricher_HasCustomEnrichedInformation()
        {
            // Arrange
            string expectedOperationId   = $"operation-{Guid.NewGuid()}";
            string expectedTransactionId = $"transaction-{Guid.NewGuid()}";
            string expectedTestId        = $"test-{Guid.NewGuid()}";

            var spySink      = new InMemoryLogSink();
            var stubAccessor = new Mock <ICorrelationInfoAccessor <TestCorrelationInfo> >();

            stubAccessor.Setup(accessor => accessor.GetCorrelationInfo())
            .Returns(new TestCorrelationInfo(expectedOperationId, expectedTransactionId, expectedTestId));

            ILogger logger = new LoggerConfiguration()
                             .Enrich.WithCorrelationInfo(new TestCorrelationInfoEnricher(stubAccessor.Object))
                             .WriteTo.Sink(spySink)
                             .CreateLogger();

            // Act
            logger.Information("This message will be enriched with custom correlation information");

            // Assert
            LogEvent logEvent = Assert.Single(spySink.CurrentLogEmits);

            Assert.False(
                logEvent.ContainsProperty(ContextProperties.Correlation.OperationId, expectedOperationId),
                $"Expected not to have a log property operation ID '{ContextProperties.Correlation.OperationId}' with the value '{expectedOperationId}'");
            Assert.False(
                logEvent.ContainsProperty(ContextProperties.Correlation.TransactionId, expectedTransactionId),
                $"Expected not to have a log property transaction ID '{ContextProperties.Correlation.TransactionId}' with the value '{expectedTransactionId}'");
            Assert.True(
                logEvent.ContainsProperty(TestCorrelationInfoEnricher.TestId, expectedTestId),
                $"Expected to have a log property test ID '{TestCorrelationInfoEnricher.TestId}' with the value '{expectedTestId}'");
        }
        public void LogEvent_WithCorrelationInfoWithCustomTransactionIdProperty_HasOperationIdAndTransactionId()
        {
            // Arrange
            string transactionIdPropertyName = $"transaction-name-{Guid.NewGuid():N}";
            string expectedOperationId       = $"operation-{Guid.NewGuid()}";
            string expectedTransactionId     = $"transaction-{Guid.NewGuid()}";

            var spySink      = new InMemoryLogSink();
            var stubAccessor = new Mock <ICorrelationInfoAccessor>();

            stubAccessor.Setup(accessor => accessor.GetCorrelationInfo())
            .Returns(new CorrelationInfo(expectedOperationId, expectedTransactionId));

            ILogger logger = new LoggerConfiguration()
                             .Enrich.WithCorrelationInfo(stubAccessor.Object, transactionIdPropertyName: transactionIdPropertyName)
                             .WriteTo.Sink(spySink)
                             .CreateLogger();

            // Act
            logger.Information("This message will be enriched with correlation information");

            // Assert
            LogEvent logEvent = Assert.Single(spySink.CurrentLogEmits);

            Assert.True(
                logEvent.ContainsProperty(ContextProperties.Correlation.OperationId, expectedOperationId),
                $"Expected to have a log property operation ID '{ContextProperties.Correlation.OperationId}' with the value '{expectedOperationId}'");
            Assert.True(
                logEvent.ContainsProperty(transactionIdPropertyName, expectedTransactionId),
                $"Expected to have a log property transaction ID '{transactionIdPropertyName}' with the value '{expectedTransactionId}'");
        }
        public IntegrationTest(ITestOutputHelper testOutput)
        {
            // The appsettings.local.json allows users to override (gitignored) settings locally for testing purposes
            Configuration   = TestConfig.Create();
            InMemoryLogSink = new InMemoryLogSink();

            var configuration = new LoggerConfiguration()
                                .WriteTo.Sink(new XunitTestLogSink(testOutput))
                                .WriteTo.Sink(InMemoryLogSink)
                                .WriteTo.AzureApplicationInsights(Configuration.GetValue <string>("Arcus:ApplicationInsights:InstrumentationKey"));

            Logger = configuration.CreateLogger();
        }
示例#15
0
        public void LogRequestMessage_WithRequestAndResponse_CreatesRequestTelemetry()
        {
            // Arrange
            var     spySink     = new InMemoryLogSink();
            string  operationId = $"operation-id-{Guid.NewGuid()}";
            ILogger logger      = CreateLogger(
                spySink, config => config.Enrich.WithProperty(ContextProperties.Correlation.OperationId, operationId));

            var telemetryContext = new Dictionary <string, object>
            {
                ["Client"]      = "https://localhost",
                ["ContentType"] = "application/json",
            };
            var      request    = new HttpRequestMessage(System.Net.Http.HttpMethod.Get, new Uri("https://" + "localhost" + "/api/v1/health"));
            var      statusCode = HttpStatusCode.OK;
            var      response   = new HttpResponseMessage(statusCode);
            TimeSpan duration   = TimeSpan.FromSeconds(5);

            logger.LogRequest(request, response, duration, telemetryContext);

            LogEvent logEvent = Assert.Single(spySink.CurrentLogEmits);

            Assert.NotNull(logEvent);

            var converter = ApplicationInsightsTelemetryConverter.Create();

            // Act
            IEnumerable <ITelemetry> telemetries = converter.Convert(logEvent, formatProvider: null);

            // Assert
            AssertDoesNotContainLogProperty(logEvent, RequestTracking.RequestLogEntry);
            Assert.Collection(telemetries, telemetry =>
            {
                var requestTelemetry = Assert.IsType <RequestTelemetry>(telemetry);
                Assert.Equal("GET /api/v1/health", requestTelemetry.Name);
                Assert.Equal(duration, requestTelemetry.Duration);
                Assert.Equal(((int)statusCode).ToString(), requestTelemetry.ResponseCode);
                Assert.True(requestTelemetry.Success);
                Assert.Equal(operationId, requestTelemetry.Id);
                Assert.Equal(new Uri("https://localhost/api/v1/health"), requestTelemetry.Url);
                AssertOperationContext(requestTelemetry, operationId);

                AssertContainsTelemetryProperty(requestTelemetry, "Client", "https://localhost");
                AssertContainsTelemetryProperty(requestTelemetry, "ContentType", "application/json");
            });
        }
示例#16
0
        public void LogHttpDependency_WithHttpDependency_CreatesHttpDependencyTelemetry()
        {
            // Arrange
            var     spySink     = new InMemoryLogSink();
            string  operationId = $"operation-id-{Guid.NewGuid()}";
            ILogger logger      = CreateLogger(spySink, config => config.Enrich.WithProperty(ContextProperties.Correlation.OperationId, operationId));

            var request          = new HttpRequestMessage(System.Net.Http.HttpMethod.Get, "https://localhost/api/v1/health");
            var startTime        = DateTimeOffset.UtcNow;
            var duration         = TimeSpan.FromSeconds(5);
            var telemetryContext = new Dictionary <string, object>
            {
                ["Port"] = "4000"
            };

            logger.LogHttpDependency(request, HttpStatusCode.OK, startTime, duration, telemetryContext);
            LogEvent logEvent = Assert.Single(spySink.CurrentLogEmits);

            Assert.NotNull(logEvent);


            var converter = ApplicationInsightsTelemetryConverter.Create();

            // Act
            IEnumerable <ITelemetry> telemetries = converter.Convert(logEvent, formatProvider: null);

            // Assert
            AssertDoesNotContainLogProperty(logEvent, DependencyTracking.DependencyLogEntry);
            Assert.Collection(telemetries, telemetry =>
            {
                var dependencyTelemetry = Assert.IsType <DependencyTelemetry>(telemetry);
                Assert.Equal(DependencyType.Http.ToString(), dependencyTelemetry.Type);
                Assert.Equal("localhost", dependencyTelemetry.Target);
                Assert.Equal("GET /api/v1/health", dependencyTelemetry.Name);
                Assert.Null(dependencyTelemetry.Data);
                Assert.Equal(startTime, dependencyTelemetry.Timestamp);
                Assert.Equal(duration, dependencyTelemetry.Duration);
                Assert.Equal("200", dependencyTelemetry.ResultCode);
                Assert.True(dependencyTelemetry.Success);
                AssertOperationContext(dependencyTelemetry, operationId);

                AssertContainsTelemetryProperty(dependencyTelemetry, "Port", "4000");
            });
        }
示例#17
0
        public async Task ServiceBusMessagePump_FailureDuringMessageHandling_TracksCorrelationInApplicationInsights()
        {
            // Arrange
            var    config           = TestConfig.Create();
            string connectionString = config.GetServiceBusConnectionString(ServiceBusEntityType.Queue);

            var spySink = new InMemoryLogSink();
            var options = new WorkerOptions();

            options.Configure(host => host.UseSerilog((context, currentConfig) =>
            {
                currentConfig
                .MinimumLevel.Debug()
                .MinimumLevel.Override("Microsoft", LogEventLevel.Information)
                .Enrich.FromLogContext()
                .Enrich.WithVersion()
                .Enrich.WithComponentName("Service Bus Queue Worker")
                .WriteTo.Sink(spySink);
            }));
            options.AddServiceBusQueueMessagePump(configuration => connectionString, opt => opt.AutoComplete = true)
            .WithServiceBusMessageHandler <OrdersSabotageAzureServiceBusMessageHandler, Order>();

            string            operationId = $"operation-{Guid.NewGuid()}", transactionId = $"transaction-{Guid.NewGuid()}";
            ServiceBusMessage orderMessage = OrderGenerator.Generate().AsServiceBusMessage(operationId, transactionId);

            await using (var worker = await Worker.StartNewAsync(options))
            {
                await using (var service = await TestMessagePumpService.StartNewAsync(config, _logger))
                {
                    // Act
                    await service.SendMessageToServiceBusAsync(connectionString, orderMessage);
                }

                // Assert
                RetryAssertUntilTelemetryShouldBeAvailable(() =>
                {
                    Assert.Contains(spySink.CurrentLogEmits,
                                    log => log.Exception?.InnerException?.Message.Contains("Sabotage") == true &&
                                    log.ContainsProperty(ContextProperties.Correlation.OperationId, operationId) &&
                                    log.ContainsProperty(ContextProperties.Correlation.TransactionId, transactionId));
                },
                                                           timeout: TimeSpan.FromMinutes(1));
            }
        }
        public void LogEvent_WithApplicationEnricher_HasComponentName()
        {
            // Arrange
            string  componentName = $"component-{Guid.NewGuid()}";
            var     spy           = new InMemoryLogSink();
            ILogger logger        = new LoggerConfiguration()
                                    .Enrich.WithComponentName(componentName)
                                    .WriteTo.Sink(spy)
                                    .CreateLogger();

            // Act
            logger.Information("This event will be enriched with application information");

            // Assert
            LogEvent logEvent = Assert.Single(spy.CurrentLogEmits);

            Assert.True(
                logEvent.ContainsProperty(ComponentName, componentName),
                "Log event should contain component name property");
        }
示例#19
0
        public void LogCosmosSqlDependency_WithTableStorageDependency_CreatesDependencyTelemetry()
        {
            // Arrange
            var     spySink          = new InMemoryLogSink();
            string  operationId      = $"operation-id-{Guid.NewGuid()}";
            ILogger logger           = CreateLogger(spySink, config => config.Enrich.WithProperty(ContextProperties.Correlation.OperationId, operationId));
            string  container        = _bogusGenerator.Commerce.ProductName();
            string  database         = _bogusGenerator.Commerce.ProductName();
            string  accountName      = _bogusGenerator.Finance.AccountName();
            var     startTime        = DateTimeOffset.UtcNow;
            var     duration         = TimeSpan.FromSeconds(5);
            var     telemetryContext = new Dictionary <string, object>
            {
                ["Namespace"] = "azure.cosmos.namespace"
            };

            logger.LogCosmosSqlDependency(accountName, database, container, isSuccessful: true, startTime: startTime, duration: duration, context: telemetryContext);
            LogEvent logEvent = Assert.Single(spySink.CurrentLogEmits);

            Assert.NotNull(logEvent);

            var converter = ApplicationInsightsTelemetryConverter.Create();

            // Act
            IEnumerable <ITelemetry> telemetries = converter.Convert(logEvent, formatProvider: null);

            // Assert
            AssertDoesNotContainLogProperty(logEvent, DependencyTracking.DependencyLogEntry);
            Assert.Collection(telemetries, telemetry =>
            {
                var dependencyTelemetry = Assert.IsType <DependencyTelemetry>(telemetry);
                Assert.Equal("Azure DocumentDB", dependencyTelemetry.Type);
                Assert.Equal($"{database}/{container}", dependencyTelemetry.Data);
                Assert.Equal(accountName, dependencyTelemetry.Target);
                Assert.Equal(startTime, dependencyTelemetry.Timestamp);
                Assert.Equal(duration, dependencyTelemetry.Duration);
                Assert.True(dependencyTelemetry.Success);

                AssertContainsTelemetryProperty(dependencyTelemetry, "Namespace", "azure.cosmos.namespace");
            });
        }
示例#20
0
        public void LogSqlDependency_WithSqlDependency_CreatesSqlDependencyTelemetry()
        {
            // Arrange
            var     spySink          = new InMemoryLogSink();
            string  operationId      = $"operation-id-{Guid.NewGuid()}";
            ILogger logger           = CreateLogger(spySink, config => config.Enrich.WithProperty(ContextProperties.Correlation.OperationId, operationId));
            var     startTime        = DateTimeOffset.UtcNow;
            var     duration         = TimeSpan.FromSeconds(5);
            var     telemetryContext = new Dictionary <string, object>
            {
                ["Statement"] = "Query"
            };

            logger.LogSqlDependency("Server", "Database", "Users", "GET", isSuccessful: true, startTime: startTime, duration: duration, telemetryContext);
            LogEvent logEvent = Assert.Single(spySink.CurrentLogEmits);

            Assert.NotNull(logEvent);

            var converter = ApplicationInsightsTelemetryConverter.Create();

            // Act
            IEnumerable <ITelemetry> telemetries = converter.Convert(logEvent, formatProvider: null);

            // Assert
            AssertDoesNotContainLogProperty(logEvent, DependencyTracking.DependencyLogEntry);
            Assert.Collection(telemetries, telemetry =>
            {
                var dependencyTelemetry = Assert.IsType <DependencyTelemetry>(telemetry);
                Assert.Equal(DependencyType.Sql.ToString(), dependencyTelemetry.Type);
                Assert.Equal("Server", dependencyTelemetry.Target);
                Assert.Equal("Database/Users", dependencyTelemetry.Name);
                Assert.Equal("GET", dependencyTelemetry.Data);
                Assert.Equal(startTime, dependencyTelemetry.Timestamp);
                Assert.Equal(duration, dependencyTelemetry.Duration);
                Assert.Null(dependencyTelemetry.ResultCode);
                Assert.True(dependencyTelemetry.Success);
                AssertOperationContext(dependencyTelemetry, operationId);

                AssertContainsTelemetryProperty(dependencyTelemetry, "Statement", "Query");
            });
        }
        public void LogEventWithComponentNameProperty_WithApplicationEnricher_DoesntAlterComponentNameProperty()
        {
            // Arrange
            string  expectedComponentName = $"expected-component-{Guid.NewGuid()}";
            string  ignoredComponentName  = $"ignored-component-{Guid.NewGuid()}";
            var     spy    = new InMemoryLogSink();
            ILogger logger = new LoggerConfiguration()
                             .Enrich.With(new ApplicationEnricher(ignoredComponentName))
                             .WriteTo.Sink(spy)
                             .CreateLogger();

            // Act
            logger.Information("This event will not be enriched with component name because it already has one called '{ComponentName}'", expectedComponentName);

            // Assert
            LogEvent logEvent = Assert.Single(spy.CurrentLogEmits);

            Assert.True(
                logEvent.ContainsProperty(ComponentName, expectedComponentName),
                "Log event should not overwrite component name property");
        }
        public void LogEvent_WithCustomComponentNamePropertyName_HasCustomComponentNamePropertyName()
        {
            // Arrange
            string  expected     = $"component-{Guid.NewGuid()}";
            string  propertyName = $"component-property-name-{Guid.NewGuid()}";
            var     spy          = new InMemoryLogSink();
            ILogger logger       = new LoggerConfiguration()
                                   .Enrich.WithComponentName(expected, propertyName)
                                   .WriteTo.Sink(spy)
                                   .CreateLogger();

            // Act
            logger.Information("This event will be enriched with a custom property name which has the component name");

            // Assert
            LogEvent logEvent = Assert.Single(spy.CurrentLogEmits);

            Assert.True(
                logEvent.ContainsProperty(propertyName, expected),
                $"Log event should have custom property '{propertyName}' with component name '{expected}'");
        }
示例#23
0
        public void CanCorrectlyParseDateTimeWithTicksFromString()
        {
            var    timestamp   = DateTimeOffset.Now;
            string propertyKey = "timestamp";

            var spySink = new InMemoryLogSink();

            ILogger logger = CreateLogger(
                spySink, config =>
            {
                config.Enrich.WithProperty(propertyKey, timestamp.ToString(FormatSpecifiers.InvariantTimestampFormat));
                return(config);
            });

            logger.LogWarning("test");

            var retrievedTimestamp = spySink.CurrentLogEmits.First().Properties.GetAsDateTimeOffset(propertyKey);

            Assert.Equal(timestamp, retrievedTimestamp);
            Assert.Equal(timestamp.Ticks, retrievedTimestamp.Ticks);
        }
示例#24
0
        public void LogServiceBusDependency_WithServiceBusDependency_CreatesDependencyTelemetry()
        {
            // Arrange
            var     spySink     = new InMemoryLogSink();
            string  operationId = $"operation-id-{Guid.NewGuid()}";
            ILogger logger      = CreateLogger(spySink, config => config.Enrich.WithProperty(ContextProperties.Correlation.OperationId, operationId));
            string  entityName  = $"entity-name-{Guid.NewGuid()}";
            const ServiceBusEntityType entityType = ServiceBusEntityType.Unknown;
            var startTime        = DateTimeOffset.UtcNow;
            var duration         = TimeSpan.FromSeconds(5);
            var telemetryContext = new Dictionary <string, object>
            {
                ["Namespace"] = "azure.servicebus.namespace"
            };

            logger.LogServiceBusDependency(entityName, entityType: entityType, isSuccessful: true, startTime: startTime, duration: duration, context: telemetryContext);
            LogEvent logEvent = Assert.Single(spySink.CurrentLogEmits);

            Assert.NotNull(logEvent);

            var converter = ApplicationInsightsTelemetryConverter.Create();

            // Act
            IEnumerable <ITelemetry> telemetries = converter.Convert(logEvent, formatProvider: null);

            // Assert
            AssertDoesNotContainLogProperty(logEvent, DependencyTracking.DependencyLogEntry);
            Assert.Collection(telemetries, telemetry =>
            {
                var dependencyTelemetry = Assert.IsType <DependencyTelemetry>(telemetry);
                Assert.Equal("Azure Service Bus", dependencyTelemetry.Type);
                Assert.Equal(entityName, dependencyTelemetry.Target);
                Assert.Equal(startTime, dependencyTelemetry.Timestamp);
                Assert.Equal(duration, dependencyTelemetry.Duration);
                Assert.True(dependencyTelemetry.Success);

                AssertContainsTelemetryProperty(dependencyTelemetry, "Namespace", "azure.servicebus.namespace");
                AssertContainsTelemetryProperty(dependencyTelemetry, "EntityType", entityType.ToString());
            });
        }
示例#25
0
        public void LogDependency_WithDependency_CreatesDependencyTelemetry()
        {
            // Arrange
            var       spySink          = new InMemoryLogSink();
            string    operationId      = $"operation-id-{Guid.NewGuid()}";
            ILogger   logger           = CreateLogger(spySink, config => config.Enrich.WithProperty(ContextProperties.Correlation.OperationId, operationId));
            string    dependencyType   = $"dependency-{Guid.NewGuid()}";
            const int dependencyData   = 10;
            var       startTime        = DateTimeOffset.UtcNow;
            var       duration         = TimeSpan.FromSeconds(5);
            var       telemetryContext = new Dictionary <string, object>
            {
                ["CustomSetting"] = "Approved"
            };

            logger.LogDependency(dependencyType, dependencyData, isSuccessful: true, startTime: startTime, duration: duration, context: telemetryContext);
            LogEvent logEvent = Assert.Single(spySink.CurrentLogEmits);

            Assert.NotNull(logEvent);

            var converter = ApplicationInsightsTelemetryConverter.Create();

            // Act
            IEnumerable <ITelemetry> telemetries = converter.Convert(logEvent, formatProvider: null);

            // Assert
            AssertDoesNotContainLogProperty(logEvent, DependencyTracking.DependencyLogEntry);
            Assert.Collection(telemetries, telemetry =>
            {
                var dependencyTelemetry = Assert.IsType <DependencyTelemetry>(telemetry);
                Assert.Equal(dependencyType, dependencyTelemetry.Type);
                Assert.Equal(dependencyData.ToString(), dependencyTelemetry.Data);
                Assert.Equal(startTime, dependencyTelemetry.Timestamp);
                Assert.Equal(duration, dependencyTelemetry.Duration);
                Assert.True(dependencyTelemetry.Success);

                AssertContainsTelemetryProperty(dependencyTelemetry, "CustomSetting", "Approved");
            });
        }
        public void LogEvent_WithCustomPropertyName_HasCustomVersionProperty()
        {
            // Arrange
            string  propertyName = $"my-version-{Guid.NewGuid():N}";
            var     spy          = new InMemoryLogSink();
            ILogger logger       =
                new LoggerConfiguration()
                .WriteTo.Sink(spy)
                .Enrich.WithVersion(propertyName)
                .CreateLogger();

            // Act
            logger.Information("This log event should contain a custom version property when written to the sink");

            // Assert
            LogEvent emit = Assert.Single(spy.CurrentLogEmits);

            Assert.NotNull(emit);
            (string key, LogEventPropertyValue value) = Assert.Single(emit.Properties);
            Assert.Equal(propertyName, key);
            Assert.True(Version.TryParse(value.ToString().Trim('\"'), out Version result));
        }
        public void LogEvent_WithCustomAppVersionReturningBlankVersion_DoesntAddVersionProperty(string version)
        {
            // Arrange
            var spy            = new InMemoryLogSink();
            var stubAppVersion = new Mock <IAppVersion>();

            stubAppVersion.Setup(v => v.GetVersion()).Returns(version);
            ILogger logger =
                new LoggerConfiguration()
                .WriteTo.Sink(spy)
                .Enrich.WithVersion(stubAppVersion.Object)
                .CreateLogger();

            // Act
            logger.Information("This log event will not be enriched with an custom application version because the version is blank");

            // Assert
            LogEvent emit = Assert.Single(spy.CurrentLogEmits);

            Assert.NotNull(emit);
            Assert.Empty(emit.Properties);
        }
        public void LogEvent_WithVersionEnricher_HasVersionProperty()
        {
            // Arrange
            var spy = new InMemoryLogSink();
            LoggerConfiguration configuration =
                new LoggerConfiguration()
                .WriteTo.Sink(spy)
                .Enrich.WithVersion();

            ILogger logger = configuration.CreateLogger();

            // Act
            logger.Information("This log event should contain a 'version' property when written to the sink");

            // Assert
            LogEvent emit = Assert.Single(spy.CurrentLogEmits);

            Assert.NotNull(emit);
            (string key, LogEventPropertyValue value) = Assert.Single(emit.Properties);
            Assert.Equal("version", key);
            Assert.True(Version.TryParse(value.ToString().Trim('\"'), out Version result));
        }
示例#29
0
        public void LogMetric_WithMetric_CreatesMetricTelemetry()
        {
            // Arrange
            const string metricName  = "Request stream";
            const double metricValue = 0.13;
            var          timestamp   = DateTimeOffset.UtcNow;
            var          spySink     = new InMemoryLogSink();
            string       operationId = $"operation-id-{Guid.NewGuid()}";
            ILogger      logger      = CreateLogger(spySink, config => config.Enrich.WithProperty(ContextProperties.Correlation.OperationId, operationId));

            var telemetryContext = new Dictionary <string, object>
            {
                ["Capacity"] = "0.45"
            };

            logger.LogMetric(metricName, metricValue, timestamp, telemetryContext);
            LogEvent logEvent = Assert.Single(spySink.CurrentLogEmits);

            Assert.NotNull(logEvent);

            var converter = ApplicationInsightsTelemetryConverter.Create();

            // Act
            IEnumerable <ITelemetry> telemetries = converter.Convert(logEvent, formatProvider: null);

            // Assert
            AssertDoesNotContainLogProperty(logEvent, MetricTracking.MetricLogEntry);
            Assert.Collection(telemetries, telemetry =>
            {
                var metricTelemetry = Assert.IsType <MetricTelemetry>(telemetry);
                Assert.Equal(metricName, metricTelemetry.Name);
                Assert.Equal(metricValue, metricTelemetry.Sum);
                Assert.Equal(timestamp, metricTelemetry.Timestamp);
                AssertOperationContext(metricTelemetry, operationId);

                AssertContainsTelemetryProperty(metricTelemetry, "Capacity", "0.45");
            });
        }
示例#30
0
        public void LogEventWithCustomNamespacePropertyName_WithKubernetesEnricher_HasEnvironmentInformation()
        {
            // Arrange
            string  expected     = $"namespace-{Guid.NewGuid()}";
            string  propertyName = $"namespace-name-{Guid.NewGuid():N}";
            var     spy          = new InMemoryLogSink();
            ILogger logger       = new LoggerConfiguration()
                                   .Enrich.WithKubernetesInfo(namespacePropertyName: propertyName)
                                   .WriteTo.Sink(spy)
                                   .CreateLogger();

            using (TemporaryEnvironmentVariable.Create(NamespaceVariable, expected))
            {
                // Act
                logger.Information("This log event should contain the custom configured Kubernetes property");
            }

            // Assert
            LogEvent logEvent = Assert.Single(spy.CurrentLogEmits);

            Assert.NotNull(logEvent);
            Assert.True(logEvent.ContainsProperty(propertyName, expected), $"Log event contain property '{propertyName}' with value '{expected}'");
        }