Commit de440ef
[3/7] Telemetry Client Management: TelemetryClient and Provider (#326)
* Add telemetry infrastructure: CircuitBreaker and FeatureFlagCache
This is part 2 of 7 in the telemetry implementation stack.
Components:
- CircuitBreaker: Per-host endpoint protection with state management
- FeatureFlagCache: Per-host feature flag caching with reference counting
- CircuitBreakerRegistry: Manages circuit breakers per host
Circuit Breaker:
- States: CLOSED (normal), OPEN (failing), HALF_OPEN (testing recovery)
- Default: 5 failures trigger OPEN, 60s timeout, 2 successes to CLOSE
- Per-host isolation prevents cascade failures
- All state transitions logged at debug level
Feature Flag Cache:
- Per-host caching with 15-minute TTL
- Reference counting for connection lifecycle management
- Automatic cache expiration and refetch
- Context removed when refCount reaches zero
Testing:
- 32 comprehensive unit tests for CircuitBreaker
- 29 comprehensive unit tests for FeatureFlagCache
- 100% function coverage, >80% line/branch coverage
- CircuitBreakerStub for testing other components
Dependencies:
- Builds on [1/7] Types and Exception Classifier
* Add authentication support for REST API calls
Implements getAuthHeaders() method for authenticated REST API requests:
- Added getAuthHeaders() to IClientContext interface
- Implemented in DBSQLClient using authProvider.authenticate()
- Updated FeatureFlagCache to fetch from connector-service API with auth
- Added driver version support for version-specific feature flags
- Replaced placeholder implementation with actual REST API calls
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* Fix feature flag and telemetry export endpoints
- Change feature flag endpoint to use NODEJS client type
- Fix telemetry endpoints to /telemetry-ext and /telemetry-unauth
- Update payload to match proto with system_configuration
- Add shared buildUrl utility for protocol handling
* Match JDBC telemetry payload format
- Change payload structure to match JDBC: uploadTime, items, protoLogs
- protoLogs contains JSON-stringified TelemetryFrontendLog objects
- Remove workspace_id (JDBC doesn't populate it)
- Remove debug logs added during testing
* Fix lint errors
- Fix import order in FeatureFlagCache
- Replace require() with import for driverVersion
- Fix variable shadowing
- Disable prefer-default-export for urlUtils
* Add telemetry infrastructure: CircuitBreaker and FeatureFlagCache
This is part 2 of 7 in the telemetry implementation stack.
Components:
- CircuitBreaker: Per-host endpoint protection with state management
- FeatureFlagCache: Per-host feature flag caching with reference counting
- CircuitBreakerRegistry: Manages circuit breakers per host
Circuit Breaker:
- States: CLOSED (normal), OPEN (failing), HALF_OPEN (testing recovery)
- Default: 5 failures trigger OPEN, 60s timeout, 2 successes to CLOSE
- Per-host isolation prevents cascade failures
- All state transitions logged at debug level
Feature Flag Cache:
- Per-host caching with 15-minute TTL
- Reference counting for connection lifecycle management
- Automatic cache expiration and refetch
- Context removed when refCount reaches zero
Testing:
- 32 comprehensive unit tests for CircuitBreaker
- 29 comprehensive unit tests for FeatureFlagCache
- 100% function coverage, >80% line/branch coverage
- CircuitBreakerStub for testing other components
Dependencies:
- Builds on [1/7] Types and Exception Classifier
* Add telemetry client management: TelemetryClient and Provider
This is part 3 of 7 in the telemetry implementation stack.
Components:
- TelemetryClient: HTTP client for telemetry export per host
- TelemetryClientProvider: Manages per-host client lifecycle with reference counting
TelemetryClient:
- Placeholder HTTP client for telemetry export
- Per-host isolation for connection pooling
- Lifecycle management (open/close)
- Ready for future HTTP implementation
TelemetryClientProvider:
- Reference counting tracks connections per host
- Automatically creates clients on first connection
- Closes and removes clients when refCount reaches zero
- Thread-safe per-host management
Design Pattern:
- Follows JDBC driver pattern for resource management
- One client per host, shared across connections
- Efficient resource utilization
- Clean lifecycle management
Testing:
- 31 comprehensive unit tests for TelemetryClient
- 31 comprehensive unit tests for TelemetryClientProvider
- 100% function coverage, >80% line/branch coverage
- Tests verify reference counting and lifecycle
Dependencies:
- Builds on [1/7] Types and [2/7] Infrastructure
* Add authentication support for REST API calls
Implements getAuthHeaders() method for authenticated REST API requests:
- Added getAuthHeaders() to IClientContext interface
- Implemented in DBSQLClient using authProvider.authenticate()
- Updated FeatureFlagCache to fetch from connector-service API with auth
- Added driver version support for version-specific feature flags
- Replaced placeholder implementation with actual REST API calls
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* Fix feature flag and telemetry export endpoints
- Change feature flag endpoint to use NODEJS client type
- Fix telemetry endpoints to /telemetry-ext and /telemetry-unauth
- Update payload to match proto with system_configuration
- Add shared buildUrl utility for protocol handling
* Match JDBC telemetry payload format
- Change payload structure to match JDBC: uploadTime, items, protoLogs
- protoLogs contains JSON-stringified TelemetryFrontendLog objects
- Remove workspace_id (JDBC doesn't populate it)
- Remove debug logs added during testing
* Fix lint errors
- Fix import order in FeatureFlagCache
- Replace require() with import for driverVersion
- Fix variable shadowing
- Disable prefer-default-export for urlUtils
* Add missing getAuthHeaders method to ClientContextStub
Fix TypeScript compilation error by implementing getAuthHeaders
method required by IClientContext interface.
* Add missing getAuthHeaders method to ClientContextStub
Fix TypeScript compilation error by implementing getAuthHeaders
method required by IClientContext interface.
* Fix prettier formatting
* Fix prettier formatting
* Add DRIVER_NAME constant for nodejs-sql-driver
* Add DRIVER_NAME constant for nodejs-sql-driver
* Add missing telemetry fields to match JDBC
Added osArch, runtimeVendor, localeName, charSetEncoding, and
processName fields to DriverConfiguration to match JDBC implementation.
* Add missing telemetry fields to match JDBC
Added osArch, runtimeVendor, localeName, charSetEncoding, and
processName fields to DriverConfiguration to match JDBC implementation.
* Fix TypeScript compilation: add missing fields to system_configuration interface
* Fix TypeScript compilation: add missing fields to system_configuration interface
* Fix telemetry PR review comments from #325
Three fixes addressing review feedback:
1. Fix documentation typo (sreekanth-db comment)
- DatabricksTelemetryExporter.ts:94
- Changed "TelemetryFrontendLog" to "DatabricksTelemetryLog"
2. Add proxy support (jadewang-db comment)
- DatabricksTelemetryExporter.ts:exportInternal()
- Get HTTP agent from connection provider
- Pass agent to fetch for proxy support
- Follows same pattern as CloudFetchResultHandler and DBSQLSession
- Supports http/https/socks proxies with authentication
3. Fix flush timer to prevent rate limiting (sreekanth-db comment)
- MetricsAggregator.ts:flush()
- Reset timer after manual flushes (batch size, terminal errors)
- Ensures consistent 30s spacing between exports
- Prevents rapid successive flushes (e.g., batch at 25s, timer at 30s)
All changes follow existing driver patterns and maintain backward compatibility.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* Add proxy support to feature flag fetching
Feature flag fetching was also missing proxy support like telemetry
exporter was. Applied the same fix:
- Get HTTP agent from connection provider
- Pass agent to fetch call for proxy support
- Follows same pattern as CloudFetchResultHandler and DBSQLSession
- Supports http/https/socks proxies with authentication
This completes proxy support for all HTTP operations in the telemetry
system (both telemetry export and feature flag fetching).
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* Merge main into telemetry-3-client-management; prefer main versions for infrastructure
Takes main's versions of CircuitBreaker, FeatureFlagCache, DatabricksTelemetryExporter,
MetricsAggregator, TelemetryEventEmitter, and types — bringing in SSRF hardening,
overflow protection, async flush/close, errorStack redaction, and IAuthentication-based
auth headers. Removes IClientContext.getAuthHeaders() in favour of the direct
authProvider injection pattern from main.
Co-authored-by: samikshya-chand_data
* fix: prettier formatting and add coverage/ to .prettierignore
Co-authored-by: samikshya-chand_data
* fix: delete host entry before awaiting close to prevent stale-client race
If getOrCreateClient ran after refCount hit 0 but before clients.delete(host),
it would receive a closing TelemetryClient. Deleting synchronously first means
any concurrent caller gets a fresh instance instead.
Co-authored-by: samikshya-chand_data
* refactor: simplify TelemetryClient.close() and TelemetryClientProvider
- close() made synchronous (no I/O, no reason for async); uses finally to
guarantee this.closed=true even when logger throws
- TelemetryClientProvider.releaseClient() made synchronous for the same reason
- Misleading ConcurrentHashMap reference removed from docstring
- getRefCount/getActiveClients marked @internal (test-only surface)
- Update tests to match: rejects→throws stubs, remove await on sync calls
Co-authored-by: samikshya-chand_data
* fix: address PR #326 review feedback from vikrant
- F5: Add refCount underflow guard and defensive warn-log in releaseClient
so a double-release cannot drive the count negative. Also add a test that
double-release does not throw or corrupt state.
- F6: Normalize host used as map key (lowercase, strip scheme, default port,
trailing slash/dot, whitespace). Aliases like https://Example.COM/ now
coalesce to a single entry; add a soft-limit warn at 128 entries to
surface alias/leak bugs. Tests added for normalization + alias-release.
- F9: Replace `catch (error: any) { error.message }` with a narrowed
`error instanceof Error ? error.message : String(error)` so non-Error
throws (string, null) cannot escape the swallow-all contract. Test added.
- F10: Rewrite header and inline comments to describe the current sync
close() semantics instead of an async-await model the code does not
implement; note the invariant to re-establish when close() becomes async.
- F12: Relax exact debug-log string assertions to regex matchers so
cosmetic log rewording does not break unrelated tests. Replace the
`expect(true).to.be.true` tautology in TelemetryClient.test.ts with a
behavioural `expect(() => client.close()).to.not.throw()`.
Signed-off-by: samikshya-chand_data <samikshya.chand@databricks.com>
Co-authored-by: Isaac
Signed-off-by: samikshya-chand_data <samikshya.chand@databricks.com>
* style: apply prettier formatting to TelemetryClientProvider.test.ts
Co-authored-by: Isaac
Signed-off-by: samikshya-chand_data <samikshya.chand@databricks.com>
---------
Signed-off-by: samikshya-chand_data <samikshya.chand@databricks.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>1 parent 3a5e659 commit de440ef
6 files changed
Lines changed: 896 additions & 0 deletions
File tree
- lib/telemetry
- tests/unit/telemetry
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
| 8 | + | |
8 | 9 | | |
9 | 10 | | |
10 | 11 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
0 commit comments