From f18b7a8b305729750b4cb38bc786edb7c46e7598 Mon Sep 17 00:00:00 2001 From: SonjaKhan Date: Wed, 29 Oct 2014 10:16:52 -0700 Subject: [PATCH 01/19] elm logger --- DiagnosticsPages.sln | 30 + samples/ElmSample/ElmSample.kproj | 19 + samples/ElmSample/Startup.cs | 33 + samples/ElmSample/project.json | 24 + .../ActivityContext.cs | 10 + .../ElmExtensions.cs | 15 + .../ElmLogger.cs | 67 ++ .../ElmLoggerProvider.cs | 24 + .../ElmMiddleware.cs | 145 +++++ .../ElmOptions.cs | 34 + .../ElmScope.cs | 108 ++++ .../ElmStore.cs | 31 + .../HttpInfo.cs | 36 ++ .../IElmStore.cs | 15 + .../LogInfo.cs | 28 + .../Microsoft.AspNet.Diagnostics.Elm.kproj | 20 + .../ScopeNode.cs | 16 + .../Views/LogPage.cs | 605 ++++++++++++++++++ .../Views/LogPage.cshtml | 175 +++++ .../Views/LogPage.css | 111 ++++ .../Views/LogPageModel.cs | 13 + .../Views/RequestPage.cs | 483 ++++++++++++++ .../Views/RequestPage.cshtml | 164 +++++ .../Views/RequestPage.css | 79 +++ .../Views/RequestPageModel.cs | 14 + .../project.json | 31 + .../Views/BaseView.cs | 98 ++- .../Views/HelperResult.cs | 42 ++ src/PageGenerator/PageGenerator.kproj | 4 + src/PageGenerator/Program.cs | 10 + src/PageGenerator/project.json | 1 + 31 files changed, 2484 insertions(+), 1 deletion(-) create mode 100644 samples/ElmSample/ElmSample.kproj create mode 100644 samples/ElmSample/Startup.cs create mode 100644 samples/ElmSample/project.json create mode 100644 src/Microsoft.AspNet.Diagnostics.Elm/ActivityContext.cs create mode 100644 src/Microsoft.AspNet.Diagnostics.Elm/ElmExtensions.cs create mode 100644 src/Microsoft.AspNet.Diagnostics.Elm/ElmLogger.cs create mode 100644 src/Microsoft.AspNet.Diagnostics.Elm/ElmLoggerProvider.cs create mode 100644 src/Microsoft.AspNet.Diagnostics.Elm/ElmMiddleware.cs create mode 100644 src/Microsoft.AspNet.Diagnostics.Elm/ElmOptions.cs create mode 100644 src/Microsoft.AspNet.Diagnostics.Elm/ElmScope.cs create mode 100644 src/Microsoft.AspNet.Diagnostics.Elm/ElmStore.cs create mode 100644 src/Microsoft.AspNet.Diagnostics.Elm/HttpInfo.cs create mode 100644 src/Microsoft.AspNet.Diagnostics.Elm/IElmStore.cs create mode 100644 src/Microsoft.AspNet.Diagnostics.Elm/LogInfo.cs create mode 100644 src/Microsoft.AspNet.Diagnostics.Elm/Microsoft.AspNet.Diagnostics.Elm.kproj create mode 100644 src/Microsoft.AspNet.Diagnostics.Elm/ScopeNode.cs create mode 100644 src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.cs create mode 100644 src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.cshtml create mode 100644 src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.css create mode 100644 src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPageModel.cs create mode 100644 src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.cs create mode 100644 src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.cshtml create mode 100644 src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.css create mode 100644 src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPageModel.cs create mode 100644 src/Microsoft.AspNet.Diagnostics.Elm/project.json create mode 100644 src/Microsoft.AspNet.Diagnostics/Views/HelperResult.cs diff --git a/DiagnosticsPages.sln b/DiagnosticsPages.sln index f3c669a4..3e77e483 100644 --- a/DiagnosticsPages.sln +++ b/DiagnosticsPages.sln @@ -28,6 +28,10 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Diagnostic EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ErrorHandlerSample", "samples\ErrorHandlerSample\ErrorHandlerSample.kproj", "{427CDB36-78B0-4583-9EBC-7F283DE60355}" EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Diagnostics.Elm", "src\Microsoft.AspNet.Diagnostics.Elm\Microsoft.AspNet.Diagnostics.Elm.kproj", "{624B0019-956A-4157-B008-270C5B229553}" +EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ElmSample", "samples\ElmSample\ElmSample.kproj", "{92A1063F-5BB7-41D0-8C9D-42CFC5973B5D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -108,6 +112,30 @@ Global {427CDB36-78B0-4583-9EBC-7F283DE60355}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {427CDB36-78B0-4583-9EBC-7F283DE60355}.Release|Mixed Platforms.Build.0 = Release|Any CPU {427CDB36-78B0-4583-9EBC-7F283DE60355}.Release|x86.ActiveCfg = Release|Any CPU + {624B0019-956A-4157-B008-270C5B229553}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {624B0019-956A-4157-B008-270C5B229553}.Debug|Any CPU.Build.0 = Debug|Any CPU + {624B0019-956A-4157-B008-270C5B229553}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {624B0019-956A-4157-B008-270C5B229553}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {624B0019-956A-4157-B008-270C5B229553}.Debug|x86.ActiveCfg = Debug|Any CPU + {624B0019-956A-4157-B008-270C5B229553}.Debug|x86.Build.0 = Debug|Any CPU + {624B0019-956A-4157-B008-270C5B229553}.Release|Any CPU.ActiveCfg = Release|Any CPU + {624B0019-956A-4157-B008-270C5B229553}.Release|Any CPU.Build.0 = Release|Any CPU + {624B0019-956A-4157-B008-270C5B229553}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {624B0019-956A-4157-B008-270C5B229553}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {624B0019-956A-4157-B008-270C5B229553}.Release|x86.ActiveCfg = Release|Any CPU + {624B0019-956A-4157-B008-270C5B229553}.Release|x86.Build.0 = Release|Any CPU + {92A1063F-5BB7-41D0-8C9D-42CFC5973B5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {92A1063F-5BB7-41D0-8C9D-42CFC5973B5D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {92A1063F-5BB7-41D0-8C9D-42CFC5973B5D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {92A1063F-5BB7-41D0-8C9D-42CFC5973B5D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {92A1063F-5BB7-41D0-8C9D-42CFC5973B5D}.Debug|x86.ActiveCfg = Debug|Any CPU + {92A1063F-5BB7-41D0-8C9D-42CFC5973B5D}.Debug|x86.Build.0 = Debug|Any CPU + {92A1063F-5BB7-41D0-8C9D-42CFC5973B5D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {92A1063F-5BB7-41D0-8C9D-42CFC5973B5D}.Release|Any CPU.Build.0 = Release|Any CPU + {92A1063F-5BB7-41D0-8C9D-42CFC5973B5D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {92A1063F-5BB7-41D0-8C9D-42CFC5973B5D}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {92A1063F-5BB7-41D0-8C9D-42CFC5973B5D}.Release|x86.ActiveCfg = Release|Any CPU + {92A1063F-5BB7-41D0-8C9D-42CFC5973B5D}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -120,5 +148,7 @@ Global {CD62A191-39F5-4C86-BC1D-7731085120F5} = {ACAA0157-A8C4-4152-93DE-90CCDF304087} {994351B4-7B2A-4139-8B72-72C5BB5CC618} = {2AF90579-B118-4583-AE88-672EFACB5BC4} {427CDB36-78B0-4583-9EBC-7F283DE60355} = {ACAA0157-A8C4-4152-93DE-90CCDF304087} + {624B0019-956A-4157-B008-270C5B229553} = {509A6F36-AD80-4A18-B5B1-717D38DFF29D} + {92A1063F-5BB7-41D0-8C9D-42CFC5973B5D} = {ACAA0157-A8C4-4152-93DE-90CCDF304087} EndGlobalSection EndGlobal diff --git a/samples/ElmSample/ElmSample.kproj b/samples/ElmSample/ElmSample.kproj new file mode 100644 index 00000000..c0c9103a --- /dev/null +++ b/samples/ElmSample/ElmSample.kproj @@ -0,0 +1,19 @@ + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + 92a1063f-5bb7-41d0-8c9d-42cfc5973b5d + ElmSample + ..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\artifacts\bin\$(MSBuildProjectName)\ + + + 2.0 + 11031 + + + \ No newline at end of file diff --git a/samples/ElmSample/Startup.cs b/samples/ElmSample/Startup.cs new file mode 100644 index 00000000..abb5f828 --- /dev/null +++ b/samples/ElmSample/Startup.cs @@ -0,0 +1,33 @@ +using System; +using Microsoft.AspNet.Builder; +using Microsoft.AspNet.Http; +using Microsoft.AspNet.Diagnostics.Elm; +using Microsoft.Framework.DependencyInjection; +using Microsoft.Framework.Logging; + +namespace ElmSampleApp +{ + public class Startup + { + public void ConfigureServices(IServiceCollection services) + { + services.AddSingleton(); // registering the service so it can be injected into constructors + services.Configure(options => + { + options.Path = new PathString("/foo"); + }); + } + + public void Configure(IApplicationBuilder app, ILoggerFactory factory) + { + app.UseElm(); +#pragma warning disable CS1998 + app.Run(async context => +#pragma warning restore CS1998 + { + await context.Response.WriteAsync("Hello world"); + throw new InvalidOperationException(); + }); + } + } +} diff --git a/samples/ElmSample/project.json b/samples/ElmSample/project.json new file mode 100644 index 00000000..217cde50 --- /dev/null +++ b/samples/ElmSample/project.json @@ -0,0 +1,24 @@ +{ + "webroot": "wwwroot", + "version": "1.0.0-*", + "exclude": [ + "wwwroot" + ], + "packExclude": [ + "**.kproj", + "**.user", + "**.vspscc" + ], + "dependencies": { + "Microsoft.AspNet.Diagnostics": "1.0.0-*", + "Microsoft.AspNet.Diagnostics.Elm": "1.0.0-*", + "Microsoft.AspNet.Http": "1.0.0-*", + "Microsoft.AspNet.PipelineCore": "1.0.0-*", + "Microsoft.AspNet.Server.IIS": "1.0.0-*", + "Microsoft.Framework.Logging.Console": "1.0.0-*" + }, + "frameworks" : { + "aspnet50" : { }, + "aspnetcore50" : { } + } +} diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/ActivityContext.cs b/src/Microsoft.AspNet.Diagnostics.Elm/ActivityContext.cs new file mode 100644 index 00000000..105c04ff --- /dev/null +++ b/src/Microsoft.AspNet.Diagnostics.Elm/ActivityContext.cs @@ -0,0 +1,10 @@ +using System; + +namespace Microsoft.AspNet.Diagnostics.Elm +{ + public class ActivityContext + { + public Guid Id { get; set; } + public HttpInfo HttpInfo { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/ElmExtensions.cs b/src/Microsoft.AspNet.Diagnostics.Elm/ElmExtensions.cs new file mode 100644 index 00000000..37b3ffca --- /dev/null +++ b/src/Microsoft.AspNet.Diagnostics.Elm/ElmExtensions.cs @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNet.Diagnostics.Elm; + +namespace Microsoft.AspNet.Builder +{ + public static class ElmExtensions + { + public static IApplicationBuilder UseElm(this IApplicationBuilder builder) + { + return builder.UseMiddleware(); + } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/ElmLogger.cs b/src/Microsoft.AspNet.Diagnostics.Elm/ElmLogger.cs new file mode 100644 index 00000000..086df896 --- /dev/null +++ b/src/Microsoft.AspNet.Diagnostics.Elm/ElmLogger.cs @@ -0,0 +1,67 @@ +// Copyright (c) Microsoft Open Technologies, Inc. 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.Collections.Generic; +using Microsoft.Framework.Logging; + +namespace Microsoft.AspNet.Diagnostics.Elm +{ + public class ElmLogger : ILogger + { + private readonly string _name; + private readonly ElmLoggerProvider _provider; + private IElmStore _store; + + public ElmLogger(string name, ElmLoggerProvider provider, IElmStore store) + { + _name = name; + _provider = provider; + _store = store; + } + + public void Write(TraceType traceType, int eventId, object state, Exception exception, + Func formatter) + { + LogInfo info = new LogInfo() + { + ActivityContext = ElmScope.Current == null ? GetNewActivityContext() : ElmScope.Current.Context, + Name = _name, + EventID = eventId, + Severity = traceType, + Exception = exception, + State = state, + Time = DateTime.Now + }; + ElmScope.Current.Node.Messages.Add(info); + _store.Add(info); + } + + public bool IsEnabled(TraceType traceType) + { + return true; + } + + public IDisposable BeginScope(object state) + { + var scope = new ElmScope(_name, state); + if (ElmScope.Current != null) + { + scope.Context = ElmScope.Current.Context; + } + else + { + scope.Context = GetNewActivityContext(); + } + return ElmScope.Push(scope); + } + + private ActivityContext GetNewActivityContext() + { + return new ActivityContext() + { + Id = Guid.NewGuid() + }; + } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/ElmLoggerProvider.cs b/src/Microsoft.AspNet.Diagnostics.Elm/ElmLoggerProvider.cs new file mode 100644 index 00000000..c167999f --- /dev/null +++ b/src/Microsoft.AspNet.Diagnostics.Elm/ElmLoggerProvider.cs @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft Open Technologies, Inc. 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; +using Microsoft.Framework.DependencyInjection; +using Microsoft.Framework.Logging; + +namespace Microsoft.AspNet.Diagnostics.Elm +{ + public class ElmLoggerProvider : ILoggerProvider + { + private readonly IElmStore _store; + + public ElmLoggerProvider(IElmStore store) + { + _store = store; + } + + public ILogger Create(string name) + { + return new ElmLogger(name, this, _store); + } + } +} diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/ElmMiddleware.cs b/src/Microsoft.AspNet.Diagnostics.Elm/ElmMiddleware.cs new file mode 100644 index 00000000..157ac09b --- /dev/null +++ b/src/Microsoft.AspNet.Diagnostics.Elm/ElmMiddleware.cs @@ -0,0 +1,145 @@ +// Copyright (c) Microsoft Open Technologies, Inc. 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.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNet.Builder; +using Microsoft.AspNet.Http; +using Microsoft.AspNet.Diagnostics.Elm.Views; +using Microsoft.Framework.Logging; +using Microsoft.Framework.OptionsModel; + +namespace Microsoft.AspNet.Diagnostics.Elm +{ + /// + /// Enables the Elm logging service + /// + public class ElmMiddleware + { + private readonly RequestDelegate _next; + private readonly ElmOptions _options; + private readonly ElmLoggerProvider _provider; + private readonly IElmStore _store; + private readonly ILogger _logger; + + public ElmMiddleware(RequestDelegate next, ILoggerFactory factory, IOptions options, IElmStore store) + { + _next = next; + _options = options.Options; + _store = store; + _logger = factory.Create(); + _provider = new ElmLoggerProvider(_store); + factory.AddProvider(_provider); + } + + public async Task Invoke(HttpContext context) + { + var requestId = Guid.NewGuid(); + + if (context.Request.Path != _options.Path && !context.Request.Path.StartsWithSegments(_options.Path)) + { + using (_logger.BeginScope(string.Format("request {0}", requestId))) + { + try + { + ElmScope.Current.Context.HttpInfo = GetHttpInfo(context, requestId); + await _next(context); + return; + } + catch (Exception ex) + { + ElmScope.Current.Context.HttpInfo = GetHttpInfo(context, requestId); + _logger.WriteError("An unhandled exception has occurred: " + ex.Message, ex); + throw; + } + } + } + + // parse params + var logs = (IEnumerable)null; + if (context.Request.Query.ContainsKey("level")) + { + var minLevel = (TraceType)int.Parse(context.Request.Query.GetValues("level")[0]); + logs = _store.GetLogs(minLevel); + _options.MinLevel = minLevel; + } + else + { + logs = _store.GetLogs(); + _options.MinLevel = TraceType.Verbose; + } + if (context.Request.Query.ContainsKey("name")) + { + var namePrefix = context.Request.Query.GetValues("name")[0]; + logs = logs.Where(l => l.Name.StartsWith(namePrefix)); + _options.NamePrefix = namePrefix; + } + + // main log page + if (context.Request.Path == _options.Path) + { + + var model = new LogPageModel() + { + // sort so most recent logs are first + Logs = logs.OrderBy(l => l.Time).Reverse(), + LogTree = ElmStore.Activities, + Options = _options + }; + var logPage = new LogPage(model); + + + + await logPage.ExecuteAsync(context); + } + // request details page + else + { + try + { + var parts = context.Request.Path.Value.Split('/'); + var id = Guid.Parse(parts[parts.Length - 1]); + var requestLogs = logs.Where(l => l.ActivityContext.HttpInfo != null ? l.ActivityContext.HttpInfo.RequestID == id : false); + var model = new RequestPageModel() + { + RequestID = id, + Logs = requestLogs, + Options = _options + }; + var requestPage = new RequestPage(model); + await requestPage.ExecuteAsync(context); + } + catch (Exception) + { + // TODO: bad url + } + } + } + + /// + /// Takes the info from the given HttpContext and copies it to an HttpInfo object + /// + /// The HttpInfo for the current elm context + private HttpInfo GetHttpInfo(HttpContext context, Guid requestId) + { + return new HttpInfo() + { + RequestID = requestId, + Host = context.Request.Host, + ContentType = context.Request.ContentType, + Path = context.Request.Path, + Scheme = context.Request.Scheme, + StatusCode = context.Response.StatusCode, + User = context.User, + Method = context.Request.Method, + Protocol = context.Request.Protocol, + Headers = context.Request.Headers, + Query = context.Request.QueryString, + Cookies = context.Request.Cookies + }; + } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/ElmOptions.cs b/src/Microsoft.AspNet.Diagnostics.Elm/ElmOptions.cs new file mode 100644 index 00000000..1b0cef90 --- /dev/null +++ b/src/Microsoft.AspNet.Diagnostics.Elm/ElmOptions.cs @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Open Technologies, Inc. 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; +using Microsoft.Framework.Logging; + +namespace Microsoft.AspNet.Diagnostics.Elm +{ + /// + /// Options for ElmMiddleware + /// + public class ElmOptions + { + public ElmOptions() + { + Path = new PathString("/Elm"); + } + + /// + /// Specifies the path to view the logs + /// + public PathString Path { get; set; } + + /// + /// The minimum severity level shown + /// + public TraceType MinLevel { get; set; } + + /// + /// prefix filter for the loggers shown + /// + public string NamePrefix { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/ElmScope.cs b/src/Microsoft.AspNet.Diagnostics.Elm/ElmScope.cs new file mode 100644 index 00000000..1411725c --- /dev/null +++ b/src/Microsoft.AspNet.Diagnostics.Elm/ElmScope.cs @@ -0,0 +1,108 @@ +using System; +#if ASPNET50 +using System.Runtime.Remoting; +using System.Runtime.Remoting.Messaging; +#endif +using System.Threading; + +namespace Microsoft.AspNet.Diagnostics.Elm +{ + public class ElmScope + { + private readonly string _name; + private readonly object _state; + + public ElmScope(string name, object state) + { + _name = name; + _state = state; + } + + public ActivityContext Context { get; set; } + + public ElmScope Parent { get; set; } + + public ScopeNode Node { get; set; } + +#if ASPNET50 + private static string FieldKey = typeof(ElmScope).FullName + ".Value"; + public static ElmScope Current + { + get + { + var handle = CallContext.LogicalGetData(FieldKey) as ObjectHandle; + + if (handle == null) + { + return default(ElmScope); + } + + return (ElmScope)handle.Unwrap(); + } + set + { + CallContext.LogicalSetData(FieldKey, new ObjectHandle(value)); + } + } +#else + private static AsyncLocal _value = new AsyncLocal(); + public static ElmScope Current + { + set + { + _value.Value = value; + } + get + { + return _value.Value; + } + } +#endif + + public static IDisposable Push(ElmScope scope) + { + var temp = Current; + Current = scope; + Current.Parent = temp; + + Current.Node = new ScopeNode() + { + StartTime = DateTime.Now, + State = Current._state, + Name = Current._name + }; + if (Current.Parent != null) + { + Current.Node.Parent = Current.Parent.Node; + Current.Parent.Node.Children.Add(Current.Node); + } + else + { + lock(ElmStore.Activities) + { + ElmStore.Activities.Add(Current.Context, Current.Node); + } + } + + return new DisposableAction(() => + { + Current.Node.EndTime = DateTime.Now; + Current = Current.Parent; + }); + } + + private class DisposableAction : IDisposable + { + private Action _action; + public DisposableAction(Action action) + { + _action = action; + } + + public void Dispose() + { + Interlocked.Exchange(ref _action, null)?.Invoke(); + } + } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/ElmStore.cs b/src/Microsoft.AspNet.Diagnostics.Elm/ElmStore.cs new file mode 100644 index 00000000..99476617 --- /dev/null +++ b/src/Microsoft.AspNet.Diagnostics.Elm/ElmStore.cs @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using System.Linq; +using Microsoft.Framework.Logging; + +namespace Microsoft.AspNet.Diagnostics.Elm +{ + public class ElmStore : IElmStore + { + private readonly List _logs = new List(); + + public static IDictionary Activities { get; set; } = new Dictionary(); + + public IEnumerable GetLogs() + { + return _logs; + } + + public IEnumerable GetLogs(TraceType minLevel) + { + return _logs.Where(l => l.Severity >= minLevel); + } + + public void Add(LogInfo info) + { + _logs.Add(info); + } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/HttpInfo.cs b/src/Microsoft.AspNet.Diagnostics.Elm/HttpInfo.cs new file mode 100644 index 00000000..8f67ce99 --- /dev/null +++ b/src/Microsoft.AspNet.Diagnostics.Elm/HttpInfo.cs @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Open Technologies, Inc. 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.Security.Claims; +using Microsoft.AspNet.Http; + +namespace Microsoft.AspNet.Diagnostics.Elm +{ + public class HttpInfo + { + public Guid RequestID { get; set; } + + public HostString Host { get; set; } + + public PathString Path { get; set; } + + public string ContentType { get; set; } + + public string Scheme { get; set; } + + public int StatusCode { get; set; } + + public ClaimsPrincipal User { get; set; } + + public string Method { get; set; } + + public string Protocol { get; set; } + + public IHeaderDictionary Headers { get; set; } + + public QueryString Query { get; set; } + + public IReadableStringCollection Cookies { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/IElmStore.cs b/src/Microsoft.AspNet.Diagnostics.Elm/IElmStore.cs new file mode 100644 index 00000000..9a0db596 --- /dev/null +++ b/src/Microsoft.AspNet.Diagnostics.Elm/IElmStore.cs @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using Microsoft.Framework.Logging; + +namespace Microsoft.AspNet.Diagnostics.Elm +{ + public interface IElmStore + { + void Add(LogInfo info); + IEnumerable GetLogs(); + IEnumerable GetLogs(TraceType minLevel); + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/LogInfo.cs b/src/Microsoft.AspNet.Diagnostics.Elm/LogInfo.cs new file mode 100644 index 00000000..447ba4f7 --- /dev/null +++ b/src/Microsoft.AspNet.Diagnostics.Elm/LogInfo.cs @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Open Technologies, Inc. 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.Collections.Generic; +using Microsoft.Framework.Logging; + +namespace Microsoft.AspNet.Diagnostics.Elm +{ + public class LogInfo + { + public ActivityContext ActivityContext { get; set; } + + public string Name { get; set; } + + public object State { get; set; } + + public Exception Exception { get; set; } + + public TraceType Severity { get; set; } + + public int EventID { get; set; } + + public DateTime Time { get; set; } + + public IList Scopes { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/Microsoft.AspNet.Diagnostics.Elm.kproj b/src/Microsoft.AspNet.Diagnostics.Elm/Microsoft.AspNet.Diagnostics.Elm.kproj new file mode 100644 index 00000000..06e8c5e0 --- /dev/null +++ b/src/Microsoft.AspNet.Diagnostics.Elm/Microsoft.AspNet.Diagnostics.Elm.kproj @@ -0,0 +1,20 @@ + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + + 624b0019-956a-4157-b008-270c5b229553 + Microsoft.AspNet.Diagnostics.Elm + ..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\artifacts\bin\$(MSBuildProjectName)\ + + + + 2.0 + + + \ No newline at end of file diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/ScopeNode.cs b/src/Microsoft.AspNet.Diagnostics.Elm/ScopeNode.cs new file mode 100644 index 00000000..dabd3705 --- /dev/null +++ b/src/Microsoft.AspNet.Diagnostics.Elm/ScopeNode.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; + +namespace Microsoft.AspNet.Diagnostics.Elm +{ + public class ScopeNode + { + public ScopeNode Parent { get; set; } + public List Children { get; set; } = new List(); + public List Messages { get; set; } = new List(); + public DateTime StartTime { get; set; } + public DateTime EndTime { get; set; } + public object State { get; set; } + public string Name { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.cs b/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.cs new file mode 100644 index 00000000..66d3bc85 --- /dev/null +++ b/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.cs @@ -0,0 +1,605 @@ +namespace Microsoft.AspNet.Diagnostics.Elm.Views +{ +#line 1 "LogPage.cshtml" +using System + +#line default +#line hidden + ; +#line 2 "LogPage.cshtml" +using System.Globalization + +#line default +#line hidden + ; +#line 3 "LogPage.cshtml" +using System.Linq + +#line default +#line hidden + ; +#line 4 "LogPage.cshtml" +using Microsoft.AspNet.Diagnostics.Elm.Views + +#line default +#line hidden + ; +#line 5 "LogPage.cshtml" +using Microsoft.Framework.Logging + +#line default +#line hidden + ; +#line 6 "LogPage.cshtml" +using Microsoft.AspNet.Diagnostics.Elm + +#line default +#line hidden + ; +#line 7 "LogPage.cshtml" +using Microsoft.AspNet.Diagnostics.Views + +#line default +#line hidden + ; + using System.Threading.Tasks; + + public class LogPage : Microsoft.AspNet.Diagnostics.Views.BaseView + { +public HelperResult +#line 20 "LogPage.cshtml" +LogRow(LogInfo log, int level) { + +#line default +#line hidden + return new HelperResult((__razor_helper_writer) => { +#line 20 "LogPage.cshtml" + + if (log.Severity >= Model.Options.MinLevel && + (string.IsNullOrEmpty(Model.Options.NamePrefix) || log.Name.StartsWith(Model.Options.NamePrefix))) + { + +#line default +#line hidden + + WriteLiteralTo(__razor_helper_writer, " \r\n "); +#line 25 "LogPage.cshtml" +WriteTo(__razor_helper_writer, string.Format("{0:MM/dd/yy}", log.Time)); + +#line default +#line hidden + WriteLiteralTo(__razor_helper_writer, "\r\n "); +#line 26 "LogPage.cshtml" +WriteTo(__razor_helper_writer, string.Format("{0:H:mm:ss}", log.Time)); + +#line default +#line hidden + WriteLiteralTo(__razor_helper_writer, "\r\n (log.Name, 818), false)); + WriteLiteralTo(__razor_helper_writer, ">"); +#line 27 "LogPage.cshtml" + WriteTo(__razor_helper_writer, log.Name); + +#line default +#line hidden + WriteLiteralTo(__razor_helper_writer, "\r\n (log.Severity, 868), false)); + WriteLiteralTo(__razor_helper_writer, ">"); +#line 28 "LogPage.cshtml" + WriteTo(__razor_helper_writer, log.Severity); + +#line default +#line hidden + WriteLiteralTo(__razor_helper_writer, "\r\n (log.State, 926), false)); + WriteLiteralTo(__razor_helper_writer, ">\r\n"); +#line 30 "LogPage.cshtml" + + +#line default +#line hidden + +#line 30 "LogPage.cshtml" + for (var i = 0; i < level; i++) + { + +#line default +#line hidden + + WriteLiteralTo(__razor_helper_writer, " \r\n"); +#line 33 "LogPage.cshtml" + } + +#line default +#line hidden + + WriteLiteralTo(__razor_helper_writer, " "); +#line 34 "LogPage.cshtml" +WriteTo(__razor_helper_writer, log.State); + +#line default +#line hidden + WriteLiteralTo(__razor_helper_writer, "\r\n \r\n (log.Exception, 1145), false)); + WriteLiteralTo(__razor_helper_writer, ">"); +#line 36 "LogPage.cshtml" + WriteTo(__razor_helper_writer, log.Exception); + +#line default +#line hidden + WriteLiteralTo(__razor_helper_writer, "\r\n \r\n"); +#line 38 "LogPage.cshtml" + } + +#line default +#line hidden + + } + ); +#line 39 "LogPage.cshtml" +} + +#line default +#line hidden + +public HelperResult +#line 41 "LogPage.cshtml" +Traverse(ScopeNode node, int level) +{ + +#line default +#line hidden + return new HelperResult((__razor_helper_writer) => { +#line 42 "LogPage.cshtml" + + // print start time + + +#line default +#line hidden + +#line 44 "LogPage.cshtml" +WriteTo(__razor_helper_writer, LogRow(new LogInfo() + { + Name = node.Name, + Time = node.StartTime, + Severity = TraceType.Verbose, + State = "Beginning " + node.State, + }, level)); + +#line default +#line hidden +#line 50 "LogPage.cshtml" + ; + var m = 0; + var c = 0; + while (m < node.Messages.Count && c < node.Children.Count) + { + if (node.Messages[m].Time < node.Children[c].StartTime) + { + + +#line default +#line hidden + +#line 57 "LogPage.cshtml" +WriteTo(__razor_helper_writer, LogRow(node.Messages[m], level)); + +#line default +#line hidden +#line 57 "LogPage.cshtml" + + m++; + } + else + { + + +#line default +#line hidden + +#line 62 "LogPage.cshtml" +WriteTo(__razor_helper_writer, Traverse(node.Children[c], level + 1)); + +#line default +#line hidden +#line 62 "LogPage.cshtml" + + c++; + } + } + if (m < node.Messages.Count) + { + for (var i = m; i < node.Messages.Count; i++) + { + + +#line default +#line hidden + +#line 70 "LogPage.cshtml" +WriteTo(__razor_helper_writer, LogRow(node.Messages[i], level)); + +#line default +#line hidden +#line 70 "LogPage.cshtml" + + } + } + else + { + for (var i = c; i < node.Children.Count; i++) + { + + +#line default +#line hidden + +#line 77 "LogPage.cshtml" +WriteTo(__razor_helper_writer, Traverse(node.Children[i], level + 1)); + +#line default +#line hidden +#line 77 "LogPage.cshtml" + + } + } + // print end time + + +#line default +#line hidden + +#line 81 "LogPage.cshtml" +WriteTo(__razor_helper_writer, LogRow(new LogInfo() + { + Name = node.Name, + Time = node.EndTime, + Severity = TraceType.Verbose, + State = string.Format("Completed {0} in {1}ms", node.State, node.EndTime - node.StartTime) + }, level)); + +#line default +#line hidden +#line 87 "LogPage.cshtml" + ; + +#line default +#line hidden + + } + ); +#line 88 "LogPage.cshtml" +} + +#line default +#line hidden + +#line 10 "LogPage.cshtml" + + public LogPage(LogPageModel model) + { + Model = model; + } + + public LogPageModel Model { get; set; } + +#line default +#line hidden + #line hidden + public LogPage() + { + } + + #pragma warning disable 1998 + public override async Task ExecuteAsync() + { + WriteLiteral("\r\n"); + WriteLiteral("\r\n\r\n"); + WriteLiteral("\r\n"); + WriteLiteral(@" + + + + + ELM + + + + +

ELM

+
+ \r\n (Model.Options.NamePrefix, 3269), false)); + WriteLiteral(@" /> + +
+ + + + + + + + + + + + + + + + +"); +#line 136 "LogPage.cshtml" + + +#line default +#line hidden + +#line 136 "LogPage.cshtml" + foreach (var activity in Model.LogTree.Reverse()) + { + +#line default +#line hidden + + WriteLiteral(" \r\n \r\n"); +#line 140 "LogPage.cshtml" + + +#line default +#line hidden + +#line 140 "LogPage.cshtml" + + if (activity.Key.HttpInfo != null) + { + var requestPath = Model.Options.Path.Value + "/" + activity.Key.HttpInfo.RequestID; + +#line default +#line hidden + + WriteLiteral(" \r\n \r\n \r\n"); +#line 147 "LogPage.cshtml" + } + else + { + +#line default +#line hidden + + WriteLiteral(" \r\n"); +#line 151 "LogPage.cshtml" + } + + +#line default +#line hidden + + WriteLiteral(@" + \r\n \r\n \r\n"); +#line 172 "LogPage.cshtml" + } + +#line default +#line hidden + + WriteLiteral("
PathHostStatus CodeLogs
(requestPath, 4197), false)); + WriteAttribute("title", Tuple.Create(" title=\"", 4210), Tuple.Create("\"", 4245), + Tuple.Create(Tuple.Create("", 4218), Tuple.Create(activity.Key.HttpInfo.Path, 4218), false)); + WriteLiteral(">"); +#line 144 "LogPage.cshtml" + Write(activity.Key.HttpInfo.Path); + +#line default +#line hidden + WriteLiteral(""); +#line 145 "LogPage.cshtml" + Write(activity.Key.HttpInfo.Host); + +#line default +#line hidden + WriteLiteral(""); +#line 146 "LogPage.cshtml" + Write(activity.Key.HttpInfo.StatusCode); + +#line default +#line hidden + WriteLiteral("BOO + + + + + + + + + + + + + "); +#line 166 "LogPage.cshtml" + Write(Traverse(activity.Value, 0)); + +#line default +#line hidden + WriteLiteral("\r\n \r\n
DateTimeNameSeverityStateError
\r\n " + +"
\r\n\r\n"); + } + #pragma warning restore 1998 + } +} diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.cshtml b/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.cshtml new file mode 100644 index 00000000..af4a07bd --- /dev/null +++ b/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.cshtml @@ -0,0 +1,175 @@ +@using System +@using System.Globalization +@using System.Linq +@using Microsoft.AspNet.Diagnostics.Elm.Views +@using Microsoft.Framework.Logging +@using Microsoft.AspNet.Diagnostics.Elm +@using Microsoft.AspNet.Diagnostics.Views + +@functions +{ + public LogPage(LogPageModel model) + { + Model = model; + } + + public LogPageModel Model { get; set; } +} + +@* writes one log row indented by the given level *@ +@helper LogRow(LogInfo log, int level) { + if (log.Severity >= Model.Options.MinLevel && + (string.IsNullOrEmpty(Model.Options.NamePrefix) || log.Name.StartsWith(Model.Options.NamePrefix))) + { + + @string.Format("{0:MM/dd/yy}", log.Time) + @string.Format("{0:H:mm:ss}", log.Time) + @log.Name + @log.Severity + + @for (var i = 0; i < level; i++) + { + + } + @log.State + + @log.Exception + + } +} + +@helper Traverse(ScopeNode node, int level) +{ + // print start time + @LogRow(new LogInfo() + { + Name = node.Name, + Time = node.StartTime, + Severity = TraceType.Verbose, + State = "Beginning " + node.State, + }, level); + var m = 0; + var c = 0; + while (m < node.Messages.Count && c < node.Children.Count) + { + if (node.Messages[m].Time < node.Children[c].StartTime) + { + @LogRow(node.Messages[m], level) + m++; + } + else + { + @Traverse(node.Children[c], level + 1) + c++; + } + } + if (m < node.Messages.Count) + { + for (var i = m; i < node.Messages.Count; i++) + { + @LogRow(node.Messages[i], level) + } + } + else + { + for (var i = c; i < node.Children.Count; i++) + { + @Traverse(node.Children[i], level + 1) + } + } + // print end time + @LogRow(new LogInfo() + { + Name = node.Name, + Time = node.EndTime, + Severity = TraceType.Verbose, + State = string.Format("Completed {0} in {1}ms", node.State, node.EndTime - node.StartTime) + }, level); +} + + + + + + ELM + + + + +

ELM

+
+ + + +
+ + + + + + + + + + + + + + + + + @foreach (var activity in Model.LogTree.Reverse()) + { + + + @{ + if (activity.Key.HttpInfo != null) + { + var requestPath = Model.Options.Path.Value + "/" + activity.Key.HttpInfo.RequestID; + + + + } + else + { + + } + } + + + + } +
PathHostStatus CodeLogs
@activity.Key.HttpInfo.Path@activity.Key.HttpInfo.Host@activity.Key.HttpInfo.StatusCodeBOO + + + + + + + + + + + + + @Traverse(activity.Value, 0) + +
DateTimeNameSeverityStateError
+
+ + \ No newline at end of file diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.css b/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.css new file mode 100644 index 00000000..9327b286 --- /dev/null +++ b/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.css @@ -0,0 +1,111 @@ +body { + font-family: 'Segoe UI', Tahoma, Arial, Helvetica, sans-serif; + font-size: .813em; + line-height: 1.4em; + white-space: nowrap; + margin: 10px; +} + +col:nth-child(2) { + background-color: #FAFAFA; +} + +h1 { + font-family: Arial, Helvetica, sans-serif; + font-size: 2em; +} + +table { + margin: 0px auto; + border-spacing: 0px; + table-layout: fixed; + width: 100%; + border-collapse: collapse; +} + +td { + text-overflow: ellipsis; + overflow: hidden; +} + +td, th { + padding: 4px; +} + +thead { + font-size: 1em; + font-family: Arial; +} + +tr { + height: 23px; +} + +tr:nth-child(2n) { + background-color: #F6F6F6; +} + +#requestHeader { + border-bottom: solid 1px gray; + border-top: solid 1px gray; + margin-bottom: 2px; + font-size: 1em; + line-height: 2em; +} + +.date, .time { + width: 70px; +} + +.logHeader { + border-bottom: 1px solid lightgray; + color: gray; + text-align: left; +} + +.logState { + text-overflow: ellipsis; + overflow: hidden; +} + +.logTd { + border-left: 1px solid gray; + padding: 0px; +} + +.logs { + width: 80%; +} + +.requestRow>td { + border-bottom: solid 1px gray; +} + +.severity { + width: 80px; +} + +.tab { + margin-left: 30px; +} + +.Critical { + background-color: red; + color: white; +} + +.Error { + color: red; +} + +.Information { + color: blue; +} + +.Verbose { + color: black; +} + +.Warning { + color: orange; +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPageModel.cs b/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPageModel.cs new file mode 100644 index 00000000..6415c0fe --- /dev/null +++ b/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPageModel.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; + +namespace Microsoft.AspNet.Diagnostics.Elm.Views +{ + public class LogPageModel + { + public IEnumerable Logs { get; set; } + + public IDictionary LogTree { get; set; } + + public ElmOptions Options { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.cs b/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.cs new file mode 100644 index 00000000..ce0aaa68 --- /dev/null +++ b/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.cs @@ -0,0 +1,483 @@ +namespace Microsoft.AspNet.Diagnostics.Elm.Views +{ +#line 1 "RequestPage.cshtml" +using System + +#line default +#line hidden + ; +#line 2 "RequestPage.cshtml" +using System.Globalization + +#line default +#line hidden + ; +#line 3 "RequestPage.cshtml" +using System.Linq + +#line default +#line hidden + ; +#line 4 "RequestPage.cshtml" +using Microsoft.AspNet.Diagnostics.Elm + +#line default +#line hidden + ; +#line 5 "RequestPage.cshtml" +using Microsoft.AspNet.Diagnostics.Elm.Views + +#line default +#line hidden + ; +#line 6 "RequestPage.cshtml" +using Microsoft.Framework.Logging + +#line default +#line hidden + ; + using System.Threading.Tasks; + + public class RequestPage : Microsoft.AspNet.Diagnostics.Views.BaseView + { +#line 9 "RequestPage.cshtml" + + public RequestPage(RequestPageModel model) + { + Model = model; + } + + public RequestPageModel Model { get; set; } + +#line default +#line hidden + #line hidden + public RequestPage() + { + } + + #pragma warning disable 1998 + public override async Task ExecuteAsync() + { + WriteLiteral("\r\n"); + WriteLiteral(@" + + + + ELM + + + +

ELM

+ +

Request Details

+ + +"); +#line 32 "RequestPage.cshtml" + + +#line default +#line hidden + +#line 32 "RequestPage.cshtml" + + var context = Model.Logs.First().ActivityContext.HttpInfo; + + +#line default +#line hidden + + WriteLiteral("\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n " + +" \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n "); +#line 53 "RequestPage.cshtml" + Write(context.Protocol); + +#line default +#line hidden + WriteLiteral(@" + + + + \r\n " + +" \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n " + +" \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n"); +#line 97 "RequestPage.cshtml" + + +#line default +#line hidden + +#line 97 "RequestPage.cshtml" + if (context.Cookies.Any()) + { + +#line default +#line hidden + + WriteLiteral(@"
Path"); +#line 37 "RequestPage.cshtml" + Write(context.Path); + +#line default +#line hidden + WriteLiteral("
Host"); +#line 41 "RequestPage.cshtml" + Write(context.Host); + +#line default +#line hidden + WriteLiteral("
Content Type"); +#line 45 "RequestPage.cshtml" + Write(context.ContentType); + +#line default +#line hidden + WriteLiteral("
Method" + +""); +#line 49 "RequestPage.cshtml" + Write(context.Method); + +#line default +#line hidden + WriteLiteral("
Protocol
Headers + + + + + + + + +"); +#line 66 "RequestPage.cshtml" + + +#line default +#line hidden + +#line 66 "RequestPage.cshtml" + foreach (var header in context.Headers) + { + +#line default +#line hidden + + WriteLiteral(" \r\n \r\n \r\n \r\n"); +#line 72 "RequestPage.cshtml" + } + +#line default +#line hidden + + WriteLiteral(" \r\n
VariableValue
"); +#line 69 "RequestPage.cshtml" + Write(header.Key); + +#line default +#line hidden + WriteLiteral(""); +#line 70 "RequestPage.cshtml" + Write(string.Join(";", header.Value)); + +#line default +#line hidden + WriteLiteral("
\r\n
Status Code"); +#line 79 "RequestPage.cshtml" + Write(context.StatusCode); + +#line default +#line hidden + WriteLiteral("
User"); +#line 84 "RequestPage.cshtml" + Write(context.User.Identity.Name); + +#line default +#line hidden + WriteLiteral("
Scheme" + +""); +#line 88 "RequestPage.cshtml" + Write(context.Scheme); + +#line default +#line hidden + WriteLiteral("
Query"); +#line 92 "RequestPage.cshtml" + Write(context.Query.Value); + +#line default +#line hidden + WriteLiteral("
Cookies
+ + + + + + + +"); +#line 107 "RequestPage.cshtml" + + +#line default +#line hidden + +#line 107 "RequestPage.cshtml" + foreach (var cookie in context.Cookies) + { + +#line default +#line hidden + + WriteLiteral(" \r\n \r\n \r\n \r\n"); +#line 113 "RequestPage.cshtml" + } + +#line default +#line hidden + + WriteLiteral(" \r\n
VariableValue
"); +#line 110 "RequestPage.cshtml" + Write(cookie.Key); + +#line default +#line hidden + WriteLiteral(""); +#line 111 "RequestPage.cshtml" + Write(string.Join(";", cookie.Value)); + +#line default +#line hidden + WriteLiteral("
\r\n"); +#line 116 "RequestPage.cshtml" + } + +#line default +#line hidden + + WriteLiteral(" \r\n \r\n \r\n\r\n

Logs

\r\n
\r\n \r\n (Model.Options.NamePrefix, 3963), false)); + WriteLiteral(@" /> + +
+ + + + + + + + + + + +"); +#line 151 "RequestPage.cshtml" + + +#line default +#line hidden + +#line 151 "RequestPage.cshtml" + foreach (var log in Model.Logs) + { + +#line default +#line hidden + + WriteLiteral(" \r\n \r\n \r\n (log.Severity, 4573), false)); + WriteLiteral(">"); +#line 156 "RequestPage.cshtml" + Write(log.Severity); + +#line default +#line hidden + WriteLiteral("\r\n (log.Name, 4635), false)); + WriteLiteral(">"); +#line 157 "RequestPage.cshtml" + Write(log.Name); + +#line default +#line hidden + WriteLiteral("\r\n (log.State, 4689), false)); + WriteLiteral(" class=\"logState\" width=\"100px\">"); +#line 158 "RequestPage.cshtml" + Write(log.State); + +#line default +#line hidden + WriteLiteral("\r\n (log.Exception, 4776), false)); + WriteLiteral(">"); +#line 159 "RequestPage.cshtml" + Write(log.Exception); + +#line default +#line hidden + WriteLiteral("\r\n \r\n"); +#line 161 "RequestPage.cshtml" + } + +#line default +#line hidden + + WriteLiteral("
DateTimeSeverityNameStateError
"); +#line 154 "RequestPage.cshtml" + Write(string.Format("{0:MM/dd/yy}", log.Time)); + +#line default +#line hidden + WriteLiteral(""); +#line 155 "RequestPage.cshtml" + Write(string.Format("{0:H:mm:ss}", log.Time)); + +#line default +#line hidden + WriteLiteral("
\r\n\r\n"); + } + #pragma warning restore 1998 + } +} diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.cshtml b/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.cshtml new file mode 100644 index 00000000..bc0824aa --- /dev/null +++ b/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.cshtml @@ -0,0 +1,164 @@ +@using System +@using System.Globalization +@using System.Linq +@using Microsoft.AspNet.Diagnostics.Elm +@using Microsoft.AspNet.Diagnostics.Elm.Views +@using Microsoft.Framework.Logging + +@functions +{ + public RequestPage(RequestPageModel model) + { + Model = model; + } + + public RequestPageModel Model { get; set; } +} + + + + + ELM + + + +

ELM

+ +

Request Details

+ + + @{ + var context = Model.Logs.First().ActivityContext.HttpInfo; + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @* TODO: show more information about the user*@ + + + + + + + + + + + + + + +
Path@context.Path
Host@context.Host
Content Type@context.ContentType
Method@context.Method
Protocol@context.Protocol
Headers + + + + + + + + + @foreach (var header in context.Headers) + { + + + + + } + +
VariableValue
@header.Key@string.Join(";", header.Value)
+
Status Code@context.StatusCode
User@context.User.Identity.Name
Scheme@context.Scheme
Query@context.Query.Value
Cookies + @if (context.Cookies.Any()) + { + + + + + + + + + @foreach (var cookie in context.Cookies) + { + + + + + } + +
VariableValue
@cookie.Key@string.Join(";", cookie.Value)
+ } +
+ +

Logs

+
+ + + +
+ + + + + + + + + + + + @foreach (var log in Model.Logs) + { + + + + + + + + + } +
DateTimeSeverityNameStateError
@string.Format("{0:MM/dd/yy}", log.Time)@string.Format("{0:H:mm:ss}", log.Time)@log.Severity@log.Name@log.State@log.Exception
+ + \ No newline at end of file diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.css b/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.css new file mode 100644 index 00000000..7f5abbea --- /dev/null +++ b/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.css @@ -0,0 +1,79 @@ +body { + font-family: 'Segoe UI', Tahoma, Arial, Helvtica, sans-serif; + font-size: 0.9em; + line-height: 1.4em; + width: 90%; + margin: 0px auto; +} + +h1, h2 { + font-weight: normal; +} + +table { + border-spacing: 0px; + width: 100%; + border-collapse: collapse; + border: 1px solid black; + white-space: pre-wrap; +} + +td { + text-overflow: ellipsis; + overflow: hidden; +} + +th { + font-family: Arial; +} + +td, th { + padding: 8px; +} + +tr:nth-child(2n) { + background-color: #F6F6F6; +} + +#headerTable { + border: none; + height: 100%; +} + +#headerTd { + white-space: normal; +} + +#label { + width: 20%; + border-right: 1px solid black; +} + +#logs>tbody>tr>td { + border-right: 1px dashed lightgray; +} + +#logs>thead>tr>th { + border: 1px solid black; +} + +.Critical { + background-color: red; + color: white; +} + +.Error { + color: red; +} + +.Information { + color: blue; +} + +.Verbose { + color: black; +} + +.Warning { + color: orange; +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPageModel.cs b/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPageModel.cs new file mode 100644 index 00000000..0daaa17b --- /dev/null +++ b/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPageModel.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; + +namespace Microsoft.AspNet.Diagnostics.Elm.Views +{ + public class RequestPageModel + { + public Guid RequestID { get; set; } + + public IEnumerable Logs { get; set; } + + public ElmOptions Options { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/project.json b/src/Microsoft.AspNet.Diagnostics.Elm/project.json new file mode 100644 index 00000000..39efedf6 --- /dev/null +++ b/src/Microsoft.AspNet.Diagnostics.Elm/project.json @@ -0,0 +1,31 @@ +{ + "version": "1.0.0-*", + "dependencies": { + "Microsoft.AspNet.Diagnostics": "1.0.0-*", + "Microsoft.AspNet.Http": "1.0.0-*", + "Microsoft.AspNet.Mvc.Razor": "6.0.0-*", + "Microsoft.AspNet.RequestContainer": "1.0.0-*", + "Microsoft.Framework.Logging.Interfaces": { "version": "1.0.0-*", "type": "build" }, + "Microsoft.Framework.Runtime.Interfaces": { "version": "1.0.0-*", "type": "build" } + }, + + "frameworks": { + "aspnet50": { }, + "aspnetcore50": { + "dependencies": { + "K.CommonFx": "1.0.0-*", + "System.Collections.Concurrent": "4.0.0-beta-*", + "System.Collections": "4.0.10-beta-*", + "System.Diagnostics.TraceSource": "4.0.0-beta-*", + "System.Globalization": "4.0.10-beta-*", + "System.Runtime": "4.0.20-beta-*", + "System.Runtime.Extensions": "4.0.10-beta-*", + "System.Runtime.InteropServices": "4.0.20-beta-*", + "System.Linq": "4.0.0-beta-*", + "System.Threading": "4.0.0-beta-*", + "System.Threading.ExecutionContext": "4.0.0-beta-*", + "Microsoft.Framework.Logging.Interfaces": { "version": "1.0.0-*", "type": "build" } + } + } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Diagnostics/Views/BaseView.cs b/src/Microsoft.AspNet.Diagnostics/Views/BaseView.cs index ee2c49d4..f3f91794 100644 --- a/src/Microsoft.AspNet.Diagnostics/Views/BaseView.cs +++ b/src/Microsoft.AspNet.Diagnostics/Views/BaseView.cs @@ -100,6 +100,35 @@ protected void WriteAttribute( WriteLiteral(trailer.Item1); } + protected void WriteAttributeTo( + TextWriter writer, + string name, + Tuple leader, + Tuple trailer, + Tuple, Tuple, bool> part1) + { + if (name == null) + { + throw new ArgumentNullException("name"); + } + if (leader == null) + { + throw new ArgumentNullException("leader"); + } + if (trailer == null) + { + throw new ArgumentNullException("trailer"); + } + if (part1 == null) + { + throw new ArgumentNullException("part1"); + } + WriteLiteralTo(writer, leader.Item1); + WriteLiteralTo(writer, part1.Item1.Item1); + WriteTo(writer, part1.Item2.Item1); + WriteLiteralTo(writer, trailer.Item1); + } + /// /// /// @@ -421,7 +450,7 @@ protected void WriteAttribute( /// private void WriteEncoded(string value) { - Output.Write(WebUtility.HtmlEncode(value)); + WriteLiteralTo(Output, WebUtility.HtmlEncode(value)); } /// @@ -441,5 +470,72 @@ protected void Write(string value) { WriteEncoded(value); } + + /// + /// is invoked + /// + /// The to invoke + protected void Write(HelperResult result) + { + WriteTo(Output, result); + } + + /// + /// Writes the specified to . + /// + /// The instance to write to. + /// The to write. + /// + /// is invoked for types. + /// For all other types, the encoded result of is written to the + /// . + /// + protected void WriteTo(TextWriter writer, object value) + { + if (value != null) + { + var helperResult = value as HelperResult; + if (helperResult != null) + { + helperResult.WriteTo(writer); + } + else + { + WriteTo(writer, value.ToString()); + } + } + } + + /// + /// Writes the specified with HTML encoding to . + /// + /// The instance to write to. + /// The to write. + protected void WriteTo(TextWriter writer, string value) + { + WriteLiteralTo(writer, WebUtility.HtmlEncode(value)); + } + + /// + /// Writes the specified without HTML encoding to the . + /// + /// The instance to write to. + /// The to write. + protected void WriteLiteralTo(TextWriter writer, object value) + { + WriteLiteralTo(writer, Convert.ToString(value, CultureInfo.InvariantCulture)); + } + + /// + /// Writes the specified without HTML encoding to . + /// + /// The to write. + protected void WriteLiteralTo(TextWriter writer, string value) + { + if (!string.IsNullOrEmpty(value)) + { + writer.Write(value); + } + } } } diff --git a/src/Microsoft.AspNet.Diagnostics/Views/HelperResult.cs b/src/Microsoft.AspNet.Diagnostics/Views/HelperResult.cs new file mode 100644 index 00000000..e8f0e769 --- /dev/null +++ b/src/Microsoft.AspNet.Diagnostics/Views/HelperResult.cs @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Open Technologies, Inc. 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; + +namespace Microsoft.AspNet.Diagnostics.Views +{ + /// + /// Represents a deferred write operation in a . + /// + public class HelperResult + { + private readonly Action _action; + + /// + /// Creates a new instance of . + /// + /// The delegate to invoke when is called. + public HelperResult(Action action) + { + _action = action; + } + + /// + /// Gets the delegate to invoke when is called. + /// + public Action WriteAction + { + get { return _action; } + } + + /// + /// Method invoked to produce content from the . + /// + /// The instance to write to. + public virtual void WriteTo(TextWriter writer) + { + _action(writer); + } + } +} \ No newline at end of file diff --git a/src/PageGenerator/PageGenerator.kproj b/src/PageGenerator/PageGenerator.kproj index dc172378..5fc6e933 100644 --- a/src/PageGenerator/PageGenerator.kproj +++ b/src/PageGenerator/PageGenerator.kproj @@ -15,6 +15,10 @@ 2.0 + 0 + + + \ No newline at end of file diff --git a/src/PageGenerator/Program.cs b/src/PageGenerator/Program.cs index a4f84c78..11bd19b4 100644 --- a/src/PageGenerator/Program.cs +++ b/src/PageGenerator/Program.cs @@ -6,6 +6,7 @@ using System.IO; using System.Linq; using Microsoft.AspNet.Razor; +using Microsoft.AspNet.Razor.Generator; using Microsoft.Framework.Runtime; namespace PageGenerator @@ -76,6 +77,15 @@ private static void GenerateCodeFile(string cshtmlFilePath, string rootNamespace var codeLang = new CSharpRazorCodeLanguage(); var host = new RazorEngineHost(codeLang); host.DefaultBaseClass = "Microsoft.AspNet.Diagnostics.Views.BaseView"; + host.GeneratedClassContext = new GeneratedClassContext( + GeneratedClassContext.DefaultExecuteMethodName, + GeneratedClassContext.DefaultWriteMethodName, + GeneratedClassContext.DefaultWriteLiteralMethodName, + "WriteTo", + "WriteLiteralTo", + "HelperResult", + "DefineSection", + new GeneratedTagHelperContext()); var engine = new RazorTemplateEngine(host); using (var fileStream = File.OpenText(cshtmlFilePath)) diff --git a/src/PageGenerator/project.json b/src/PageGenerator/project.json index 228d7c87..177e5624 100644 --- a/src/PageGenerator/project.json +++ b/src/PageGenerator/project.json @@ -2,6 +2,7 @@ "version": "1.0.0-*", "dependencies": { "Microsoft.AspNet.Diagnostics": "1.0.0-*", + "Microsoft.AspNet.Diagnostics.Elm": "1.0.0-*", "Microsoft.AspNet.Razor": "4.0.0-*", "Microsoft.Framework.Runtime.Interfaces": "1.0.0-*" }, From e971917a6690f90d091cf73887e280a44cb658a6 Mon Sep 17 00:00:00 2001 From: SonjaKhan Date: Thu, 30 Oct 2014 13:47:16 -0700 Subject: [PATCH 02/19] incorporating feedback --- .../ElmMiddleware.cs | 56 +++++++++---------- .../ElmStore.cs | 13 ++++- 2 files changed, 38 insertions(+), 31 deletions(-) diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/ElmMiddleware.cs b/src/Microsoft.AspNet.Diagnostics.Elm/ElmMiddleware.cs index 157ac09b..c7c079e2 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/ElmMiddleware.cs +++ b/src/Microsoft.AspNet.Diagnostics.Elm/ElmMiddleware.cs @@ -59,63 +59,61 @@ public async Task Invoke(HttpContext context) } // parse params - var logs = (IEnumerable)null; - if (context.Request.Query.ContainsKey("level")) + var logs = _store.GetLogs(); + var options = new ElmOptions() { - var minLevel = (TraceType)int.Parse(context.Request.Query.GetValues("level")[0]); - logs = _store.GetLogs(minLevel); - _options.MinLevel = minLevel; - } - else + Path = _options.Path, + MinLevel = TraceType.Verbose, + NamePrefix = "" + }; + if (context.Request.Query.ContainsKey("level")) { - logs = _store.GetLogs(); - _options.MinLevel = TraceType.Verbose; + var minLevel = options.MinLevel; + if (Enum.TryParse(context.Request.Query.GetValues("level")[0], out minLevel)) + { + logs = _store.GetLogs(minLevel); + options.MinLevel = minLevel; + } } if (context.Request.Query.ContainsKey("name")) { var namePrefix = context.Request.Query.GetValues("name")[0]; logs = logs.Where(l => l.Name.StartsWith(namePrefix)); - _options.NamePrefix = namePrefix; + options.NamePrefix = namePrefix; } // main log page if (context.Request.Path == _options.Path) { - var model = new LogPageModel() { // sort so most recent logs are first Logs = logs.OrderBy(l => l.Time).Reverse(), LogTree = ElmStore.Activities, - Options = _options + Options = options }; var logPage = new LogPage(model); - - await logPage.ExecuteAsync(context); } // request details page else { - try + var parts = context.Request.Path.Value.Split('/'); + var id = Guid.Empty; + if (!Guid.TryParse(parts[parts.Length - 1], out id)) { - var parts = context.Request.Path.Value.Split('/'); - var id = Guid.Parse(parts[parts.Length - 1]); - var requestLogs = logs.Where(l => l.ActivityContext.HttpInfo != null ? l.ActivityContext.HttpInfo.RequestID == id : false); - var model = new RequestPageModel() - { - RequestID = id, - Logs = requestLogs, - Options = _options - }; - var requestPage = new RequestPage(model); - await requestPage.ExecuteAsync(context); + return; } - catch (Exception) + var requestLogs = logs.Where(l => l.ActivityContext.HttpInfo != null ? l.ActivityContext.HttpInfo.RequestID == id : false); + var model = new RequestPageModel() { - // TODO: bad url - } + RequestID = id, + Logs = requestLogs, + Options = options + }; + var requestPage = new RequestPage(model); + await requestPage.ExecuteAsync(context); } } diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/ElmStore.cs b/src/Microsoft.AspNet.Diagnostics.Elm/ElmStore.cs index 99476617..ba080ded 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/ElmStore.cs +++ b/src/Microsoft.AspNet.Diagnostics.Elm/ElmStore.cs @@ -9,7 +9,9 @@ namespace Microsoft.AspNet.Diagnostics.Elm { public class ElmStore : IElmStore { - private readonly List _logs = new List(); + private const int Capacity = 1000; + + private readonly Queue _logs = new Queue(); public static IDictionary Activities { get; set; } = new Dictionary(); @@ -25,7 +27,14 @@ public IEnumerable GetLogs(TraceType minLevel) public void Add(LogInfo info) { - _logs.Add(info); + lock(_logs) + { + _logs.Enqueue(info); + while (_logs.Count > Capacity) + { + _logs.Dequeue(); + } + } } } } \ No newline at end of file From 5cb468e6966ffeda78cb4edfe2a83a4290481901 Mon Sep 17 00:00:00 2001 From: SonjaKhan Date: Fri, 31 Oct 2014 11:06:42 -0700 Subject: [PATCH 03/19] updating elm --- samples/ElmSample/Startup.cs | 2 -- samples/ElmSample/project.json | 6 +---- .../ElmLogger.cs | 4 ++-- .../ElmMiddleware.cs | 10 ++++---- .../ElmOptions.cs | 10 -------- .../ElmScope.cs | 8 +++---- .../LogInfo.cs | 2 +- .../ScopeNode.cs | 4 ++-- .../ViewOptions.cs | 23 +++++++++++++++++++ .../Views/LogPage.cs | 10 ++++---- .../Views/LogPage.cshtml | 2 +- .../Views/LogPageModel.cs | 5 +++- .../Views/RequestPageModel.cs | 2 +- .../project.json | 4 +--- 14 files changed, 51 insertions(+), 41 deletions(-) create mode 100644 src/Microsoft.AspNet.Diagnostics.Elm/ViewOptions.cs diff --git a/samples/ElmSample/Startup.cs b/samples/ElmSample/Startup.cs index abb5f828..6a054e04 100644 --- a/samples/ElmSample/Startup.cs +++ b/samples/ElmSample/Startup.cs @@ -21,9 +21,7 @@ public void ConfigureServices(IServiceCollection services) public void Configure(IApplicationBuilder app, ILoggerFactory factory) { app.UseElm(); -#pragma warning disable CS1998 app.Run(async context => -#pragma warning restore CS1998 { await context.Response.WriteAsync("Hello world"); throw new InvalidOperationException(); diff --git a/samples/ElmSample/project.json b/samples/ElmSample/project.json index 217cde50..ade7bae6 100644 --- a/samples/ElmSample/project.json +++ b/samples/ElmSample/project.json @@ -10,12 +10,8 @@ "**.vspscc" ], "dependencies": { - "Microsoft.AspNet.Diagnostics": "1.0.0-*", "Microsoft.AspNet.Diagnostics.Elm": "1.0.0-*", - "Microsoft.AspNet.Http": "1.0.0-*", - "Microsoft.AspNet.PipelineCore": "1.0.0-*", - "Microsoft.AspNet.Server.IIS": "1.0.0-*", - "Microsoft.Framework.Logging.Console": "1.0.0-*" + "Microsoft.AspNet.Server.IIS": "1.0.0-*" }, "frameworks" : { "aspnet50" : { }, diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/ElmLogger.cs b/src/Microsoft.AspNet.Diagnostics.Elm/ElmLogger.cs index 086df896..43e90b43 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/ElmLogger.cs +++ b/src/Microsoft.AspNet.Diagnostics.Elm/ElmLogger.cs @@ -31,9 +31,9 @@ public void Write(TraceType traceType, int eventId, object state, Exception exce Severity = traceType, Exception = exception, State = state, - Time = DateTime.Now + Time = DateTimeOffset.UtcNow }; - ElmScope.Current.Node.Messages.Add(info); + ElmScope.Current?.Node?.Messages?.Add(info); _store.Add(info); } diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/ElmMiddleware.cs b/src/Microsoft.AspNet.Diagnostics.Elm/ElmMiddleware.cs index c7c079e2..ca714db6 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/ElmMiddleware.cs +++ b/src/Microsoft.AspNet.Diagnostics.Elm/ElmMiddleware.cs @@ -60,9 +60,8 @@ public async Task Invoke(HttpContext context) // parse params var logs = _store.GetLogs(); - var options = new ElmOptions() + var options = new ViewOptions() { - Path = _options.Path, MinLevel = TraceType.Verbose, NamePrefix = "" }; @@ -90,7 +89,8 @@ public async Task Invoke(HttpContext context) // sort so most recent logs are first Logs = logs.OrderBy(l => l.Time).Reverse(), LogTree = ElmStore.Activities, - Options = options + Options = options, + Path = _options.Path }; var logPage = new LogPage(model); @@ -103,9 +103,11 @@ public async Task Invoke(HttpContext context) var id = Guid.Empty; if (!Guid.TryParse(parts[parts.Length - 1], out id)) { + context.Response.StatusCode = 400; + await context.Response.WriteAsync("Invalid Request Id"); return; } - var requestLogs = logs.Where(l => l.ActivityContext.HttpInfo != null ? l.ActivityContext.HttpInfo.RequestID == id : false); + var requestLogs = logs.Where(l => l.ActivityContext?.HttpInfo?.RequestID == id); var model = new RequestPageModel() { RequestID = id, diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/ElmOptions.cs b/src/Microsoft.AspNet.Diagnostics.Elm/ElmOptions.cs index 1b0cef90..3cfbb453 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/ElmOptions.cs +++ b/src/Microsoft.AspNet.Diagnostics.Elm/ElmOptions.cs @@ -20,15 +20,5 @@ public ElmOptions() /// Specifies the path to view the logs /// public PathString Path { get; set; } - - /// - /// The minimum severity level shown - /// - public TraceType MinLevel { get; set; } - - /// - /// prefix filter for the loggers shown - /// - public string NamePrefix { get; set; } } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/ElmScope.cs b/src/Microsoft.AspNet.Diagnostics.Elm/ElmScope.cs index 1411725c..4b952dac 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/ElmScope.cs +++ b/src/Microsoft.AspNet.Diagnostics.Elm/ElmScope.cs @@ -67,7 +67,7 @@ public static IDisposable Push(ElmScope scope) Current.Node = new ScopeNode() { - StartTime = DateTime.Now, + StartTime = DateTimeOffset.UtcNow, State = Current._state, Name = Current._name }; @@ -78,15 +78,15 @@ public static IDisposable Push(ElmScope scope) } else { - lock(ElmStore.Activities) + lock (ElmStore.Activities) { ElmStore.Activities.Add(Current.Context, Current.Node); } } - + return new DisposableAction(() => { - Current.Node.EndTime = DateTime.Now; + Current.Node.EndTime = DateTimeOffset.UtcNow; Current = Current.Parent; }); } diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/LogInfo.cs b/src/Microsoft.AspNet.Diagnostics.Elm/LogInfo.cs index 447ba4f7..4b59964f 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/LogInfo.cs +++ b/src/Microsoft.AspNet.Diagnostics.Elm/LogInfo.cs @@ -21,7 +21,7 @@ public class LogInfo public int EventID { get; set; } - public DateTime Time { get; set; } + public DateTimeOffset Time { get; set; } public IList Scopes { get; set; } } diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/ScopeNode.cs b/src/Microsoft.AspNet.Diagnostics.Elm/ScopeNode.cs index dabd3705..21f13bab 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/ScopeNode.cs +++ b/src/Microsoft.AspNet.Diagnostics.Elm/ScopeNode.cs @@ -8,8 +8,8 @@ public class ScopeNode public ScopeNode Parent { get; set; } public List Children { get; set; } = new List(); public List Messages { get; set; } = new List(); - public DateTime StartTime { get; set; } - public DateTime EndTime { get; set; } + public DateTimeOffset StartTime { get; set; } + public DateTimeOffset EndTime { get; set; } public object State { get; set; } public string Name { get; set; } } diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/ViewOptions.cs b/src/Microsoft.AspNet.Diagnostics.Elm/ViewOptions.cs new file mode 100644 index 00000000..53b21a3e --- /dev/null +++ b/src/Microsoft.AspNet.Diagnostics.Elm/ViewOptions.cs @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.Framework.Logging; + +namespace Microsoft.AspNet.Diagnostics.Elm +{ + /// + /// Options for ElmMiddleware + /// + public class ViewOptions + { + /// + /// The minimum severity level shown + /// + public TraceType MinLevel { get; set; } + + /// + /// prefix filter for the loggers shown + /// + public string NamePrefix { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.cs b/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.cs index 66d3bc85..e0597005 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.cs +++ b/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.cs @@ -525,16 +525,16 @@ public override async Task ExecuteAsync() if (activity.Key.HttpInfo != null) { - var requestPath = Model.Options.Path.Value + "/" + activity.Key.HttpInfo.RequestID; + var requestPath = Model.Path.Value + "/" + activity.Key.HttpInfo.RequestID; #line default #line hidden WriteLiteral(" (requestPath, 4197), false)); - WriteAttribute("title", Tuple.Create(" title=\"", 4210), Tuple.Create("\"", 4245), - Tuple.Create(Tuple.Create("", 4218), Tuple.Create(activity.Key.HttpInfo.Path, 4218), false)); + WriteAttribute("href", Tuple.Create(" href=\"", 4182), Tuple.Create("\"", 4201), + Tuple.Create(Tuple.Create("", 4189), Tuple.Create(requestPath, 4189), false)); + WriteAttribute("title", Tuple.Create(" title=\"", 4202), Tuple.Create("\"", 4237), + Tuple.Create(Tuple.Create("", 4210), Tuple.Create(activity.Key.HttpInfo.Path, 4210), false)); WriteLiteral(">"); #line 144 "LogPage.cshtml" Write(activity.Key.HttpInfo.Path); diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.cshtml b/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.cshtml index af4a07bd..53513ddd 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.cshtml +++ b/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.cshtml @@ -140,7 +140,7 @@ @{ if (activity.Key.HttpInfo != null) { - var requestPath = Model.Options.Path.Value + "/" + activity.Key.HttpInfo.RequestID; + var requestPath = Model.Path.Value + "/" + activity.Key.HttpInfo.RequestID; @activity.Key.HttpInfo.Path @activity.Key.HttpInfo.Host @activity.Key.HttpInfo.StatusCode diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPageModel.cs b/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPageModel.cs index 6415c0fe..33b58a3c 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPageModel.cs +++ b/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPageModel.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Microsoft.AspNet.Http; namespace Microsoft.AspNet.Diagnostics.Elm.Views { @@ -8,6 +9,8 @@ public class LogPageModel public IDictionary LogTree { get; set; } - public ElmOptions Options { get; set; } + public ViewOptions Options { get; set; } + + public PathString Path { get; set; } } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPageModel.cs b/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPageModel.cs index 0daaa17b..380dc945 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPageModel.cs +++ b/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPageModel.cs @@ -9,6 +9,6 @@ public class RequestPageModel public IEnumerable Logs { get; set; } - public ElmOptions Options { get; set; } + public ViewOptions Options { get; set; } } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/project.json b/src/Microsoft.AspNet.Diagnostics.Elm/project.json index 39efedf6..5014719b 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/project.json +++ b/src/Microsoft.AspNet.Diagnostics.Elm/project.json @@ -13,7 +13,6 @@ "aspnet50": { }, "aspnetcore50": { "dependencies": { - "K.CommonFx": "1.0.0-*", "System.Collections.Concurrent": "4.0.0-beta-*", "System.Collections": "4.0.10-beta-*", "System.Diagnostics.TraceSource": "4.0.0-beta-*", @@ -23,8 +22,7 @@ "System.Runtime.InteropServices": "4.0.20-beta-*", "System.Linq": "4.0.0-beta-*", "System.Threading": "4.0.0-beta-*", - "System.Threading.ExecutionContext": "4.0.0-beta-*", - "Microsoft.Framework.Logging.Interfaces": { "version": "1.0.0-*", "type": "build" } + "System.Threading.ExecutionContext": "4.0.0-beta-*" } } } From 08d6dbf539ffc7b4f7068a5dc424cb1c1c41fa5a Mon Sep 17 00:00:00 2001 From: SonjaKhan Date: Fri, 31 Oct 2014 15:10:57 -0700 Subject: [PATCH 04/19] more updates --- samples/ElmSample/Startup.cs | 7 + .../ActivityContext.cs | 3 + .../ElmLogger.cs | 19 +- .../ElmMiddleware.cs | 2 +- .../ElmOptions.cs | 7 +- .../ElmScope.cs | 9 +- .../ElmStore.cs | 12 +- .../Views/LogPage.cs | 119 +++--- .../Views/LogPage.cshtml | 50 +-- .../Views/LogPage.css | 32 -- .../Views/LogPageModel.cs | 2 +- .../Views/RequestPage.cs | 376 ++++++++---------- .../Views/RequestPage.cshtml | 171 ++++---- .../Views/RequestPage.css | 32 -- .../Views/RequestPageModel.cs | 2 +- .../Views/Shared.css | 34 ++ 16 files changed, 400 insertions(+), 477 deletions(-) create mode 100644 src/Microsoft.AspNet.Diagnostics.Elm/Views/Shared.css diff --git a/samples/ElmSample/Startup.cs b/samples/ElmSample/Startup.cs index 6a054e04..cab0e84b 100644 --- a/samples/ElmSample/Startup.cs +++ b/samples/ElmSample/Startup.cs @@ -21,9 +21,16 @@ public void ConfigureServices(IServiceCollection services) public void Configure(IApplicationBuilder app, ILoggerFactory factory) { app.UseElm(); + var logger = factory.Create(); + app.Run(async context => { await context.Response.WriteAsync("Hello world"); + using (logger.BeginScope("startup")) + { + logger.WriteInformation("Hello world!"); + logger.WriteError("Mort"); + } throw new InvalidOperationException(); }); } diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/ActivityContext.cs b/src/Microsoft.AspNet.Diagnostics.Elm/ActivityContext.cs index 105c04ff..fa5e65bd 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/ActivityContext.cs +++ b/src/Microsoft.AspNet.Diagnostics.Elm/ActivityContext.cs @@ -6,5 +6,8 @@ public class ActivityContext { public Guid Id { get; set; } public HttpInfo HttpInfo { get; set; } + public ScopeNode Root { get; set; } + public DateTimeOffset Time { get; set; } + public int Size { get; set; } } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/ElmLogger.cs b/src/Microsoft.AspNet.Diagnostics.Elm/ElmLogger.cs index 43e90b43..a3d0e530 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/ElmLogger.cs +++ b/src/Microsoft.AspNet.Diagnostics.Elm/ElmLogger.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Collections.Generic; using Microsoft.Framework.Logging; namespace Microsoft.AspNet.Diagnostics.Elm @@ -33,7 +32,11 @@ public void Write(TraceType traceType, int eventId, object state, Exception exce State = state, Time = DateTimeOffset.UtcNow }; - ElmScope.Current?.Node?.Messages?.Add(info); + if (ElmScope.Current != null) + { + ElmScope.Current.Context.Size++; + ElmScope.Current.Node.Messages.Add(info); + } _store.Add(info); } @@ -45,14 +48,7 @@ public bool IsEnabled(TraceType traceType) public IDisposable BeginScope(object state) { var scope = new ElmScope(_name, state); - if (ElmScope.Current != null) - { - scope.Context = ElmScope.Current.Context; - } - else - { - scope.Context = GetNewActivityContext(); - } + scope.Context = ElmScope.Current?.Context ?? GetNewActivityContext(); return ElmScope.Push(scope); } @@ -60,7 +56,8 @@ private ActivityContext GetNewActivityContext() { return new ActivityContext() { - Id = Guid.NewGuid() + Id = Guid.NewGuid(), + Time = DateTimeOffset.UtcNow }; } } diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/ElmMiddleware.cs b/src/Microsoft.AspNet.Diagnostics.Elm/ElmMiddleware.cs index ca714db6..e993fade 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/ElmMiddleware.cs +++ b/src/Microsoft.AspNet.Diagnostics.Elm/ElmMiddleware.cs @@ -123,7 +123,7 @@ public async Task Invoke(HttpContext context) /// Takes the info from the given HttpContext and copies it to an HttpInfo object /// /// The HttpInfo for the current elm context - private HttpInfo GetHttpInfo(HttpContext context, Guid requestId) + private static HttpInfo GetHttpInfo(HttpContext context, Guid requestId) { return new HttpInfo() { diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/ElmOptions.cs b/src/Microsoft.AspNet.Diagnostics.Elm/ElmOptions.cs index 3cfbb453..49acfd2e 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/ElmOptions.cs +++ b/src/Microsoft.AspNet.Diagnostics.Elm/ElmOptions.cs @@ -11,14 +11,9 @@ namespace Microsoft.AspNet.Diagnostics.Elm /// public class ElmOptions { - public ElmOptions() - { - Path = new PathString("/Elm"); - } - /// /// Specifies the path to view the logs /// - public PathString Path { get; set; } + public PathString Path { get; set; } = new PathString("/Elm"); } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/ElmScope.cs b/src/Microsoft.AspNet.Diagnostics.Elm/ElmScope.cs index 4b952dac..fbc3c225 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/ElmScope.cs +++ b/src/Microsoft.AspNet.Diagnostics.Elm/ElmScope.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; #if ASPNET50 using System.Runtime.Remoting; using System.Runtime.Remoting.Messaging; @@ -71,6 +72,7 @@ public static IDisposable Push(ElmScope scope) State = Current._state, Name = Current._name }; + if (Current.Parent != null) { Current.Node.Parent = Current.Parent.Node; @@ -80,7 +82,12 @@ public static IDisposable Push(ElmScope scope) { lock (ElmStore.Activities) { - ElmStore.Activities.Add(Current.Context, Current.Node); + Current.Context.Root = Current.Node; + ElmStore.Activities.AddLast(Current.Context); + while (ElmStore.NumLogs() > ElmStore.Capacity) + { + ElmStore.Activities.RemoveFirst(); + } } } diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/ElmStore.cs b/src/Microsoft.AspNet.Diagnostics.Elm/ElmStore.cs index ba080ded..579301b4 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/ElmStore.cs +++ b/src/Microsoft.AspNet.Diagnostics.Elm/ElmStore.cs @@ -9,11 +9,11 @@ namespace Microsoft.AspNet.Diagnostics.Elm { public class ElmStore : IElmStore { - private const int Capacity = 1000; + public const int Capacity = 200; private readonly Queue _logs = new Queue(); - public static IDictionary Activities { get; set; } = new Dictionary(); + public static LinkedList Activities { get; set; } = new LinkedList(); public IEnumerable GetLogs() { @@ -27,7 +27,7 @@ public IEnumerable GetLogs(TraceType minLevel) public void Add(LogInfo info) { - lock(_logs) + lock (_logs) { _logs.Enqueue(info); while (_logs.Count > Capacity) @@ -36,5 +36,11 @@ public void Add(LogInfo info) } } } + + // returns the number of log messages stored in Activities + public static int NumLogs() + { + return Activities.Sum(a => a.Size); + } } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.cs b/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.cs index e0597005..96205354 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.cs +++ b/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.cs @@ -84,17 +84,17 @@ public HelperResult #line default #line hidden WriteLiteralTo(__razor_helper_writer, "\r\n (log.Severity, 868), false)); + WriteAttributeTo(__razor_helper_writer, "class", Tuple.Create(" class=\"", 860), Tuple.Create("\"", 911), + Tuple.Create(Tuple.Create("", 868), Tuple.Create(log.Severity.ToString().ToLowerInvariant(), 868), false)); WriteLiteralTo(__razor_helper_writer, ">"); #line 28 "LogPage.cshtml" - WriteTo(__razor_helper_writer, log.Severity); + WriteTo(__razor_helper_writer, log.Severity); #line default #line hidden WriteLiteralTo(__razor_helper_writer, "\r\n (log.State, 926), false)); + WriteAttributeTo(__razor_helper_writer, "title", Tuple.Create(" title=\"", 948), Tuple.Create("\"", 966), + Tuple.Create(Tuple.Create("", 956), Tuple.Create(log.State, 956), false)); WriteLiteralTo(__razor_helper_writer, ">\r\n"); #line 30 "LogPage.cshtml" @@ -123,8 +123,8 @@ public HelperResult #line default #line hidden WriteLiteralTo(__razor_helper_writer, "\r\n \r\n (log.Exception, 1145), false)); + WriteAttributeTo(__razor_helper_writer, "title", Tuple.Create(" title=\"", 1167), Tuple.Create("\"", 1189), + Tuple.Create(Tuple.Create("", 1175), Tuple.Create(log.Exception, 1175), false)); WriteLiteralTo(__razor_helper_writer, ">"); #line 36 "LogPage.cshtml" WriteTo(__razor_helper_writer, log.Exception); @@ -175,11 +175,11 @@ public HelperResult #line hidden #line 50 "LogPage.cshtml" ; - var m = 0; - var c = 0; - while (m < node.Messages.Count && c < node.Children.Count) + var messageIndex = 0; + var childIndex = 0; + while (messageIndex < node.Messages.Count && childIndex < node.Children.Count) { - if (node.Messages[m].Time < node.Children[c].StartTime) + if (node.Messages[messageIndex].Time < node.Children[childIndex].StartTime) { @@ -187,13 +187,13 @@ public HelperResult #line hidden #line 57 "LogPage.cshtml" -WriteTo(__razor_helper_writer, LogRow(node.Messages[m], level)); +WriteTo(__razor_helper_writer, LogRow(node.Messages[messageIndex], level)); #line default #line hidden #line 57 "LogPage.cshtml" - - m++; + + messageIndex++; } else { @@ -203,18 +203,18 @@ public HelperResult #line hidden #line 62 "LogPage.cshtml" -WriteTo(__razor_helper_writer, Traverse(node.Children[c], level + 1)); +WriteTo(__razor_helper_writer, Traverse(node.Children[childIndex], level + 1)); #line default #line hidden #line 62 "LogPage.cshtml" - - c++; + + childIndex++; } } - if (m < node.Messages.Count) + if (messageIndex < node.Messages.Count) { - for (var i = m; i < node.Messages.Count; i++) + for (var i = messageIndex; i < node.Messages.Count; i++) { @@ -232,7 +232,7 @@ public HelperResult } else { - for (var i = c; i < node.Children.Count; i++) + for (var i = childIndex; i < node.Children.Count; i++) { @@ -307,12 +307,9 @@ public override async Task ExecuteAsync() ELM - @@ -436,19 +437,19 @@ public override async Task ExecuteAsync() #line 104 "LogPage.cshtml" foreach (var severity in Enum.GetValues(typeof(TraceType))) { - var s = (int)severity; - if ((int)Model.Options.MinLevel == s) + var severityInt = (int)severity; + if ((int)Model.Options.MinLevel == severityInt) { #line default #line hidden WriteLiteral(" (s, 3007), false)); + WriteAttribute("value", Tuple.Create(" value=\"", 3128), Tuple.Create("\"", 3148), + Tuple.Create(Tuple.Create("", 3136), Tuple.Create(severityInt, 3136), false)); WriteLiteral(" selected=\"selected\">"); #line 109 "LogPage.cshtml" - Write(severity); + Write(severity); #line default #line hidden @@ -462,11 +463,11 @@ public override async Task ExecuteAsync() #line hidden WriteLiteral(" (s, 3146), false)); + WriteAttribute("value", Tuple.Create(" value=\"", 3277), Tuple.Create("\"", 3297), + Tuple.Create(Tuple.Create("", 3285), Tuple.Create(severityInt, 3285), false)); WriteLiteral(">"); #line 113 "LogPage.cshtml" - Write(severity); + Write(severity); #line default #line hidden @@ -479,8 +480,8 @@ public override async Task ExecuteAsync() #line hidden WriteLiteral(" \r\n (Model.Options.NamePrefix, 3269), false)); + WriteAttribute("value", Tuple.Create(" value=\"", 3410), Tuple.Create("\"", 3443), + Tuple.Create(Tuple.Create("", 3418), Tuple.Create(Model.Options.NamePrefix, 3418), false)); WriteLiteral(@" /> @@ -523,33 +524,33 @@ public override async Task ExecuteAsync() #line 140 "LogPage.cshtml" - if (activity.Key.HttpInfo != null) + if (activity.HttpInfo != null) { - var requestPath = Model.Path.Value + "/" + activity.Key.HttpInfo.RequestID; + var requestPath = Model.Path.Value + "/" + activity.HttpInfo.RequestID; #line default #line hidden WriteLiteral(" (requestPath, 4189), false)); - WriteAttribute("title", Tuple.Create(" title=\"", 4202), Tuple.Create("\"", 4237), - Tuple.Create(Tuple.Create("", 4210), Tuple.Create(activity.Key.HttpInfo.Path, 4210), false)); + WriteAttribute("href", Tuple.Create(" href=\"", 4323), Tuple.Create("\"", 4342), + Tuple.Create(Tuple.Create("", 4330), Tuple.Create(requestPath, 4330), false)); + WriteAttribute("title", Tuple.Create(" title=\"", 4343), Tuple.Create("\"", 4374), + Tuple.Create(Tuple.Create("", 4351), Tuple.Create(activity.HttpInfo.Path, 4351), false)); WriteLiteral(">"); #line 144 "LogPage.cshtml" - Write(activity.Key.HttpInfo.Path); + Write(activity.HttpInfo.Path); #line default #line hidden WriteLiteral("\r\n "); #line 145 "LogPage.cshtml" - Write(activity.Key.HttpInfo.Host); + Write(activity.HttpInfo.Host); #line default #line hidden WriteLiteral("\r\n "); #line 146 "LogPage.cshtml" - Write(activity.Key.HttpInfo.StatusCode); + Write(activity.HttpInfo.StatusCode); #line default #line hidden @@ -562,7 +563,7 @@ public override async Task ExecuteAsync() #line default #line hidden - WriteLiteral(" BOO\r\n"); + WriteLiteral(" \r\n"); #line 151 "LogPage.cshtml" } @@ -580,13 +581,13 @@ public override async Task ExecuteAsync() Name Severity State - Error + Error "); #line 166 "LogPage.cshtml" - Write(Traverse(activity.Value, 0)); + Write(Traverse(activity.Root, 0)); #line default #line hidden diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.cshtml b/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.cshtml index 53513ddd..dcc2b2e4 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.cshtml +++ b/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.cshtml @@ -25,7 +25,7 @@ @string.Format("{0:MM/dd/yy}", log.Time) @string.Format("{0:H:mm:ss}", log.Time) @log.Name - @log.Severity + @log.Severity @for (var i = 0; i < level; i++) { @@ -48,31 +48,31 @@ Severity = TraceType.Verbose, State = "Beginning " + node.State, }, level); - var m = 0; - var c = 0; - while (m < node.Messages.Count && c < node.Children.Count) + var messageIndex = 0; + var childIndex = 0; + while (messageIndex < node.Messages.Count && childIndex < node.Children.Count) { - if (node.Messages[m].Time < node.Children[c].StartTime) + if (node.Messages[messageIndex].Time < node.Children[childIndex].StartTime) { - @LogRow(node.Messages[m], level) - m++; + @LogRow(node.Messages[messageIndex], level) + messageIndex++; } else { - @Traverse(node.Children[c], level + 1) - c++; + @Traverse(node.Children[childIndex], level + 1) + childIndex++; } } - if (m < node.Messages.Count) + if (messageIndex < node.Messages.Count) { - for (var i = m; i < node.Messages.Count; i++) + for (var i = messageIndex; i < node.Messages.Count; i++) { @LogRow(node.Messages[i], level) } } else { - for (var i = c; i < node.Children.Count; i++) + for (var i = childIndex; i < node.Children.Count; i++) { @Traverse(node.Children[i], level + 1) } @@ -92,9 +92,9 @@ ELM - @@ -103,14 +103,14 @@ @@ -138,16 +138,16 @@ @{ - if (activity.Key.HttpInfo != null) + if (activity.HttpInfo != null) { - var requestPath = Model.Path.Value + "/" + activity.Key.HttpInfo.RequestID; - @activity.Key.HttpInfo.Path - @activity.Key.HttpInfo.Host - @activity.Key.HttpInfo.StatusCode + var requestPath = Model.Path.Value + "/" + activity.HttpInfo.RequestID; + @activity.HttpInfo.Path + @activity.HttpInfo.Host + @activity.HttpInfo.StatusCode } else { - BOO + } } @@ -159,11 +159,11 @@ Name Severity State - Error + Error - @Traverse(activity.Value, 0) + @Traverse(activity.Root, 0) diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.css b/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.css index 9327b286..0709ccb0 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.css +++ b/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.css @@ -1,7 +1,5 @@ body { - font-family: 'Segoe UI', Tahoma, Arial, Helvetica, sans-serif; font-size: .813em; - line-height: 1.4em; white-space: nowrap; margin: 10px; } @@ -23,11 +21,6 @@ table { border-collapse: collapse; } -td { - text-overflow: ellipsis; - overflow: hidden; -} - td, th { padding: 4px; } @@ -41,10 +34,6 @@ tr { height: 23px; } -tr:nth-child(2n) { - background-color: #F6F6F6; -} - #requestHeader { border-bottom: solid 1px gray; border-top: solid 1px gray; @@ -87,25 +76,4 @@ tr:nth-child(2n) { .tab { margin-left: 30px; -} - -.Critical { - background-color: red; - color: white; -} - -.Error { - color: red; -} - -.Information { - color: blue; -} - -.Verbose { - color: black; -} - -.Warning { - color: orange; } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPageModel.cs b/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPageModel.cs index 33b58a3c..201fb630 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPageModel.cs +++ b/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPageModel.cs @@ -7,7 +7,7 @@ public class LogPageModel { public IEnumerable Logs { get; set; } - public IDictionary LogTree { get; set; } + public IEnumerable LogTree { get; set; } public ViewOptions Options { get; set; } diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.cs b/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.cs index ce0aaa68..653f4a65 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.cs +++ b/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.cs @@ -60,312 +60,246 @@ public RequestPage() public override async Task ExecuteAsync() { WriteLiteral("\r\n"); - WriteLiteral(@" - - - - ELM - \r\n\r\n\r\n

ELM

\r\n"); +#line 29 "RequestPage.cshtml" + -.Error { - color: red; -} +#line default +#line hidden -.Information { - color: blue; -} +#line 29 "RequestPage.cshtml" + + var context = Model.Logs.FirstOrDefault()?.ActivityContext?.HttpInfo; + -.Verbose { - color: black; -} +#line default +#line hidden -.Warning { - color: orange; -} - - - -

ELM

- -

Request Details

- - -"); + WriteLiteral("\r\n"); #line 32 "RequestPage.cshtml" - + #line default #line hidden #line 32 "RequestPage.cshtml" - - var context = Model.Logs.First().ActivityContext.HttpInfo; - + if (context != null) + { #line default #line hidden - WriteLiteral("\r\n \r\n \r\n \r\n \r\n
Path"); -#line 37 "RequestPage.cshtml" - Write(context.Path); + WriteLiteral("

Request Details

\r\n \r\n " + +" \r\n\r\n \r\n " + +" \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n " + +" \r\n \r\n \r\n \r\n " + -" \r\n \r\n \r\n " + +"\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n " + +" \r\n \r\n \r\n \r\n "); -#line 53 "RequestPage.cshtml" - Write(context.Protocol); + WriteLiteral("\r\n \r\n \r\n \r\n " + +" - - - - \r\n \r\n \r" + +"\n \r\n \r\n \r\n \r\n \r\n " + -" \r\n \r\n \r\n \r\n " + +" \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n " + +" \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n " + +" \r\n \r\n \r\n \r\n \r\n"); -#line 97 "RequestPage.cshtml" - + WriteLiteral("\r\n \r\n \r\n \r\n " + +" \r\n
Path"); +#line 40 "RequestPage.cshtml" + Write(context.Path); #line default #line hidden - WriteLiteral("
Host"); -#line 41 "RequestPage.cshtml" - Write(context.Host); + WriteLiteral("
Host"); +#line 44 "RequestPage.cshtml" + Write(context.Host); #line default #line hidden - WriteLiteral("
Content Type"); -#line 45 "RequestPage.cshtml" - Write(context.ContentType); + WriteLiteral("
Content Type"); +#line 48 "RequestPage.cshtml" + Write(context.ContentType); #line default #line hidden - WriteLiteral("
Method" + -""); -#line 49 "RequestPage.cshtml" - Write(context.Method); + WriteLiteral("
Method"); +#line 52 "RequestPage.cshtml" + Write(context.Method); #line default #line hidden - WriteLiteral("
Protocol
Protocol"); +#line 56 "RequestPage.cshtml" + Write(context.Protocol); #line default #line hidden WriteLiteral(@"
Headers - - - - - - - - + + + + \r\n " + -" \r\n \r\n \r\n \r\n
VariableValue
Headers + + + + + + + + "); -#line 66 "RequestPage.cshtml" - +#line 69 "RequestPage.cshtml" + #line default #line hidden -#line 66 "RequestPage.cshtml" - foreach (var header in context.Headers) - { +#line 69 "RequestPage.cshtml" + foreach (var header in context.Headers) + { #line default #line hidden - WriteLiteral(" \r\n \r\n \r\n \r\n \r\n \r\n"); -#line 72 "RequestPage.cshtml" - } + WriteLiteral("\r\n \r\n"); +#line 75 "RequestPage.cshtml" + } #line default #line hidden - WriteLiteral(" \r\n
VariableValue
"); -#line 69 "RequestPage.cshtml" - Write(header.Key); + WriteLiteral("
"); +#line 72 "RequestPage.cshtml" + Write(header.Key); #line default #line hidden - WriteLiteral(""); -#line 70 "RequestPage.cshtml" - Write(string.Join(";", header.Value)); + WriteLiteral(""); +#line 73 "RequestPage.cshtml" + Write(string.Join(";", header.Value)); #line default #line hidden - WriteLiteral("
\r\n
Status Code"); -#line 79 "RequestPage.cshtml" - Write(context.StatusCode); + WriteLiteral("
\r\n <" + +"/td>\r\n
Status Code"); +#line 82 "RequestPage.cshtml" + Write(context.StatusCode); #line default #line hidden - WriteLiteral("
User"); -#line 84 "RequestPage.cshtml" - Write(context.User.Identity.Name); + WriteLiteral("
User"); +#line 87 "RequestPage.cshtml" + Write(context.User.Identity.Name); #line default #line hidden - WriteLiteral("
Scheme" + -""); -#line 88 "RequestPage.cshtml" - Write(context.Scheme); + WriteLiteral("
Scheme"); +#line 91 "RequestPage.cshtml" + Write(context.Scheme); #line default #line hidden - WriteLiteral("
Query"); -#line 92 "RequestPage.cshtml" - Write(context.Query.Value); + WriteLiteral("
Query"); +#line 95 "RequestPage.cshtml" + Write(context.Query.Value); #line default #line hidden - WriteLiteral("
Cookies
Cookies\r\n"); +#line 100 "RequestPage.cshtml" + #line default #line hidden -#line 97 "RequestPage.cshtml" - if (context.Cookies.Any()) - { +#line 100 "RequestPage.cshtml" + if (context.Cookies.Any()) + { #line default #line hidden - WriteLiteral(@" - - - - - - - + WriteLiteral(@"
VariableValue
+ + + + + + + "); -#line 107 "RequestPage.cshtml" - +#line 110 "RequestPage.cshtml" + #line default #line hidden -#line 107 "RequestPage.cshtml" - foreach (var cookie in context.Cookies) - { +#line 110 "RequestPage.cshtml" + foreach (var cookie in context.Cookies) + { #line default #line hidden - WriteLiteral(" \r\n \r\n " + +" \r\n \r\n \r\n \r\n"); -#line 113 "RequestPage.cshtml" - } + WriteLiteral("\r\n \r\n"); +#line 116 "RequestPage.cshtml" + } #line default #line hidden - WriteLiteral(" \r\n
VariableValue
"); -#line 110 "RequestPage.cshtml" - Write(cookie.Key); + WriteLiteral("
"); +#line 113 "RequestPage.cshtml" + Write(cookie.Key); #line default #line hidden - WriteLiteral(""); -#line 111 "RequestPage.cshtml" - Write(string.Join(";", cookie.Value)); + WriteLiteral(""); +#line 114 "RequestPage.cshtml" + Write(string.Join(";", cookie.Value)); #line default #line hidden - WriteLiteral("
\r\n"); -#line 116 "RequestPage.cshtml" - } + WriteLiteral("
\r\n"); +#line 119 "RequestPage.cshtml" + } #line default #line hidden - WriteLiteral("
\r\n\r\n

Logs

\r\n
\r\n \r\n"); +#line 127 "RequestPage.cshtml" #line default #line hidden -#line 124 "RequestPage.cshtml" +#line 127 "RequestPage.cshtml" foreach (var severity in Enum.GetValues(typeof(TraceType))) { - var s = (int)severity; - if ((int)Model.Options.MinLevel == s) + var severityInt = (int)severity; + if ((int)Model.Options.MinLevel == severityInt) { #line default #line hidden WriteLiteral(" (s, 3701), false)); + WriteAttribute("value", Tuple.Create(" value=\"", 4139), Tuple.Create("\"", 4159), + Tuple.Create(Tuple.Create("", 4147), Tuple.Create(severityInt, 4147), false)); WriteLiteral(" selected=\"selected\">"); -#line 129 "RequestPage.cshtml" - Write(severity); +#line 132 "RequestPage.cshtml" + Write(severity); #line default #line hidden WriteLiteral("\r\n"); -#line 130 "RequestPage.cshtml" +#line 133 "RequestPage.cshtml" } else { @@ -374,16 +308,16 @@ public override async Task ExecuteAsync() #line hidden WriteLiteral(" (s, 3840), false)); + WriteAttribute("value", Tuple.Create(" value=\"", 4288), Tuple.Create("\"", 4308), + Tuple.Create(Tuple.Create("", 4296), Tuple.Create(severityInt, 4296), false)); WriteLiteral(">"); -#line 133 "RequestPage.cshtml" - Write(severity); +#line 136 "RequestPage.cshtml" + Write(severity); #line default #line hidden WriteLiteral("\r\n"); -#line 134 "RequestPage.cshtml" +#line 137 "RequestPage.cshtml" } } @@ -391,8 +325,8 @@ public override async Task ExecuteAsync() #line hidden WriteLiteral(" \r\n (Model.Options.NamePrefix, 3963), false)); + WriteAttribute("value", Tuple.Create(" value=\"", 4421), Tuple.Create("\"", 4454), + Tuple.Create(Tuple.Create("", 4429), Tuple.Create(Model.Options.NamePrefix, 4429), false)); WriteLiteral(@" /> @@ -408,13 +342,13 @@ public override async Task ExecuteAsync() "); -#line 151 "RequestPage.cshtml" +#line 154 "RequestPage.cshtml" #line default #line hidden -#line 151 "RequestPage.cshtml" +#line 154 "RequestPage.cshtml" foreach (var log in Model.Logs) { @@ -422,55 +356,55 @@ public override async Task ExecuteAsync() #line hidden WriteLiteral(" \r\n "); -#line 154 "RequestPage.cshtml" +#line 157 "RequestPage.cshtml" Write(string.Format("{0:MM/dd/yy}", log.Time)); #line default #line hidden WriteLiteral("\r\n "); -#line 155 "RequestPage.cshtml" +#line 158 "RequestPage.cshtml" Write(string.Format("{0:H:mm:ss}", log.Time)); #line default #line hidden WriteLiteral("\r\n (log.Severity, 4573), false)); + WriteAttribute("class", Tuple.Create(" class=\"", 5031), Tuple.Create("\"", 5082), + Tuple.Create(Tuple.Create("", 5039), Tuple.Create(log.Severity.ToString().ToLowerInvariant(), 5039), false)); WriteLiteral(">"); -#line 156 "RequestPage.cshtml" - Write(log.Severity); +#line 159 "RequestPage.cshtml" + Write(log.Severity); #line default #line hidden WriteLiteral("\r\n (log.Name, 4635), false)); + WriteAttribute("title", Tuple.Create(" title=\"", 5123), Tuple.Create("\"", 5140), + Tuple.Create(Tuple.Create("", 5131), Tuple.Create(log.Name, 5131), false)); WriteLiteral(">"); -#line 157 "RequestPage.cshtml" +#line 160 "RequestPage.cshtml" Write(log.Name); #line default #line hidden WriteLiteral("\r\n (log.State, 4689), false)); + WriteAttribute("title", Tuple.Create(" title=\"", 5177), Tuple.Create("\"", 5195), + Tuple.Create(Tuple.Create("", 5185), Tuple.Create(log.State, 5185), false)); WriteLiteral(" class=\"logState\" width=\"100px\">"); -#line 158 "RequestPage.cshtml" +#line 161 "RequestPage.cshtml" Write(log.State); #line default #line hidden WriteLiteral("\r\n (log.Exception, 4776), false)); + WriteAttribute("title", Tuple.Create(" title=\"", 5264), Tuple.Create("\"", 5286), + Tuple.Create(Tuple.Create("", 5272), Tuple.Create(log.Exception, 5272), false)); WriteLiteral(">"); -#line 159 "RequestPage.cshtml" +#line 162 "RequestPage.cshtml" Write(log.Exception); #line default #line hidden WriteLiteral("\r\n \r\n"); -#line 161 "RequestPage.cshtml" +#line 164 "RequestPage.cshtml" } #line default diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.cshtml b/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.cshtml index bc0824aa..8a55e90b 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.cshtml +++ b/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.cshtml @@ -20,83 +20,45 @@ ELM

ELM

+ @{ + var context = Model.Logs.FirstOrDefault()?.ActivityContext?.HttpInfo; + } + @if (context != null) + { +

Request Details

+ + -

Request Details

-
- - @{ - var context = Model.Logs.First().ActivityContext.HttpInfo; - } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @* TODO: show more information about the user*@ - - - - - - - - - - - - - + + + + + + + + @* TODO: show more information about the user*@ + + + + + + + + + + + + + + +
Path@context.Path
Host@context.Host
Content Type@context.ContentType
Method@context.Method
Protocol@context.Protocol
Headers - - - - - - - - - @foreach (var header in context.Headers) - { - - - - - } - -
VariableValue
@header.Key@string.Join(";", header.Value)
-
Status Code@context.StatusCode
User@context.User.Identity.Name
Scheme@context.Scheme
Query@context.Query.Value
Cookies - @if (context.Cookies.Any()) - { - + + + + + + + + + + + + + + + + + + + + + + + - -
Path@context.Path
Host@context.Host
Content Type@context.ContentType
Method@context.Method
Protocol@context.Protocol
Headers + @@ -104,33 +66,74 @@ - @foreach (var cookie in context.Cookies) + @foreach (var header in context.Headers) { - - + + }
Variable
@cookie.Key@string.Join(";", cookie.Value)@header.Key@string.Join(";", header.Value)
- } -
- +
Status Code@context.StatusCode
User@context.User.Identity.Name
Scheme@context.Scheme
Query@context.Query.Value
Cookies + @if (context.Cookies.Any()) + { + + + + + + + + + @foreach (var cookie in context.Cookies) + { + + + + + } + +
VariableValue
@cookie.Key@string.Join(";", cookie.Value)
+ } +
+ }

Logs

@@ -153,7 +156,7 @@ @string.Format("{0:MM/dd/yy}", log.Time) @string.Format("{0:H:mm:ss}", log.Time) - @log.Severity + @log.Severity @log.Name @log.State @log.Exception diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.css b/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.css index 7f5abbea..31c5da4a 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.css +++ b/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.css @@ -1,7 +1,5 @@ body { - font-family: 'Segoe UI', Tahoma, Arial, Helvtica, sans-serif; font-size: 0.9em; - line-height: 1.4em; width: 90%; margin: 0px auto; } @@ -18,11 +16,6 @@ table { white-space: pre-wrap; } -td { - text-overflow: ellipsis; - overflow: hidden; -} - th { font-family: Arial; } @@ -31,10 +24,6 @@ td, th { padding: 8px; } -tr:nth-child(2n) { - background-color: #F6F6F6; -} - #headerTable { border: none; height: 100%; @@ -55,25 +44,4 @@ tr:nth-child(2n) { #logs>thead>tr>th { border: 1px solid black; -} - -.Critical { - background-color: red; - color: white; -} - -.Error { - color: red; -} - -.Information { - color: blue; -} - -.Verbose { - color: black; -} - -.Warning { - color: orange; } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPageModel.cs b/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPageModel.cs index 380dc945..287fd180 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPageModel.cs +++ b/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPageModel.cs @@ -6,7 +6,7 @@ namespace Microsoft.AspNet.Diagnostics.Elm.Views public class RequestPageModel { public Guid RequestID { get; set; } - + public IEnumerable Logs { get; set; } public ViewOptions Options { get; set; } diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/Views/Shared.css b/src/Microsoft.AspNet.Diagnostics.Elm/Views/Shared.css new file mode 100644 index 00000000..04164bd3 --- /dev/null +++ b/src/Microsoft.AspNet.Diagnostics.Elm/Views/Shared.css @@ -0,0 +1,34 @@ +body { + font-family: 'Segoe UI', Tahoma, Arial, Helvtica, sans-serif; + line-height: 1.4em; +} + +td { + text-overflow: ellipsis; + overflow: hidden; +} + +tr:nth-child(2n) { + background-color: #F6F6F6; +} + +.critical { + background-color: red; + color: white; +} + +.error { + color: red; +} + +.information { + color: blue; +} + +.verbose { + color: black; +} + +.warning { + color: orange; +} \ No newline at end of file From 0279c78f5e4115dd2f33cefcc371df3cb03215f2 Mon Sep 17 00:00:00 2001 From: SonjaKhan Date: Mon, 3 Nov 2014 09:34:04 -0800 Subject: [PATCH 05/19] making activities private --- .../ElmLogger.cs | 9 ++++++-- .../ElmMiddleware.cs | 2 +- .../ElmScope.cs | 11 ++------- .../ElmStore.cs | 23 ++++++++++++++++--- .../LogInfo.cs | 3 --- 5 files changed, 30 insertions(+), 18 deletions(-) diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/ElmLogger.cs b/src/Microsoft.AspNet.Diagnostics.Elm/ElmLogger.cs index a3d0e530..b0fca5f4 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/ElmLogger.cs +++ b/src/Microsoft.AspNet.Diagnostics.Elm/ElmLogger.cs @@ -24,7 +24,7 @@ public void Write(TraceType traceType, int eventId, object state, Exception exce { LogInfo info = new LogInfo() { - ActivityContext = ElmScope.Current == null ? GetNewActivityContext() : ElmScope.Current.Context, + ActivityContext = GetCurrentActivityContext(), Name = _name, EventID = eventId, Severity = traceType, @@ -34,7 +34,7 @@ public void Write(TraceType traceType, int eventId, object state, Exception exce }; if (ElmScope.Current != null) { - ElmScope.Current.Context.Size++; + GetCurrentActivityContext().Size++; ElmScope.Current.Node.Messages.Add(info); } _store.Add(info); @@ -60,5 +60,10 @@ private ActivityContext GetNewActivityContext() Time = DateTimeOffset.UtcNow }; } + + private ActivityContext GetCurrentActivityContext() + { + return ElmScope.Current?.Context ?? GetNewActivityContext(); + } } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/ElmMiddleware.cs b/src/Microsoft.AspNet.Diagnostics.Elm/ElmMiddleware.cs index e993fade..d73ef67a 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/ElmMiddleware.cs +++ b/src/Microsoft.AspNet.Diagnostics.Elm/ElmMiddleware.cs @@ -88,7 +88,7 @@ public async Task Invoke(HttpContext context) { // sort so most recent logs are first Logs = logs.OrderBy(l => l.Time).Reverse(), - LogTree = ElmStore.Activities, + LogTree = ElmStore.GetActivities(), Options = options, Path = _options.Path }; diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/ElmScope.cs b/src/Microsoft.AspNet.Diagnostics.Elm/ElmScope.cs index fbc3c225..e41a28de 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/ElmScope.cs +++ b/src/Microsoft.AspNet.Diagnostics.Elm/ElmScope.cs @@ -80,15 +80,8 @@ public static IDisposable Push(ElmScope scope) } else { - lock (ElmStore.Activities) - { - Current.Context.Root = Current.Node; - ElmStore.Activities.AddLast(Current.Context); - while (ElmStore.NumLogs() > ElmStore.Capacity) - { - ElmStore.Activities.RemoveFirst(); - } - } + Current.Context.Root = Current.Node; + ElmStore.AddActivity(Current.Context); } return new DisposableAction(() => diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/ElmStore.cs b/src/Microsoft.AspNet.Diagnostics.Elm/ElmStore.cs index 579301b4..2de6de6d 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/ElmStore.cs +++ b/src/Microsoft.AspNet.Diagnostics.Elm/ElmStore.cs @@ -9,11 +9,11 @@ namespace Microsoft.AspNet.Diagnostics.Elm { public class ElmStore : IElmStore { - public const int Capacity = 200; + private const int Capacity = 200; private readonly Queue _logs = new Queue(); - public static LinkedList Activities { get; set; } = new LinkedList(); + private static LinkedList Activities { get; set; } = new LinkedList(); public IEnumerable GetLogs() { @@ -38,9 +38,26 @@ public void Add(LogInfo info) } // returns the number of log messages stored in Activities - public static int NumLogs() + private static int NumLogs() { return Activities.Sum(a => a.Size); } + + public static IEnumerable GetActivities() + { + return Activities; + } + + public static void AddActivity(ActivityContext activity) + { + lock (Activities) + { + Activities.AddLast(activity); + while (NumLogs() > Capacity) + { + Activities.RemoveFirst(); + } + } + } } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/LogInfo.cs b/src/Microsoft.AspNet.Diagnostics.Elm/LogInfo.cs index 4b59964f..8c56fa2e 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/LogInfo.cs +++ b/src/Microsoft.AspNet.Diagnostics.Elm/LogInfo.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Collections.Generic; using Microsoft.Framework.Logging; namespace Microsoft.AspNet.Diagnostics.Elm @@ -22,7 +21,5 @@ public class LogInfo public int EventID { get; set; } public DateTimeOffset Time { get; set; } - - public IList Scopes { get; set; } } } \ No newline at end of file From eee5c1570004a4c85bfbaae97f14b47596086107 Mon Sep 17 00:00:00 2001 From: SonjaKhan Date: Fri, 7 Nov 2014 10:32:20 -0800 Subject: [PATCH 06/19] reacting to changes in the Logging enum name --- .../ElmLogger.cs | 6 ++-- .../ElmMiddleware.cs | 4 +-- .../ElmStore.cs | 2 +- .../IElmStore.cs | 2 +- .../LogInfo.cs | 2 +- .../ViewOptions.cs | 2 +- .../Views/LogPage.cs | 26 ++++++++-------- .../Views/LogPage.cshtml | 6 ++-- .../Views/RequestPage.cs | 30 +++++++++---------- .../Views/RequestPage.cshtml | 2 +- 10 files changed, 41 insertions(+), 41 deletions(-) diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/ElmLogger.cs b/src/Microsoft.AspNet.Diagnostics.Elm/ElmLogger.cs index b0fca5f4..7d66583e 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/ElmLogger.cs +++ b/src/Microsoft.AspNet.Diagnostics.Elm/ElmLogger.cs @@ -19,7 +19,7 @@ public ElmLogger(string name, ElmLoggerProvider provider, IElmStore store) _store = store; } - public void Write(TraceType traceType, int eventId, object state, Exception exception, + public void Write(LogLevel logLevel, int eventId, object state, Exception exception, Func formatter) { LogInfo info = new LogInfo() @@ -27,7 +27,7 @@ public void Write(TraceType traceType, int eventId, object state, Exception exce ActivityContext = GetCurrentActivityContext(), Name = _name, EventID = eventId, - Severity = traceType, + Severity = logLevel, Exception = exception, State = state, Time = DateTimeOffset.UtcNow @@ -40,7 +40,7 @@ public void Write(TraceType traceType, int eventId, object state, Exception exce _store.Add(info); } - public bool IsEnabled(TraceType traceType) + public bool IsEnabled(LogLevel logLevel) { return true; } diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/ElmMiddleware.cs b/src/Microsoft.AspNet.Diagnostics.Elm/ElmMiddleware.cs index d73ef67a..62adb607 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/ElmMiddleware.cs +++ b/src/Microsoft.AspNet.Diagnostics.Elm/ElmMiddleware.cs @@ -62,13 +62,13 @@ public async Task Invoke(HttpContext context) var logs = _store.GetLogs(); var options = new ViewOptions() { - MinLevel = TraceType.Verbose, + MinLevel = LogLevel.Verbose, NamePrefix = "" }; if (context.Request.Query.ContainsKey("level")) { var minLevel = options.MinLevel; - if (Enum.TryParse(context.Request.Query.GetValues("level")[0], out minLevel)) + if (Enum.TryParse(context.Request.Query.GetValues("level")[0], out minLevel)) { logs = _store.GetLogs(minLevel); options.MinLevel = minLevel; diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/ElmStore.cs b/src/Microsoft.AspNet.Diagnostics.Elm/ElmStore.cs index 2de6de6d..689c0f2e 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/ElmStore.cs +++ b/src/Microsoft.AspNet.Diagnostics.Elm/ElmStore.cs @@ -20,7 +20,7 @@ public IEnumerable GetLogs() return _logs; } - public IEnumerable GetLogs(TraceType minLevel) + public IEnumerable GetLogs(LogLevel minLevel) { return _logs.Where(l => l.Severity >= minLevel); } diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/IElmStore.cs b/src/Microsoft.AspNet.Diagnostics.Elm/IElmStore.cs index 9a0db596..9bc4d212 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/IElmStore.cs +++ b/src/Microsoft.AspNet.Diagnostics.Elm/IElmStore.cs @@ -10,6 +10,6 @@ public interface IElmStore { void Add(LogInfo info); IEnumerable GetLogs(); - IEnumerable GetLogs(TraceType minLevel); + IEnumerable GetLogs(LogLevel minLevel); } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/LogInfo.cs b/src/Microsoft.AspNet.Diagnostics.Elm/LogInfo.cs index 8c56fa2e..1270a105 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/LogInfo.cs +++ b/src/Microsoft.AspNet.Diagnostics.Elm/LogInfo.cs @@ -16,7 +16,7 @@ public class LogInfo public Exception Exception { get; set; } - public TraceType Severity { get; set; } + public LogLevel Severity { get; set; } public int EventID { get; set; } diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/ViewOptions.cs b/src/Microsoft.AspNet.Diagnostics.Elm/ViewOptions.cs index 53b21a3e..ca88eb38 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/ViewOptions.cs +++ b/src/Microsoft.AspNet.Diagnostics.Elm/ViewOptions.cs @@ -13,7 +13,7 @@ public class ViewOptions /// /// The minimum severity level shown /// - public TraceType MinLevel { get; set; } + public LogLevel MinLevel { get; set; } /// /// prefix filter for the loggers shown diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.cs b/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.cs index 96205354..806a6751 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.cs +++ b/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.cs @@ -167,7 +167,7 @@ public HelperResult { Name = node.Name, Time = node.StartTime, - Severity = TraceType.Verbose, + Severity = LogLevel.Verbose, State = "Beginning " + node.State, }, level)); @@ -259,7 +259,7 @@ public HelperResult { Name = node.Name, Time = node.EndTime, - Severity = TraceType.Verbose, + Severity = LogLevel.Verbose, State = string.Format("Completed {0} in {1}ms", node.State, node.EndTime - node.StartTime) }, level)); @@ -435,7 +435,7 @@ public override async Task ExecuteAsync() #line hidden #line 104 "LogPage.cshtml" - foreach (var severity in Enum.GetValues(typeof(TraceType))) + foreach (var severity in Enum.GetValues(typeof(LogLevel))) { var severityInt = (int)severity; if ((int)Model.Options.MinLevel == severityInt) @@ -445,8 +445,8 @@ public override async Task ExecuteAsync() #line hidden WriteLiteral(" (severityInt, 3136), false)); + WriteAttribute("value", Tuple.Create(" value=\"", 3125), Tuple.Create("\"", 3145), + Tuple.Create(Tuple.Create("", 3133), Tuple.Create(severityInt, 3133), false)); WriteLiteral(" selected=\"selected\">"); #line 109 "LogPage.cshtml" Write(severity); @@ -463,8 +463,8 @@ public override async Task ExecuteAsync() #line hidden WriteLiteral(" (severityInt, 3285), false)); + WriteAttribute("value", Tuple.Create(" value=\"", 3274), Tuple.Create("\"", 3294), + Tuple.Create(Tuple.Create("", 3282), Tuple.Create(severityInt, 3282), false)); WriteLiteral(">"); #line 113 "LogPage.cshtml" Write(severity); @@ -480,8 +480,8 @@ public override async Task ExecuteAsync() #line hidden WriteLiteral(" \r\n (Model.Options.NamePrefix, 3418), false)); + WriteAttribute("value", Tuple.Create(" value=\"", 3407), Tuple.Create("\"", 3440), + Tuple.Create(Tuple.Create("", 3415), Tuple.Create(Model.Options.NamePrefix, 3415), false)); WriteLiteral(@" /> @@ -532,10 +532,10 @@ public override async Task ExecuteAsync() #line hidden WriteLiteral(" (requestPath, 4330), false)); - WriteAttribute("title", Tuple.Create(" title=\"", 4343), Tuple.Create("\"", 4374), - Tuple.Create(Tuple.Create("", 4351), Tuple.Create(activity.HttpInfo.Path, 4351), false)); + WriteAttribute("href", Tuple.Create(" href=\"", 4320), Tuple.Create("\"", 4339), + Tuple.Create(Tuple.Create("", 4327), Tuple.Create(requestPath, 4327), false)); + WriteAttribute("title", Tuple.Create(" title=\"", 4340), Tuple.Create("\"", 4371), + Tuple.Create(Tuple.Create("", 4348), Tuple.Create(activity.HttpInfo.Path, 4348), false)); WriteLiteral(">"); #line 144 "LogPage.cshtml" Write(activity.HttpInfo.Path); diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.cshtml b/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.cshtml index dcc2b2e4..6c8c9f68 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.cshtml +++ b/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.cshtml @@ -45,7 +45,7 @@ { Name = node.Name, Time = node.StartTime, - Severity = TraceType.Verbose, + Severity = LogLevel.Verbose, State = "Beginning " + node.State, }, level); var messageIndex = 0; @@ -82,7 +82,7 @@ { Name = node.Name, Time = node.EndTime, - Severity = TraceType.Verbose, + Severity = LogLevel.Verbose, State = string.Format("Completed {0} in {1}ms", node.State, node.EndTime - node.StartTime) }, level); } @@ -101,7 +101,7 @@

ELM

\r\n (Model.Options.NamePrefix, 4429), false)); + WriteAttribute("value", Tuple.Create(" value=\"", 4420), Tuple.Create("\"", 4453), + Tuple.Create(Tuple.Create("", 4428), Tuple.Create(Model.Options.NamePrefix, 4428), false)); WriteLiteral(@" /> @@ -368,8 +368,8 @@ public override async Task ExecuteAsync() #line default #line hidden WriteLiteral("\r\n (log.Severity.ToString().ToLowerInvariant(), 5039), false)); + WriteAttribute("class", Tuple.Create(" class=\"", 5030), Tuple.Create("\"", 5081), + Tuple.Create(Tuple.Create("", 5038), Tuple.Create(log.Severity.ToString().ToLowerInvariant(), 5038), false)); WriteLiteral(">"); #line 159 "RequestPage.cshtml" Write(log.Severity); @@ -377,8 +377,8 @@ public override async Task ExecuteAsync() #line default #line hidden WriteLiteral("\r\n (log.Name, 5131), false)); + WriteAttribute("title", Tuple.Create(" title=\"", 5122), Tuple.Create("\"", 5139), + Tuple.Create(Tuple.Create("", 5130), Tuple.Create(log.Name, 5130), false)); WriteLiteral(">"); #line 160 "RequestPage.cshtml" Write(log.Name); @@ -386,8 +386,8 @@ public override async Task ExecuteAsync() #line default #line hidden WriteLiteral("\r\n (log.State, 5185), false)); + WriteAttribute("title", Tuple.Create(" title=\"", 5176), Tuple.Create("\"", 5194), + Tuple.Create(Tuple.Create("", 5184), Tuple.Create(log.State, 5184), false)); WriteLiteral(" class=\"logState\" width=\"100px\">"); #line 161 "RequestPage.cshtml" Write(log.State); @@ -395,8 +395,8 @@ public override async Task ExecuteAsync() #line default #line hidden WriteLiteral("\r\n (log.Exception, 5272), false)); + WriteAttribute("title", Tuple.Create(" title=\"", 5263), Tuple.Create("\"", 5285), + Tuple.Create(Tuple.Create("", 5271), Tuple.Create(log.Exception, 5271), false)); WriteLiteral(">"); #line 162 "RequestPage.cshtml" Write(log.Exception); diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.cshtml b/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.cshtml index 8a55e90b..cf9d1896 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.cshtml +++ b/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.cshtml @@ -124,7 +124,7 @@

Logs

"); #line 104 "LogPage.cshtml" @@ -445,8 +458,8 @@ public override async Task ExecuteAsync() #line hidden WriteLiteral(" (severityInt, 3133), false)); + WriteAttribute("value", Tuple.Create(" value=\"", 3158), Tuple.Create("\"", 3178), + Tuple.Create(Tuple.Create("", 3166), Tuple.Create(severityInt, 3166), false)); WriteLiteral(" selected=\"selected\">"); #line 109 "LogPage.cshtml" Write(severity); @@ -463,8 +476,8 @@ public override async Task ExecuteAsync() #line hidden WriteLiteral(" (severityInt, 3282), false)); + WriteAttribute("value", Tuple.Create(" value=\"", 3307), Tuple.Create("\"", 3327), + Tuple.Create(Tuple.Create("", 3315), Tuple.Create(severityInt, 3315), false)); WriteLiteral(">"); #line 113 "LogPage.cshtml" Write(severity); @@ -480,8 +493,8 @@ public override async Task ExecuteAsync() #line hidden WriteLiteral(" \r\n (Model.Options.NamePrefix, 3415), false)); + WriteAttribute("value", Tuple.Create(" value=\"", 3440), Tuple.Create("\"", 3473), + Tuple.Create(Tuple.Create("", 3448), Tuple.Create(Model.Options.NamePrefix, 3448), false)); WriteLiteral(@" /> @@ -509,7 +522,7 @@ public override async Task ExecuteAsync() #line hidden #line 136 "LogPage.cshtml" - foreach (var activity in Model.LogTree.Reverse()) + foreach (var activity in Model.Activities.Reverse()) { #line default @@ -532,10 +545,10 @@ public override async Task ExecuteAsync() #line hidden WriteLiteral(" (requestPath, 4327), false)); - WriteAttribute("title", Tuple.Create(" title=\"", 4340), Tuple.Create("\"", 4371), - Tuple.Create(Tuple.Create("", 4348), Tuple.Create(activity.HttpInfo.Path, 4348), false)); + WriteAttribute("href", Tuple.Create(" href=\"", 4356), Tuple.Create("\"", 4375), + Tuple.Create(Tuple.Create("", 4363), Tuple.Create(requestPath, 4363), false)); + WriteAttribute("title", Tuple.Create(" title=\"", 4376), Tuple.Create("\"", 4407), + Tuple.Create(Tuple.Create("", 4384), Tuple.Create(activity.HttpInfo.Path, 4384), false)); WriteLiteral(">"); #line 144 "LogPage.cshtml" Write(activity.HttpInfo.Path); @@ -563,7 +576,13 @@ public override async Task ExecuteAsync() #line default #line hidden - WriteLiteral(" \r\n"); + WriteLiteral(" "); +#line 150 "LogPage.cshtml" + Write(activity.Root.State); + +#line default +#line hidden + WriteLiteral("\r\n"); #line 151 "LogPage.cshtml" } @@ -585,15 +604,52 @@ public override async Task ExecuteAsync() - "); +"); #line 166 "LogPage.cshtml" - Write(Traverse(activity.Root, 0)); + #line default #line hidden - WriteLiteral("\r\n \r\n \r\n " + -" \r\n \r\n \r\n"); -#line 172 "LogPage.cshtml" + +#line 166 "LogPage.cshtml" + if (activity.Id.Equals(Guid.Empty)) + { + // message not within a scope + + +#line default +#line hidden + +#line 169 "LogPage.cshtml" + Write(LogRow(activity.Root.Messages.FirstOrDefault(), 0)); + +#line default +#line hidden +#line 169 "LogPage.cshtml" + + } + else + { + + +#line default +#line hidden + +#line 173 "LogPage.cshtml" + Write(Traverse(activity.Root, 0)); + +#line default +#line hidden +#line 173 "LogPage.cshtml" + + } + +#line default +#line hidden + + WriteLiteral(" \r\n \r\n " + +" \r\n \r\n \r\n"); +#line 180 "LogPage.cshtml" } #line default diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.cshtml b/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.cshtml index 6c8c9f68..402e7689 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.cshtml +++ b/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.cshtml @@ -26,12 +26,12 @@ @string.Format("{0:H:mm:ss}", log.Time) @log.Name @log.Severity - + @for (var i = 0; i < level; i++) { } - @log.State + @log.Message @log.Exception @@ -40,13 +40,13 @@ @helper Traverse(ScopeNode node, int level) { - // print start time + // print start of scope @LogRow(new LogInfo() { Name = node.Name, Time = node.StartTime, Severity = LogLevel.Verbose, - State = "Beginning " + node.State, + Message = "Beginning " + node.State, }, level); var messageIndex = 0; var childIndex = 0; @@ -77,13 +77,13 @@ @Traverse(node.Children[i], level + 1) } } - // print end time + // print end of scope @LogRow(new LogInfo() { Name = node.Name, Time = node.EndTime, Severity = LogLevel.Verbose, - State = string.Format("Completed {0} in {1}ms", node.State, node.EndTime - node.StartTime) + Message = string.Format("Completed {0} in {1}ms", node.State, node.EndTime - node.StartTime) }, level); } @@ -99,7 +99,7 @@

ELM

-
+ \r\n"); -#line 127 "RequestPage.cshtml" +#line 152 "RequestPage.cshtml" #line default #line hidden -#line 127 "RequestPage.cshtml" +#line 152 "RequestPage.cshtml" foreach (var severity in Enum.GetValues(typeof(LogLevel))) { var severityInt = (int)severity; @@ -290,16 +450,16 @@ public override async Task ExecuteAsync() #line hidden WriteLiteral(" (severityInt, 4146), false)); + WriteAttribute("value", Tuple.Create(" value=\"", 5169), Tuple.Create("\"", 5189), + Tuple.Create(Tuple.Create("", 5177), Tuple.Create(severityInt, 5177), false)); WriteLiteral(" selected=\"selected\">"); -#line 132 "RequestPage.cshtml" +#line 157 "RequestPage.cshtml" Write(severity); #line default #line hidden WriteLiteral("\r\n"); -#line 133 "RequestPage.cshtml" +#line 158 "RequestPage.cshtml" } else { @@ -308,16 +468,16 @@ public override async Task ExecuteAsync() #line hidden WriteLiteral(" (severityInt, 4295), false)); + WriteAttribute("value", Tuple.Create(" value=\"", 5318), Tuple.Create("\"", 5338), + Tuple.Create(Tuple.Create("", 5326), Tuple.Create(severityInt, 5326), false)); WriteLiteral(">"); -#line 136 "RequestPage.cshtml" +#line 161 "RequestPage.cshtml" Write(severity); #line default #line hidden WriteLiteral("\r\n"); -#line 137 "RequestPage.cshtml" +#line 162 "RequestPage.cshtml" } } @@ -325,8 +485,8 @@ public override async Task ExecuteAsync() #line hidden WriteLiteral(" \r\n (Model.Options.NamePrefix, 4428), false)); + WriteAttribute("value", Tuple.Create(" value=\"", 5451), Tuple.Create("\"", 5484), + Tuple.Create(Tuple.Create("", 5459), Tuple.Create(Model.Options.NamePrefix, 5459), false)); WriteLiteral(@" /> @@ -342,13 +502,13 @@ public override async Task ExecuteAsync() "); -#line 154 "RequestPage.cshtml" +#line 179 "RequestPage.cshtml" #line default #line hidden -#line 154 "RequestPage.cshtml" +#line 179 "RequestPage.cshtml" foreach (var log in Model.Logs) { @@ -356,61 +516,81 @@ public override async Task ExecuteAsync() #line hidden WriteLiteral(" \r\n "); -#line 157 "RequestPage.cshtml" +#line 182 "RequestPage.cshtml" Write(string.Format("{0:MM/dd/yy}", log.Time)); #line default #line hidden WriteLiteral("\r\n "); -#line 158 "RequestPage.cshtml" +#line 183 "RequestPage.cshtml" Write(string.Format("{0:H:mm:ss}", log.Time)); #line default #line hidden WriteLiteral("\r\n (log.Severity.ToString().ToLowerInvariant(), 5038), false)); + WriteAttribute("class", Tuple.Create(" class=\"", 6061), Tuple.Create("\"", 6112), + Tuple.Create(Tuple.Create("", 6069), Tuple.Create(log.Severity.ToString().ToLowerInvariant(), 6069), false)); WriteLiteral(">"); -#line 159 "RequestPage.cshtml" +#line 184 "RequestPage.cshtml" Write(log.Severity); #line default #line hidden WriteLiteral("\r\n (log.Name, 5130), false)); + WriteAttribute("title", Tuple.Create(" title=\"", 6153), Tuple.Create("\"", 6170), + Tuple.Create(Tuple.Create("", 6161), Tuple.Create(log.Name, 6161), false)); WriteLiteral(">"); -#line 160 "RequestPage.cshtml" +#line 185 "RequestPage.cshtml" Write(log.Name); #line default #line hidden WriteLiteral("\r\n (log.State, 5184), false)); + WriteAttribute("title", Tuple.Create(" title=\"", 6207), Tuple.Create("\"", 6227), + Tuple.Create(Tuple.Create("", 6215), Tuple.Create(log.Message, 6215), false)); WriteLiteral(" class=\"logState\" width=\"100px\">"); -#line 161 "RequestPage.cshtml" - Write(log.State); +#line 186 "RequestPage.cshtml" + Write(log.Message); #line default #line hidden WriteLiteral("\r\n (log.Exception, 5271), false)); + WriteAttribute("title", Tuple.Create(" title=\"", 6298), Tuple.Create("\"", 6320), + Tuple.Create(Tuple.Create("", 6306), Tuple.Create(log.Exception, 6306), false)); WriteLiteral(">"); -#line 162 "RequestPage.cshtml" +#line 187 "RequestPage.cshtml" Write(log.Exception); #line default #line hidden WriteLiteral("\r\n \r\n"); -#line 164 "RequestPage.cshtml" +#line 189 "RequestPage.cshtml" } #line default #line hidden - WriteLiteral(" \r\n\r\n"); + WriteLiteral(@" + + +"); } #pragma warning restore 1998 } diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.cshtml b/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.cshtml index cf9d1896..6b18a469 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.cshtml +++ b/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.cshtml @@ -19,6 +19,7 @@ ELM + -

ELM

+

ASP.NET Logs

\r\n (Model.Options.NamePrefix, 3448), false)); + WriteAttribute("value", Tuple.Create(" value=\"", 3484), Tuple.Create("\"", 3517), + Tuple.Create(Tuple.Create("", 3492), Tuple.Create(Model.Options.NamePrefix, 3492), false)); WriteLiteral(@" /> @@ -545,10 +548,10 @@ public override async Task ExecuteAsync() #line hidden WriteLiteral(" (requestPath, 4363), false)); - WriteAttribute("title", Tuple.Create(" title=\"", 4376), Tuple.Create("\"", 4407), - Tuple.Create(Tuple.Create("", 4384), Tuple.Create(activity.HttpInfo.Path, 4384), false)); + WriteAttribute("href", Tuple.Create(" href=\"", 4400), Tuple.Create("\"", 4419), + Tuple.Create(Tuple.Create("", 4407), Tuple.Create(requestPath, 4407), false)); + WriteAttribute("title", Tuple.Create(" title=\"", 4420), Tuple.Create("\"", 4451), + Tuple.Create(Tuple.Create("", 4428), Tuple.Create(activity.HttpInfo.Path, 4428), false)); WriteLiteral(">"); #line 144 "LogPage.cshtml" Write(activity.HttpInfo.Path); diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.cshtml b/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.cshtml index 402e7689..da02a197 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.cshtml +++ b/src/Microsoft.AspNet.Diagnostics.Elm/Views/LogPage.cshtml @@ -2,9 +2,9 @@ @using System.Globalization @using System.Linq @using Microsoft.AspNet.Diagnostics.Elm.Views -@using Microsoft.Framework.Logging @using Microsoft.AspNet.Diagnostics.Elm @using Microsoft.AspNet.Diagnostics.Views +@using Microsoft.Framework.Logging @functions { @@ -19,7 +19,7 @@ @* writes one log row indented by the given level *@ @helper LogRow(LogInfo log, int level) { if (log.Severity >= Model.Options.MinLevel && - (string.IsNullOrEmpty(Model.Options.NamePrefix) || log.Name.StartsWith(Model.Options.NamePrefix))) + (string.IsNullOrEmpty(Model.Options.NamePrefix) || log.Name.StartsWith(Model.Options.NamePrefix, StringComparison.Ordinal))) { @string.Format("{0:MM/dd/yy}", log.Time) @@ -91,14 +91,14 @@ - ELM + ASP.NET Logs -

ELM

+

ASP.NET Logs

\r\n (Model.Options.NamePrefix, 5459), false)); + WriteAttribute("value", Tuple.Create(" value=\"", 5469), Tuple.Create("\"", 5502), + Tuple.Create(Tuple.Create("", 5477), Tuple.Create(Model.Options.NamePrefix, 5477), false)); WriteLiteral(@" /> @@ -528,8 +537,8 @@ public override async Task ExecuteAsync() #line default #line hidden WriteLiteral("\r\n (log.Severity.ToString().ToLowerInvariant(), 6069), false)); + WriteAttribute("class", Tuple.Create(" class=\"", 6079), Tuple.Create("\"", 6130), + Tuple.Create(Tuple.Create("", 6087), Tuple.Create(log.Severity.ToString().ToLowerInvariant(), 6087), false)); WriteLiteral(">"); #line 184 "RequestPage.cshtml" Write(log.Severity); @@ -537,8 +546,8 @@ public override async Task ExecuteAsync() #line default #line hidden WriteLiteral("\r\n (log.Name, 6161), false)); + WriteAttribute("title", Tuple.Create(" title=\"", 6171), Tuple.Create("\"", 6188), + Tuple.Create(Tuple.Create("", 6179), Tuple.Create(log.Name, 6179), false)); WriteLiteral(">"); #line 185 "RequestPage.cshtml" Write(log.Name); @@ -546,8 +555,8 @@ public override async Task ExecuteAsync() #line default #line hidden WriteLiteral("\r\n (log.Message, 6215), false)); + WriteAttribute("title", Tuple.Create(" title=\"", 6225), Tuple.Create("\"", 6245), + Tuple.Create(Tuple.Create("", 6233), Tuple.Create(log.Message, 6233), false)); WriteLiteral(" class=\"logState\" width=\"100px\">"); #line 186 "RequestPage.cshtml" Write(log.Message); @@ -555,8 +564,8 @@ public override async Task ExecuteAsync() #line default #line hidden WriteLiteral("\r\n (log.Exception, 6306), false)); + WriteAttribute("title", Tuple.Create(" title=\"", 6316), Tuple.Create("\"", 6338), + Tuple.Create(Tuple.Create("", 6324), Tuple.Create(log.Exception, 6324), false)); WriteLiteral(">"); #line 187 "RequestPage.cshtml" Write(log.Exception); @@ -570,27 +579,10 @@ public override async Task ExecuteAsync() #line default #line hidden - WriteLiteral(@" - - -"); + WriteLiteral(" \r\n \r\n\r\n"); } #pragma warning restore 1998 } diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.cshtml b/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.cshtml index 6b18a469..188d9b58 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.cshtml +++ b/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.cshtml @@ -18,7 +18,7 @@ - ELM + ASP.NET Logs -

ELM

+

ASP.NET Logs

@{ var context = Model.Logs.FirstOrDefault()?.ActivityContext?.HttpInfo; } @@ -190,20 +190,9 @@ diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.css b/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.css index 5826f5c0..d0803ebf 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.css +++ b/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.css @@ -4,7 +4,11 @@ margin: 0px auto; } -h1, h2 { +h1 { + padding-bottom: 10px; +} + +h2 { font-weight: normal; } diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/Views/Shared.css b/src/Microsoft.AspNet.Diagnostics.Elm/Views/Shared.css index 04164bd3..7f355343 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/Views/Shared.css +++ b/src/Microsoft.AspNet.Diagnostics.Elm/Views/Shared.css @@ -3,6 +3,11 @@ line-height: 1.4em; } +h1 { + font-family: 'Segoe UI', Helvetica, sans-serif; + font-size: 2.5em; +} + td { text-overflow: ellipsis; overflow: hidden; diff --git a/test/Microsoft.AspNet.Diagnostics.Tests/ElmLoggerTest.cs b/test/Microsoft.AspNet.Diagnostics.Tests/ElmLoggerTest.cs index b9ca8a20..14a17c3f 100644 --- a/test/Microsoft.AspNet.Diagnostics.Tests/ElmLoggerTest.cs +++ b/test/Microsoft.AspNet.Diagnostics.Tests/ElmLoggerTest.cs @@ -31,13 +31,12 @@ public void LogsWhenNullFormatterGiven() var t = SetUp(); var logger = t.Item1; var store = t.Item2; - var initialCount = (store.GetActivities().SelectMany(a => a.AllMessages).ToList()).Count; // Act logger.Write(LogLevel.Information, 0, _state, null, null); // Assert - Assert.Equal(1, (store.GetActivities().SelectMany(a => a.AllMessages).ToList()).Count - initialCount); + Assert.Single(store.GetActivities()); } [Fact] @@ -47,13 +46,12 @@ public void DoesNotLogWithEmptyStateAndException() var t = SetUp(); var logger = t.Item1; var store = t.Item2; - var initialCount = (store.GetActivities().SelectMany(a => a.AllMessages).ToList()).Count; // Act logger.Write(LogLevel.Information, 0, null, null, null); // Assert - Assert.Equal(0, (store.GetActivities().SelectMany(a => a.AllMessages).ToList()).Count - initialCount); + Assert.Empty(store.GetActivities()); } [Fact] @@ -63,7 +61,6 @@ public void DefaultLogsForAllLogLevels() var t = SetUp(); var logger = t.Item1; var store = t.Item2; - var initialCount = (store.GetActivities().SelectMany(a => a.AllMessages).ToList()).Count; // Act logger.Write(LogLevel.Verbose, 0, _state, null, null); @@ -73,7 +70,7 @@ public void DefaultLogsForAllLogLevels() logger.Write(LogLevel.Critical, 0, _state, null, null); // Assert - Assert.Equal(5, (store.GetActivities().SelectMany(a => a.AllMessages).ToList()).Count - initialCount); + Assert.Equal(5, (store.GetActivities().SelectMany(a => a.AllMessages).ToList()).Count); } [Theory] @@ -86,10 +83,9 @@ public void DefaultLogsForAllLogLevels() public void Filter_LogsWhenAppropriate(LogLevel minLevel, string prefix, int count) { // Arrange - var t = SetUp((name, level) => (name.StartsWith(prefix) && level >= minLevel), _name); + var t = SetUp((name, level) => (name.StartsWith(prefix, StringComparison.Ordinal) && level >= minLevel), _name); var logger = t.Item1; var store = t.Item2; - var initialCount = (store.GetActivities().SelectMany(a => a.AllMessages).ToList()).Count; // Act logger.Write(LogLevel.Verbose, 0, _state, null, null); @@ -99,7 +95,7 @@ public void Filter_LogsWhenAppropriate(LogLevel minLevel, string prefix, int cou logger.Write(LogLevel.Critical, 0, _state, null, null); // Assert - Assert.Equal(count, (store.GetActivities().SelectMany(a => a.AllMessages).ToList()).Count - initialCount); + Assert.Equal(count, (store.GetActivities().SelectMany(a => a.AllMessages).ToList()).Count); } [Fact] @@ -109,8 +105,6 @@ public void ThreadsHaveSeparateActivityContexts() var t = SetUp(); var logger = t.Item1; var store = t.Item2; - var initialCount = (store.GetActivities().SelectMany(a => a.AllMessages).ToList()).Count; - var initialActivityCount = store.GetActivities().ToList().Count; var testThread = new TestThread(logger); Thread workerThread = new Thread(testThread.work); @@ -126,8 +120,8 @@ public void ThreadsHaveSeparateActivityContexts() workerThread.Join(); // Assert - Assert.Equal(17, (store.GetActivities().SelectMany(a => a.AllMessages).ToList()).Count - initialCount); - Assert.Equal(2, store.GetActivities().ToList().Count - initialActivityCount); + Assert.Equal(17, (store.GetActivities().SelectMany(a => a.AllMessages).ToList()).Count); + Assert.Equal(2, store.GetActivities().ToList().Count); } [Fact] @@ -152,17 +146,18 @@ public void ScopesHaveProperTreeStructure() workerThread.Join(); // Assert - var root1 = (store.GetActivities()).Where(a => a.Root.State?.Equals("test2") ?? false)?.ElementAt(0)?.Root; + // get the root of the activity for scope "test2" + var root1 = (store.GetActivities()).Where(a => a.Root.State.Equals("test2"))?.FirstOrDefault()?.Root; Assert.NotNull(root1); - var root2 = (store.GetActivities()).Where(a => a.Root.State?.Equals("test12") ?? false)?.ElementAt(0)?.Root; + var root2 = (store.GetActivities()).Where(a => a.Root.State.Equals("test12"))?.FirstOrDefault()?.Root; Assert.NotNull(root2); Assert.Equal(0, root1.Children.Count); Assert.Equal(2, root1.Messages.Count); Assert.Equal(1, root2.Children.Count); Assert.Equal(12, root2.Messages.Count); - Assert.Equal(0, root2.Children.ElementAt(0).Children.Count); - Assert.Equal(3, root2.Children.ElementAt(0).Messages.Count); + Assert.Equal(0, root2.Children.First().Children.Count); + Assert.Equal(3, root2.Children.First().Messages.Count); } [Fact] @@ -172,7 +167,6 @@ public void CollapseTree_CollapsesWhenNoLogsInSingleScope() var t = SetUp(); var logger = t.Item1; var store = t.Item2; - var initialActivityCount = store.GetActivities().ToList().Count; // Act using (logger.BeginScope("test3")) @@ -180,7 +174,7 @@ public void CollapseTree_CollapsesWhenNoLogsInSingleScope() } // Assert - Assert.Equal(0, store.GetActivities().ToList().Count - initialActivityCount); + Assert.Empty(store.GetActivities()); } [Fact] @@ -190,7 +184,6 @@ public void CollapseTree_CollapsesWhenNoLogsInNestedScope() var t = SetUp(); var logger = t.Item1; var store = t.Item2; - var initialActivityCount = store.GetActivities().ToList().Count; // Act using (logger.BeginScope("test4")) @@ -201,7 +194,7 @@ public void CollapseTree_CollapsesWhenNoLogsInNestedScope() } // Assert - Assert.Equal(0, store.GetActivities().ToList().Count - initialActivityCount); + Assert.Empty(store.GetActivities()); } [Fact] @@ -211,7 +204,6 @@ public void CollapseTree_DoesNotCollapseWhenLogsExist() var t = SetUp(); var logger = t.Item1; var store = t.Item2; - var initialActivityCount = store.GetActivities().ToList().Count; // Act using (logger.BeginScope("test6")) @@ -223,7 +215,7 @@ public void CollapseTree_DoesNotCollapseWhenLogsExist() } // Assert - Assert.Equal(1, store.GetActivities().ToList().Count - initialActivityCount); + Assert.Single(store.GetActivities()); } [Fact] @@ -233,7 +225,6 @@ public void CollapseTree_CollapsesAppropriateNodes() var t = SetUp(); var logger = t.Item1; var store = t.Item2; - var initialActivityCount = store.GetActivities().ToList().Count; // Act using (logger.BeginScope("test8")) @@ -245,7 +236,7 @@ public void CollapseTree_CollapsesAppropriateNodes() } // Assert - Assert.Equal(1, store.GetActivities().ToList().Count - initialActivityCount); + Assert.Single(store.GetActivities()); var context = store.GetActivities().Where(a => a.Root.State.Equals("test8")).First(); Assert.Empty(context.Root.Children); } @@ -257,7 +248,6 @@ public void CollapseTree_WorksWithFilter() var t = SetUp((_, level) => level >= LogLevel.Warning, null); var logger = t.Item1; var store = t.Item2; - var initialActivityCount = store.GetActivities().ToList().Count; // Act using (logger.BeginScope("test10")) @@ -269,7 +259,7 @@ public void CollapseTree_WorksWithFilter() } // Assert - Assert.Equal(0, store.GetActivities().ToList().Count - initialActivityCount); + Assert.Empty(store.GetActivities()); } private class TestThread diff --git a/test/Microsoft.AspNet.Diagnostics.Tests/ElmMiddlewareTest.cs b/test/Microsoft.AspNet.Diagnostics.Tests/ElmMiddlewareTest.cs index 7fe661de..f6862ca7 100644 --- a/test/Microsoft.AspNet.Diagnostics.Tests/ElmMiddlewareTest.cs +++ b/test/Microsoft.AspNet.Diagnostics.Tests/ElmMiddlewareTest.cs @@ -110,7 +110,7 @@ public async void Invoke_WithMatchingPath_FulfillsRequest() // Assert contextMock.VerifyGet(c => c.Request.Query, Times.AtLeastOnce()); - Assert.True(response.Contains("ELM")); + Assert.True(response.Contains("ASP.NET Logs")); } } From e4c1ad64a948880bba420d6d626f47c527fbaa8f Mon Sep 17 00:00:00 2001 From: SonjaKhan Date: Fri, 21 Nov 2014 09:22:52 -0800 Subject: [PATCH 17/19] updating based on feedback --- src/Microsoft.AspNet.Diagnostics.Elm/ElmLogger.cs | 2 +- src/Microsoft.AspNet.Diagnostics.Elm/ElmStore.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/ElmLogger.cs b/src/Microsoft.AspNet.Diagnostics.Elm/ElmLogger.cs index 42bbbebc..151ba79a 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/ElmLogger.cs +++ b/src/Microsoft.AspNet.Diagnostics.Elm/ElmLogger.cs @@ -22,7 +22,7 @@ public ElmLogger(string name, ElmOptions options, ElmStore store) public void Write(LogLevel logLevel, int eventId, object state, Exception exception, Func formatter) { - if (!IsEnabled(logLevel) || state == null && exception == null) + if (!IsEnabled(logLevel) || (state == null && exception == null)) { return; } diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/ElmStore.cs b/src/Microsoft.AspNet.Diagnostics.Elm/ElmStore.cs index f03fd8ec..6235450d 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/ElmStore.cs +++ b/src/Microsoft.AspNet.Diagnostics.Elm/ElmStore.cs @@ -41,7 +41,7 @@ public IEnumerable GetActivities() /// The id of the request to get the logs of /// The minimum of the returned logs /// An IEnumerable of objects - public IEnumerable GetActivityLogs([NotNull] Guid requestId, [NotNull] LogLevel minLevel) + public IEnumerable GetActivityLogs(Guid requestId, LogLevel minLevel) { return Activities.Where(a => a.HttpInfo?.RequestID == requestId).FirstOrDefault()?.AllMessages?.Where(m => m.Severity >= minLevel); } From f4ba7c4e8be4df1e3d4886e9ff9ab6540316dd67 Mon Sep 17 00:00:00 2001 From: SonjaKhan Date: Mon, 24 Nov 2014 17:43:35 -0800 Subject: [PATCH 18/19] removing AllMessages --- .../ActivityContext.cs | 2 - .../ElmLogger.cs | 2 - .../ElmPageMiddleware.cs | 4 +- .../ElmStore.cs | 40 +- .../Views/RequestPage.cs | 373 ++++++++++++------ .../Views/RequestPage.cshtml | 64 ++- .../Views/RequestPageModel.cs | 2 +- .../ElmLoggerTest.cs | 49 ++- 8 files changed, 375 insertions(+), 161 deletions(-) diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/ActivityContext.cs b/src/Microsoft.AspNet.Diagnostics.Elm/ActivityContext.cs index b318bed5..41833c39 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/ActivityContext.cs +++ b/src/Microsoft.AspNet.Diagnostics.Elm/ActivityContext.cs @@ -13,8 +13,6 @@ public class ActivityContext public DateTimeOffset Time { get; set; } - public List AllMessages { get; private set; } = new List(); - public bool IsCollapsed { get; set; } } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/ElmLogger.cs b/src/Microsoft.AspNet.Diagnostics.Elm/ElmLogger.cs index 151ba79a..9238d6d6 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/ElmLogger.cs +++ b/src/Microsoft.AspNet.Diagnostics.Elm/ElmLogger.cs @@ -39,7 +39,6 @@ public void Write(LogLevel logLevel, int eventId, object state, Exception except }; if (ElmScope.Current != null) { - GetCurrentActivityContext().AllMessages.Add(info); ElmScope.Current.Node.Messages.Add(info); } // The log does not belong to any scope - create a new context for it @@ -49,7 +48,6 @@ public void Write(LogLevel logLevel, int eventId, object state, Exception except context.Id = Guid.Empty; // mark as a non-scope log context.Root = new ScopeNode(); context.Root.Messages.Add(info); - context.AllMessages.Add(info); // to keep the log count accurate _store.AddActivity(context); } } diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/ElmPageMiddleware.cs b/src/Microsoft.AspNet.Diagnostics.Elm/ElmPageMiddleware.cs index bc9c9533..94bf3a42 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/ElmPageMiddleware.cs +++ b/src/Microsoft.AspNet.Diagnostics.Elm/ElmPageMiddleware.cs @@ -8,6 +8,7 @@ using Microsoft.AspNet.Diagnostics.Elm.Views; using Microsoft.Framework.Logging; using Microsoft.Framework.OptionsModel; +using System.Linq; namespace Microsoft.AspNet.Diagnostics.Elm { @@ -70,11 +71,10 @@ private async void RenderRequestDetailsPage(ViewOptions options, HttpContext con await context.Response.WriteAsync("Invalid Request Id"); return; } - var requestLogs = _store.GetActivityLogs(id, options.MinLevel); var model = new RequestPageModel() { RequestID = id, - Logs = requestLogs, + Activity = _store.GetActivities().Where(a => a.HttpInfo?.RequestID == id).FirstOrDefault(), Options = options }; var requestPage = new RequestPage(model); diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/ElmStore.cs b/src/Microsoft.AspNet.Diagnostics.Elm/ElmStore.cs index 6235450d..b328d80e 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/ElmStore.cs +++ b/src/Microsoft.AspNet.Diagnostics.Elm/ElmStore.cs @@ -13,8 +13,6 @@ public class ElmStore { private const int Capacity = 200; - private static int _count; - private LinkedList Activities { get; set; } = new LinkedList(); /// @@ -34,18 +32,6 @@ public IEnumerable GetActivities() return Activities; } - /// - /// Returns an IEnumerable of objects for the given request id, - /// with a minimum of minLevel - /// - /// The id of the request to get the logs of - /// The minimum of the returned logs - /// An IEnumerable of objects - public IEnumerable GetActivityLogs(Guid requestId, LogLevel minLevel) - { - return Activities.Where(a => a.HttpInfo?.RequestID == requestId).FirstOrDefault()?.AllMessages?.Where(m => m.Severity >= minLevel); - } - /// /// Adds a new to the store. /// @@ -55,14 +41,36 @@ public void AddActivity([NotNull] ActivityContext activity) lock (Activities) { Activities.AddLast(activity); - _count += activity.AllMessages.Count; - while (_count > Capacity) + while (Count() > Capacity) { Activities.RemoveFirst(); } } } + /// + /// Returns the total number of logs in all activities in the store + /// + /// The total log count + public int Count() + { + return Activities.Sum(a => Count(a.Root)); + } + + private int Count(ScopeNode node) + { + if (node == null) + { + return 0; + } + var sum = node.Messages.Count; + foreach (var child in node.Children) + { + sum += Count(child); + } + return sum; + } + /// /// Removes any nodes on the context's scope tree that doesn't have any logs /// This may occur as a result of the filters turned on diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.cs b/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.cs index 40b2ad84..fbee9111 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.cs +++ b/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.cs @@ -25,12 +25,18 @@ namespace Microsoft.AspNet.Diagnostics.Elm.Views #line hidden ; #line 5 "RequestPage.cshtml" -using Microsoft.AspNet.Diagnostics.Elm.Views +using Microsoft.AspNet.Diagnostics.Views #line default #line hidden ; #line 6 "RequestPage.cshtml" +using Microsoft.AspNet.Diagnostics.Elm.Views + +#line default +#line hidden + ; +#line 7 "RequestPage.cshtml" using Microsoft.Framework.Logging #line default @@ -40,7 +46,182 @@ namespace Microsoft.AspNet.Diagnostics.Elm.Views public class RequestPage : Microsoft.AspNet.Diagnostics.Views.BaseView { -#line 9 "RequestPage.cshtml" +public HelperResult +#line 19 "RequestPage.cshtml" +LogRow(LogInfo log) +{ + +#line default +#line hidden + return new HelperResult((__razor_helper_writer) => { +#line 20 "RequestPage.cshtml" + + if (log.Severity >= Model.Options.MinLevel && + (string.IsNullOrEmpty(Model.Options.NamePrefix) || log.Name.StartsWith(Model.Options.NamePrefix, StringComparison.Ordinal))) + { + +#line default +#line hidden + + WriteLiteralTo(__razor_helper_writer, " \r\n "); +#line 25 "RequestPage.cshtml" +WriteTo(__razor_helper_writer, string.Format("{0:MM/dd/yy}", log.Time)); + +#line default +#line hidden + WriteLiteralTo(__razor_helper_writer, "\r\n "); +#line 26 "RequestPage.cshtml" +WriteTo(__razor_helper_writer, string.Format("{0:H:mm:ss}", log.Time)); + +#line default +#line hidden + WriteLiteralTo(__razor_helper_writer, "\r\n (log.Severity.ToString().ToLowerInvariant(), 776), false)); + WriteLiteralTo(__razor_helper_writer, ">"); +#line 27 "RequestPage.cshtml" + WriteTo(__razor_helper_writer, log.Severity); + +#line default +#line hidden + WriteLiteralTo(__razor_helper_writer, "\r\n (log.Name, 864), false)); + WriteLiteralTo(__razor_helper_writer, ">"); +#line 28 "RequestPage.cshtml" + WriteTo(__razor_helper_writer, log.Name); + +#line default +#line hidden + WriteLiteralTo(__razor_helper_writer, "\r\n (log.Message, 914), false)); + WriteLiteralTo(__razor_helper_writer, " class=\"logState\" width=\"100px\">"); +#line 29 "RequestPage.cshtml" + WriteTo(__razor_helper_writer, log.Message); + +#line default +#line hidden + WriteLiteralTo(__razor_helper_writer, "\r\n (log.Exception, 1001), false)); + WriteLiteralTo(__razor_helper_writer, ">"); +#line 30 "RequestPage.cshtml" + WriteTo(__razor_helper_writer, log.Exception); + +#line default +#line hidden + WriteLiteralTo(__razor_helper_writer, "\r\n \r\n"); +#line 32 "RequestPage.cshtml" + } + +#line default +#line hidden + + } + ); +#line 33 "RequestPage.cshtml" +} + +#line default +#line hidden + +public HelperResult +#line 35 "RequestPage.cshtml" +Traverse(ScopeNode node) +{ + +#line default +#line hidden + return new HelperResult((__razor_helper_writer) => { +#line 36 "RequestPage.cshtml" + + var messageIndex = 0; + var childIndex = 0; + while (messageIndex < node.Messages.Count && childIndex < node.Children.Count) + { + if (node.Messages[messageIndex].Time < node.Children[childIndex].StartTime) + { + + +#line default +#line hidden + +#line 43 "RequestPage.cshtml" +WriteTo(__razor_helper_writer, LogRow(node.Messages[messageIndex])); + +#line default +#line hidden +#line 43 "RequestPage.cshtml" + + messageIndex++; + } + else + { + + +#line default +#line hidden + +#line 48 "RequestPage.cshtml" +WriteTo(__razor_helper_writer, Traverse(node.Children[childIndex])); + +#line default +#line hidden +#line 48 "RequestPage.cshtml" + + childIndex++; + } + } + if (messageIndex < node.Messages.Count) + { + for (var i = messageIndex; i < node.Messages.Count; i++) + { + + +#line default +#line hidden + +#line 56 "RequestPage.cshtml" +WriteTo(__razor_helper_writer, LogRow(node.Messages[i])); + +#line default +#line hidden +#line 56 "RequestPage.cshtml" + + } + } + else + { + for (var i = childIndex; i < node.Children.Count; i++) + { + + +#line default +#line hidden + +#line 63 "RequestPage.cshtml" +WriteTo(__razor_helper_writer, Traverse(node.Children[i])); + +#line default +#line hidden +#line 63 "RequestPage.cshtml" + + } + } + +#line default +#line hidden + + } + ); +#line 66 "RequestPage.cshtml" +} + +#line default +#line hidden + +#line 10 "RequestPage.cshtml" public RequestPage(RequestPageModel model) { @@ -59,6 +240,8 @@ public RequestPage() #pragma warning disable 1998 public override async Task ExecuteAsync() { + WriteLiteral("\r\n"); + WriteLiteral("\r\n"); WriteLiteral("\r\n"); WriteLiteral(@" @@ -167,28 +350,28 @@ public override async Task ExecuteAsync()

ASP.NET Logs

"); -#line 30 "RequestPage.cshtml" +#line 80 "RequestPage.cshtml" #line default #line hidden -#line 30 "RequestPage.cshtml" +#line 80 "RequestPage.cshtml" - var context = Model.Logs.FirstOrDefault()?.ActivityContext?.HttpInfo; + var context = Model.Activity?.HttpInfo; #line default #line hidden WriteLiteral("\r\n"); -#line 33 "RequestPage.cshtml" +#line 83 "RequestPage.cshtml" #line default #line hidden -#line 33 "RequestPage.cshtml" +#line 83 "RequestPage.cshtml" if (context != null) { @@ -198,35 +381,35 @@ public override async Task ExecuteAsync() WriteLiteral("

Request Details

\r\n \r\n \r\n\r\n " + " \r\n \r\n \r\n \r\n \r\n \r\n " + " \r\n \r\n \r\n " + "\r\n \r\n \r\n \r\n \r\n " + " \r\n \r\n \r\n \r\n " + " "); -#line 70 "RequestPage.cshtml" +#line 120 "RequestPage.cshtml" #line default #line hidden -#line 70 "RequestPage.cshtml" +#line 120 "RequestPage.cshtml" foreach (var header in context.Headers) { @@ -259,19 +442,19 @@ public override async Task ExecuteAsync() #line hidden WriteLiteral(" \r\n \r\n \r\n \r\n"); -#line 76 "RequestPage.cshtml" +#line 126 "RequestPage.cshtml" } #line default @@ -280,27 +463,27 @@ public override async Task ExecuteAsync() WriteLiteral(" \r\n
Path"); -#line 41 "RequestPage.cshtml" +#line 91 "RequestPage.cshtml" Write(context.Path); #line default #line hidden WriteLiteral("
Host"); -#line 45 "RequestPage.cshtml" +#line 95 "RequestPage.cshtml" Write(context.Host); #line default #line hidden WriteLiteral("
Content Type"); -#line 49 "RequestPage.cshtml" +#line 99 "RequestPage.cshtml" Write(context.ContentType); #line default #line hidden WriteLiteral("
Method"); -#line 53 "RequestPage.cshtml" +#line 103 "RequestPage.cshtml" Write(context.Method); #line default #line hidden WriteLiteral("
Protocol"); -#line 57 "RequestPage.cshtml" +#line 107 "RequestPage.cshtml" Write(context.Protocol); #line default @@ -245,13 +428,13 @@ public override async Task ExecuteAsync()
"); -#line 73 "RequestPage.cshtml" +#line 123 "RequestPage.cshtml" Write(header.Key); #line default #line hidden WriteLiteral(""); -#line 74 "RequestPage.cshtml" +#line 124 "RequestPage.cshtml" Write(string.Join(";", header.Value)); #line default #line hidden WriteLiteral("
\r\n <" + "/td>\r\n \r\n \r\n Status Code\r" + "\n "); -#line 83 "RequestPage.cshtml" +#line 133 "RequestPage.cshtml" Write(context.StatusCode); #line default #line hidden WriteLiteral("\r\n \r\n \r\n User\r\n " + " "); -#line 87 "RequestPage.cshtml" +#line 137 "RequestPage.cshtml" Write(context.User.Identity.Name); #line default #line hidden WriteLiteral("\r\n \r\n \r\n Claims\r\n " + " \r\n"); -#line 92 "RequestPage.cshtml" +#line 142 "RequestPage.cshtml" #line default #line hidden -#line 92 "RequestPage.cshtml" +#line 142 "RequestPage.cshtml" if (context.User.Claims.Any()) { @@ -316,13 +499,13 @@ public override async Task ExecuteAsync() "); -#line 102 "RequestPage.cshtml" +#line 152 "RequestPage.cshtml" #line default #line hidden -#line 102 "RequestPage.cshtml" +#line 152 "RequestPage.cshtml" foreach (var claim in context.User.Claims) { @@ -331,26 +514,26 @@ public override async Task ExecuteAsync() WriteLiteral(" \r\n " + " "); -#line 105 "RequestPage.cshtml" +#line 155 "RequestPage.cshtml" Write(claim.Issuer); #line default #line hidden WriteLiteral("\r\n "); -#line 106 "RequestPage.cshtml" +#line 156 "RequestPage.cshtml" Write(claim.Value); #line default #line hidden WriteLiteral("\r\n \r\n"); -#line 108 "RequestPage.cshtml" +#line 158 "RequestPage.cshtml" } #line default #line hidden WriteLiteral(" \r\n \r\n"); -#line 111 "RequestPage.cshtml" +#line 161 "RequestPage.cshtml" } #line default @@ -358,27 +541,27 @@ public override async Task ExecuteAsync() WriteLiteral(" \r\n \r\n \r\n S" + "cheme\r\n "); -#line 116 "RequestPage.cshtml" +#line 166 "RequestPage.cshtml" Write(context.Scheme); #line default #line hidden WriteLiteral("\r\n \r\n \r\n Query\r\n " + " "); -#line 120 "RequestPage.cshtml" +#line 170 "RequestPage.cshtml" Write(context.Query.Value); #line default #line hidden WriteLiteral("\r\n \r\n \r\n Cookies\r\n " + " \r\n"); -#line 125 "RequestPage.cshtml" +#line 175 "RequestPage.cshtml" #line default #line hidden -#line 125 "RequestPage.cshtml" +#line 175 "RequestPage.cshtml" if (context.Cookies.Any()) { @@ -394,13 +577,13 @@ public override async Task ExecuteAsync() "); -#line 135 "RequestPage.cshtml" +#line 185 "RequestPage.cshtml" #line default #line hidden -#line 135 "RequestPage.cshtml" +#line 185 "RequestPage.cshtml" foreach (var cookie in context.Cookies) { @@ -409,46 +592,46 @@ public override async Task ExecuteAsync() WriteLiteral(" \r\n " + " "); -#line 138 "RequestPage.cshtml" +#line 188 "RequestPage.cshtml" Write(cookie.Key); #line default #line hidden WriteLiteral("\r\n "); -#line 139 "RequestPage.cshtml" +#line 189 "RequestPage.cshtml" Write(string.Join(";", cookie.Value)); #line default #line hidden WriteLiteral("\r\n \r\n"); -#line 141 "RequestPage.cshtml" +#line 191 "RequestPage.cshtml" } #line default #line hidden WriteLiteral(" \r\n \r\n"); -#line 144 "RequestPage.cshtml" +#line 194 "RequestPage.cshtml" } #line default #line hidden WriteLiteral(" \r\n \r\n \r\n"); -#line 148 "RequestPage.cshtml" +#line 198 "RequestPage.cshtml" } #line default #line hidden WriteLiteral("

Logs

\r\n
\r\n \r\n (Model.Options.NamePrefix, 5477), false)); + WriteAttribute("value", Tuple.Create(" value=\"", 6985), Tuple.Create("\"", 7018), + Tuple.Create(Tuple.Create("", 6993), Tuple.Create(Model.Options.NamePrefix, 6993), false)); WriteLiteral(@" /> @@ -510,79 +693,23 @@ public override async Task ExecuteAsync() Error -"); -#line 179 "RequestPage.cshtml" - - -#line default -#line hidden - -#line 179 "RequestPage.cshtml" - foreach (var log in Model.Logs) - { - -#line default -#line hidden - - WriteLiteral(" \r\n "); -#line 182 "RequestPage.cshtml" - Write(string.Format("{0:MM/dd/yy}", log.Time)); - -#line default -#line hidden - WriteLiteral("\r\n "); -#line 183 "RequestPage.cshtml" - Write(string.Format("{0:H:mm:ss}", log.Time)); - -#line default -#line hidden - WriteLiteral("\r\n (log.Severity.ToString().ToLowerInvariant(), 6087), false)); - WriteLiteral(">"); -#line 184 "RequestPage.cshtml" - Write(log.Severity); - -#line default -#line hidden - WriteLiteral("\r\n (log.Name, 6179), false)); - WriteLiteral(">"); -#line 185 "RequestPage.cshtml" - Write(log.Name); - -#line default -#line hidden - WriteLiteral("\r\n (log.Message, 6233), false)); - WriteLiteral(" class=\"logState\" width=\"100px\">"); -#line 186 "RequestPage.cshtml" - Write(log.Message); - -#line default -#line hidden - WriteLiteral("\r\n (log.Exception, 6324), false)); - WriteLiteral(">"); -#line 187 "RequestPage.cshtml" - Write(log.Exception); - -#line default -#line hidden - WriteLiteral("\r\n \r\n"); -#line 189 "RequestPage.cshtml" - } - -#line default -#line hidden - - WriteLiteral(" \r\n \r\n\r\n"); + "); +#line 229 "RequestPage.cshtml" + Write(Traverse(Model.Activity.Root)); + +#line default +#line hidden + WriteLiteral(@" + + + +"); } #pragma warning restore 1998 } diff --git a/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.cshtml b/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.cshtml index 188d9b58..60a4bf1b 100644 --- a/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.cshtml +++ b/src/Microsoft.AspNet.Diagnostics.Elm/Views/RequestPage.cshtml @@ -2,6 +2,7 @@ @using System.Globalization @using System.Linq @using Microsoft.AspNet.Diagnostics.Elm +@using Microsoft.AspNet.Diagnostics.Views @using Microsoft.AspNet.Diagnostics.Elm.Views @using Microsoft.Framework.Logging @@ -14,6 +15,55 @@ public RequestPageModel Model { get; set; } } + +@helper LogRow(LogInfo log) +{ + if (log.Severity >= Model.Options.MinLevel && + (string.IsNullOrEmpty(Model.Options.NamePrefix) || log.Name.StartsWith(Model.Options.NamePrefix, StringComparison.Ordinal))) + { + + @string.Format("{0:MM/dd/yy}", log.Time) + @string.Format("{0:H:mm:ss}", log.Time) + @log.Severity + @log.Name + @log.Message + @log.Exception + + } +} + +@helper Traverse(ScopeNode node) +{ + var messageIndex = 0; + var childIndex = 0; + while (messageIndex < node.Messages.Count && childIndex < node.Children.Count) + { + if (node.Messages[messageIndex].Time < node.Children[childIndex].StartTime) + { + @LogRow(node.Messages[messageIndex]) + messageIndex++; + } + else + { + @Traverse(node.Children[childIndex]) + childIndex++; + } + } + if (messageIndex < node.Messages.Count) + { + for (var i = messageIndex; i < node.Messages.Count; i++) + { + @LogRow(node.Messages[i]) + } + } + else + { + for (var i = childIndex; i < node.Children.Count; i++) + { + @Traverse(node.Children[i]) + } + } +} @@ -28,7 +78,7 @@

ASP.NET Logs

@{ - var context = Model.Logs.FirstOrDefault()?.ActivityContext?.HttpInfo; + var context = Model.Activity?.HttpInfo; } @if (context != null) { @@ -176,17 +226,7 @@ Error - @foreach (var log in Model.Logs) - { - - @string.Format("{0:MM/dd/yy}", log.Time) - @string.Format("{0:H:mm:ss}", log.Time) - @log.Severity - @log.Name - @log.Message - @log.Exception - - } + @Traverse(Model.Activity.Root)