Skip to content

Commit b145019

Browse files
authored
feat(telemetry): add telemetry options to SDK init (#27)
- Node.js: Add TelemetryOptions to InitOptions, send in registerWorkerMetadata - Python: Add TelemetryOptions to InitOptions, include in _get_worker_metadata - Rust: Add WorkerTelemetryMeta to WorkerMetadata, auto-detect language from LANG
1 parent 30bf8c3 commit b145019

File tree

4 files changed

+73
-2
lines changed

4 files changed

+73
-2
lines changed

packages/node/iii/src/iii.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,13 @@ function getDefaultWorkerName(): string {
7474
/** Callback type for connection state changes */
7575
export type ConnectionStateCallback = (state: IIIConnectionState) => void
7676

77+
export type TelemetryOptions = {
78+
language?: string
79+
project_name?: string
80+
framework?: string
81+
amplitude_api_key?: string
82+
}
83+
7784
export type InitOptions = {
7885
workerName?: string
7986
enableMetricsReporting?: boolean
@@ -85,6 +92,7 @@ export type InitOptions = {
8592
* Set `{ enabled: false }` or env `OTEL_ENABLED=false/0/no/off` to disable.
8693
* The engineWsUrl is set automatically from the III address. */
8794
otel?: Omit<OtelConfig, 'engineWsUrl'>
95+
telemetry?: TelemetryOptions
8896
}
8997

9098
class Sdk implements ISdk {
@@ -114,7 +122,7 @@ class Sdk implements ISdk {
114122

115123
constructor(
116124
private readonly address: string,
117-
options?: InitOptions,
125+
private readonly options?: InitOptions,
118126
) {
119127
this.workerName = options?.workerName ?? getDefaultWorkerName()
120128
this.metricsReportingEnabled = options?.enableMetricsReporting ?? true
@@ -297,11 +305,23 @@ class Sdk implements ISdk {
297305
}
298306

299307
private registerWorkerMetadata(): void {
308+
const telemetryOpts = this.options?.telemetry
309+
const language =
310+
telemetryOpts?.language ??
311+
Intl.DateTimeFormat().resolvedOptions().locale ??
312+
process.env.LANG?.split('.')[0]
313+
300314
this.triggerVoid(EngineFunctions.REGISTER_WORKER, {
301315
runtime: 'node',
302316
version: SDK_VERSION,
303317
name: this.workerName,
304318
os: getOsInfo(),
319+
telemetry: {
320+
language,
321+
project_name: telemetryOpts?.project_name,
322+
framework: telemetryOpts?.framework,
323+
amplitude_api_key: telemetryOpts?.amplitude_api_key,
324+
},
305325
})
306326
}
307327

packages/python/iii/src/iii/iii.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,16 @@ class FunctionRef:
7272
unregister: Callable[[], None]
7373

7474

75+
@dataclass
76+
class TelemetryOptions:
77+
"""Telemetry metadata to be reported to the engine."""
78+
79+
language: str | None = None
80+
project_name: str | None = None
81+
framework: str | None = None
82+
amplitude_api_key: str | None = None
83+
84+
7585
@dataclass
7686
class InitOptions:
7787
"""Options for configuring the III SDK."""
@@ -81,6 +91,7 @@ class InitOptions:
8191
invocation_timeout_ms: int = DEFAULT_INVOCATION_TIMEOUT_MS
8292
reconnection_config: ReconnectionConfig | None = None
8393
otel: dict[str, Any] | None = None
94+
telemetry: TelemetryOptions | None = None
8495

8596

8697
class III:
@@ -593,11 +604,26 @@ def _get_worker_metadata(self) -> dict[str, Any]:
593604

594605
worker_name = self._options.worker_name or f"{platform.node()}:{os.getpid()}"
595606

607+
telemetry_opts = self._options.telemetry
608+
language = (
609+
(telemetry_opts.language if telemetry_opts else None)
610+
or os.environ.get("LANG", "").split(".")[0]
611+
or None
612+
)
613+
614+
telemetry: dict[str, Any] = {
615+
"language": language,
616+
"project_name": telemetry_opts.project_name if telemetry_opts else None,
617+
"framework": telemetry_opts.framework if telemetry_opts else None,
618+
"amplitude_api_key": telemetry_opts.amplitude_api_key if telemetry_opts else None,
619+
}
620+
596621
return {
597622
"runtime": "python",
598623
"version": sdk_version,
599624
"name": worker_name,
600625
"os": f"{platform.system()} {platform.release()} ({platform.machine()})",
626+
"telemetry": telemetry,
601627
}
602628

603629
def _register_worker_metadata(self) -> None:

packages/rust/iii/Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/rust/iii/src/iii.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,28 @@ pub struct TriggerInfo {
8686
pub config: Value,
8787
}
8888

89+
/// Telemetry metadata provided by the SDK to the engine.
90+
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
91+
pub struct WorkerTelemetryMeta {
92+
#[serde(skip_serializing_if = "Option::is_none")]
93+
pub language: Option<String>,
94+
#[serde(skip_serializing_if = "Option::is_none")]
95+
pub project_name: Option<String>,
96+
#[serde(skip_serializing_if = "Option::is_none")]
97+
pub framework: Option<String>,
98+
#[serde(skip_serializing_if = "Option::is_none")]
99+
pub amplitude_api_key: Option<String>,
100+
}
101+
89102
/// Worker metadata for auto-registration
90103
#[derive(Debug, Clone, Serialize, Deserialize)]
91104
pub struct WorkerMetadata {
92105
pub runtime: String,
93106
pub version: String,
94107
pub name: String,
95108
pub os: String,
109+
#[serde(skip_serializing_if = "Option::is_none")]
110+
pub telemetry: Option<WorkerTelemetryMeta>,
96111
}
97112

98113
impl Default for WorkerMetadata {
@@ -108,11 +123,21 @@ impl Default for WorkerMetadata {
108123
std::env::consts::FAMILY
109124
);
110125

126+
let language = std::env::var("LANG")
127+
.or_else(|_| std::env::var("LC_ALL"))
128+
.ok()
129+
.filter(|s| !s.is_empty())
130+
.map(|s| s.split('.').next().unwrap_or(&s).to_string());
131+
111132
Self {
112133
runtime: "rust".to_string(),
113134
version: SDK_VERSION.to_string(),
114135
name: format!("{}:{}", hostname, pid),
115136
os: os_info,
137+
telemetry: Some(WorkerTelemetryMeta {
138+
language,
139+
..Default::default()
140+
}),
116141
}
117142
}
118143
}

0 commit comments

Comments
 (0)