public async Task SendAsync_WritesExpectedTraces()
        {
            string requestId      = Guid.NewGuid().ToString();
            var    context        = new DefaultHttpContext();
            Uri    uri            = new Uri("http://functions.com/api/testfunc?code=123");
            var    requestFeature = context.Request.HttpContext.Features.Get <IHttpRequestFeature>();

            requestFeature.Method      = "GET";
            requestFeature.Scheme      = uri.Scheme;
            requestFeature.Path        = uri.GetComponents(UriComponents.KeepDelimiter | UriComponents.Path, UriFormat.Unescaped);
            requestFeature.PathBase    = string.Empty;
            requestFeature.QueryString = uri.GetComponents(UriComponents.KeepDelimiter | UriComponents.Query, UriFormat.Unescaped);

            var headers = new HeaderDictionary();

            headers.Add(ScriptConstants.AntaresLogIdHeaderName, new StringValues(requestId));
            headers.Add("User-Agent", new StringValues("TestAgent"));
            requestFeature.Headers = headers;

            var principal = new ClaimsPrincipal();

            principal.AddIdentity(new ClaimsIdentity(new List <Claim>
            {
                new Claim(SecurityConstants.AuthLevelClaimType, AuthorizationLevel.Function.ToString())
            }, AuthLevelAuthenticationDefaults.AuthenticationScheme));
            principal.AddIdentity(new ClaimsIdentity(new List <Claim>
            {
                new Claim(SecurityConstants.AuthLevelClaimType, "CustomLevel")
            }, "CustomScheme"));
            context.User = principal;

            await _middleware.Invoke(context);

            var logs = _loggerProvider.GetAllLogMessages().ToArray();

            Assert.Equal(2, logs.Length);

            // validate executing trace
            var log = logs[0];

            Assert.Equal(typeof(SystemTraceMiddleware).FullName, log.Category);
            Assert.Equal(LogLevel.Information, log.Level);
            var idx     = log.FormattedMessage.IndexOf(':');
            var message = log.FormattedMessage.Substring(0, idx).Trim();

            Assert.Equal("Executing HTTP request", message);
            var details = log.FormattedMessage.Substring(idx + 1).Trim();
            var jo      = JObject.Parse(details);

            Assert.Equal(4, jo.Count);
            Assert.Equal(requestId, jo["requestId"]);
            Assert.Equal("GET", jo["method"]);
            Assert.Equal("/api/testfunc", jo["uri"]);
            Assert.Equal("TestAgent", jo["userAgent"]);

            // validate executed trace
            log = logs[1];
            Assert.Equal(typeof(SystemTraceMiddleware).FullName, log.Category);
            Assert.Equal(LogLevel.Information, log.Level);
            idx     = log.FormattedMessage.IndexOf(':');
            message = log.FormattedMessage.Substring(0, idx).Trim();
            Assert.Equal("Executed HTTP request", message);
            details = log.FormattedMessage.Substring(idx + 1).Trim();
            jo      = JObject.Parse(details);
            Assert.Equal(4, jo.Count);
            Assert.Equal(requestId, jo["requestId"]);
            Assert.Equal(200, jo["status"]);
            var duration = (long)jo["duration"];

            Assert.True(duration > 0);

            string identities = (string)jo["identities"];

            Assert.Equal($"({AuthLevelAuthenticationDefaults.AuthenticationScheme}:Function, CustomScheme:CustomLevel)", identities);
        }
        public async Task SendAsync_WritesExpectedTraces()
        {
            Assert.Equal(TestHostName, _hostNameProvider.Value);

            string requestId      = Guid.NewGuid().ToString();
            var    context        = new DefaultHttpContext();
            Uri    uri            = new Uri("http://functions.com/api/testfunc?code=123");
            var    requestFeature = context.Request.HttpContext.Features.Get <IHttpRequestFeature>();

            requestFeature.Method      = "GET";
            requestFeature.Scheme      = uri.Scheme;
            requestFeature.Path        = uri.GetComponents(UriComponents.KeepDelimiter | UriComponents.Path, UriFormat.Unescaped);
            requestFeature.PathBase    = string.Empty;
            requestFeature.QueryString = uri.GetComponents(UriComponents.KeepDelimiter | UriComponents.Query, UriFormat.Unescaped);

            var headers = new HeaderDictionary();

            headers.Add(ScriptConstants.AntaresLogIdHeaderName, new StringValues(requestId));
            headers.Add(ScriptConstants.AntaresDefaultHostNameHeader, "test2.azurewebsites.net");
            requestFeature.Headers = headers;

            var claims = new List <Claim>
            {
                new Claim(SecurityConstants.AuthLevelClaimType, AuthorizationLevel.Function.ToString())
            };
            var identity = new ClaimsIdentity(claims, AuthLevelAuthenticationDefaults.AuthenticationScheme);

            context.User = new ClaimsPrincipal(identity);

            await _middleware.Invoke(context);

            var logs = _loggerProvider.GetAllLogMessages().ToArray();

            Assert.Equal(3, logs.Length);

            // validate hostname sync trace
            var log = logs[0];

            Assert.Equal("Microsoft.Azure.WebJobs.Script.WebHost.HostNameProvider", log.Category);
            Assert.Equal(LogLevel.Information, log.Level);
            Assert.Equal("HostName updated from 'test.azurewebsites.net' to 'test2.azurewebsites.net'", log.FormattedMessage);

            // validate executing trace
            log = logs[1];
            Assert.Equal(typeof(SystemTraceMiddleware).FullName, log.Category);
            Assert.Equal(LogLevel.Information, log.Level);
            var idx     = log.FormattedMessage.IndexOf(':');
            var message = log.FormattedMessage.Substring(0, idx).Trim();

            Assert.Equal("Executing HTTP request", message);
            var details = log.FormattedMessage.Substring(idx + 1).Trim();
            var jo      = JObject.Parse(details);

            Assert.Equal(3, jo.Count);
            Assert.Equal(requestId, jo["requestId"]);
            Assert.Equal("GET", jo["method"]);
            Assert.Equal("/api/testfunc", jo["uri"]);

            // validate executed trace
            log = logs[2];
            Assert.Equal(typeof(SystemTraceMiddleware).FullName, log.Category);
            Assert.Equal(LogLevel.Information, log.Level);
            idx     = log.FormattedMessage.IndexOf(':');
            message = log.FormattedMessage.Substring(0, idx).Trim();
            Assert.Equal("Executed HTTP request", message);
            details = log.FormattedMessage.Substring(idx + 1).Trim();
            jo      = JObject.Parse(details);
            Assert.Equal(6, jo.Count);
            Assert.Equal(requestId, jo["requestId"]);
            Assert.Equal("GET", jo["method"]);
            Assert.Equal("/api/testfunc", jo["uri"]);
            Assert.Equal(200, jo["status"]);
            var duration = (long)jo["duration"];

            Assert.True(duration > 0);

            var authentication = (JArray)jo["identities"];

            Assert.Equal(1, authentication.Count);
            var keyIdentity = authentication.Single();

            Assert.Equal(AuthLevelAuthenticationDefaults.AuthenticationScheme, keyIdentity["type"]);
            Assert.Equal("Function", keyIdentity["level"]);

            // verify the hostname was synchronized
            Assert.Equal("test2.azurewebsites.net", _hostNameProvider.Value);
        }