Skip to main content
Version: v0.1.0

Write different telemetry types

Logs are a great way to gain insights, but sometimes they are not the best approach for the job.

We provide the capability to track the following telemetry types on top of ILogger with good support on Serilog:

For most optimal output, we recommend using our Azure Application Insights sink.

Installation#

This feature requires to install our NuGet package

PM > Install-Package Arcus.Observability.Telemetry.Core -Version 0.1.0

Dependencies#

Dependencies allow you to track how your external dependencies are doing to give you insights on performance and error rate.

We provide support for the following dependencies:

Measuring Azure Service Bus dependencies#

We allow you to measure Azure Service Bus dependencies for both queues & topics.

Here is how you can report an Azure Service Bus Queue dependency:

using Arcus.Observability.Telemetry.Core;using Microsoft.Extensions.Logging;
var telemetryContext = new Dictionary<string, object>{    { "Namespace", "azure.servicebus.namespace" }};
var durationMeasurement = new Stopwatch();
// Start measuringdurationMeasurement.Start();var startTime = DateTimeOffset.UtcNow;
_logger.LogServiceBusQueueDependency(queueName: "ordersqueue", isSuccessful: true, startTime, durationMeasurement.Elapsed, telemetryContext);// Output: "Dependency Azure Service Bus Queue named ordersqueue in 00:00:00.2521801 at 03/23/2020 09:56:31 +00:00 (Successful: True - Context: [Namespace, azure.servicebus.namespace])"

Or alternatively one can use our DependencyMeasurement model to manage the timing for you:

using Arcus.Observability.Telemetry.Core;using Microsoft.Extensions.Logging;
var telemetryContext = new Dictionary<string, object>{    { "Namespace", "azure.servicebus.namespace" }};
// Start measuringusing (var measurement = DependencyMeasurement.Start()){    _logger.LogServiceBusQueueDependency(queueName: "ordersqueue", isSuccessful: true, measurement, telemetryContext);    // Output: "Dependency Azure Service Bus Queue named ordersqueue in 00:00:00.2521801 at 03/23/2020 09:56:31 +00:00 (Successful: True - Context: [Namespace, azure.servicebus.namespace])"}

Note that we have an LogServiceBusTopicDependency to log dependency logs for an Azure Service Bus Topic and an LogServiceBusDependency to log Azure Service Bus logs where the entity type is not known.

Measuring HTTP dependencies#

Here is how you can report a HTTP dependency:

using Microsoft.Extensions.Logging;
var telemetryContext = new Dictionary<string, object>{    { "Tenant", "Contoso"},};
var durationMeasurement = new Stopwatch();
// Create requestvar request = new HttpRequestMessage(HttpMethod.Post, "http://requestbin.net/r/ujxglouj"){    Content = new StringContent("{\"message\":\"Hello World!\"")};
// Start measuringdurationMeasurement.Start();var startTime = DateTimeOffset.UtcNow;// Send request to dependant servicevar response = await httpClient.SendAsync(request);
_logger.LogHttpDependency(request, response.StatusCode, startTime, durationMeasurement.Elapsed, telemetryContext);// Output: "HTTP Dependency requestbin.net for POST /r/ujxglouj completed with 200 in 00:00:00.2521801 at 03/23/2020 09:56:31 +00:00 (Successful: True - Context: [Tenant, Contoso])"

Or alternatively one can use our DependencyMeasurement model to manage the timing for you:

using Arcus.Observability.Telemetry.Core;using Microsoft.Extensions.Logging;
var telemetryContext = new Dictionary<string, object>{    { "Tenant", "Contoso"},};
// Create requestvar request = new HttpRequestMessage(HttpMethod.Post, "http://requestbin.net/r/ujxglouj"){    Content = new StringContent("{\"message\":\"Hello World!\"")};
// Start measuringusing (var measurement = DependencyMeasurement.Start()){    // Send request to dependant service    var response = await httpClient.SendAsync(request);        _logger.LogHttpDependency(request, response.StatusCode, measurement, telemetryContext);    // Output: "HTTP Dependency requestbin.net for POST /r/ujxglouj completed with 200 in 00:00:00.2521801 at 03/23/2020 09:56:31 +00:00 (Successful: True - Context: [Tenant, Contoso])"}

Measuring SQL dependencies#

Here is how you can report a SQL dependency:

using Microsoft.Extensions.Logging;
var telemetryContext = new Dictionary<string, object>{    { "Catalog", "Products"},    { "Tenant", "Contoso"},};
var durationMeasurement = new Stopwatch();
// Start measuringvar startTime = DateTimeOffset.UtcNow;durationMeasurement.Start();
// Interact with databasevar products = await _repository.GetProducts();
_logger.LogSqlDependency("sample-server", "sample-database", "my-table", "get-products", isSuccessful: true, startTime: startTime, duration: durationMeasurement.Elapsed, context: telemetryContext);// Output: "SQL Dependency sample-server for sample-database/my-table for operation get-products in 00:00:01.2396312 at 03/23/2020 09:32:02 +00:00 (Successful: True - Context: [Catalog, Products], [Tenant, Contoso])"

Or alternatively, one can use our DependencyMeasurement model to manage the timing for you:

using Arcus.Observability.Telemetry.Core;using Microsoft.Extensions.Logging;
var telemetryContext = new Dictionary<string, object>{    { "Catalog", "Products"},    { "Tenant", "Contoso"},};
// Start measuringusing (var measurement = DependencyMeasurement.Start("get-products")){    // Interact with database    var products = await _repository.GetProducts();        _logger.LogSqlDependency("sample-server", "sample-database", "my-table", "get-products", isSuccessful: true, measurement: measurement, context: telemetryContext);    // Output: "SQL Dependency sample-server for sample-database/my-table for operation get-products in 00:00:01.2396312 at 03/23/2020 09:32:02 +00:00 (Successful: True - Context: [Catalog, Products], [Tenant, Contoso])"}

Measuring custom dependencies#

Here is how you can areport a custom depenency:

using Microsoft.Extensions.Logging;
var telemetryContext = new Dictionary<string, object>{    { "Subject", "Your order is being processed!" },    { "OrderId", "ABC" }};
// Start measuringvar startTime = DateTimeOffset.UtcNow;durationMeasurement.Start();
string dependencyName = "SendGrid";object dependencyData = "http://my.sendgrid.uri/"
_logger.LogDependency("SendGrid", dependencyData, isSuccessful: true, startTime: startTime, duration: durationMeasurement.Elapsed, context: telemetryContext);// Output: "Dependency SendGrid http://my.sendgrid.uri/ in 00:00:01.2396312 at 03/23/2020 09:32:02 +00:00 (Successful: True - Context: [Subject, Your order is being processed!], [OrderId, ABC])"

Or alternatively, one can use our DependencyMeasurement model to manage the timing for you:

using Arcus.Observability.Telemetry.Core;using Microsoft.Extensions.Logging;
var telemetryContext = new Dictionary<string, object>{    { "Subject", "Your order is being processed!" },    { "OrderId", "ABC" }};
// Start measuringusing (var measurement = DependencyMeasurement.Start()){    string dependencyName = "SendGrid";    object dependencyData = "http://my.sendgrid.uri/"
    _logger.LogDependency("SendGrid", dependencyData, isSuccessful: true, measurement: measurement, context: telemetryContext);    // Output: "Dependency SendGrid http://my.sendgrid.uri/ in 00:00:01.2396312 at 03/23/2020 09:32:02 +00:00 (Successful: True - Context: [Subject, Your order is being processed!], [OrderId, ABC])"}

Events#

Events allow you to report custom events which are a great way to track business-related events.

Here is how you can report an Order Created event:

logger.LogEvent("Order Created");// Output: "Events Order Created (Context: )"

Contextual information is essential, that's why we provide an overload to give more information about the event:

using Microsoft.Extensions.Logging;
// Provide context around eventvar telemetryContext = new Dictionary<string, object>{    {"Customer", "Arcus"},    {"OrderId", "ABC"},};
logger.LogEvent("Order Created", telemetryContext);// Output: "Events Order Created (Context: [Customer, Arcus], [OrderId, ABC])"

Security Events#

Some events are considered "security events" when they relate to possible malicious activity, authentication, input validation...

Here is how an invalid Order can be reported:

using Microsoft.Extensions.Logging;
// Provide context around security eventvar telemetryContext = new Dictionary<string, object>{    {"OrderId", "OrderId was not in correct format"}};
loger.LogSecurityEvent("Invalid Order", telemetryContext);// Output: "Events Invalid Order (Context: [EventType, Security], [OrderId, OrderId was not in correct format])"

Metrics#

Metrics allow you to report custom metrics which allow you to give insights on application-specific metrics.

Here is how you can report an Invoice Received metric:

using Microsoft.Extensions.Logging;
// Provide context around metricvar telemetryContext = new Dictionary<string, object>{    { "InvoiceId", "ABC"},    { "Vendor", "Contoso"},};
logger.LogMetric("Invoice Received", 133.37, telemetryContext);// Output: "Metric Invoice Received: 133.37 (Context: [InvoiceId, ABC], [Vendor, Contoso])"

By using contextual information, you can create powerful metrics. When writing to Application Insights, for example, which will report the Invoice Received metric as multi-dimensional metrics which allow you to filter the metric based on its context.

Requests#

Requests allow you to keep track of the HTTP requests that are performed against your API and what the response was that was sent out.

Here is how you can keep track of requests:

using Microsoft.Extensions.Logging;
// Determine calling tenantstring tenantName = "Unknown";if (httpContext.Request?.Headers?.ContainsKey("X-Tenant") == true){    tenantName = httpContext.Request.Headers["X-Tenant"];}
// Provide context around requestvar telemetryContext = new Dictionary<string, object>{    { "Tenant", tenantName},};
var stopWatch = Stopwatch.StartNew();
// Perform action that creates a response, in this case call next middleware in the chain.await _next(httpContext);
logger.LogRequest(httpContext.Request, httpContext.Response, stopWatch.Elapsed, telemetryContext);// Output: "HTTP Request GET http://localhost:5000//weatherforecast completed with 200 in 00:00:00.0191554 at 03/23/2020 10:12:55 +00:00 - (Context: [Tenant, Contoso])"