Skip to content

Commit 467dffd

Browse files
authored
feat: integrate ActivitySource for improved observability in resource watchers and operator builder (#895)
Add telemetry options to the resource watcher ```csharp builder .Services .AddKubernetesOperator(settings => settings.Name = OperatorName) .... builder.Services .AddOpenTelemetry() .WithTracing(tracingProviderBuilder => tracingProviderBuilder .SetResourceBuilder( ResourceBuilder.CreateDefault() .AddService(serviceName: OperatorName, serviceVersion: "1.0.0")) .AddSource(OperatorName)) .UseAzureMonitor(); ``` thanks 👋🏼 m.
1 parent 9896d8f commit 467dffd

File tree

4 files changed

+24
-6
lines changed

4 files changed

+24
-6
lines changed

src/KubeOps.Operator/Builder/OperatorBuilder.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
using k8s;
1+
using System.Diagnostics;
2+
3+
using k8s;
24
using k8s.Models;
35

46
using KubeOps.Abstractions.Builder;
@@ -19,7 +21,7 @@
1921

2022
namespace KubeOps.Operator.Builder;
2123

22-
internal class OperatorBuilder : IOperatorBuilder
24+
internal sealed class OperatorBuilder : IOperatorBuilder
2325
{
2426
private readonly OperatorSettings _settings;
2527

@@ -96,6 +98,7 @@ public IOperatorBuilder AddFinalizer<TImplementation, TEntity>(string identifier
9698
private void AddOperatorBase()
9799
{
98100
Services.AddSingleton(_settings);
101+
Services.AddSingleton(new ActivitySource(_settings.Name));
99102

100103
// Add the default configuration and the client separately. This allows external users to override either
101104
// just the config (e.g. for integration tests) or to replace the whole client, e.g. with a mock.

src/KubeOps.Operator/Watcher/LeaderAwareResourceWatcher{TEntity}.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using System.Diagnostics;
2+
13
using k8s;
24
using k8s.LeaderElection;
35
using k8s.Models;
@@ -13,6 +15,7 @@
1315
namespace KubeOps.Operator.Watcher;
1416

1517
internal sealed class LeaderAwareResourceWatcher<TEntity>(
18+
ActivitySource activitySource,
1619
ILogger<LeaderAwareResourceWatcher<TEntity>> logger,
1720
IServiceProvider provider,
1821
TimedEntityQueue<TEntity> queue,
@@ -21,7 +24,14 @@ internal sealed class LeaderAwareResourceWatcher<TEntity>(
2124
IKubernetesClient client,
2225
IHostApplicationLifetime hostApplicationLifetime,
2326
LeaderElector elector)
24-
: ResourceWatcher<TEntity>(logger, provider, queue, settings, labelSelector, client)
27+
: ResourceWatcher<TEntity>(
28+
activitySource,
29+
logger,
30+
provider,
31+
queue,
32+
settings,
33+
labelSelector,
34+
client)
2535
where TEntity : IKubernetesObject<V1ObjectMeta>
2636
{
2737
private CancellationTokenSource _cts = new();

src/KubeOps.Operator/Watcher/ResourceWatcher{TEntity}.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Collections.Concurrent;
2+
using System.Diagnostics;
23
using System.Net;
34
using System.Runtime.Serialization;
45
using System.Text.Json;
@@ -21,6 +22,7 @@
2122
namespace KubeOps.Operator.Watcher;
2223

2324
public class ResourceWatcher<TEntity>(
25+
ActivitySource activitySource,
2426
ILogger<ResourceWatcher<TEntity>> logger,
2527
IServiceProvider provider,
2628
TimedEntityQueue<TEntity> requeue,
@@ -201,6 +203,7 @@ private async Task WatchClientEventsAsync(CancellationToken stoppingToken)
201203
cancellationToken: stoppingToken))
202204
{
203205
#pragma warning disable SA1312
206+
using var __ = activitySource.StartActivity($"""processing "{type}" event""", ActivityKind.Consumer);
204207
using var _ = logger.BeginScope(EntityLoggingScope.CreateFor(type, entity));
205208
logger.LogInformation(
206209
"""Received watch event "{EventType}" for "{Kind}/{Name}", last observed resource version: {ResourceVersion}.""",

test/KubeOps.Operator.Test/Watcher/ResourceWatcher{TEntity}.Test.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Runtime.CompilerServices;
1+
using System.Diagnostics;
2+
using System.Runtime.CompilerServices;
23

34
using k8s;
45
using k8s.Models;
@@ -21,18 +22,19 @@ public sealed class ResourceWatcherTest
2122
public async Task Restarting_Watcher_Should_Trigger_New_Watch()
2223
{
2324
// Arrange.
25+
var activitySource = new ActivitySource("unit-test");
2426
var logger = Mock.Of<ILogger<ResourceWatcher<V1Pod>>>();
2527
var serviceProvider = Mock.Of<IServiceProvider>();
2628
var timedEntityQueue = new TimedEntityQueue<V1Pod>();
27-
var operatorSettings = new OperatorSettings() { Namespace = "unit-test" };
29+
var operatorSettings = new OperatorSettings { Namespace = "unit-test" };
2830
var kubernetesClient = Mock.Of<IKubernetesClient>();
2931
var labelSelector = new DefaultEntityLabelSelector<V1Pod>();
3032

3133
Mock.Get(kubernetesClient)
3234
.Setup(client => client.WatchAsync<V1Pod>("unit-test", null, null, true, It.IsAny<CancellationToken>()))
3335
.Returns<string?, string?, string?, bool?, CancellationToken>((_, _, _, _, cancellationToken) => WaitForCancellationAsync<(WatchEventType, V1Pod)>(cancellationToken));
3436

35-
var resourceWatcher = new ResourceWatcher<V1Pod>(logger, serviceProvider, timedEntityQueue, operatorSettings, labelSelector, kubernetesClient);
37+
var resourceWatcher = new ResourceWatcher<V1Pod>(activitySource, logger, serviceProvider, timedEntityQueue, operatorSettings, labelSelector, kubernetesClient);
3638

3739
// Act.
3840
// Start and stop the watcher.

0 commit comments

Comments
 (0)