Ejemplo n.º 1
0
        /// <summary>
        /// Gets a ClientTimings object from a <see cref="ResultRequest"/>.
        /// </summary>
        /// <param name="request">The request to convert.</param>
        /// <returns>A <see cref="ClientTimings"/> object.</returns>
        public static ClientTimings FromRequest(ResultRequest request)
        {
            var result = new ClientTimings()
            {
                RedirectCount = request.RedirectCount ?? 0,
                Timings       = new List <ClientTiming>(request.Performance?.Count + request.Probes?.Count ?? 0)
            };

            if (request.Performance?.Count > 0)
            {
                foreach (var t in request.Performance)
                {
                    if (t.Name?.EndsWith("End") == true)
                    {
                        continue;
                    }
                    result.Timings.Add(t);
                }
            }
            if (request.Probes?.Count > 0)
            {
                result.Timings.AddRange(request.Probes);
            }
            // Noise
            result.Timings.RemoveAll(t => t.Start < 0 || t.Duration < 0);
            // Sort for storage later
            result.Timings.Sort((a, b) => a.Start.CompareTo(b.Start));

            // TODO: Collapse client start/end timings? Probably...
            return(result);
        }
        /// <summary>
        /// Returns null if there is not client timing stuff
        /// </summary>
        /// <param name="request">The <see cref="HttpRequest"/> to get client timings from.</param>
        public static ClientTimings GetClientTimings(this HttpRequest request)
        {
            var dict = new Dictionary <string, string>();
            var form = request.Form;

            foreach (var k in form.AllKeys)
            {
                dict.Add(k, form[k]);
            }
            return(ClientTimings.FromForm(dict));
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Returns either json or full page html of a previous <see cref="MiniProfiler"/> session,
        /// identified by its <c>"?id=GUID"</c> on the query.
        /// </summary>
        /// <param name="context">The context to get a profiler response for.</param>
        private string GetSingleProfilerResult(HttpContext context)
        {
            Guid          id;
            ResultRequest clientRequest = null;
            // When we're rendering as a button/popup in the corner, it's an AJAX/JSON request.
            // If that's absent, we're rendering results as a full page for sharing.
            var jsonRequest = context.Request.Headers["Accept"]?.Contains("application/json") == true;

            // Try to parse from the JSON payload first
            if (jsonRequest &&
                context.Request.ContentLength > 0 &&
                ResultRequest.TryParse(context.Request.InputStream, out clientRequest) &&
                clientRequest.Id.HasValue)
            {
                id = clientRequest.Id.Value;
            }
            else if (Guid.TryParse(context.Request["id"], out id))
            {
                // We got the guid from the querystring
            }
            else if (Options.StopwatchProvider != null)
            {
                // Fall back to the last result
                id = Options.Storage.List(1).FirstOrDefault();
            }

            if (id == default(Guid))
            {
                return(jsonRequest ? NotFound(context) : NotFound(context, "text/plain", "No Guid id specified on the query string"));
            }

            var    profiler = Options.Storage.Load(id);
            string user     = Options.UserIdProvider?.Invoke(context.Request);

            Options.Storage.SetViewed(user, id);

            if (profiler == null)
            {
                return(jsonRequest ? NotFound(context) : NotFound(context, "text/plain", "No MiniProfiler results found with Id=" + id.ToString()));
            }

            bool needsSave = false;

            if (profiler.ClientTimings == null && clientRequest?.TimingCount > 0)
            {
                profiler.ClientTimings = ClientTimings.FromRequest(clientRequest);
                needsSave = true;
            }

            if (!profiler.HasUserViewed)
            {
                profiler.HasUserViewed = true;
                needsSave = true;
            }

            if (needsSave)
            {
                Options.Storage.Save(profiler);
            }

            if (!AuthorizeRequest(context, isList: false, message: out string authorizeMessage))
            {
                context.Response.ContentType = "application/json";
                return(@"""hidden"""); // JSON
            }

            return(jsonRequest ? ResultsJson(context, profiler) : ResultsFullPage(context, profiler));
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Returns null if there is not client timing stuff
        /// </summary>
        public static ClientTimings FromRequest(HttpRequest request)
        {
            ClientTimings timing = null;
            long navigationStart;
            long.TryParse(request[ClientTimingPrefix + "navigationStart]"], out navigationStart);
            if (navigationStart > 0)
            {
                var timings = new List<ClientTiming>();

                timing = new ClientTimings();

                int redirectCount;
                int.TryParse(request["clientPerformance[navigation][redirectCount]"], out redirectCount);
                timing.RedirectCount = redirectCount;

                var clientPerf = new Dictionary<string, ClientTiming>();
                var clientProbes = new Dictionary<int, ClientTiming>();

                foreach (
                    string key in
                        request.Form.Keys.Cast<string>()
                               .OrderBy(i => i.IndexOf("Start]", StringComparison.Ordinal) > 0 ? "_" + i : i))
                {
                    if (key.StartsWith(ClientTimingPrefix))
                    {
                        long val;
                        long.TryParse(request[key], out val);
                        val -= navigationStart;

                        string parsedName = key.Substring(
                            ClientTimingPrefix.Length, (key.Length - 1) - ClientTimingPrefix.Length);

                        // just ignore stuff that is negative ... not relevant
                        if (val > 0)
                        {
                            if (parsedName.EndsWith("Start"))
                            {
                                var shortName = parsedName.Substring(0, parsedName.Length - 5);
                                clientPerf[shortName] = new ClientTiming
                                                            {
                                                                Duration = -1,
                                                                Name = parsedName,
                                                                Start = val
                                                            };
                            }
                            else if (parsedName.EndsWith("End"))
                            {
                                var shortName = parsedName.Substring(0, parsedName.Length - 3);
                                ClientTiming t;
                                if (clientPerf.TryGetValue(shortName, out t))
                                {
                                    t.Duration = val - t.Start;
                                    t.Name = shortName;
                                }
                            }
                            else
                            {
                                clientPerf[parsedName] = new ClientTiming { Name = parsedName, Start = val, Duration = -1 };
                            }
                        }
                    }

                    if (key.StartsWith(ClientProbesPrefix))
                    { 
                        int probeId;
                        if (key.IndexOf("]", StringComparison.Ordinal) > 0 && int.TryParse(key.Substring(ClientProbesPrefix.Length, key.IndexOf("]", StringComparison.Ordinal) - ClientProbesPrefix.Length), out probeId))
                        {
                            ClientTiming t;
                            if (!clientProbes.TryGetValue(probeId, out t))
                            {
                                t = new ClientTiming();
                                clientProbes.Add(probeId, t);
                            }

                            if (key.EndsWith("[n]"))
                            {
                                t.Name = request[key];
                            }

                            if (key.EndsWith("[d]")) 
                            {
                                long val;
                                long.TryParse(request[key], out val);
                                if (val > 0)
                                {
                                    t.Start = val - navigationStart;
                                }
                            }
                        }
                    }
                }

                foreach (var group in clientProbes
                          .Values.OrderBy(p => p.Name)
                          .GroupBy(p => p.Name))
                {
                    ClientTiming current = null;
                    foreach (var item in group)
                    {
                        if (current == null)
                        {
                            current = item;
                        }
                        else
                        {
                            current.Duration = item.Start - current.Start;
                            timings.Add(current);
                            current = null;
                        }
                    }
                }

                foreach (var item in clientPerf.Values)
                {
                    item.Name = SentenceCase(item.Name);
                }

                timings.AddRange(clientPerf.Values);
                timing.Timings = timings.OrderBy(t => t.Start).ToList();
            }

            return timing;
        }
        /// <summary>
        /// Returns null if there is not client timing stuff
        /// </summary>
        public static ClientTimings FromRequest(HttpRequest request)
        {
            ClientTimings timing = null;
            long          navigationStart;

            long.TryParse(request[ClientTimingPrefix + "navigationStart]"], out navigationStart);
            if (navigationStart > 0)
            {
                var timings = new List <ClientTiming>();

                timing = new ClientTimings();

                int redirectCount;
                int.TryParse(request["clientPerformance[navigation][redirectCount]"], out redirectCount);
                timing.RedirectCount = redirectCount;

                var clientPerf   = new Dictionary <string, ClientTiming>();
                var clientProbes = new Dictionary <int, ClientTiming>();

                foreach (
                    string key in
                    request.Form.Keys.Cast <string>()
                    .OrderBy(i => i.IndexOf("Start]", StringComparison.Ordinal) > 0 ? "_" + i : i))
                {
                    if (key.StartsWith(ClientTimingPrefix))
                    {
                        long val;
                        long.TryParse(request[key], out val);
                        val -= navigationStart;

                        string parsedName = key.Substring(
                            ClientTimingPrefix.Length, (key.Length - 1) - ClientTimingPrefix.Length);

                        // just ignore stuff that is negative ... not relevant
                        if (val > 0)
                        {
                            if (parsedName.EndsWith("Start"))
                            {
                                var shortName = parsedName.Substring(0, parsedName.Length - 5);
                                clientPerf[shortName] = new ClientTiming
                                {
                                    Duration = -1,
                                    Name     = parsedName,
                                    Start    = val
                                };
                            }
                            else if (parsedName.EndsWith("End"))
                            {
                                var          shortName = parsedName.Substring(0, parsedName.Length - 3);
                                ClientTiming t;
                                if (clientPerf.TryGetValue(shortName, out t))
                                {
                                    t.Duration = val - t.Start;
                                    t.Name     = shortName;
                                }
                            }
                            else
                            {
                                clientPerf[parsedName] = new ClientTiming {
                                    Name = parsedName, Start = val, Duration = -1
                                };
                            }
                        }
                    }

                    if (key.StartsWith(ClientProbesPrefix))
                    {
                        int probeId;
                        if (key.IndexOf("]", StringComparison.Ordinal) > 0 && int.TryParse(key.Substring(ClientProbesPrefix.Length, key.IndexOf("]", StringComparison.Ordinal) - ClientProbesPrefix.Length), out probeId))
                        {
                            ClientTiming t;
                            if (!clientProbes.TryGetValue(probeId, out t))
                            {
                                t = new ClientTiming();
                                clientProbes.Add(probeId, t);
                            }

                            if (key.EndsWith("[n]"))
                            {
                                t.Name = request[key];
                            }

                            if (key.EndsWith("[d]"))
                            {
                                long val;
                                long.TryParse(request[key], out val);
                                if (val > 0)
                                {
                                    t.Start = val - navigationStart;
                                }
                            }
                        }
                    }
                }

                foreach (var group in clientProbes
                         .Values.OrderBy(p => p.Name)
                         .GroupBy(p => p.Name))
                {
                    ClientTiming current = null;
                    foreach (var item in group)
                    {
                        if (current == null)
                        {
                            current = item;
                        }
                        else
                        {
                            current.Duration = item.Start - current.Start;
                            timings.Add(current);
                            current = null;
                        }
                    }
                }

                foreach (var item in clientPerf.Values)
                {
                    item.Name = SentenceCase(item.Name);
                }

                timings.AddRange(clientPerf.Values);
                timing.Timings = timings.OrderBy(t => t.Start).ToList();
            }

            return(timing);
        }
        /// <summary>
        /// Returns either JSON or full page HTML of a previous <c>MiniProfiler</c> session,
        /// identified by its <c>"?id=GUID"</c> on the query.
        /// </summary>
        /// <param name="context">The context to get a profiler response for.</param>
        private async Task <string> GetSingleProfilerResultAsync(HttpContext context)
        {
            Guid          id;
            ResultRequest clientRequest = null;
            // When we're rendering as a button/popup in the corner, it's an AJAX/JSON request.
            // If that's absent, we're rendering results as a full page for sharing.
            bool jsonRequest = context.Request.Headers["Accept"].FirstOrDefault()?.Contains("application/json") == true;

            // Try to parse from the JSON payload first
            if (jsonRequest &&
                context.Request.ContentLength > 0 &&
                ResultRequest.TryParse(context.Request.Body, out clientRequest) &&
                clientRequest.Id.HasValue)
            {
                id = clientRequest.Id.Value;
            }
            else if (Guid.TryParse(context.Request.Query["id"], out id))
            {
                // We got the guid from the querystring
            }
            else if (Options.StopwatchProvider != null)
            {
                // Fall back to the last result
                id = (await Options.Storage.ListAsync(1).ConfigureAwait(false)).FirstOrDefault();
            }

            if (id == default(Guid))
            {
                return(NotFound(context, jsonRequest ? null : "No GUID id specified on the query string"));
            }

            var profiler = await Options.Storage.LoadAsync(id).ConfigureAwait(false);

            string user = Options.UserIdProvider?.Invoke(context.Request);

            await Options.Storage.SetViewedAsync(user, id).ConfigureAwait(false);

            if (profiler == null)
            {
                return(NotFound(context, jsonRequest ? null : "No MiniProfiler results found with Id=" + id.ToString()));
            }

            bool needsSave = false;

            if (profiler.ClientTimings == null && clientRequest?.TimingCount > 0)
            {
                profiler.ClientTimings = ClientTimings.FromRequest(clientRequest);
                needsSave = true;
            }

            if (!profiler.HasUserViewed)
            {
                profiler.HasUserViewed = true;
                needsSave = true;
            }

            if (needsSave)
            {
                await Options.Storage.SaveAsync(profiler).ConfigureAwait(false);
            }

            if (!AuthorizeRequest(context, isList: false, message: out string authorizeMessage))
            {
                context.Response.ContentType = "application/json";
                return(@"""hidden"""); // JSON
            }

            if (jsonRequest)
            {
                context.Response.ContentType = "application/json";
                return(profiler.ToJson());
            }
            else
            {
                context.Response.ContentType = "text/html; charset=utf-8";
                return(Render.SingleResultHtml(profiler, context.Request.PathBase + Options.RouteBasePath.Value.EnsureTrailingSlash()));
            }
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Returns either json or full page html of a previous <c>MiniProfiler</c> session,
        /// identified by its <c>"?id=GUID"</c> on the query.
        /// </summary>
        private static string GetSingleProfilerResult(HttpContext context)
        {
            // when we're rendering as a button/popup in the corner, we'll pass ?popup=1
            // if it's absent, we're rendering results as a full page for sharing
            var isPopup = context.Request["popup"].HasValue();

            // this guid is the MiniProfiler.Id property
            // if this guid is not supplied, the last set of results needs to be
            // displayed. The home page doesn't have profiling otherwise.
            Guid id;

            if (!Guid.TryParse(context.Request["id"], out id))
            {
                id = MiniProfiler.Settings.Storage.List(1).FirstOrDefault();
            }

            if (id == default(Guid))
            {
                return(isPopup ? NotFound(context) : NotFound(context, "text/plain", "No Guid id specified on the query string"));
            }

            MiniProfiler.Settings.EnsureStorageStrategy();
            var profiler = MiniProfiler.Settings.Storage.Load(id);

            var    provider = WebRequestProfilerProvider.Settings.UserProvider;
            string user     = null;

            if (provider != null)
            {
                user = provider.GetUser(context.Request);
            }

            MiniProfiler.Settings.Storage.SetViewed(user, id);

            if (profiler == null)
            {
                return(isPopup ? NotFound(context) : NotFound(context, "text/plain", "No MiniProfiler results found with Id=" + id.ToString()));
            }

            bool needsSave = false;

            if (profiler.ClientTimings == null)
            {
                profiler.ClientTimings = ClientTimings.FromRequest(context.Request);
                if (profiler.ClientTimings != null)
                {
                    needsSave = true;
                }
            }

            if (!profiler.HasUserViewed)
            {
                profiler.HasUserViewed = true;
                needsSave = true;
            }

            if (needsSave)
            {
                MiniProfiler.Settings.Storage.Save(profiler);
            }

            var authorize = MiniProfiler.Settings.Results_Authorize;

            if (authorize != null && !authorize(context.Request))
            {
                context.Response.ContentType = "application/json";
                return("hidden".ToJson());
            }

            return(isPopup ? ResultsJson(context, profiler) : ResultsFullPage(context, profiler));
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Returns either json or full page html of a previous <c>MiniProfiler</c> session,
        /// identified by its <c>"?id=GUID"</c> on the query.
        /// </summary>
        /// <param name="context">The context to get a profiler response for.</param>
        private async Task <string> GetSingleProfilerResultAsync(HttpContext context)
        {
            bool            jsonRequest = false;
            IFormCollection form        = null;

            // When we're rendering as a button/popup in the corner, we'll pass { popup: 1 } from jQuery
            // If it's absent, we're rendering results as a full page for sharing.
            if (context.Request.HasFormContentType)
            {
                form = await context.Request.ReadFormAsync().ConfigureAwait(false);

                // TODO: Get rid of popup and switch to application/json Accept header detection
                jsonRequest = form["popup"] == "1";
            }

            // This guid is the MiniProfiler.Id property. If a guid is not supplied,
            // the last set of results needs to be displayed.
            string requestId = form?["id"] ?? context.Request.Query["id"];

            if (!Guid.TryParse(requestId, out var id) && MiniProfiler.Settings.Storage != null)
            {
                id = (await MiniProfiler.Settings.Storage.ListAsync(1).ConfigureAwait(false)).FirstOrDefault();
            }

            if (id == default(Guid))
            {
                return(NotFound(context, jsonRequest ? null : "No GUID id specified on the query string"));
            }

            var profiler = await MiniProfiler.Settings.Storage.LoadAsync(id).ConfigureAwait(false);

            string user = Options.UserIdProvider?.Invoke(context.Request);

            await MiniProfiler.Settings.Storage.SetViewedAsync(user, id).ConfigureAwait(false);

            if (profiler == null)
            {
                return(NotFound(context, jsonRequest ? null : "No MiniProfiler results found with Id=" + id.ToString()));
            }

            bool needsSave = false;

            if (profiler.ClientTimings == null && form != null)
            {
                var dict = new Dictionary <string, string>();
                foreach (var k in form.Keys)
                {
                    dict.Add(k, form[k]);
                }
                profiler.ClientTimings = ClientTimings.FromForm(dict);

                if (profiler.ClientTimings != null)
                {
                    needsSave = true;
                }
            }

            if (!profiler.HasUserViewed)
            {
                profiler.HasUserViewed = true;
                needsSave = true;
            }

            if (needsSave)
            {
                await MiniProfiler.Settings.Storage.SaveAsync(profiler).ConfigureAwait(false);
            }

            if (!AuthorizeRequest(context, isList: false, message: out string authorizeMessage))
            {
                context.Response.ContentType = "application/json";
                return(@"""hidden"""); // JSON
            }

            return(jsonRequest ? ResultsJson(context, profiler) : ResultsFullPage(context, profiler));
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Returns null if there is not client timing stuff
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public static ClientTimings FromRequest(HttpRequest request)
        {
            ClientTimings timing = null;
            long navigationStart = 0;
            long.TryParse(request[clientTimingPrefix + "navigationStart]"], out navigationStart);
            if (navigationStart > 0)
            {
                timing = new ClientTimings();

                int redirectCount = 0;
                int.TryParse(request["clientPerformance[navigation][redirectCount]"], out redirectCount);
                timing.RedirectCount = redirectCount;

                foreach (string key in request.Form.Keys)
                {
                    if (key.StartsWith(clientTimingPrefix))
                    {
                        long val = 0;
                        long.TryParse(request[key], out val);
                        val -= navigationStart;

                        string parsedName = key.Substring(clientTimingPrefix.Length, (key.Length-1) - clientTimingPrefix.Length);

                        // just ignore stuff that is negative ... not relevant
                        if (val > 0)
                        {
                            switch (parsedName)
                            {
                                case "unloadEventStart" :
                                    timing.UnloadEventStart = val;
                                    break;
                                case "unloadEventEnd":
                                    timing.UnloadEventEnd = val;
                                    break;
                                case "redirectStart":
                                    timing.RedirectStart = val;
                                    break;
                                case "redirectEnd":
                                    timing.RedirectEnd = val;
                                    break;
                                case "fetchStart":
                                    timing.FetchStart = val;
                                    break;
                                case "domainLookupStart":
                                    timing.DomainLookupStart = val;
                                    break;
                                case "domainLookupEnd":
                                    timing.DomainLookupEnd = val;
                                    break;
                                case "connectStart":
                                    timing.ConnectStart = val;
                                    break;
                                case "connectEnd":
                                    timing.ConnectEnd = val;
                                    break;
                                case "secureConnectionStart":
                                    timing.SecureConnectionStart = val;
                                    break;
                                case "requestStart":
                                    timing.RequestStart = val;
                                    break;
                                case "responseStart":
                                    timing.ResponseStart = val;
                                    break;
                                case "responseEnd":
                                    timing.ResponseEnd = val;
                                    break;
                                case "domLoading":
                                    timing.DomLoading = val;
                                    break;
                                case "domInteractive":
                                    timing.DomInteractive = val;
                                    break;
                                case "domContentLoadedEventStart":
                                    timing.DomContentLoadedEventStart = val;
                                    break;
                                case "domContentLoadedEventEnd":
                                    timing.DomContentLoadedEventEnd = val;
                                    break;
                                case "domComplete":
                                    timing.DomComplete = val;
                                    break;
                                case "loadEventStart":
                                    timing.LoadEventStart = val;
                                    break;
                                case "loadEventEnd":
                                    timing.LoadEventEnd = val;
                                    break;
                                default:
                                    break;
                            }
                        }

                    }
                }
            }
            return timing;
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Returns either json or full page html of a previous <c>MiniProfiler</c> session,
        /// identified by its <c>"?id=GUID"</c> on the query.
        /// </summary>
        /// <param name="context">The context to get a profiler response for.</param>
        private async Task <string> GetSingleProfilerResultAsync(HttpContext context)
        {
            var isPost = context.Request.HasFormContentType;
            // when we're rendering as a button/popup in the corner, we'll pass ?popup=1
            // if it's absent, we're rendering results as a full page for sharing
            var isPopup = isPost && context.Request.Form["popup"].FirstOrDefault() == "1";
            // this guid is the MiniProfiler.Id property
            // if this guid is not supplied, the last set of results needs to be
            // displayed. The home page doesn't have profiling otherwise.
            var requestId = isPost
                ? context.Request.Form["id"]
                : context.Request.Query["id"];

            if (!Guid.TryParse(requestId, out var id) && MiniProfiler.Settings.Storage != null)
            {
                id = (await MiniProfiler.Settings.Storage.ListAsync(1).ConfigureAwait(false)).FirstOrDefault();
            }

            if (id == default(Guid))
            {
                return(isPopup ? NotFound(context) : NotFound(context, "No GUID id specified on the query string"));
            }

            var profiler = await MiniProfiler.Settings.Storage.LoadAsync(id).ConfigureAwait(false);

            string user = Options.UserIdProvider?.Invoke(context.Request);

            await MiniProfiler.Settings.Storage.SetViewedAsync(user, id).ConfigureAwait(false);

            if (profiler == null)
            {
                return(isPopup ? NotFound(context) : NotFound(context, "No MiniProfiler results found with Id=" + id.ToString()));
            }

            bool needsSave = false;

            if (profiler.ClientTimings == null && isPost)
            {
                var form = context.Request.Form;
                var dict = new Dictionary <string, string>();
                foreach (var k in form.Keys)
                {
                    dict.Add(k, form[k]);
                }
                profiler.ClientTimings = ClientTimings.FromForm(dict);

                if (profiler.ClientTimings != null)
                {
                    needsSave = true;
                }
            }

            if (!profiler.HasUserViewed)
            {
                profiler.HasUserViewed = true;
                needsSave = true;
            }

            if (needsSave)
            {
                await MiniProfiler.Settings.Storage.SaveAsync(profiler).ConfigureAwait(false);
            }

            if (!AuthorizeRequest(context, isList: false, message: out string authorizeMessage))
            {
                context.Response.ContentType = "application/json";
                return("\"hidden\""); // JSON
            }

            return(isPopup ? ResultsJson(context, profiler) : ResultsFullPage(context, profiler));
        }
Ejemplo n.º 11
0
        public async Task AdddClientTiming()
        {
            var resultRequest = await jsRuntime.InvokeAsync <ResultRequest>("MiniProfiler.Blazor.getClientTimings");

            MiniProfiler.Current.ClientTimings = ClientTimings.FromRequest(resultRequest);
        }