Backend: Error Monitoring
Backend: Logging
Go
JS
Python
Ruby
Java
Rust
Hosting Providers
Backend: Tracing
Native OpenTelemetry
Fullstack Frameworks
Overview
Self Host & Local Dev
Menu
C# .NET 4 ASP
Error Monitoring / Logging / Tracing in .NET 4.x via the OpenTelemetry Protocol (OTLP).
1
.NET supports OpenTelemetry instrumentation out of the box.
Below, we explain how to define a HighlightConfig
class which will setup opentelemetry export to highlight.
2
Install dependencies.
Run the following in your .NET project to install dependencies.
dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocol
dotnet add package OpenTelemetry.Instrumentation.AspNet
3
Define the Highlight configuration class.
Copy the following code into a HighlightConfig.cs
file in your project. Make sure to update the ProjectId
and ServiceName
values.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Web;
using OpenTelemetry;
using OpenTelemetry.Exporter;
using OpenTelemetry.Metrics;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
namespace cs
{
public class HighlightTraceProcessor : BaseProcessor<Activity>
{
public override void OnStart(Activity data)
{
var ctx = HighlightConfig.GetHighlightContext();
foreach (var entry in ctx)
{
data.SetTag(entry.Key, entry.Value);
}
base.OnStart(data);
}
}
public class HighlightConfig
{
// For highlight.io self-hosted, update to your collector endpoint
public static readonly String OtlpEndpoint = "https://otel.highlight.io:4318";
// Replace with your project ID and service name.
public static readonly String ProjectId = "<YOUR_PROJECT_ID>";
public static readonly String ServiceName = "highlight-dot-net-example";
public static readonly String TracesEndpoint = OtlpEndpoint + "/v1/traces";
public static readonly String MetricsEndpoint = OtlpEndpoint + "/v1/metrics";
public static readonly OtlpExportProtocol ExportProtocol = OtlpExportProtocol.HttpProtobuf;
public static readonly String HighlightHeader = "x-highlight-request";
public static readonly Dictionary<string, object> ResourceAttributes = new Dictionary<string, object>
{
{ "highlight.project_id", ProjectId },
{ "service.name", ServiceName },
};
private static TracerProvider _tracerProvider;
private static MeterProvider _meterProvider;
public static Dictionary<string, string> GetHighlightContext()
{
var ctx = new Dictionary<string, string>
{
{ "highlight.project_id", ProjectId },
{ "service.name", ServiceName },
};
var headerValue = Baggage.GetBaggage(HighlightHeader);
if (headerValue == null) return ctx;
var parts = headerValue.Split('/');
if (parts.Length < 2) return ctx;
ctx["highlight.session_id"] = parts[0];
ctx["highlight.trace_id"] = parts[1];
return ctx;
}
private static void EnrichWithHttpRequest(Activity activity, HttpRequest httpRequest)
{
activity.SetTag("http.client_ip", httpRequest.UserHostAddress);
activity.SetTag("http.flavor", httpRequest.Url.Scheme);
activity.SetTag("http.host", httpRequest.UserHostName);
activity.SetTag("http.method", httpRequest.HttpMethod);
activity.SetTag("http.request_content_length", httpRequest.ContentLength);
activity.SetTag("http.request_content_type", httpRequest.ContentType);
activity.SetTag("http.request_query", httpRequest.Url.Query);
activity.SetTag("http.route", httpRequest.RequestContext.RouteData.Route);
activity.SetTag("http.scheme", httpRequest.Url.Scheme);
activity.SetTag("http.url", httpRequest.Path);
activity.SetTag("http.user_agent", httpRequest.Headers["User-Agent"]);
foreach(string header in httpRequest.Headers)
{
var value = httpRequest.Headers[header];
activity.SetTag($"http.request.header.{header}", value);
}
var headerValue = httpRequest.Headers.Get(HighlightHeader);
if (headerValue == null) return;
var parts = headerValue.Split('/');
if (parts.Length < 2) return;
activity.SetTag("highlight.session_id", parts[0]);
activity.SetTag("highlight.trace_id", parts[1]);
Baggage.SetBaggage(new[]
{
new KeyValuePair<string, string>(HighlightHeader, headerValue)
});
}
private static void EnrichWithHttpResponse(Activity activity, HttpResponse httpResponse)
{
activity.SetTag("http.status_code", httpResponse.StatusCode);
foreach(string header in httpResponse.Headers)
{
var value = httpResponse.Headers[header];
activity.SetTag($"http.request.header.{header}", value);
}
}
public static void Register()
{
_tracerProvider = Sdk.CreateTracerProviderBuilder()
.SetResourceBuilder(ResourceBuilder.CreateDefault().AddAttributes(ResourceAttributes))
.AddAspNetInstrumentation(options =>
{
options.RecordException = true;
options.EnrichWithHttpRequest = EnrichWithHttpRequest;
options.EnrichWithHttpResponse = EnrichWithHttpResponse;
})
.AddSource(ServiceName)
.AddProcessor(new HighlightTraceProcessor())
.AddOtlpExporter(exporterOptions =>
{
exporterOptions.Endpoint = new Uri(TracesEndpoint);
exporterOptions.Protocol = ExportProtocol;
})
.Build();
_meterProvider = Sdk.CreateMeterProviderBuilder()
.AddMeter(ServiceName)
.AddAspNetInstrumentation()
.AddOtlpExporter(options =>
{
options.Endpoint = new Uri(MetricsEndpoint);
options.Protocol = ExportProtocol;
})
.Build();
}
public static void Unregister()
{
_tracerProvider.Dispose();
_meterProvider.Dispose();
}
}
}
4
Bootstrap Highlight with your ASP 4 application MVC entrypoint.
Update your Global.asax.cs
application entrypoint to initialize highlight.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
namespace cs
{
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
HighlightConfig.Register();
}
protected void Application_End()
{
HighlightConfig.Unregister();
}
}
}
5
Verify your errors are being recorded.
Verify that the backend error handling works by triggering the code that reports the error to highlight and visiting the highlight errors portal.
6
Verify your backend logs are being recorded.
Visit the highlight logs portal and check that backend logs are coming in.
7
Verify your backend traces are being recorded.
Visit the highlight traces portal and check that backend traces are coming in.