public void Trace_Ignores_FunctionUserCategory()
        {
            // Create a logger with the Function.{FunctionName}.User category, which is what determines user logs.
            ILogger logger = new SystemLogger(Guid.NewGuid().ToString(), LogCategories.CreateFunctionUserCategory(_functionName), _mockEventGenerator.Object, _settingsManager);

            logger.LogDebug("TestMessage");

            // Make sure it's never been called.
            _mockEventGenerator.Verify(p => p.LogFunctionTraceEvent(It.IsAny <LogLevel>(), It.IsAny <string>(), It.IsAny <string>(), It.IsAny <string>(), It.IsAny <string>(), It.IsAny <string>(), It.IsAny <string>(), It.IsAny <string>(), string.Empty, string.Empty, string.Empty, string.Empty, string.Empty), Times.Never);
        }
Пример #2
0
        public Task <IValueProvider> BindAsync(BindingContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            ILogger logger = _loggerFactory.CreateLogger(LogCategories.CreateFunctionUserCategory(context.ValueContext.FunctionContext.MethodName));

            return(BindAsync(logger, context.ValueContext));
        }
Пример #3
0
 public SampleBotApplication(
     ILineMessagingClient lineMessagingClient, LineMessagingApiSettings settings,
     IDurableClientFactory durableClientFactory,
     INaturalLanguageUnderstandingClient nluClient,
     ILoggerFactory loggerFactory, params ISkill[] skills)
     : base(lineMessagingClient, settings, durableClientFactory, nluClient,
            loggerFactory.CreateLogger(LogCategories.CreateFunctionUserCategory(nameof(WebhookEndpointFunction))),
            skills)
 {
     LineMessagingClient = lineMessagingClient;
 }
        protected async Task <LogMessage> WaitForTraceAsync(string functionName, Func <LogMessage, bool> filter)
        {
            LogMessage logMessage = null;

            await TestHelpers.Await(() =>
            {
                logMessage = Fixture.Host.GetLogMessages(LogCategories.CreateFunctionUserCategory(functionName)).SingleOrDefault(filter);
                return(logMessage != null);
            });

            return(logMessage);
        }
Пример #5
0
        private static void ValidateMetric(MetricTelemetry telemetry, string expectedOperationId, string expectedOperationName)
        {
            ValidateTelemetry(telemetry, expectedOperationId, expectedOperationName, LogCategories.CreateFunctionUserCategory(expectedOperationName), SeverityLevel.Information);

            Assert.Equal("TestMetric", telemetry.Name);
            Assert.Equal(1234, telemetry.Sum);
            Assert.Equal(50, telemetry.Count);
            Assert.Equal(10.4, telemetry.Min);
            Assert.Equal(23, telemetry.Max);
            Assert.Equal("100", telemetry.Properties[$"{LogConstants.CustomPropertyPrefix}MyCustomMetricProperty"]);

            ValidateSdkVersion(telemetry);
        }
        public async Task Scenario_Logging()
        {
            string  testData = Guid.NewGuid().ToString();
            JObject input    = new JObject
            {
                { "scenario", "logging" },
                { "input", testData },
            };

            Fixture.Host.ClearLogMessages();

            await Fixture.Host.BeginFunctionAsync("Scenarios", input);

            string         userCategory = LogCategories.CreateFunctionUserCategory("Scenarios");
            IList <string> logs         = null;
            await TestHelpers.Await(() =>
            {
                logs = Fixture.Host.GetLogMessages(userCategory).Select(p => p.FormattedMessage).ToList();
                return(logs.Count == 10);
            }, userMessageCallback : Fixture.Host.GetLog);

            // verify use of context.log to log complex objects
            LogMessage scriptTrace = Fixture.Host.GetLogMessages(userCategory).Single(p => p.FormattedMessage != null && p.FormattedMessage.Contains(testData));

            Assert.Equal(LogLevel.Information, scriptTrace.Level);
            JObject logEntry = JObject.Parse(scriptTrace.FormattedMessage);

            Assert.Equal("This is a test", logEntry["message"]);
            Assert.Equal(testData, logEntry["input"]);

            // verify log levels in traces
            LogMessage[] traces = Fixture.Host.GetLogMessages(userCategory).Where(t => t.FormattedMessage != null && t.FormattedMessage.Contains("loglevel")).ToArray();
            Assert.Equal(LogLevel.Information, traces[0].Level);
            Assert.Equal("loglevel default", traces[0].FormattedMessage);
            Assert.Equal(LogLevel.Information, traces[1].Level);
            Assert.Equal("loglevel info", traces[1].FormattedMessage);
            Assert.Equal(LogLevel.Trace, traces[2].Level);
            Assert.Equal("loglevel verbose", traces[2].FormattedMessage);
            Assert.Equal(LogLevel.Warning, traces[3].Level);
            Assert.Equal("loglevel warn", traces[3].FormattedMessage);
            Assert.Equal(LogLevel.Error, traces[4].Level);
            Assert.Equal("loglevel error", traces[4].FormattedMessage);

            // verify most of the logs look correct
            Assert.EndsWith("Mathew Charles", logs[1]);
            Assert.EndsWith("null", logs[2]);
            Assert.EndsWith("1234", logs[3]);
            Assert.EndsWith("true", logs[4]);
            Assert.EndsWith("loglevel default", logs[5]);
            Assert.EndsWith("loglevel info", logs[6]);
        }
Пример #7
0
        public async Task ApplicationInsights_SuccessfulFunction()
        {
            string testName = nameof(TestApplicationInsightsInformation);

            using (IHost host = ConfigureHost())
            {
                await host.StartAsync();

                MethodInfo methodInfo = GetType().GetMethod(testName, BindingFlags.Public | BindingFlags.Static);
                await host.GetJobHost().CallAsync(methodInfo, new { input = "function input" });

                await host.StopAsync();

                Assert.Equal(11, _channel.Telemetries.Count);

                // Validate the request
                RequestTelemetry request = _channel.Telemetries
                                           .OfType <RequestTelemetry>()
                                           .Single();
                ValidateRequest(request, testName, true);

                // invocation id is retrievable from the request
                request.Properties.TryGetValue(LogConstants.InvocationIdKey, out string invocationId);

                // Validate the traces. Order by message string as the requests may come in
                // slightly out-of-order or on different threads
                TraceTelemetry[] telemetries = _channel.Telemetries
                                               .OfType <TraceTelemetry>()
                                               .OrderBy(t => t.Message)
                                               .ToArray();

                string expectedFunctionCategory     = LogCategories.CreateFunctionCategory(testName);
                string expectedFunctionUserCategory = LogCategories.CreateFunctionUserCategory(testName);

                ValidateTrace(telemetries[0], "Executed ", expectedFunctionCategory, testName, invocationId);
                ValidateTrace(telemetries[1], "Executing ", expectedFunctionCategory, testName, invocationId, request.Context.Operation.Id, request.Id);
                ValidateTrace(telemetries[2], "Found the following functions:\r\n", LogCategories.Startup);
                ValidateTrace(telemetries[3], "Job host started", LogCategories.Startup);
                ValidateTrace(telemetries[4], "Job host stopped", LogCategories.Startup);
                ValidateTrace(telemetries[5], "Logger", expectedFunctionUserCategory, testName, invocationId, request.Context.Operation.Id, request.Id, hasCustomScope: true);
                ValidateTrace(telemetries[6], "Starting JobHost", "Microsoft.Azure.WebJobs.Hosting.JobHostService");
                ValidateTrace(telemetries[7], "Stopping JobHost", "Microsoft.Azure.WebJobs.Hosting.JobHostService");
                ValidateTrace(telemetries[8], "Trace", expectedFunctionUserCategory, testName, invocationId, request.Context.Operation.Id, request.Id);

                // We should have 1 custom metric.
                MetricTelemetry metric = _channel.Telemetries
                                         .OfType <MetricTelemetry>()
                                         .Single();
                ValidateMetric(metric, testName);
            }
        }
Пример #8
0
        private static ILogger CreateILogger(IServiceProvider serviceProvider)
        {
            ILogger toReturn = null;

            ILoggerFactory loggerFactory =
                serviceProvider.GetService <ILoggerFactory>();

            string categoryName = LogCategories.CreateFunctionUserCategory(
                nameof(Dfe.CdcEventApi));

            toReturn = loggerFactory.CreateLogger(categoryName);

            return(toReturn);
        }
Пример #9
0
        private static void ValidateMetric(MetricTelemetry telemetry, string expectedOperationName)
        {
            Assert.Equal(expectedOperationName, telemetry.Context.Operation.Name);
            Assert.NotNull(telemetry.Context.Operation.Id);
            Assert.Equal(LogCategories.CreateFunctionUserCategory(expectedOperationName), telemetry.Properties[LogConstants.CategoryNameKey]);
            Assert.Equal(LogLevel.Information.ToString(), telemetry.Properties[LogConstants.LogLevelKey]);

            Assert.Equal("MyCustomMetric", telemetry.Name);
            Assert.Equal(5.1, telemetry.Sum);
            Assert.Equal(50, telemetry.Count);
            Assert.Equal(10.4, telemetry.Min);
            Assert.Equal(23, telemetry.Max);
            Assert.Null(telemetry.StandardDeviation);
            Assert.Equal("100", telemetry.Properties[$"{LogConstants.CustomPropertyPrefix}MyCustomMetricProperty"]);
            ValidateCustomScopeProperty(telemetry);

            ValidateSdkVersion(telemetry);
        }
        public Task <IValueProvider> BindAsync(BindingContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            ILogger     logger = _loggerFactory.CreateLogger(LogCategories.CreateFunctionUserCategory(context.ValueContext.FunctionContext.MethodName));
            TraceWriter trace  = new LoggerTraceWriter(logger);

            object tracer = trace;

            if (_parameter.ParameterType == typeof(TextWriter))
            {
                // bind to an adapter
                tracer = TextWriterTraceAdapter.Synchronized(trace);
            }

            return(BindAsync(tracer, context.ValueContext));
        }
Пример #11
0
        public IServiceProvider Build()
        {
            var services = new ServiceCollection();

            services.AddSingleton(_ => _loggerFactory.CreateLogger(LogCategories.CreateFunctionUserCategory("Common")));

            services.AddMediatR(typeof(ContactCreatedHandler).GetTypeInfo().Assembly);

            services.AddDbContext <ContactDbContext>(options =>
            {
                options.UseSqlServer(_config.GetConnectionString("DefaultConnection"));
            })
            .AddSingleton <IContactDbContext>(c => c.GetRequiredService <ContactDbContext>())
            .AddSingleton <IUnitOfWork>(c => c.GetRequiredService <ContactDbContext>());

            services.AddTransient <IContactService, ContactService>();
            services.AddTransient <IContactRepository, ContactRepository>();

            return(services.BuildServiceProvider());
        }
        public IServiceProvider Build()
        {
            var services = new ServiceCollection();

            services.Configure <global::DAS.DigitalEngagement.Models.Infrastructure.Configuration>(Configuration.GetSection("Values"));

            services.AddOptions();

            // Important: We need to call CreateFunctionUserCategory, otherwise our log entries might be filtered out.
            services.AddSingleton <ILogger>(_ => _loggerFactory.CreateLogger(LogCategories.CreateFunctionUserCategory("Common")));

            services.AddTransient <IRegisterHandler, RegisterHandler>();
            services.AddTransient <IUserDataValidator, UserDataValidator>();
            services.AddTransient(typeof(IHttpClient <>), typeof(HttpClient <>));
            services.AddTransient <IMarketoService, MarketoLeadService>();

            services.AddMarketoClient(Configuration);

            return(services.BuildServiceProvider());
        }
        protected async Task <JObject> GetFunctionTestResult(string functionName)
        {
            string logEntry = null;

            await TestHelpers.Await(() =>
            {
                // search the logs for token "TestResult:" and parse the following JSON
                var logs = Fixture.Host.GetLogMessages(LogCategories.CreateFunctionUserCategory(functionName));
                if (logs != null)
                {
                    logEntry = logs.Select(p => p.FormattedMessage).SingleOrDefault(p => p != null && p.Contains("TestResult:"));
                }
                return(logEntry != null);
            });

            int idx = logEntry.IndexOf("{");

            logEntry = logEntry.Substring(idx);

            return(JObject.Parse(logEntry));
        }
        public void CreateLogger_UsesSameFileWriter_ForSameFile()
        {
            var rootPath = Path.GetTempPath();

            using (var provider = new FunctionFileLoggerProvider(Guid.NewGuid().ToString(), rootPath, () => true, () => true))
            {
                provider.CreateLogger(LogCategories.CreateFunctionCategory("Test1"));
                provider.CreateLogger(LogCategories.CreateFunctionUserCategory("Test1"));
                provider.CreateLogger(LogCategories.CreateFunctionCategory("Test1"));

                Assert.Single(provider.FileWriterCache);

                // This creates a new entry.
                provider.CreateLogger(LogCategories.CreateFunctionCategory("Test2"));

                Assert.Equal(2, provider.FileWriterCache.Count);
                Assert.NotSame(
                    provider.FileWriterCache[Path.Combine("Function", "Test1")],
                    provider.FileWriterCache[Path.Combine("Function", "Test2")]);
            }
        }
Пример #15
0
        public IServiceProvider Build()
        {
            var services = new ServiceCollection();

            services.Configure <ForecastingJobsConfiguration>(Configuration.GetSection("ForecastingJobs"));

            var nLogConfiguration = new NLogConfiguration();

            services.AddLogging((options) =>
            {
                options.AddConfiguration(Configuration.GetSection("Logging"));
                options.SetMinimumLevel(LogLevel.Trace);
                options.AddNLog(new NLogProviderOptions
                {
                    CaptureMessageTemplates  = true,
                    CaptureMessageProperties = true
                });

                options.AddConsole();
                options.AddDebug();

                nLogConfiguration.ConfigureNLog(Configuration);
            });

            services.AddSingleton(typeof(ILogger <>), typeof(Logger <>));

            services.AddSingleton(_ => _loggerFactory.CreateLogger(LogCategories.CreateFunctionUserCategory("Common")));
            EncodingConfig encodingConfig = GetEncodingConfig();

            services.AddSingleton(encodingConfig);
            services.AddSingleton <IEncodingService, EncodingService>();

            services.AddSingleton <ILevyCompleteTriggerHandler, LevyCompleteTriggerHandler>();
            services.AddSingleton <IRefreshPaymentDataCompletedTriggerHandler, PaymentCompleteTriggerHandler>();
            services.AddSingleton <ILevyForecastService, LevyForecastService>();
            services.AddSingleton <IPaymentForecastService, PaymentForecastService>();
            services.AddSingleton(typeof(IHttpFunctionClient <>), typeof(HttpFunctionClient <>));

            return(services.BuildServiceProvider());
        }
Пример #16
0
        private static void ValidateException(
            ExceptionTelemetry telemetry,
            string expectedCategory,
            string expectedOperationName,
            string expectedOperationId,
            string expectedParentId)
        {
            Assert.Equal(expectedCategory, telemetry.Properties[LogConstants.CategoryNameKey]);
            Assert.Equal(expectedOperationName, telemetry.Context.Operation.Name);
            Assert.Equal(expectedOperationId, telemetry.Context.Operation.Id);
            Assert.Equal(expectedParentId, telemetry.Context.Operation.ParentId);

            if (expectedCategory == LogCategories.CreateFunctionUserCategory(expectedOperationName))
            {
                // It came directly from the user
                Assert.IsType <Exception>(telemetry.Exception);

                // Result logs do not include custom scopes.
                ValidateCustomScopeProperty(telemetry);
            }
            else if (expectedCategory == LogCategories.CreateFunctionCategory(expectedOperationName))
            {
                // It came directly from the host, so wrapped in a FunctionInvocationException
                Assert.IsType <FunctionInvocationException>(telemetry.Exception);
            }
            else if (expectedCategory == LogCategories.Results)
            {
                // Check that the Function details show up as 'prop__'. We may change this in the future as
                // it may not be exceptionally useful.
                Assert.Equal(expectedOperationName, telemetry.Properties[$"{LogConstants.CustomPropertyPrefix}{LogConstants.NameKey}"]);
                Assert.Equal("This function was programmatically called via the host APIs.", telemetry.Properties[$"{LogConstants.CustomPropertyPrefix}{LogConstants.TriggerReasonKey}"]);

                Assert.IsType <FunctionInvocationException>(telemetry.Exception);
                Assert.IsType <Exception>(telemetry.Exception.InnerException);
            }

            ValidateSdkVersion(telemetry);
        }
Пример #17
0
        public void ILogger_Succeeds()
        {
            string functionName = nameof(ILoggerFunctions.ILogger);

            using (JobHost host = new JobHost(CreateConfig()))
            {
                var method = typeof(ILoggerFunctions).GetMethod(functionName);
                host.Call(method);
            }

            // Six loggers are the startup, singleton, results, function and function.user
            Assert.Equal(5, _loggerProvider.CreatedLoggers.Count());

            var functionLogger = _loggerProvider.CreatedLoggers.Where(l => l.Category == LogCategories.CreateFunctionUserCategory(functionName)).Single();
            var resultsLogger  = _loggerProvider.CreatedLoggers.Where(l => l.Category == LogCategories.Results).Single();

            var messages = functionLogger.GetLogMessages();

            Assert.Equal(2, messages.Count);
            var infoMessage  = messages[0];
            var errorMessage = messages[1];

            // These get the {OriginalFormat} property as well as the 2 from structured log properties
            Assert.Equal(3, infoMessage.State.Count());
            Assert.Equal(3, errorMessage.State.Count());

            Assert.Equal(1, resultsLogger.GetLogMessages().Count);

            // TODO: beef these verifications up
        }
 public VentriloquismLineBotApp(ILineMessagingClient client, SkillSettings settings, ILoggerFactory loggerFactory)
     : base(client, settings.ChannelSecret)
 {
     Logger = loggerFactory.CreateLogger(LogCategories.CreateFunctionUserCategory(nameof(LineBotFunctions)));
 }
Пример #19
0
        public void TimerTrigger()
        {
            var logs = Fixture.Host.GetLogMessages(LogCategories.CreateFunctionUserCategory("TimerTrigger"));

            Assert.Contains(logs, log => log.FormattedMessage.Contains("Timer function ran!"));
        }
Пример #20
0
 private void AddLogging(IServiceCollection services)
 {
     services.AddLogging();
     services.AddScoped <ILogger>(provider =>
                                  provider.GetService <ILoggerFactory>().CreateLogger(LogCategories.CreateFunctionUserCategory("GiasAdapter")));
     services.AddScoped <ILoggerWrapper, LoggerWrapper>();
 }
Пример #21
0
        private void AddLogging(IServiceCollection services)
        {
            services.AddLogging();
            services.AddScoped <ILogger>(provider =>
                                         provider.GetService <ILoggerFactory>().CreateLogger(LogCategories.CreateFunctionUserCategory("Common")));
            services.AddScoped <ILoggerWrapper, LoggerWrapper>();

            services.AddScoped <IHttpSpiExecutionContextManager, HttpSpiExecutionContextManager>();
            services.AddScoped <ISpiExecutionContextManager>((provider) =>
                                                             (ISpiExecutionContextManager)provider.GetService(typeof(IHttpSpiExecutionContextManager)));
            services.AddScoped <ILoggerWrapper, LoggerWrapper>();
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="StartUp"/> class.
        /// </summary>
        public StartUp()
        {
            var functionLoggerFactory = new LoggerFactory();

            _logger = functionLoggerFactory.CreateLogger(LogCategories.CreateFunctionUserCategory("Common"));
        }
Пример #23
0
        public async Task TraceWriter_ForwardsTo_ILogger()
        {
            string functionName = nameof(ILoggerFunctions.TraceWriterWithILoggerFactory);

            IHost host           = ConfigureHostBuilder().Build();
            var   loggerProvider = host.GetTestLoggerProvider();

            using (host)
            {
                var method = typeof(ILoggerFunctions).GetMethod(functionName);
                await host.GetJobHost().CallAsync(method);
            }

            // Five loggers are the startup, singleton, results, function and function.user
            Assert.Equal(7, loggerProvider.CreatedLoggers.Count); // $$$ was 9?
            var functionLogger = loggerProvider.CreatedLoggers.Where(l => l.Category == LogCategories.CreateFunctionUserCategory(functionName)).Single();

            Assert.Equal(2, functionLogger.GetLogMessages().Count);
            var infoMessage  = functionLogger.GetLogMessages()[0];
            var errorMessage = functionLogger.GetLogMessages()[1];

            // These get the {OriginalFormat} only
            Assert.Single(infoMessage.State);
            Assert.Single(errorMessage.State);

            //TODO: beef these verifications up
        }
 public void CreateLogger_ReturnsNullLogger_ForUserCategory()
 {
     Assert.IsType <NullLogger>(_provider.CreateLogger(LogCategories.CreateFunctionUserCategory("TestFunction")));
 }
Пример #25
0
        public void ILogger_Succeeds()
        {
            string functionName   = nameof(ILoggerFunctions.ILogger);
            IHost  host           = ConfigureHostBuilder().Build();
            var    loggerProvider = host.GetTestLoggerProvider();

            using (host)
            {
                var method = typeof(ILoggerFunctions).GetMethod(functionName);
                host.GetJobHost().Call(method);
            }

            // Six loggers are the startup, singleton, results, function and function.user
            // Note: We currently have 3 additional Logger<T> categories that need to be renamed
            Assert.Equal(7, loggerProvider.CreatedLoggers.Count); // $$$ was 9?

            var functionLogger = loggerProvider.CreatedLoggers.Where(l => l.Category == LogCategories.CreateFunctionUserCategory(functionName)).Single();
            var resultsLogger  = loggerProvider.CreatedLoggers.Where(l => l.Category == LogCategories.Results).Single();

            Assert.Equal(2, functionLogger.GetLogMessages().Count);
            var infoMessage  = functionLogger.GetLogMessages()[0];
            var errorMessage = functionLogger.GetLogMessages()[1];

            // These get the {OriginalFormat} property as well as the 2 from structured log properties
            Assert.Equal(3, infoMessage.State.Count());
            Assert.Equal(3, errorMessage.State.Count());

            Assert.Equal(1, resultsLogger.GetLogMessages().Count);

            // TODO: beef these verifications up
        }
        private async Task WaitForFunctionTrace(string functionName, string functionTrace)
        {
            // watch for the specific user log, then make sure the request telemetry has flushed, which
            // indicates all logging is done for this function invocation
            await TestHelpers.Await(() =>
            {
                bool done = false;
                TraceTelemetry logTrace = _fixture.Channel.Telemetries.OfType <TraceTelemetry>().SingleOrDefault(p => p.Message.Contains(functionTrace) && p.Properties[LogConstants.CategoryNameKey] == LogCategories.CreateFunctionUserCategory(functionName));

                if (logTrace != null)
                {
                    string invocationId      = logTrace.Properties[LogConstants.InvocationIdKey];
                    RequestTelemetry request = _fixture.Channel.Telemetries.OfType <RequestTelemetry>().SingleOrDefault(p => GetInvocationId(p) == invocationId);
                    done = request != null;
                }

                return(done);
            },
                                    userMessageCallback : _fixture.TestHost.GetLog);
        }
Пример #27
0
        public async Task Scenario_Logging()
        {
            string  testData = Guid.NewGuid().ToString();
            JObject input    = new JObject
            {
                { "scenario", "logging" },
                { "input", testData },
            };

            Fixture.Host.ClearLogMessages();
            Fixture.MetricsLogger.ClearCollections();

            await Fixture.Host.BeginFunctionAsync("Scenarios", input);

            string         userCategory = LogCategories.CreateFunctionUserCategory("Scenarios");
            IList <string> userLogs     = null;
            string         consoleLog   = null;
            await TestHelpers.Await(() =>
            {
                userLogs   = Fixture.Host.GetScriptHostLogMessages(userCategory).Select(p => p.FormattedMessage).ToList();
                consoleLog = Fixture.Host.GetScriptHostLogMessages(LanguageWorkerConstants.FunctionConsoleLogCategoryName).Select(p => p.FormattedMessage).SingleOrDefault();
                return(userLogs.Count == 10 && consoleLog != null);
            }, userMessageCallback : Fixture.Host.GetLog);

            // verify use of context.log to log complex objects
            LogMessage scriptTrace = Fixture.Host.GetScriptHostLogMessages(userCategory).Single(p => p.FormattedMessage != null && p.FormattedMessage.Contains(testData));

            Assert.Equal(LogLevel.Information, scriptTrace.Level);
            JObject logEntry = JObject.Parse(scriptTrace.FormattedMessage);

            Assert.Equal("This is a test", logEntry["message"]);
            Assert.Equal(testData, logEntry["input"]);

            // verify log levels in traces
            LogMessage[] traces = Fixture.Host.GetScriptHostLogMessages(userCategory).Where(t => t.FormattedMessage != null && t.FormattedMessage.Contains("loglevel")).ToArray();
            Assert.Equal(LogLevel.Information, traces[0].Level);
            Assert.Equal("loglevel default", traces[0].FormattedMessage);
            Assert.Equal(LogLevel.Information, traces[1].Level);
            Assert.Equal("loglevel info", traces[1].FormattedMessage);
            Assert.Equal(LogLevel.Trace, traces[2].Level);
            Assert.Equal("loglevel verbose", traces[2].FormattedMessage);
            Assert.Equal(LogLevel.Warning, traces[3].Level);
            Assert.Equal("loglevel warn", traces[3].FormattedMessage);
            Assert.Equal(LogLevel.Error, traces[4].Level);
            Assert.Equal("loglevel error", traces[4].FormattedMessage);

            // verify most of the logs look correct
            Assert.EndsWith("Mathew Charles", userLogs[1]);
            Assert.EndsWith("null", userLogs[2]);
            Assert.EndsWith("1234", userLogs[3]);
            Assert.EndsWith("true", userLogs[4]);
            Assert.EndsWith("loglevel default", userLogs[5]);
            Assert.EndsWith("loglevel info", userLogs[6]);

            // verify the console log
            Assert.Equal("console log", consoleLog);

            // TODO: Re-enable once we can override IMetricsLogger
            // We only expect 9 user log metrics to be counted, since
            // verbose logs are filtered by default (the TestLogger explicitly
            // allows all levels for testing purposes)
            var key = MetricsEventManager.GetAggregateKey(MetricEventNames.FunctionUserLog, "Scenarios");
            // Assert.Equal(9, Fixture.MetricsLogger.LoggedEvents.Where(p => p == key).Count());
        }
        public async Task HttpTrigger_CustomRoute_Get_ReturnsExpectedResponse()
        {
            var    id          = "4e2796ae-b865-4071-8a20-2a15cbaf856c";
            string functionKey = await _fixture.Host.GetFunctionSecretAsync("HttpTrigger-CustomRoute-Get");

            string             uri     = $"api/node/products/electronics/{id}?code={functionKey}";
            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, uri);

            request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/plain"));

            HttpResponseMessage response = await _fixture.Host.HttpClient.SendAsync(request);

            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
            string json = await response.Content.ReadAsStringAsync();

            JArray products = JArray.Parse(json);

            Assert.Equal(1, products.Count);
            var product = products[0];

            Assert.Equal("electronics", (string)product["category"]);
            Assert.Equal(id, (string)product["id"]);

            // test optional route param (id)
            uri     = $"api/node/products/electronics?code={functionKey}";
            request = new HttpRequestMessage(HttpMethod.Get, uri);
            request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/plain"));
            response = await _fixture.Host.HttpClient.SendAsync(request);

            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
            json = await response.Content.ReadAsStringAsync();

            products = JArray.Parse(json);
            Assert.Equal(2, products.Count);

            // test optional route param (category)
            uri     = $"api/node/products?code={functionKey}";
            request = new HttpRequestMessage(HttpMethod.Get, uri);
            request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/plain"));
            response = await _fixture.Host.HttpClient.SendAsync(request);

            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
            json = await response.Content.ReadAsStringAsync();

            products = JArray.Parse(json);
            Assert.Equal(3, products.Count);

            // test a constraint violation (invalid id)
            uri     = $"api/node/products/electronics/notaguid?code={functionKey}";
            request = new HttpRequestMessage(HttpMethod.Get, uri);
            request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/plain"));
            response = await _fixture.Host.HttpClient.SendAsync(request);

            Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);

            // test a constraint violation (invalid category)
            uri     = $"api/node/products/999/{id}?code={functionKey}";
            request = new HttpRequestMessage(HttpMethod.Get, uri);
            request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/plain"));
            response = await _fixture.Host.HttpClient.SendAsync(request);

            Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);

            // verify route parameters were part of binding data
            var logs = _fixture.Host.GetLogMessages(LogCategories.CreateFunctionUserCategory("HttpTrigger-CustomRoute-Get"));
            var log  = logs.Single(p => p.FormattedMessage.Contains($"category: electronics id: {id}"));

            Assert.NotNull(log);
        }
        public async Task HttpTrigger_CSharp_CustomRoute_ReturnsExpectedResponse()
        {
            string functionName = "HttpTrigger-CSharp-CustomRoute";
            string functionKey  = await _fixture.Host.GetFunctionSecretAsync(functionName);

            string             uri     = $"api/csharp/products/electronics/123?code={functionKey}";
            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, uri);

            HttpResponseMessage response = await _fixture.Host.HttpClient.SendAsync(request);

            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
            string json = await response.Content.ReadAsStringAsync();

            var product = JObject.Parse(json);

            Assert.Equal("electronics", (string)product["category"]);
            Assert.Equal(123, (int?)product["id"]);

            // test optional id parameter
            uri      = $"api/csharp/products/electronics?code={functionKey}";
            request  = new HttpRequestMessage(HttpMethod.Get, uri);
            response = await _fixture.Host.HttpClient.SendAsync(request);

            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
            json = await response.Content.ReadAsStringAsync();

            product = JObject.Parse(json);
            Assert.Equal("electronics", (string)product["category"]);
            Assert.Null((int?)product["id"]);

            // test optional category parameter
            uri      = $"api/csharp/products?code={functionKey}";
            request  = new HttpRequestMessage(HttpMethod.Get, uri);
            response = await _fixture.Host.HttpClient.SendAsync(request);

            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
            json = await response.Content.ReadAsStringAsync();

            product = JObject.Parse(json);
            Assert.Null((string)product["category"]);
            Assert.Null((int?)product["id"]);

            // test a constraint violation (invalid id)
            uri      = $"api/csharp/products/electronics/1x3?code={functionKey}";
            request  = new HttpRequestMessage(HttpMethod.Get, uri);
            response = await _fixture.Host.HttpClient.SendAsync(request);

            Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);

            // test a constraint violation (invalid category)
            uri      = $"api/csharp/products/999/123?code={functionKey}";
            request  = new HttpRequestMessage(HttpMethod.Get, uri);
            response = await _fixture.Host.HttpClient.SendAsync(request);

            Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);

            // verify route parameters were part of binding data
            var logs = _fixture.Host.GetLogMessages(LogCategories.CreateFunctionUserCategory(functionName));

            Assert.True(logs.Any(p => p.FormattedMessage.Contains("Parameters: category=electronics id=123")));
            Assert.True(logs.Any(p => p.FormattedMessage.Contains("ProductInfo: Category=electronics Id=123")));
        }
Пример #30
0
        public void TraceWriter_ForwardsTo_ILogger()
        {
            string functionName = nameof(ILoggerFunctions.TraceWriterWithILoggerFactory);

            using (JobHost host = new JobHost(CreateConfig()))
            {
                var method = typeof(ILoggerFunctions).GetMethod(functionName);
                host.Call(method);
            }

            // Five loggers are the startup, singleton, results, function and function.user
            Assert.Equal(5, _loggerProvider.CreatedLoggers.Count());
            var functionLogger = _loggerProvider.CreatedLoggers.Where(l => l.Category == LogCategories.CreateFunctionUserCategory(functionName)).Single();
            var messages       = functionLogger.GetLogMessages();

            Assert.Equal(2, messages.Count);
            var infoMessage  = messages[0];
            var errorMessage = messages[1];

            // These get the {OriginalFormat} only
            Assert.Single(infoMessage.State);
            Assert.Single(errorMessage.State);

            //TODO: beef these verifications up
        }