Skip to content

Commit

Permalink
Docs - publish v2.0 feature docs (#172)
Browse files Browse the repository at this point in the history
* Docs - publish v2.0 feature docs

* Update index.md
  • Loading branch information
stijnmoreels authored Jan 8, 2021
1 parent 4eded15 commit aa7c671
Show file tree
Hide file tree
Showing 11 changed files with 1,272 additions and 18 deletions.
5 changes: 4 additions & 1 deletion docs/features/telemetry-enrichment.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,9 @@ Value: `0477E377-414D-47CD-8756-BCBE3DBE3ACB`
**Usage**

```csharp
IServiceProvider serviceProvider = ...
ILogger logger = new LoggerConfiguration()
.Enrich.WithCorrelationInfo()
.Enrich.WithCorrelationInfo(serviceProvider)
.CreateLogger();

logger.Information("This event will be enriched with the correlation information");
Expand All @@ -112,8 +113,10 @@ The correlation information enricher allows you to specify the names of the log
This is available on all extension overloads. By default the operation ID is set to `OperationId` and the transaction ID to `TransactionId`.

```csharp
IServiceProvider serviceProvider = ...
ILogger logger = new LoggerConfiguration()
.Enrich.WithCorrelationInfo(
serviceProvider,
operationIdPropertyName: "MyOperationId",
transactionIdPropertyName: "MyTransactionId")
.CreateLogger();
Expand Down
64 changes: 47 additions & 17 deletions docs/features/writing-different-telemetry-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ We provide support for the following dependencies:
- [Azure Cosmos DB](#measuring-azure-cosmos-db-dependencies)
- [Azure Event Hubs](#measuring-azure-event-hubs-dependencies)
- [Azure IoT Hub](#measuring-azure-iot-hub-dependencies)
- [Azure Key Vault](#measuring-azure-key-vault-dependencies)
- [Azure Search](#measuring-azure-search-dependencies)
- [Azure Service Bus](#measuring-azure-service-bus-dependencies)
- [Azure Table Storage](#measuring-azure-table-storage-dependencies)
Expand All @@ -60,7 +61,7 @@ var durationMeasurement = new Stopwatch();
durationMeasurement.Start();
var startTime = DateTimeOffset.UtcNow;

_logger.LogBlobStorageDependency(accountName: "multimedia", containerName: "images", isSuccessful: true, startTime, durationMeasurement.Elapsed);
logger.LogBlobStorageDependency(accountName: "multimedia", containerName: "images", isSuccessful: true, startTime, durationMeasurement.Elapsed);
// Output: "Dependency Azure blob multimedia named images in 00:00:00.2521801 at 03/23/2020 09:56:31 +00:00 (Successful: True - Context: )"
```

Expand All @@ -79,7 +80,7 @@ var durationMeasurement = new Stopwatch();
durationMeasurement.Start();
var startTime = DateTimeOffset.UtcNow;

_logger.LogCosmosSqlDependency(accountName: "administration", database: "docs", container: "purchases", isSuccessful: true, startTime: startTime, duration: durationMeasurement.Elapsed);
logger.LogCosmosSqlDependency(accountName: "administration", database: "docs", container: "purchases", isSuccessful: true, startTime: startTime, duration: durationMeasurement.Elapsed);
// Output: "Dependency Azure DocumentDB docs/purchases named administration in 00:00:00.2521801 at 03/23/2020 09:56:31 +00:00 (Successful: True - Context: )"
```

Expand All @@ -96,7 +97,7 @@ var durationMeasurement = new Stopwatch();
durationMeasurement.Start();
var startTime = DateTimeOffset.UtcNow;

_logger.LogEventHubsDependency(namespaceName: "be.sensors.contoso", eventHubName: "temperature", isSuccessful: true, startTime: startTime, duration: durationMeasurement.Elapsed);
logger.LogEventHubsDependency(namespaceName: "be.sensors.contoso", eventHubName: "temperature", isSuccessful: true, startTime: startTime, duration: durationMeasurement.Elapsed);
// Output: "Dependency Azure Event Hubs be.sensors.contoso named temerature in 00:00:00.2521801 at 03/23/2020 09:56:31 +00:00 (Successful: True - Context: )"
```

Expand All @@ -115,7 +116,7 @@ var durationMeasurement = new Stopwatch();
durationMeasurement.Start();
var startTime = DateTimeOffset.UtcNow;

_logger.logger.LogIotHubDependency(iotHubName: "sensors", isSuccessful: true, startTime: startTime, duration: durationMeasurement.Elapsed);
logger.LogIotHubDependency(iotHubName: "sensors", isSuccessful: true, startTime: startTime, duration: durationMeasurement.Elapsed);
// Output: "Dependency Azure IoT Hub named sensors in 00:00:00.2521801 at 03/23/2020 09:56:31 +00:00 (Successful: True - Context: )"
```

Expand All @@ -140,10 +141,29 @@ var durationMeasurement = new Stopwatch();
durationMeasurement.Start();
var startTime = DateTimeOffset.UtcNow;

_logger.logger.LogIotHubDependency(iotHubConnectionString: "Hostname=sensors;", isSuccessful: true, startTime: startTime, duration: durationMeasurement.Elapsed);
logger.LogIotHubDependency(iotHubConnectionString: "Hostname=sensors;", isSuccessful: true, startTime: startTime, duration: durationMeasurement.Elapsed);
// Output: "Dependency Azure IoT Hub named sensors in 00:00:00.2521801 at 03/23/2020 09:56:31 +00:00 (Successful: True - Context: )"
```

### Measuring Azure Key Vault dependencies

We allow you to measure Azure Key vault dependencies.

**Example**

Here is how you can report a dependency call:

```csharp
var durationMeasurement = new StopWatch();

// Start measuring
durationMeasurement.Start();
var startTime = DateTimeOffset.UtcNow;

logger.AzureKeyVaultDependency(vaultUri: "https://my-secret-store.vault.azure.net", secretName: "ServiceBus-ConnectionString", isSuccessful: true, startTime: startTime, duration: durationMeasurement.Elapsed);
// Output: "Dependency Azure key vault get secret named https://my-secret-store.vault.azure.net in 00:00:00.2521801 at 03/23/2020 09:56:31 +00:00 (Successful: True - Context: )"
```

### Measuring Azure Search dependencies

We allow you to measure Azure Search depdendencies for cognetive services.
Expand All @@ -157,7 +177,7 @@ var durationMeasurement = new Stopwatch();
durationMeasurement.Start();
var startTime = DateTimeOffset.UtcNow;

_logger.LogAzureSearchDependency(searchServiceName: "orders-search", operationName: "get-orders", isSuccessful: true, startTime: startTime, duration: durationMeasurement.Elapsed);
logger.LogAzureSearchDependency(searchServiceName: "orders-search", operationName: "get-orders", isSuccessful: true, startTime: startTime, duration: durationMeasurement.Elapsed);
// Output: "Dependency Azure Search get-orders named orders-search in 00:00:00.2521801 at 03/23/2020 09:56:31 +00:00 (Successful: True - Context: )"
### Measuring Azure Service Bus dependencies
Expand All @@ -173,7 +193,7 @@ var durationMeasurement = new Stopwatch();
durationMeasurement.Start();
var startTime = DateTimeOffset.UtcNow;

_logger.LogServiceBusQueueDependency(queueName: "ordersqueue", isSuccessful: true, startTime: startTime, duration: durationMeasurement.Elapsed);
logger.LogServiceBusQueueDependency(queueName: "ordersqueue", isSuccessful: true, startTime: startTime, duration: durationMeasurement.Elapsed);
// 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: )"
```

Expand All @@ -192,7 +212,7 @@ var durationMeasurement = new Stopwatch();
durationMeasurement.Start();
var startTime = DateTimeOffset.UtcNow;

_logger.LogTableStorageDependency(accountName: "orderAccount", tableName: "orders", isSuccessful: true, startTime: startTime, duration: durationMeasurement.Elapsed);
logger.LogTableStorageDependency(accountName: "orderAccount", tableName: "orders", isSuccessful: true, startTime: startTime, duration: durationMeasurement.Elapsed);
// Output: "Dependency Azure table orders named orderAccount in 00:00:00.2521801 at 03/23/2020 09:56:31 +00:00 (Successful: True - Context: )"
```

Expand All @@ -215,7 +235,7 @@ var startTime = DateTimeOffset.UtcNow;
// Send request to dependant service
var response = await httpClient.SendAsync(request);

_logger.LogHttpDependency(request, statusCode: response.StatusCode, startTime: startTime, duration: durationMeasurement.Elapsed);
logger.LogHttpDependency(request, statusCode: response.StatusCode, startTime: startTime, duration: durationMeasurement.Elapsed);
// 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: )"
```

Expand All @@ -233,7 +253,7 @@ durationMeasurement.Start();
// Interact with database
var products = await _repository.GetProducts();

_logger.LogSqlDependency("sample-server", "sample-database", "my-table", "get-products", isSuccessful: true, startTime: startTime, duration: durationMeasurement.Elapsed);
logger.LogSqlDependency("sample-server", "sample-database", "my-table", "get-products", isSuccessful: true, startTime: startTime, duration: durationMeasurement.Elapsed);
// 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: )"
```

Expand All @@ -260,7 +280,7 @@ durationMeasurement.Start();
// Interact with database
var products = await _repository.GetProducts();

_logger.LogSqlDependency(connectionString, "my-table", "get-products", isSuccessful: true, measurement: measurement);
logger.LogSqlDependency(connectionString, "my-table", "get-products", isSuccessful: true, measurement: measurement);
// 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: )"
```

Expand All @@ -278,7 +298,7 @@ durationMeasurement.Start();
string dependencyName = "SendGrid";
object dependencyData = "http://my.sendgrid.uri/"

_logger.LogDependency("SendGrid", dependencyData, isSuccessful: true, startTime: startTime, duration: durationMeasurement.Elapsed);
logger.LogDependency("SendGrid", dependencyData, isSuccessful: true, startTime: startTime, duration: durationMeasurement.Elapsed);
// Output: "Dependency SendGrid http://my.sendgrid.uri/ in 00:00:01.2396312 at 03/23/2020 09:32:02 +00:00 (Successful: True - Context: )"
```

Expand All @@ -298,7 +318,7 @@ durationMeasurement.Start();
/// Track dependency
string dependencyName = "SendGrid";
object dependencyData = "https://my.sendgrid.uri/";
_logger.LogDependency("SendGrid", dependencyData, isSuccessful: true, startTime: startTime, duration: durationMeasurement.Elapsed, context: telemetryContext);
logger.LogDependency("SendGrid", dependencyData, isSuccessful: true, startTime: startTime, duration: durationMeasurement.Elapsed, context: telemetryContext);
```

However, by using `DependencyMeasurement.Start()` we take care of the measuring aspect:
Expand All @@ -312,7 +332,7 @@ using (var measurement = DependencyMeasurement.Start())
// Track dependency
string dependencyName = "SendGrid";
object dependencyData = "https://my.sendgrid.uri/";
_logger.LogDependency(dependencyName, dependencyData, isSuccessful: true, startTime: measurement, context: telemetryContext);
logger.LogDependency(dependencyName, dependencyData, isSuccessful: true, startTime: measurement, context: telemetryContext);
}
```

Expand All @@ -327,12 +347,12 @@ try
// Interact with SendGrid...
// Done!
_logger.LogDependency(dependencyName, dependencyData, isSuccessful: true, startTime: measurement, context: telemetryContext);
logger.LogDependency(dependencyName, dependencyData, isSuccessful: true, startTime: measurement, context: telemetryContext);
}
catch (Exception exception)
{
_logger.LogError(exception, "Failed to interact with SendGrid");
_logger.LogDependency(dependencyName, dependencyData, isSuccessful: false, startTime: measurement, context: telemetryContext);
logger.LogError(exception, "Failed to interact with SendGrid");
logger.LogDependency(dependencyName, dependencyData, isSuccessful: false, startTime: measurement, context: telemetryContext);
}
```

Expand Down Expand Up @@ -373,6 +393,16 @@ logger.LogMetric("Invoice Received", 133.37, telemetryContext);

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.

**Installation**

If you want to track the `HttpRequest` and `HttpResponse` of an ASP.NET Core project, you'll have to install an additional package to include these ASP.NET Core dependencies:

```shell
PM > Install-Package Arcus.Observability.Telemetry.AspNetCore
```

**Example**

Here is how you can keep track of requests:

```csharp
Expand Down
1 change: 1 addition & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ This is licensed under The MIT License (MIT). Which means that you can use, copy

# Older Versions

- [v1.0](v1.0)
- [v0.4](v0.4)
- [v0.3](v0.3)
- [v0.2.0](v0.2.0)
Expand Down
172 changes: 172 additions & 0 deletions docs/v2.0/features/correlation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
---
title: "Correlation"
layout: default
---

# Correlation

`CorrelationInfo` provides a common set of correlation levels:

- Transaction Id - ID that relates different requests together into a functional transaction.
- Operation Id - Unique ID information for a single request.

## Installation

This feature requires to install our NuGet package

```shell
PM > Install-Package Arcus.Observability.Correlation
```

## What We Provide

The `Arcus.Observability.Correlation` library provides a way to get access to correlation information across your application.
What it **DOES NOT** provide is how this correlation information is initially set.

It uses the the Microsoft dependency injection mechanism to register an `ICorrelationInfoAccessor` and `ICorrelationInfoAccessor<>` implementation that is available.

**Example**

```csharp
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// Adds operation and transaction correlation to the application,
// using the `DefaultCorrelationInfoAccessor` as `ICorrelationInfoAccessor` that stores the `CorrelationInfo` model internally.
services.AddCorrelation();
}
}
```
## Custom Correlation

We register two interfaces during the registration of the correlation: `ICorrealtionInfoAccessor` and `ICorrelationInfoAccessor<>`.
The reason is because some applications require a custom `CorrelationInfo` model, and with using the generic interface `ICorrelationInfoAccessor<>` we can support this.

**Example**

```csharp
public class OrderCorrelationInfo : CorrelationInfo
{
public string OrderId { get; }
}

public class Startup
{
public void ConfigureService(IServiceCollection services)
{
services.AddCorrelation<OrderCorrelationInfo>();
}
}
```

## Accessing Correlation Throughout the Application

When a part of the application needs access to the correlation information, you can inject one of the two interfaces:

```csharp
public class OrderService
{
public OrderService(ICorrelationInfoAccessor accessor)
{
CorrelationInfo correlationInfo = accessor.CorrelationInfo;
}
}
```

Or, alternatively when using custom correlation:

```csharp
public class OrderService
{
public OrderService(ICorrelationInfoAccessor<OrderCorrelationInfo> accessor)
{
OrderCorrelationInfo correlationInfo = accessor.CorrelationInfo;
}
}
```

## Configuration

The library also provides a way configure some correlation specific options that you can later retrieve during get/set of the correlation information in your application.

```csharp
public void ConfigureServices(IServiceCollection services)
{
services.AddCorrelation(options =>
{
// Configuration on the transaction ID (`X-Transaction-ID`) request/response header.
// ---------------------------------------------------------------------------------
// Whether the transaction ID can be specified in the request, and will be used throughout the request handling.
// The request will return early when the `.AllowInRequest` is set to `false` and the request does contain the header (default: true).
options.Transaction.AllowInRequest = true;

// Whether or not the transaction ID should be generated when there isn't any transaction ID found in the request.
// When the `.GenerateWhenNotSpecified` is set to `false` and the request doesn't contain the header, no value will be available for the transaction ID;
// otherwise a GUID will be generated (default: true).
options.Transaction.GenerateWhenNotSpecified = true;

// Whether to include the transaction ID in the response (default: true).
options.Transaction.IncludeInResponse = true;

// The header to look for in the request, and will be set in the response (default: X-Transaction-ID).
options.Transaction.HeaderName = "X-Transaction-ID";

// The function that will generate the transaction ID, when the `.GenerateWhenNotSpecified` is set to `false` and the request doesn't contain the header.
// (default: new `Guid`).
options.Transaction.GenerateId = () => $"Transaction-{Guid.NewGuid()}";

// Configuration on the operation ID (`RequestId`) response header.
// ----------------------------------------------------------------
// Whether to include the operation ID in the response (default: true).
options.Operation.IncludeInResponse = true;

// The header that will contain the operation ID in the response (default: RequestId).
options.Operation.HeaderName = "RequestId";

// The function that will generate the operation ID header value.
// (default: new `Guid`).
options.Operation.GenerateId = () => $"Operation-{Guid.NewGuid()}";
});
}
```

Later in the application, the options can be retrieved by injecting the `IOptions<CorrelationInfoOptions>` type.

### Custom Configuration

We also provide a way to provide custom configuration options when the application uses a custom correlation model.

For example, with a custom correlation model:

```csharp
public class OrderCorrelationInfo : CorrelationInfo
{
public string OrderId { get; }
}
```

We could introduce an `OrderCorrelationInfoOptions` model:

```csharp
public class OrderCorrelationInfoOptions : CorrelationInfoOptions
{
public bool IncludeOrderId { get; set; }
}
```

This custom options model can then be included when registering the correlation:

```csharp
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddCorrelation<OrderCorrelationInfo, OrderCorrelationInfoOptions>(options => options.IncludeOrderId = true);
}
}
```

[&larr; back](/)
Loading

0 comments on commit aa7c671

Please sign in to comment.