Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 29 additions & 6 deletions csharp/doc/telemetry-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -615,23 +615,38 @@ namespace AdbcDrivers.Databricks.Telemetry
/// </summary>
internal sealed class TelemetryClientManager
{
private static readonly TelemetryClientManager Instance = new();
public static TelemetryClientManager GetInstance() => Instance;
private static TelemetryClientManager s_instance = new TelemetryClientManager();
public static TelemetryClientManager GetInstance() => s_instance;

/// <summary>
/// Gets or creates a telemetry client for the host.
/// Increments reference count.
/// </summary>
public ITelemetryClient GetOrCreateClient(
string host,
HttpClient httpClient,
Func<ITelemetryExporter> exporterFactory,
TelemetryConfiguration config);

/// <summary>
/// Decrements reference count for the host.
/// Closes and removes client when ref count reaches zero.
/// </summary>
public Task ReleaseClientAsync(string host);

/// <summary>
/// Replaces singleton with test instance; returns IDisposable to restore.
/// </summary>
internal static IDisposable UseTestInstance(TelemetryClientManager testInstance);

/// <summary>
/// Resets the manager by closing and removing all clients.
/// </summary>
internal void Reset();

/// <summary>
/// Creates a new isolated instance for testing.
/// </summary>
internal static TelemetryClientManager CreateForTesting();
}

/// <summary>
Expand All @@ -640,11 +655,13 @@ namespace AdbcDrivers.Databricks.Telemetry
internal sealed class TelemetryClientHolder
{
public ITelemetryClient Client { get; }
public int RefCount { get; set; }
internal int _refCount = 1; // Managed via Interlocked
}
}
```

> **Note**: The `GetOrCreateClient` signature uses `Func<ITelemetryExporter> exporterFactory` instead of `HttpClient` because `TelemetryClient` takes an `ITelemetryExporter`, not an `HttpClient`. The factory pattern defers exporter creation until a new client is actually needed.

**JDBC Reference**: `TelemetryClientFactory.java:27` maintains `ConcurrentHashMap<String, TelemetryClientHolder>` with per-host clients and reference counting.

---
Expand Down Expand Up @@ -1870,8 +1887,8 @@ public sealed class DatabricksConnection : AdbcConnection
// Step 2: Release telemetry client (decrements ref count, closes if last)
await TelemetryClientManager.GetInstance().ReleaseClientAsync(_host);

// Step 3: Release feature flag context (decrements ref count)
FeatureFlagCache.GetInstance().ReleaseContext(_host);
// Note: FeatureFlagCache uses cache-level TTL eviction (IMemoryCache sliding expiration)
// rather than reference counting, so no ReleaseContext call is needed.
}
catch (Exception ex)
{
Expand All @@ -1885,6 +1902,12 @@ public sealed class DatabricksConnection : AdbcConnection
}
```

> **Implementation Note**: The actual implementation uses `Dispose(bool)` (synchronous) instead of
> `DisposeAsyncCore` since the base class hierarchy (`HiveServer2Connection`) uses `IDisposable`, not
> `IAsyncDisposable`. Async operations in dispose are handled via `.ConfigureAwait(false).GetAwaiter().GetResult()`.
> Additionally, `FeatureFlagCache.ReleaseContext()` was not implemented as the cache uses IMemoryCache with
> sliding expiration for automatic eviction rather than reference counting.

### 9.3 TelemetryClient Close Implementation

```csharp
Expand Down
416 changes: 342 additions & 74 deletions csharp/doc/telemetry-sprint-plan.md

Large diffs are not rendered by default.

Empty file added csharp/doc/telemetry-tasks.json
Empty file.
Loading
Loading