diff --git a/docs/docs/operator/deployment.mdx b/docs/docs/operator/deployment.mdx index f08cefd5..10267813 100644 --- a/docs/docs/operator/deployment.mdx +++ b/docs/docs/operator/deployment.mdx @@ -1,7 +1,7 @@ --- title: Deployment description: Deploying your KubeOps Operator -sidebar_position: 6 +sidebar_position: 7 --- # Deployment diff --git a/docs/docs/operator/logging.mdx b/docs/docs/operator/logging.mdx new file mode 100644 index 00000000..192fb8e3 --- /dev/null +++ b/docs/docs/operator/logging.mdx @@ -0,0 +1,177 @@ +--- +title: Logging +description: Logging, Tracing, and OpenTelemetry +sidebar_position: 6 +--- + +# Logging, Tracing, and OpenTelemetry + +## 1. Logging with `ILogger` and Scopes + +This project uses Microsoft's [`ILogger`](https://learn.microsoft.com/en-us/dotnet/core/extensions/logging) interface for logging. It provides a standardized and extensible way to capture events within the application. + +Using *scopes* enables hierarchical organization of log messages and allows contextual information to be attached to each entry. + +### 1.1 ILogger Basics + +The `ILogger` interface is part of [`Microsoft.Extensions.Logging`](https://www.nuget.org/packages/Microsoft.Extensions.Logging) and provides methods to log messages at various severity levels (e.g., `Information`, `Warning`, `Error`). + +Logging can be enabled using either `WebApplication.CreateBuilder`, `Host.CreateDefaultBuilder`, or the `AddLogging` extension method on the `IServiceCollection`. + +You can log from your code by injecting `ILogger` (or a similar type) into your component. + +### 1.2 Using Scopes + +Scopes define a logical boundary in which all log entries are automatically enriched with contextual metadata. This is especially useful for correlating logs related to a specific request or operation. + +By default, the [ResourceWatcher](https://github.com/buehler/dotnet-operator-sdk/blob/main/src/KubeOps.Operator/Watcher/ResourceWatcher%7BTEntity%7D.cs) starts a new scope for every watch event it processes. Each scope includes: + +- `EventType`: Type of the received watch event (`Added`, `Modified`, `Deleted`, `Error`, `Bookmark`) +- `Kind`: Custom Resource Definition (CRD) kind +- `Namespace`: CRD namespace +- `Name`: CRD name +- `ResourceVersion`: CRD resource version + +You can create additional scopes in your code using `logger.BeginScope(state)`, where `state` can be either a string or a custom object. + +To include scopes in the logging output, they must be explicitly enabled either via configuration or code: + +**`appsettings.json`:** + +```json +"Logging": { + "Console": { + "FormatterName": "Simple", + "FormatterOptions": { + "IncludeScopes": true + } + }, + "LogLevel": { + "Default": "Information", + "KubeOps": "Trace" + } +} +``` + +**Programmatic configuration:** + +```csharp +builder + .ConfigureLogging((hostBuilderContext, loggingBuilder) => + { + loggingBuilder + .AddSimpleConsole(options => options.IncludeScopes = true); + }); +``` + +:::tip +To enable scopes with OpenTelemetry, configure it as follows: + +```json +"OpenTelemetry": { + "IncludeScopes": true, + "ParseStateValues": true, + "IncludeFormattedMessage": true +} +``` + +The scope state must be an `IReadOnlyDictionary` to ensure correct serialization and inclusion in log entries. +::: + +## 2. Tracing with `System.Diagnostics` and `ActivitySource` + +For [distributed tracing](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/distributed-tracing-concepts), this project uses `System.Diagnostics` in combination with `ActivitySource`. +Activities can be started using `ActivitySource.StartActivity`. + +The operator registers an `ActivitySource` instance with the operator name in the dependency injection (DI) container. To use a custom `ActivitySource`, simply register your own, the DI will provide the last registered instance when requested. + +:::tip +You can configure the operator name (and thus the `ActivitySource` name) via `OperatorSettings`: + +```csharp +const string OperatorName = "my-operator"; + +builder + .Services + .AddKubernetesOperator(settings => settings.Name = OperatorName); +``` + +If you're using OpenTelemetry, tracing must be explicitly configured in code. Make sure to add the same source name used when creating the `ActivitySource`. + +Also, create a `ResourceBuilder` to name your service properly in trace output: + +```csharp +builder.Services + .AddOpenTelemetry() + .WithTracing(tracerProviderBuilder => + tracerProviderBuilder + .SetResourceBuilder( + ResourceBuilder.CreateDefault() + .AddService(serviceName: OperatorName, serviceVersion: "1.0.0")) + .AddSource(OperatorName)); +``` +::: + +## 3. OpenTelemetry Configuration for Azure Logging + +To use OpenTelemetry with Azure, it is recommended to adopt the [Azure Monitor OpenTelemetry Distro](https://learn.microsoft.com/en-us/azure/azure-monitor/app/opentelemetry-enable). +You can enable it via code: + +```csharp +builder.Services + .AddOpenTelemetry() + .UseAzureMonitor(); +``` + +### 3.2 Full Example Configuration in `Program.cs` (or `Startup.cs`) + +A complete setup with logging, tracing, and OpenTelemetry might look like this: + +**`appsettings.json`:** + +```json +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "KubeOps": "Trace" + }, + "Console": { + "FormatterName": "Simple", + "FormatterOptions": { + "IncludeScopes": true, + "SingleLine": true + } + }, + "OpenTelemetry": { + "IncludeScopes": true, + "ParseStateValues": true, + "IncludeFormattedMessage": true + } + } +} +``` + +**`Program.cs`:** + +```csharp +const string OperatorName = "my-platform-operator"; + +var builder = WebApplication.CreateBuilder(args); + +builder + .Services + .AddKubernetesOperator(settings => settings.Name = OperatorName) + .RegisterComponents(); + +builder + .Services + .AddOpenTelemetry() + .WithTracing(tracerProviderBuilder => + tracerProviderBuilder + .SetResourceBuilder( + ResourceBuilder.CreateDefault() + .AddService(serviceName: OperatorName, serviceVersion: "1.0.0")) + .AddSource(OperatorName)) + .UseAzureMonitor(); +``` \ No newline at end of file diff --git a/docs/docs/operator/testing/_category_.json b/docs/docs/operator/testing/_category_.json index 57ccaf1c..56f722ea 100644 --- a/docs/docs/operator/testing/_category_.json +++ b/docs/docs/operator/testing/_category_.json @@ -1,5 +1,5 @@ { - "position": 7, + "position": 8, "label": "Testing", "collapsible": true, "collapsed": true