Reputation: 3678
I have an ASP.NET Website. I am using the following code in Global.Asax.cs
protected void Application_BeginRequest(object sender, EventArgs e)
{
Context.Response.SetServerTiming(
new ServerTimingMetric("cache", 300, "Cache"),
new ServerTimingMetric("sql", 900, "Sql Server"),
new ServerTimingMetric("fs", 600, "FileSystem"),
new ServerTimingMetric("cpu", 1230, "Total CPU")
);
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
/// <summary>
/// Summary description for HttpResponseHeadersExtensions
/// </summary>
public static class HttpResponseHeadersExtensions
{
public static void SetServerTiming(this HttpResponse response, params ServerTimingMetric[] metrics)
{
ServerTimingHeaderValue serverTiming = new ServerTimingHeaderValue();
foreach (ServerTimingMetric metric in metrics)
{
serverTiming.Metrics.Add(metric);
response.Headers.Add("Server-Timing", serverTiming.ToString());
}
//response.Headers.Append("Server-Timing", serverTiming.ToString());
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
/// <summary>
/// Summary description for IServerTiming
/// </summary>
public interface IServerTiming
{
ICollection<ServerTimingMetric> Metrics { get; }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
internal class ServerTiming : IServerTiming
{
public ICollection<ServerTimingMetric> Metrics { get; }
public ServerTiming()
{
Metrics = new List<ServerTimingMetric>();
}
}
using System;
using System.Collections.Generic;
public class ServerTimingHeaderValue
{
public ICollection<ServerTimingMetric> Metrics { get; }
public ServerTimingHeaderValue()
{
Metrics = new List<ServerTimingMetric>();
}
public override string ToString()
{
return String.Join(",", Metrics);
}
}
using System.Globalization;
using System;
public struct ServerTimingMetric
{
private string _serverTimingMetric;
public string Name { get; }
public decimal? Value { get; }
public string Description { get; }
public ServerTimingMetric(string name, decimal? value, string description)
{
if (String.IsNullOrEmpty(name))
throw new ArgumentNullException(nameof(name));
Name = name;
Value = value;
Description = description;
_serverTimingMetric = null;
}
public override string ToString()
{
if (_serverTimingMetric == null)
{
_serverTimingMetric = Name;
if (Value.HasValue)
_serverTimingMetric = _serverTimingMetric + "=" + Value.Value.ToString(CultureInfo.InvariantCulture);
if (!String.IsNullOrEmpty(Description))
_serverTimingMetric = _serverTimingMetric + ";\"" + Description + "\"";
}
return _serverTimingMetric;
}
}
I am getting the following output,
Has anyone configured the Server Timing API for the old ASP.NET Website?
Upvotes: 1
Views: 579
Reputation: 23334
Your code sends out more than 1 Server-Timing
HTTP header while there should only be 1.
The image you included shows 4 cache
items in the lower left.
Also, the HTTP header value being sent out is not according to the specifications.
That is the reason why you only see cache
(4 times) in your image; the other parts are not being recognized.
In order to get the result you are looking for, that single Server-Timing
HTTP header must look like below.
Server-Timing: cache;desc="Cache";dur=300, sql;desc="Sql Server";dur=900, fs;desc="FileSystem";dur=600, cpu;desc="Total CPU";dur=1230
Each timing item has a name, e.g. cache
, optionally followed by key value pairs separated by a semicolon, with desc
for the description and dur
for the duration. When a description (desc
) is present and when it contains a space then it must be enclosed by double quotes.
An example: sql;desc="Sql Server";dur=900
With the correct header in place, my web browser (Chrome) shows below.
I made these changes.
HttpResponseHeadersExtensions
, add only a single Server-Timing
HTTP header.public static class HttpResponseHeadersExtensions
{
public static void SetServerTiming(this HttpResponse response, params ServerTimingMetric[] metrics)
{
ServerTimingHeaderValue serverTiming = new ServerTimingHeaderValue();
foreach (ServerTimingMetric metric in metrics)
{
serverTiming.Metrics.Add(metric);
}
response.Headers.Add("Server-Timing", serverTiming.ToString());
}
}
ServerTimingMetric
, format the string representation differently.public struct ServerTimingMetric
{
// Existing code left out for brevity.
public override string ToString()
{
if (_serverTimingMetric == null)
{
var builder = new StringBuilder(Name);
if (!string.IsNullOrEmpty(Description))
builder.AppendFormat(@";desc=""{0}""", Description);
if (Value != null)
builder.AppendFormat(@";dur=""{0}""", Value);
_serverTimingMetric = builder.ToString();
}
return _serverTimingMetric;
}
}
ServerTimingHeaderValue
, join the metrics by a comma and space instead of only by a comma.public class ServerTimingHeaderValue
{
// Other code left out for brevity.
public override string ToString()
{
return String.Join(", ", Metrics);
}
}
Upvotes: 1