Merge branch 'release' into dev
This commit is contained in:
commit
22449a09f7
|
|
@ -27,3 +27,4 @@ nuget.exe
|
|||
node_modules
|
||||
*.sln.ide
|
||||
project.lock.json
|
||||
.vs/
|
||||
|
|
@ -1,4 +1,6 @@
|
|||
using System;
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.AspNet.Http;
|
||||
|
|
@ -19,11 +21,13 @@ namespace ElmPageSample
|
|||
|
||||
public async Task Invoke(HttpContext httpContext)
|
||||
{
|
||||
using (_logger.BeginScope("C"))
|
||||
using (_logger.BeginScope("Scope1"))
|
||||
{
|
||||
_logger.LogVerbose("Getting message");
|
||||
|
||||
await httpContext.Response.WriteAsync("Hello World!");
|
||||
httpContext.Response.ContentType = "text/html; charset=utf-8";
|
||||
await httpContext.Response.WriteAsync(
|
||||
"<html><body><h2>Hello World!</h2><a href=\"/Elm\">Elm Logs</a></body></html>");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
using Microsoft.AspNet.Builder;
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.Framework.Logging;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@
|
|||
"dependencies": {
|
||||
"Microsoft.AspNet.Diagnostics.Elm": "1.0.0-*",
|
||||
"Microsoft.AspNet.Server.IIS": "1.0.0-*",
|
||||
"Microsoft.AspNet.Server.WebListener": "1.0.0-*",
|
||||
"Microsoft.AspNet.StaticFiles": "1.0.0-*"
|
||||
"Microsoft.AspNet.Server.WebListener": "1.0.0-*"
|
||||
},
|
||||
"commands": {
|
||||
"web": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.WebListener --server.urls http://localhost:5000"
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
Sample demonstrating ElmPageMiddleware
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Http.Features;
|
||||
using Microsoft.Framework.Logging;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
|
||||
|
|
@ -28,18 +28,20 @@ namespace Microsoft.AspNet.Diagnostics.Elm
|
|||
|
||||
public async Task Invoke(HttpContext context)
|
||||
{
|
||||
var requestId = Guid.NewGuid();
|
||||
using (_logger.BeginScope(string.Format("request {0}", requestId)))
|
||||
using (RequestIdentifier.Ensure(context))
|
||||
{
|
||||
var p = ElmScope.Current;
|
||||
ElmScope.Current.Context.HttpInfo = GetHttpInfo(context, requestId);
|
||||
try
|
||||
var requestId = context.GetFeature<IHttpRequestIdentifierFeature>().TraceIdentifier;
|
||||
using (_logger.BeginScope("Request: {RequestId}", requestId))
|
||||
{
|
||||
await _next(context);
|
||||
}
|
||||
finally
|
||||
{
|
||||
ElmScope.Current.Context.HttpInfo.StatusCode = context.Response.StatusCode;
|
||||
try
|
||||
{
|
||||
ElmScope.Current.Context.HttpInfo = GetHttpInfo(context);
|
||||
await _next(context);
|
||||
}
|
||||
finally
|
||||
{
|
||||
ElmScope.Current.Context.HttpInfo.StatusCode = context.Response.StatusCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -48,11 +50,11 @@ namespace Microsoft.AspNet.Diagnostics.Elm
|
|||
/// Takes the info from the given HttpContext and copies it to an HttpInfo object
|
||||
/// </summary>
|
||||
/// <returns>The HttpInfo for the current elm context</returns>
|
||||
private static HttpInfo GetHttpInfo(HttpContext context, Guid requestId)
|
||||
private static HttpInfo GetHttpInfo(HttpContext context)
|
||||
{
|
||||
return new HttpInfo()
|
||||
{
|
||||
RequestID = requestId,
|
||||
RequestID = context.GetFeature<IHttpRequestIdentifierFeature>().TraceIdentifier,
|
||||
Host = context.Request.Host,
|
||||
ContentType = context.Request.ContentType,
|
||||
Path = context.Request.Path,
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ namespace Microsoft.AspNet.Diagnostics.Elm
|
|||
{
|
||||
public class HttpInfo
|
||||
{
|
||||
public Guid RequestID { get; set; }
|
||||
public string RequestID { get; set; }
|
||||
|
||||
public HostString Host { get; set; }
|
||||
|
||||
|
|
@ -20,7 +20,7 @@ namespace Microsoft.AspNet.Diagnostics.Elm
|
|||
public string Scheme { get; set; }
|
||||
|
||||
public int StatusCode { get; set; }
|
||||
|
||||
|
||||
public ClaimsPrincipal User { get; set; }
|
||||
|
||||
public string Method { get; set; }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Http.Features;
|
||||
|
||||
namespace Microsoft.AspNet.Diagnostics.Elm
|
||||
{
|
||||
internal class HttpRequestIdentifierFeature : IHttpRequestIdentifierFeature
|
||||
{
|
||||
public string TraceIdentifier { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Http.Features;
|
||||
|
||||
namespace Microsoft.AspNet.Diagnostics.Elm
|
||||
{
|
||||
internal class RequestIdentifier : IDisposable
|
||||
{
|
||||
private readonly bool _addedFeature;
|
||||
private readonly bool _updatedIdentifier;
|
||||
private readonly string _originalIdentifierValue;
|
||||
private readonly HttpContext _context;
|
||||
private readonly IHttpRequestIdentifierFeature _feature;
|
||||
|
||||
private RequestIdentifier(HttpContext context)
|
||||
{
|
||||
_context = context;
|
||||
_feature = context.GetFeature<IHttpRequestIdentifierFeature>();
|
||||
|
||||
if (_feature == null)
|
||||
{
|
||||
_feature = new HttpRequestIdentifierFeature()
|
||||
{
|
||||
TraceIdentifier = Guid.NewGuid().ToString()
|
||||
};
|
||||
context.SetFeature(_feature);
|
||||
_addedFeature = true;
|
||||
}
|
||||
else if (string.IsNullOrEmpty(_feature.TraceIdentifier))
|
||||
{
|
||||
_originalIdentifierValue = _feature.TraceIdentifier;
|
||||
_feature.TraceIdentifier = Guid.NewGuid().ToString();
|
||||
_updatedIdentifier = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static IDisposable Ensure(HttpContext context)
|
||||
{
|
||||
return new RequestIdentifier(context);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_addedFeature)
|
||||
{
|
||||
_context.SetFeature<IHttpRequestIdentifierFeature>(null);
|
||||
}
|
||||
else if (_updatedIdentifier)
|
||||
{
|
||||
_feature.TraceIdentifier = _originalIdentifierValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -241,7 +241,6 @@ WriteTo(__razor_helper_writer, Traverse(node.Children[i]));
|
|||
public override async Task ExecuteAsync()
|
||||
{
|
||||
Response.ContentType = "text/html; charset=utf-8";
|
||||
Response.ContentLength = null; // Clear any prior Content-Length
|
||||
WriteLiteral("\r\n");
|
||||
WriteLiteral("\r\n");
|
||||
WriteLiteral("\r\n");
|
||||
|
|
|
|||
|
|
@ -307,7 +307,6 @@ WriteTo(__razor_helper_writer, LogRow(new LogInfo()
|
|||
public override async Task ExecuteAsync()
|
||||
{
|
||||
Response.ContentType = "text/html; charset=utf-8";
|
||||
Response.ContentLength = null; // Clear any prior Content-Length
|
||||
WriteLiteral("\r\n");
|
||||
WriteLiteral("\r\n\r\n");
|
||||
WriteLiteral("\r\n");
|
||||
|
|
|
|||
|
|
@ -193,7 +193,7 @@ using Views
|
|||
#line hidden
|
||||
|
||||
#line 48 "CompilationErrorPage.cshtml"
|
||||
if (frame.Line != 0 && frame.ContextCode.Any())
|
||||
if (frame.Line != 0 && frame.ContextCode !=null && frame.ContextCode.Any())
|
||||
{
|
||||
|
||||
#line default
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@
|
|||
<h3>@frame.ErrorDetails</h3>
|
||||
}
|
||||
|
||||
@if (frame.Line != 0 && frame.ContextCode.Any())
|
||||
@if (frame.Line != 0 && frame.ContextCode !=null && frame.ContextCode.Any())
|
||||
{
|
||||
<div class="source">
|
||||
@if (frame.PreContextCode != null)
|
||||
|
|
|
|||
|
|
@ -355,7 +355,7 @@ using Views
|
|||
#line hidden
|
||||
|
||||
#line 97 "ErrorPage.cshtml"
|
||||
if (frame.Line != 0 && frame.ContextCode.Any())
|
||||
if (frame.Line != 0 && frame.ContextCode !=null && frame.ContextCode.Any())
|
||||
{
|
||||
|
||||
#line default
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@
|
|||
<h3>@frame.Function in <code title="@frame.File">@System.IO.Path.GetFileName(frame.File)</code></h3>
|
||||
}
|
||||
|
||||
@if (frame.Line != 0 && frame.ContextCode.Any())
|
||||
@if (frame.Line != 0 && frame.ContextCode !=null && frame.ContextCode.Any())
|
||||
{
|
||||
<div class="source">
|
||||
@if (frame.PreContextCode != null)
|
||||
|
|
|
|||
|
|
@ -1,13 +1,18 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Security.Claims;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.AspNet.Diagnostics.Elm;
|
||||
using Microsoft.AspNet.FeatureModel;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Http.Features;
|
||||
using Microsoft.AspNet.Http.Features.Internal;
|
||||
using Microsoft.AspNet.Http.Internal;
|
||||
using Microsoft.Framework.Logging;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
#if DNX451
|
||||
|
|
@ -213,9 +218,119 @@ namespace Microsoft.AspNet.Diagnostics.Tests
|
|||
contextMock
|
||||
.Setup(c => c.Request.HasFormContentType)
|
||||
.Returns(true);
|
||||
|
||||
var requestIdentifier = new Mock<IHttpRequestIdentifierFeature>();
|
||||
requestIdentifier.Setup(f => f.TraceIdentifier).Returns(Guid.NewGuid().ToString());
|
||||
contextMock.Setup(c => c.GetFeature<IHttpRequestIdentifierFeature>())
|
||||
.Returns(requestIdentifier.Object);
|
||||
return contextMock;
|
||||
}
|
||||
#endif
|
||||
|
||||
[Fact]
|
||||
public async Task SetsNewIdentifierFeature_IfNotPresentOnContext()
|
||||
{
|
||||
// Arrange
|
||||
var context = new DefaultHttpContext();
|
||||
var loggerFactory = new LoggerFactory();
|
||||
loggerFactory.AddProvider(new ElmLoggerProvider(new ElmStore(), new ElmOptions()));
|
||||
|
||||
// Act & Assert
|
||||
var errorPageMiddleware = new ElmCaptureMiddleware((innerContext) =>
|
||||
{
|
||||
var feature = innerContext.GetFeature<IHttpRequestIdentifierFeature>();
|
||||
Assert.NotNull(feature);
|
||||
Assert.False(string.IsNullOrEmpty(feature.TraceIdentifier));
|
||||
return Task.FromResult(0);
|
||||
}, loggerFactory, new TestElmOptions());
|
||||
|
||||
await errorPageMiddleware.Invoke(context);
|
||||
|
||||
Assert.Null(context.GetFeature<IHttpRequestIdentifierFeature>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task UsesIdentifierFeature_IfAlreadyPresentOnContext()
|
||||
{
|
||||
// Arrange
|
||||
var requestIdentifierFeature = new HttpRequestIdentifierFeature()
|
||||
{
|
||||
TraceIdentifier = Guid.NewGuid().ToString()
|
||||
};
|
||||
var features = new FeatureCollection();
|
||||
features.Add(typeof(IHttpRequestFeature), new HttpRequestFeature());
|
||||
features.Add(typeof(IHttpRequestIdentifierFeature), requestIdentifierFeature);
|
||||
features.Add(typeof(IHttpResponseFeature), new HttpResponseFeature());
|
||||
var context = new DefaultHttpContext(features);
|
||||
var loggerFactory = new LoggerFactory();
|
||||
loggerFactory.AddProvider(new ElmLoggerProvider(new ElmStore(), new ElmOptions()));
|
||||
|
||||
// Act & Assert
|
||||
var errorPageMiddleware = new ElmCaptureMiddleware((innerContext) =>
|
||||
{
|
||||
Assert.Same(requestIdentifierFeature, innerContext.GetFeature<IHttpRequestIdentifierFeature>());
|
||||
return Task.FromResult(0);
|
||||
}, loggerFactory, new TestElmOptions());
|
||||
|
||||
await errorPageMiddleware.Invoke(context);
|
||||
|
||||
Assert.Same(requestIdentifierFeature, context.GetFeature<IHttpRequestIdentifierFeature>());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("")]
|
||||
public async Task UpdatesTraceIdentifier_IfNullOrEmpty(string requestId)
|
||||
{
|
||||
// Arrange
|
||||
var requestIdentifierFeature = new HttpRequestIdentifierFeature() { TraceIdentifier = requestId };
|
||||
var features = new FeatureCollection();
|
||||
features.Add(typeof(IHttpRequestIdentifierFeature), requestIdentifierFeature);
|
||||
features.Add(typeof(IHttpRequestFeature), new HttpRequestFeature());
|
||||
features.Add(typeof(IHttpResponseFeature), new HttpResponseFeature());
|
||||
var context = new DefaultHttpContext(features);
|
||||
var loggerFactory = new LoggerFactory();
|
||||
loggerFactory.AddProvider(new ElmLoggerProvider(new ElmStore(), new ElmOptions()));
|
||||
|
||||
// Act & Assert
|
||||
var errorPageMiddleware = new ElmCaptureMiddleware((innerContext) =>
|
||||
{
|
||||
var feature = innerContext.GetFeature<IHttpRequestIdentifierFeature>();
|
||||
Assert.NotNull(feature);
|
||||
Assert.False(string.IsNullOrEmpty(feature.TraceIdentifier));
|
||||
return Task.FromResult(0);
|
||||
}, loggerFactory, new TestElmOptions());
|
||||
|
||||
await errorPageMiddleware.Invoke(context);
|
||||
|
||||
Assert.Equal(requestId, context.GetFeature<IHttpRequestIdentifierFeature>().TraceIdentifier);
|
||||
}
|
||||
|
||||
private class TestElmOptions : IOptions<ElmOptions>
|
||||
{
|
||||
private readonly ElmOptions _innerOptions;
|
||||
|
||||
public TestElmOptions() :
|
||||
this(new ElmOptions())
|
||||
{
|
||||
}
|
||||
|
||||
public TestElmOptions(ElmOptions innerOptions)
|
||||
{
|
||||
_innerOptions = innerOptions;
|
||||
}
|
||||
|
||||
public ElmOptions Options
|
||||
{
|
||||
get
|
||||
{
|
||||
return _innerOptions;
|
||||
}
|
||||
}
|
||||
|
||||
public ElmOptions GetNamedOptions(string name)
|
||||
{
|
||||
return _innerOptions;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue