private void HandleServerTiming(HttpContext context, IServerTiming serverTiming) { context.Response.OnStarting(() => { if (serverTiming.Metrics.Count > 0) { context.Response.SetServerTiming(new ServerTimingHeaderValue(serverTiming.Metrics)); } return(_completedTask); }); }
private async Task HandleServerTimingAsync(HttpContext context, IServerTiming serverTiming) { if (context.Request.AllowsTrailers() && context.Response.SupportsTrailers()) { await HandleServerTimingAsTrailerHeaderAsync(context, serverTiming); } else { await HandleServerTimingAsResponseHeaderAsync(context, serverTiming); } }
public WebCamGallery(IConfiguration configuration, IServerTiming serverTiming) { Watch = new Stopwatch(); Watch.Start(); _imageDirectory = configuration["ImageDirectory"]; _serverTiming = serverTiming; BaseWebCamURL = configuration["BaseWebCamURL"]; LiveWebCamURL = configuration["LiveWebCamURL"]; }
/// <summary> /// Time an async task. /// </summary> /// <typeparam name="T">Type of the task.</typeparam> /// <param name="task">The <see cref="Task"/> to time.</param> /// <param name="serverTiming">The <see cref="IServerTiming"/> to add metric to.</param> /// <param name="metricName">Optional, metric name, if passed will override any caller name.</param> /// <param name="functionName">Optional, populated compile-time with the name of the calling function.</param> /// <param name="filePath">Optional, populated compile-time with the path to the calling file.</param> /// <param name="lineNumber">Optional, populated compile-time with line number in the calling file.</param> /// <returns></returns> public static async Task <T> TimeTask <T>(this IServerTiming serverTiming, Task <T> task, string metricName = null, [CallerMemberName] string functionName = null, [CallerFilePath] string filePath = null, [CallerLineNumber] int lineNumber = 0) { using (serverTiming.TimeAction(metricName, functionName, filePath, lineNumber)) { return(await task); } }
/// <summary> /// Called on GET. /// </summary> /// <param name="configuration">The configuration.</param> /// <param name="serverTiming">The server timing.</param> /// <param name="fileName">Name of the file.</param> /// <returns></returns> public IActionResult OnGet([FromServices] IConfiguration configuration, [FromServices] IServerTiming serverTiming, string fileName) { var watch = new Stopwatch(); watch.Start(); string imageDirectory = configuration["ImageDirectory"]; if (string.IsNullOrEmpty(fileName) || string.IsNullOrEmpty(imageDirectory)) { serverTiming.Metrics.Add(new Lib.AspNetCore.ServerTiming.Http.Headers.ServerTimingMetric("GET", watch.ElapsedMilliseconds, "error")); return(NotFound("No image directory present")); } string path = Path.Combine(imageDirectory, fileName); if (System.IO.File.Exists(path)) { if (Path.GetDirectoryName(path) == imageDirectory) { var fi = new FileInfo(path); var length = fi.Length; DateTimeOffset last = fi.LastWriteTime; // Truncate to the second. var lastModified = new DateTimeOffset(last.Year, last.Month, last.Day, last.Hour, last.Minute, last.Second, last.Offset).ToUniversalTime(); long etagHash = lastModified.ToFileTime() ^ length; var etag_str = $"\"{Convert.ToString(etagHash, 16)}\""; if (Request.Headers.TryGetValue(HeaderNames.IfNoneMatch, out StringValues incomingEtag) && string.Compare(incomingEtag[0], etag_str) == 0) { Response.Clear(); Response.StatusCode = (int)HttpStatusCode.NotModified; serverTiming.Metrics.Add(new Lib.AspNetCore.ServerTiming.Http.Headers.ServerTimingMetric("GET", watch.ElapsedMilliseconds, "NotModified GET")); return(new StatusCodeResult((int)HttpStatusCode.NotModified)); } var etag = new EntityTagHeaderValue(etag_str); //var fs = new FileStream(path, FileMode.Open, FileAccess.Read); PhysicalFileResult pfr = base.PhysicalFile(path, MediaTypeNames.Image.Jpeg); pfr.EntityTag = etag; //pfr.LastModified = lastModified; serverTiming.Metrics.Add(new Lib.AspNetCore.ServerTiming.Http.Headers.ServerTimingMetric("GET", watch.ElapsedMilliseconds, "full file GET")); return(pfr); } } serverTiming.Metrics.Add(new Lib.AspNetCore.ServerTiming.Http.Headers.ServerTimingMetric("GET", watch.ElapsedMilliseconds, "not found GET")); return(NotFound()); }
private void HandleServerTiming(HttpContext context) { context.Response.OnStarting(() => { IServerTiming serverTiming = context.RequestServices.GetRequiredService <IServerTiming>(); if (serverTiming.Metrics.Count > 0) { context.Response.SetServerTiming(new ServerTimingHeaderValue(serverTiming.Metrics)); } return(_completedTask); }); }
public WebCamGallery(IConfiguration configuration, IServerTiming serverTiming) : base(configuration) { Watch = new Stopwatch(); Watch.Start(); _imageDirectory = configuration["ImageDirectory"]; _serverTiming = serverTiming; BaseWebCamURL = configuration["BaseWebCamURL"]; LiveWebCamURL = configuration["LiveWebCamURL"]; YouTubePlaylistId = configuration["YouTubeAPI:playlistId"]; }
public void Configure(IApplicationBuilder app) { app.UseServerTiming() .Run(async(context) => { IServerTiming serverTiming = context.RequestServices.GetService <IServerTiming>(); await Task.Delay(DELAY_SERVER_TIMING_METRIC_VALUE); serverTiming.Metrics.Add(new ServerTimingMetric(DELAY_SERVER_TIMING_METRIC_NAME, DELAY_SERVER_TIMING_METRIC_VALUE, DELAY_SERVER_TIMING_METRIC_DESCRIPTION)); await context.Response.WriteAsync(RESPONSE_BODY); }); }
/// <summary> /// Process an individual request. /// </summary> /// <param name="context">The context.</param> /// <param name="serverTiming">The instance of <see cref="IServerTiming"/> for current requet.</param> /// <returns>The task object representing the asynchronous operation.</returns> public Task Invoke(HttpContext context, IServerTiming serverTiming) { if (serverTiming is null) { throw new ArgumentNullException(nameof(serverTiming)); } if (_timingAllowOriginHeaderValue != null) { context.Response.SetResponseHeader(HeaderNames.TimingAllowOrigin, _timingAllowOriginHeaderValue); } return(HandleServerTimingAsync(context, serverTiming)); }
/// <summary> /// Time a block of code. /// </summary> /// <param name="serverTiming">The <see cref="IServerTiming"/> to add metric to.</param> /// <param name="metricName">Optional, metric name, if passed will override any caller name.</param> /// <param name="functionName">Optional, populated compile-time with the name of the calling function.</param> /// <param name="filePath">Optional, populated compile-time with the path to the calling file.</param> /// <param name="lineNumber">Optional, populated compile-time with line number in the calling file.</param> public static IDisposable TimeAction(this IServerTiming serverTiming, string metricName = null, [CallerMemberName] string functionName = null, [CallerFilePath] string filePath = null, [CallerLineNumber] int lineNumber = 0) { if (serverTiming is null) { return(null); } string caller = metricName ?? FormatCallerName(functionName, filePath, lineNumber); return(new ServerTimingInstance(serverTiming, caller)); }
private Task HandleServerTimingAsResponseHeaderAsync(HttpContext context, IServerTiming serverTiming) { context.Response.OnStarting(() => { if (serverTiming.Metrics.Count > 0) { context.Response.SetServerTiming(new ServerTimingHeaderValue(serverTiming.Metrics)); } return(_completedTask); }); serverTiming.SetServerTimingDeliveryMode(ServerTimingDeliveryMode.ResponseHeader); return(_next(context)); }
/// <summary> /// Add a timed metric to the timing, if present. /// </summary> /// <param name="serverTiming">The <see cref="IServerTiming"/> to add metric to.</param> /// <param name="duration">The duration to log in ms.</param> /// <param name="metricName">The name of the metric to log.</param> /// <param name="functionName">Optional, populated compile-time with the name of the calling function</param> /// <param name="filePath">Optional, populated compile-time with the path to the calling file</param> /// <param name="lineNumber">Optional, populated compile-time with line number in the calling file</param> public static void AddMetric(this IServerTiming serverTiming, decimal duration, string metricName = null, [CallerMemberName] string functionName = null, [CallerFilePath] string filePath = null, [CallerLineNumber] int lineNumber = 0) { if (serverTiming is null) { return; } ServerTimingMetric metric = new ServerTimingMetric(metricName ?? FormatCallerName(functionName, filePath, lineNumber), duration); serverTiming.Metrics.Add(metric); }
/// <summary> /// Called on live image GET. /// </summary> /// <param name="configuration">The configuration.</param> /// <param name="serverTiming">The server timing.</param> /// <param name="fileName">Name of the file.</param> /// <returns></returns> public async Task <IActionResult> OnGetLiveAsync([FromServices] IServerTiming serverTiming, [FromServices] IMjpgStreamerHttpClient client) { var watch = new Stopwatch(); watch.Start(); try { var file = await client.GetLiveImage(HttpContext.RequestAborted); return(file); } catch (Exception) { throw; } finally { serverTiming.Metrics.Add(new Lib.AspNetCore.ServerTiming.Http.Headers.ServerTimingMetric("GET", watch.ElapsedMilliseconds, "live image get")); } }
internal async Task OnResponseCompleted(HttpContext httpContext, IServerTiming serverTiming, IReadOnlyList <IServerTimingCallback> callbacks) { var metrics = serverTiming.GetMetrics(); var timingEvent = new ServerTimingEvent(httpContext, metrics); var tasks = new Task[callbacks.Count]; for (var i = 0; i < callbacks.Count; i++) { tasks[i] = callbacks[i].OnServerTiming(timingEvent); } var aggregationTask = Task.WhenAll(tasks); try { await aggregationTask; } // ReSharper disable once EmptyGeneralCatchClause catch (Exception) { // AggregateException will be available below with exceptions from all tasks. } if (aggregationTask.Exception == null) { return; } var innerExceptions = aggregationTask.Exception.InnerExceptions; // ReSharper disable once ForCanBeConvertedToForeach for (var i = 0; i < innerExceptions.Count; i++) { _logger.LogError(innerExceptions[i], "Exception was thrown invoking Server Timing callback"); } }
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseServerTiming() .UseRouting() .UseEndpoints(endpoints => { endpoints.MapControllers(); }) .Run(async(context) => { IServerTiming serverTiming = context.RequestServices.GetRequiredService <IServerTiming>(); serverTiming.Metrics.Add(new ServerTimingMetric("cache", 300, "Cache")); serverTiming.Metrics.Add(new ServerTimingMetric("sql", 900, "Sql Server")); serverTiming.Metrics.Add(new ServerTimingMetric("fs", 600, "FileSystem")); serverTiming.Metrics.Add(new ServerTimingMetric("cpu", 1230, "Total CPU")); await context.Response.WriteAsync("-- Demo.AspNetCore.ServerTiming --"); }); }
private Task HandleServerTimingAsync(HttpContext context, IServerTiming serverTiming) { return(HandleServerTimingAsResponseHeaderAsync(context, serverTiming)); }
private async Task HandleServerTimingAsTrailerHeaderAsync(HttpContext context, IServerTiming serverTiming) { context.Response.DeclareTrailer(HeaderNames.ServerTiming); serverTiming.SetServerTimingDeliveryMode(ServerTimingDeliveryMode.Trailer); await _next(context); RunServerTimingMetricFilters(serverTiming, context); if (serverTiming.Metrics.Any()) { context.Response.SetServerTimingTrailer(new ServerTimingHeaderValue(serverTiming.Metrics)); } }
public SampleController(IServerTiming serverTiming) => _serverTiming = serverTiming;
internal Task OnResponseStarting(HttpContext httpContext, IManualMetric totalMetric, IServerTiming serverTiming, RequestTimingOptions requestOptions) { totalMetric.Stop(); var metrics = serverTiming.GetMetrics(); if (_options.ValidateMetrics && httpContext.Response.StatusCode != 500) { // ReSharper disable once ForCanBeConvertedToForeach for (var i = 0; i < metrics.Count; i++) { if (metrics[i] is IValidatableMetric validatableMetric) { if (!validatableMetric.Validate(out var message)) { _logger.LogWarning(message); } } } } if (!requestOptions.WriteHeader) { return(Task.CompletedTask); } if (!requestOptions.IncludeCustomMetrics) { metrics = new[] { (IMetric)totalMetric } } ; _headerWriter.WriteHeaders(httpContext.Response.Headers, requestOptions.IncludeDescriptions, metrics); return(Task.CompletedTask); }