@vymalo/opencode-otel 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +91 -0
- package/dist/config.d.ts +27 -0
- package/dist/config.js +224 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/instruments.d.ts +29 -0
- package/dist/instruments.js +102 -0
- package/dist/instruments.js.map +1 -0
- package/dist/lib.d.ts +8 -0
- package/dist/lib.js +8 -0
- package/dist/lib.js.map +1 -0
- package/dist/logging.d.ts +16 -0
- package/dist/logging.js +72 -0
- package/dist/logging.js.map +1 -0
- package/dist/opencode.d.ts +23 -0
- package/dist/opencode.js +141 -0
- package/dist/opencode.js.map +1 -0
- package/dist/propagation.d.ts +22 -0
- package/dist/propagation.js +55 -0
- package/dist/propagation.js.map +1 -0
- package/dist/providers.d.ts +55 -0
- package/dist/providers.js +179 -0
- package/dist/providers.js.map +1 -0
- package/dist/recorder.d.ts +85 -0
- package/dist/recorder.js +546 -0
- package/dist/recorder.js.map +1 -0
- package/dist/types.d.ts +76 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +81 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 vymalo contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# `@vymalo/opencode-otel`
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@vymalo/opencode-otel)
|
|
4
|
+
|
|
5
|
+
**OpenTelemetry export for OpenCode.** Ships what actually happens in a session — cost, tokens, tool
|
|
6
|
+
calls, permission decisions, errors, lines of code — as standard OTLP **traces, metrics and logs**,
|
|
7
|
+
to any OpenTelemetry backend. The OpenCode counterpart to
|
|
8
|
+
[Claude Code's monitoring](https://code.claude.com/docs/en/monitoring-usage) and
|
|
9
|
+
[Codex's `[otel]` block](https://learn.chatgpt.com/docs/config-file/config-advanced).
|
|
10
|
+
|
|
11
|
+
Part of the [OpenCode Toolbelt](https://github.com/ADORSYS-GIS/lightbridge-opencode-toolbeit).
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
npm install @vymalo/opencode-otel
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
```jsonc
|
|
20
|
+
// opencode.json
|
|
21
|
+
{
|
|
22
|
+
"plugin": [
|
|
23
|
+
["@vymalo/opencode-otel", { "endpoint": "http://localhost:4318" }]
|
|
24
|
+
]
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Or configure it entirely from the environment:
|
|
29
|
+
|
|
30
|
+
```sh
|
|
31
|
+
export OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4318"
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
With **neither** configured the plugin is completely inert — no providers, no sockets, no hooks.
|
|
35
|
+
|
|
36
|
+
## Why another one
|
|
37
|
+
|
|
38
|
+
[`opencode-otel-plugin`](https://github.com/felixti/opencode-otel-plugin) already covers traces and
|
|
39
|
+
metrics well, and this package deliberately reuses its GenAI-semconv vocabulary so both land on the
|
|
40
|
+
same dashboards. What it adds:
|
|
41
|
+
|
|
42
|
+
- **The logs signal** — `user_prompt`, `assistant_response`, `tool_result`, `tool_decision`,
|
|
43
|
+
`api_error` and friends. This is the developer-interaction stream; Claude Code ships 17 log event
|
|
44
|
+
types against 8 metrics, and it is where the interesting data lives.
|
|
45
|
+
- **Real USD cost.** OpenCode's host computes `AssistantMessage.cost`; this exports it directly, so
|
|
46
|
+
there is no price table to maintain and nothing to drift when a provider changes rates.
|
|
47
|
+
- **All five token types** — `input`, `output`, `reasoning`, `cache_read`, `cache_write`. On a
|
|
48
|
+
cached agentic session cache-read is routinely the majority of tokens, so summing input+output
|
|
49
|
+
alone measures a different quantity.
|
|
50
|
+
- **Permission decisions**, mapped from OpenCode's `permission.*` events.
|
|
51
|
+
- **`opencode.json` configuration**, not just environment variables — required for
|
|
52
|
+
`.well-known/opencode` distribution.
|
|
53
|
+
|
|
54
|
+
Run one or the other, not both: they would double-count.
|
|
55
|
+
|
|
56
|
+
## At a glance
|
|
57
|
+
|
|
58
|
+
| Signal | What you get |
|
|
59
|
+
| --- | --- |
|
|
60
|
+
| **Metrics** | `opencode.cost.usage` (USD), `gen_ai.client.token.usage` (5 token types), `gen_ai.client.operation.duration`, session/request/compaction counts, active time, lines of code, tool invocations, permission decisions |
|
|
61
|
+
| **Logs** | `opencode.session_start` / `_idle`, `user_prompt`, `assistant_response`, `tool_result`, `tool_decision`, `api_error`, `file_edited`, `compaction`, `command_executed` |
|
|
62
|
+
| **Traces** | `invoke_agent opencode` → `chat {model}` → `execute_tool {name}`, with W3C `traceparent` propagated into provider requests |
|
|
63
|
+
|
|
64
|
+
## Privacy
|
|
65
|
+
|
|
66
|
+
**No content is captured** — not prompts, responses, tool arguments or API bodies. Log records carry
|
|
67
|
+
shape only: lengths, counts, durations, sizes, outcomes, error classes.
|
|
68
|
+
|
|
69
|
+
Resource attributes identify the **machine and project, never the developer**. The git author email
|
|
70
|
+
is not collected; add `OTEL_RESOURCE_ATTRIBUTES="enduser.id=…"` if you want per-person attribution.
|
|
71
|
+
|
|
72
|
+
Session id is attached to logs and spans always, but to **metrics only** when `includeSessionId` is
|
|
73
|
+
enabled — it is unbounded cardinality and metric backends bill per series.
|
|
74
|
+
|
|
75
|
+
## Transport
|
|
76
|
+
|
|
77
|
+
OTLP over **HTTP with a protobuf payload**, only. gRPC is deliberately absent: OpenCode plugins run
|
|
78
|
+
under Bun as well as Node, and `@grpc/grpc-js` is unreliable there. Put a collector in front if your
|
|
79
|
+
backend needs gRPC. See
|
|
80
|
+
[ADR-0009](https://github.com/ADORSYS-GIS/lightbridge-opencode-toolbeit/blob/main/docs/adr/0009-otel-otlp-http-not-grpc.md).
|
|
81
|
+
|
|
82
|
+
## Full reference
|
|
83
|
+
|
|
84
|
+
- [`docs/otel.md`](https://github.com/ADORSYS-GIS/lightbridge-opencode-toolbeit/blob/main/docs/otel.md)
|
|
85
|
+
— every option, metric, log event and attribute; backend recipes; troubleshooting.
|
|
86
|
+
- [`plans/otel.md`](https://github.com/ADORSYS-GIS/lightbridge-opencode-toolbeit/blob/main/plans/otel.md)
|
|
87
|
+
— design rationale, the prior-art sweep, and the OpenCode-event → OTel-signal mapping table.
|
|
88
|
+
|
|
89
|
+
## License
|
|
90
|
+
|
|
91
|
+
MIT
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ResolvedOtelConfig, SignalName } from "./types.js";
|
|
2
|
+
export declare const SIGNALS: readonly SignalName[];
|
|
3
|
+
/** Env source, injectable so tests never touch `process.env`. */
|
|
4
|
+
export type EnvSource = Record<string, string | undefined>;
|
|
5
|
+
/**
|
|
6
|
+
* Parse the OTel `key=value,key2=value2` list format used by both
|
|
7
|
+
* `OTEL_EXPORTER_OTLP_HEADERS` and `OTEL_RESOURCE_ATTRIBUTES`. Values are
|
|
8
|
+
* percent-decoded per spec; an undecodable value is kept verbatim rather than
|
|
9
|
+
* dropping the whole pair.
|
|
10
|
+
*/
|
|
11
|
+
export declare function parseKeyValueList(raw: string | undefined): Record<string, string>;
|
|
12
|
+
/**
|
|
13
|
+
* Resolve plugin options against the environment.
|
|
14
|
+
*
|
|
15
|
+
* **Precedence: environment overrides plugin options.** Options are the base
|
|
16
|
+
* layer so a `.well-known/opencode` document can ship a working default for a
|
|
17
|
+
* whole organization; `OTEL_*` variables override per machine so a developer
|
|
18
|
+
* can point at a local collector without editing served config. See
|
|
19
|
+
* `plans/otel.md`.
|
|
20
|
+
*/
|
|
21
|
+
export declare function resolveOtelConfig(raw: unknown, env?: EnvSource): ResolvedOtelConfig;
|
|
22
|
+
/**
|
|
23
|
+
* Resolve the OTLP URL for one signal. A per-signal endpoint is used verbatim
|
|
24
|
+
* (spec: it already includes the path); the base endpoint gets the signal path
|
|
25
|
+
* appended.
|
|
26
|
+
*/
|
|
27
|
+
export declare function signalUrl(config: ResolvedOtelConfig, signal: SignalName): string | undefined;
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
export const SIGNALS = ["traces", "metrics", "logs"];
|
|
2
|
+
const DEFAULTS = {
|
|
3
|
+
serviceName: "opencode",
|
|
4
|
+
metricExportIntervalMs: 60_000,
|
|
5
|
+
logExportIntervalMs: 5_000,
|
|
6
|
+
traceExportIntervalMs: 5_000,
|
|
7
|
+
metricTemporality: "delta"
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* The `OTEL_*` variable names read per signal. The first entry of each tuple is
|
|
11
|
+
* the OTel-spec name; the second (where present) is the Claude-Code-compatible
|
|
12
|
+
* alias, accepted so an operator can move a working env block across tools.
|
|
13
|
+
*/
|
|
14
|
+
const SIGNAL_ENV = {
|
|
15
|
+
traces: {
|
|
16
|
+
exporter: "OTEL_TRACES_EXPORTER",
|
|
17
|
+
endpoint: "OTEL_EXPORTER_OTLP_TRACES_ENDPOINT",
|
|
18
|
+
interval: ["OTEL_BSP_SCHEDULE_DELAY", "OTEL_TRACES_EXPORT_INTERVAL"]
|
|
19
|
+
},
|
|
20
|
+
metrics: {
|
|
21
|
+
exporter: "OTEL_METRICS_EXPORTER",
|
|
22
|
+
endpoint: "OTEL_EXPORTER_OTLP_METRICS_ENDPOINT",
|
|
23
|
+
interval: ["OTEL_METRIC_EXPORT_INTERVAL"]
|
|
24
|
+
},
|
|
25
|
+
logs: {
|
|
26
|
+
exporter: "OTEL_LOGS_EXPORTER",
|
|
27
|
+
endpoint: "OTEL_EXPORTER_OTLP_LOGS_ENDPOINT",
|
|
28
|
+
interval: ["OTEL_BLRP_SCHEDULE_DELAY", "OTEL_LOGS_EXPORT_INTERVAL"]
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
function parseBool(value) {
|
|
32
|
+
if (value === undefined) {
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
if (/^(1|true|yes|on)$/i.test(value)) {
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
if (/^(0|false|no|off)$/i.test(value)) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
function parsePositiveInt(value) {
|
|
44
|
+
if (value === undefined) {
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
const n = Number.parseInt(value.trim(), 10);
|
|
48
|
+
return Number.isFinite(n) && n > 0 ? n : undefined;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Parse the OTel `key=value,key2=value2` list format used by both
|
|
52
|
+
* `OTEL_EXPORTER_OTLP_HEADERS` and `OTEL_RESOURCE_ATTRIBUTES`. Values are
|
|
53
|
+
* percent-decoded per spec; an undecodable value is kept verbatim rather than
|
|
54
|
+
* dropping the whole pair.
|
|
55
|
+
*/
|
|
56
|
+
export function parseKeyValueList(raw) {
|
|
57
|
+
if (!raw) {
|
|
58
|
+
return {};
|
|
59
|
+
}
|
|
60
|
+
const out = {};
|
|
61
|
+
for (const pair of raw.split(",")) {
|
|
62
|
+
const eq = pair.indexOf("=");
|
|
63
|
+
if (eq <= 0) {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
const key = pair.slice(0, eq).trim();
|
|
67
|
+
const rawValue = pair.slice(eq + 1).trim();
|
|
68
|
+
if (!key) {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
try {
|
|
72
|
+
out[key] = decodeURIComponent(rawValue);
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
out[key] = rawValue;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return out;
|
|
79
|
+
}
|
|
80
|
+
function parseExporter(value) {
|
|
81
|
+
if (value === undefined) {
|
|
82
|
+
return undefined;
|
|
83
|
+
}
|
|
84
|
+
// The spec allows a comma-separated list; we honour the first recognised
|
|
85
|
+
// entry rather than fanning out to multiple exporters.
|
|
86
|
+
for (const candidate of value.split(",").map((v) => v.trim().toLowerCase())) {
|
|
87
|
+
if (candidate === "otlp" || candidate === "console" || candidate === "none") {
|
|
88
|
+
return candidate;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return undefined;
|
|
92
|
+
}
|
|
93
|
+
function firstDefined(env, keys) {
|
|
94
|
+
for (const key of keys) {
|
|
95
|
+
const value = env[key];
|
|
96
|
+
if (value !== undefined && value !== "") {
|
|
97
|
+
return value;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
function stringRecord(raw) {
|
|
103
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
104
|
+
return {};
|
|
105
|
+
}
|
|
106
|
+
const out = {};
|
|
107
|
+
for (const [key, value] of Object.entries(raw)) {
|
|
108
|
+
if (typeof value === "string") {
|
|
109
|
+
out[key] = value;
|
|
110
|
+
}
|
|
111
|
+
else if (typeof value === "number" || typeof value === "boolean") {
|
|
112
|
+
out[key] = String(value);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return out;
|
|
116
|
+
}
|
|
117
|
+
function stringList(raw) {
|
|
118
|
+
if (Array.isArray(raw)) {
|
|
119
|
+
return raw.filter((v) => typeof v === "string" && v.trim() !== "");
|
|
120
|
+
}
|
|
121
|
+
if (typeof raw === "string") {
|
|
122
|
+
return raw
|
|
123
|
+
.split(",")
|
|
124
|
+
.map((v) => v.trim())
|
|
125
|
+
.filter((v) => v !== "");
|
|
126
|
+
}
|
|
127
|
+
return [];
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Resolve plugin options against the environment.
|
|
131
|
+
*
|
|
132
|
+
* **Precedence: environment overrides plugin options.** Options are the base
|
|
133
|
+
* layer so a `.well-known/opencode` document can ship a working default for a
|
|
134
|
+
* whole organization; `OTEL_*` variables override per machine so a developer
|
|
135
|
+
* can point at a local collector without editing served config. See
|
|
136
|
+
* `plans/otel.md`.
|
|
137
|
+
*/
|
|
138
|
+
export function resolveOtelConfig(raw, env = process.env) {
|
|
139
|
+
const opts = (raw ?? {});
|
|
140
|
+
const enabled = parseBool(env.OPENCODE_OTEL_ENABLED) ?? opts.enabled !== false;
|
|
141
|
+
const endpoint = env.OTEL_EXPORTER_OTLP_ENDPOINT || opts.endpoint || undefined;
|
|
142
|
+
const endpoints = {};
|
|
143
|
+
for (const signal of SIGNALS) {
|
|
144
|
+
const value = env[SIGNAL_ENV[signal].endpoint] || opts.endpoints?.[signal];
|
|
145
|
+
if (value) {
|
|
146
|
+
endpoints[signal] = value;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
// Env headers merge over option headers key-by-key rather than replacing the
|
|
150
|
+
// map, so a machine can override just its auth token without restating the
|
|
151
|
+
// whole set the served config provided.
|
|
152
|
+
const headers = {
|
|
153
|
+
...stringRecord(opts.headers),
|
|
154
|
+
...parseKeyValueList(env.OTEL_EXPORTER_OTLP_HEADERS)
|
|
155
|
+
};
|
|
156
|
+
// An endpoint anywhere is what makes OTLP the implicit default; with none
|
|
157
|
+
// configured the plugin stays completely inert.
|
|
158
|
+
const hasEndpoint = Boolean(endpoint) || SIGNALS.some((s) => Boolean(endpoints[s]));
|
|
159
|
+
const fallback = hasEndpoint ? "otlp" : "none";
|
|
160
|
+
const exporters = {};
|
|
161
|
+
for (const signal of SIGNALS) {
|
|
162
|
+
exporters[signal] =
|
|
163
|
+
parseExporter(env[SIGNAL_ENV[signal].exporter]) ?? opts.exporters?.[signal] ?? fallback;
|
|
164
|
+
}
|
|
165
|
+
const resourceAttributes = {
|
|
166
|
+
...stringRecord(opts.resourceAttributes),
|
|
167
|
+
...parseKeyValueList(env.OTEL_RESOURCE_ATTRIBUTES)
|
|
168
|
+
};
|
|
169
|
+
const temporality = env.OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE?.trim().toLowerCase() === "cumulative"
|
|
170
|
+
? "cumulative"
|
|
171
|
+
: env.OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE?.trim().toLowerCase() === "delta"
|
|
172
|
+
? "delta"
|
|
173
|
+
: (opts.metricTemporality ?? DEFAULTS.metricTemporality);
|
|
174
|
+
const filteredTools = new Set(env.OTEL_OPENCODE_FILTERED_TOOLS !== undefined
|
|
175
|
+
? stringList(env.OTEL_OPENCODE_FILTERED_TOOLS)
|
|
176
|
+
: stringList(opts.filteredTools));
|
|
177
|
+
const enabledSignals = SIGNALS.filter((s) => exporters[s] !== "none");
|
|
178
|
+
return {
|
|
179
|
+
enabled,
|
|
180
|
+
active: enabled && enabledSignals.length > 0,
|
|
181
|
+
endpoint,
|
|
182
|
+
endpoints,
|
|
183
|
+
headers,
|
|
184
|
+
exporters,
|
|
185
|
+
serviceName: env.OTEL_SERVICE_NAME || opts.serviceName || DEFAULTS.serviceName,
|
|
186
|
+
environment: env.OPENCODE_OTEL_ENVIRONMENT || opts.environment || undefined,
|
|
187
|
+
resourceAttributes,
|
|
188
|
+
metricExportIntervalMs: parsePositiveInt(firstDefined(env, SIGNAL_ENV.metrics.interval)) ??
|
|
189
|
+
(opts.metricExportIntervalMs && opts.metricExportIntervalMs > 0
|
|
190
|
+
? opts.metricExportIntervalMs
|
|
191
|
+
: DEFAULTS.metricExportIntervalMs),
|
|
192
|
+
logExportIntervalMs: parsePositiveInt(firstDefined(env, SIGNAL_ENV.logs.interval)) ??
|
|
193
|
+
(opts.logExportIntervalMs && opts.logExportIntervalMs > 0
|
|
194
|
+
? opts.logExportIntervalMs
|
|
195
|
+
: DEFAULTS.logExportIntervalMs),
|
|
196
|
+
traceExportIntervalMs: parsePositiveInt(firstDefined(env, SIGNAL_ENV.traces.interval)) ??
|
|
197
|
+
(opts.traceExportIntervalMs && opts.traceExportIntervalMs > 0
|
|
198
|
+
? opts.traceExportIntervalMs
|
|
199
|
+
: DEFAULTS.traceExportIntervalMs),
|
|
200
|
+
metricTemporality: temporality,
|
|
201
|
+
includeSessionId: parseBool(env.OTEL_METRICS_INCLUDE_SESSION_ID) ?? opts.includeSessionId === true,
|
|
202
|
+
filteredTools,
|
|
203
|
+
propagateTraceContext: parseBool(env.OPENCODE_OTEL_PROPAGATE_TRACE_CONTEXT) ??
|
|
204
|
+
(opts.propagateTraceContext !== false && exporters.traces !== "none")
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Resolve the OTLP URL for one signal. A per-signal endpoint is used verbatim
|
|
209
|
+
* (spec: it already includes the path); the base endpoint gets the signal path
|
|
210
|
+
* appended.
|
|
211
|
+
*/
|
|
212
|
+
export function signalUrl(config, signal) {
|
|
213
|
+
const explicit = config.endpoints[signal];
|
|
214
|
+
if (explicit) {
|
|
215
|
+
return explicit;
|
|
216
|
+
}
|
|
217
|
+
if (!config.endpoint) {
|
|
218
|
+
return undefined;
|
|
219
|
+
}
|
|
220
|
+
const base = config.endpoint.replace(/\/+$/, "");
|
|
221
|
+
const path = signal === "traces" ? "v1/traces" : signal === "metrics" ? "v1/metrics" : "v1/logs";
|
|
222
|
+
return `${base}/${path}`;
|
|
223
|
+
}
|
|
224
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from "./opencode.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// Intentionally tiny. OpenCode iterates every named export of the main entry
|
|
2
|
+
// and rejects anything that isn't a `Plugin` function, so the only thing this
|
|
3
|
+
// module exposes is the default plugin. Library/utility exports live in
|
|
4
|
+
// `./lib` (see lib.ts), which OpenCode never inspects.
|
|
5
|
+
export { default } from "./opencode.js";
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,8EAA8E;AAC9E,wEAAwE;AACxE,uDAAuD;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Counter, Histogram, Meter } from "@opentelemetry/api";
|
|
2
|
+
/**
|
|
3
|
+
* Every metric this plugin emits, created once per plugin instance.
|
|
4
|
+
*
|
|
5
|
+
* Naming follows the GenAI semantic conventions where one exists
|
|
6
|
+
* (`gen_ai.client.*`) and `opencode.*` otherwise — deliberately matching the
|
|
7
|
+
* vocabulary `opencode-otel-plugin` already established, so both plugins' data
|
|
8
|
+
* lands on the same dashboards. See `plans/otel.md`.
|
|
9
|
+
*/
|
|
10
|
+
export interface Instruments {
|
|
11
|
+
/** Real USD, straight from `AssistantMessage.cost` — no price table involved. */
|
|
12
|
+
cost: Counter;
|
|
13
|
+
/** All five token types, discriminated by `gen_ai.token.type`. */
|
|
14
|
+
tokens: Histogram;
|
|
15
|
+
/** Assistant-message wall time, seconds. */
|
|
16
|
+
duration: Histogram;
|
|
17
|
+
sessions: Counter;
|
|
18
|
+
requests: Counter;
|
|
19
|
+
compactions: Counter;
|
|
20
|
+
/** Wall time a session spent `busy`, seconds. */
|
|
21
|
+
activeTime: Counter;
|
|
22
|
+
linesOfCode: Counter;
|
|
23
|
+
toolInvocations: Counter;
|
|
24
|
+
permissionDecisions: Counter;
|
|
25
|
+
commands: Counter;
|
|
26
|
+
}
|
|
27
|
+
export declare function createInstruments(meter: Meter): Instruments;
|
|
28
|
+
/** Best-effort language for a path, by extension. `undefined` when unknown. */
|
|
29
|
+
export declare function detectLanguage(file: string): string | undefined;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
export function createInstruments(meter) {
|
|
2
|
+
return {
|
|
3
|
+
cost: meter.createCounter("opencode.cost.usage", {
|
|
4
|
+
description: "Cost of model usage, as reported by the OpenCode host",
|
|
5
|
+
unit: "USD"
|
|
6
|
+
}),
|
|
7
|
+
tokens: meter.createHistogram("gen_ai.client.token.usage", {
|
|
8
|
+
description: "Tokens consumed per assistant message, by token type",
|
|
9
|
+
unit: "{token}"
|
|
10
|
+
}),
|
|
11
|
+
duration: meter.createHistogram("gen_ai.client.operation.duration", {
|
|
12
|
+
description: "Duration of a model operation",
|
|
13
|
+
unit: "s"
|
|
14
|
+
}),
|
|
15
|
+
sessions: meter.createCounter("opencode.session.count", {
|
|
16
|
+
description: "Sessions started",
|
|
17
|
+
unit: "{session}"
|
|
18
|
+
}),
|
|
19
|
+
requests: meter.createCounter("opencode.session.request.count", {
|
|
20
|
+
description: "Assistant messages completed",
|
|
21
|
+
unit: "{request}"
|
|
22
|
+
}),
|
|
23
|
+
compactions: meter.createCounter("opencode.session.compaction.count", {
|
|
24
|
+
description: "Context compactions performed",
|
|
25
|
+
unit: "{compaction}"
|
|
26
|
+
}),
|
|
27
|
+
activeTime: meter.createCounter("opencode.active_time.total", {
|
|
28
|
+
description: "Wall time sessions spent busy",
|
|
29
|
+
unit: "s"
|
|
30
|
+
}),
|
|
31
|
+
linesOfCode: meter.createCounter("opencode.lines_of_code.count", {
|
|
32
|
+
description: "Lines added or removed across session diffs",
|
|
33
|
+
unit: "{line}"
|
|
34
|
+
}),
|
|
35
|
+
toolInvocations: meter.createCounter("opencode.tool.invocations", {
|
|
36
|
+
description: "Tool executions",
|
|
37
|
+
unit: "{invocation}"
|
|
38
|
+
}),
|
|
39
|
+
permissionDecisions: meter.createCounter("opencode.permission.decision.count", {
|
|
40
|
+
description: "Permission prompts resolved",
|
|
41
|
+
unit: "{decision}"
|
|
42
|
+
}),
|
|
43
|
+
commands: meter.createCounter("opencode.command.executed.count", {
|
|
44
|
+
description: "Slash commands executed",
|
|
45
|
+
unit: "{command}"
|
|
46
|
+
})
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
const EXTENSION_LANGUAGES = {
|
|
50
|
+
ts: "typescript",
|
|
51
|
+
tsx: "typescript",
|
|
52
|
+
mts: "typescript",
|
|
53
|
+
cts: "typescript",
|
|
54
|
+
js: "javascript",
|
|
55
|
+
jsx: "javascript",
|
|
56
|
+
mjs: "javascript",
|
|
57
|
+
cjs: "javascript",
|
|
58
|
+
py: "python",
|
|
59
|
+
rs: "rust",
|
|
60
|
+
go: "go",
|
|
61
|
+
java: "java",
|
|
62
|
+
kt: "kotlin",
|
|
63
|
+
kts: "kotlin",
|
|
64
|
+
swift: "swift",
|
|
65
|
+
dart: "dart",
|
|
66
|
+
rb: "ruby",
|
|
67
|
+
php: "php",
|
|
68
|
+
cs: "csharp",
|
|
69
|
+
c: "c",
|
|
70
|
+
h: "c",
|
|
71
|
+
cc: "cpp",
|
|
72
|
+
cpp: "cpp",
|
|
73
|
+
hpp: "cpp",
|
|
74
|
+
m: "objective-c",
|
|
75
|
+
mm: "objective-c",
|
|
76
|
+
scala: "scala",
|
|
77
|
+
ex: "elixir",
|
|
78
|
+
exs: "elixir",
|
|
79
|
+
sh: "shell",
|
|
80
|
+
bash: "shell",
|
|
81
|
+
zsh: "shell",
|
|
82
|
+
sql: "sql",
|
|
83
|
+
html: "html",
|
|
84
|
+
css: "css",
|
|
85
|
+
scss: "scss",
|
|
86
|
+
json: "json",
|
|
87
|
+
yaml: "yaml",
|
|
88
|
+
yml: "yaml",
|
|
89
|
+
toml: "toml",
|
|
90
|
+
md: "markdown",
|
|
91
|
+
tf: "terraform"
|
|
92
|
+
};
|
|
93
|
+
/** Best-effort language for a path, by extension. `undefined` when unknown. */
|
|
94
|
+
export function detectLanguage(file) {
|
|
95
|
+
const base = file.slice(file.lastIndexOf("/") + 1);
|
|
96
|
+
const dot = base.lastIndexOf(".");
|
|
97
|
+
if (dot <= 0) {
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
100
|
+
return EXTENSION_LANGUAGES[base.slice(dot + 1).toLowerCase()];
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=instruments.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instruments.js","sourceRoot":"","sources":["../src/instruments.ts"],"names":[],"mappings":"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"}
|
package/dist/lib.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { createOtelPlugin, OpencodeOtelPlugin, type OtelPluginFactoryOptions } from "./opencode.js";
|
|
2
|
+
export { type EnvSource, parseKeyValueList, resolveOtelConfig, signalUrl, SIGNALS } from "./config.js";
|
|
3
|
+
export { buildResource, createProviders, type ExporterFactories, type TelemetryProviders } from "./providers.js";
|
|
4
|
+
export { createInstruments, detectLanguage, type Instruments } from "./instruments.js";
|
|
5
|
+
export { type RecorderDeps, TelemetryRecorder } from "./recorder.js";
|
|
6
|
+
export { installTracePropagation, type PropagationConfigInput, type ProviderConfigLike } from "./propagation.js";
|
|
7
|
+
export { createJsonConsoleLogger, DEFAULT_LOG_LEVEL, fromOpenCodeLogLevel, type LogFields, type Logger, type LogLevel } from "./logging.js";
|
|
8
|
+
export type { ExporterKind, MetricTemporality, OtelPluginOptions, ResolvedOtelConfig, SignalName } from "./types.js";
|
package/dist/lib.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { createOtelPlugin, OpencodeOtelPlugin } from "./opencode.js";
|
|
2
|
+
export { parseKeyValueList, resolveOtelConfig, signalUrl, SIGNALS } from "./config.js";
|
|
3
|
+
export { buildResource, createProviders } from "./providers.js";
|
|
4
|
+
export { createInstruments, detectLanguage } from "./instruments.js";
|
|
5
|
+
export { TelemetryRecorder } from "./recorder.js";
|
|
6
|
+
export { installTracePropagation } from "./propagation.js";
|
|
7
|
+
export { createJsonConsoleLogger, DEFAULT_LOG_LEVEL, fromOpenCodeLogLevel } from "./logging.js";
|
|
8
|
+
//# sourceMappingURL=lib.js.map
|
package/dist/lib.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lib.js","sourceRoot":"","sources":["../src/lib.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAEnB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAEL,iBAAiB,EACjB,iBAAiB,EACjB,SAAS,EACT,OAAO,EACR,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,aAAa,EACb,eAAe,EAGhB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAoB,MAAM,kBAAkB,CAAC;AAEvF,OAAO,EAAqB,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAErE,OAAO,EACL,uBAAuB,EAGxB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,uBAAuB,EACvB,iBAAiB,EACjB,oBAAoB,EAIrB,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { LogLevel } from "./types.js";
|
|
2
|
+
export type { LogLevel } from "./types.js";
|
|
3
|
+
export declare const LOG_LEVEL_PRIORITY: Record<LogLevel, number>;
|
|
4
|
+
export declare const DEFAULT_LOG_LEVEL: LogLevel;
|
|
5
|
+
export interface LogFields {
|
|
6
|
+
[key: string]: unknown;
|
|
7
|
+
}
|
|
8
|
+
export interface Logger {
|
|
9
|
+
trace(event: string, fields?: LogFields): void;
|
|
10
|
+
debug(event: string, fields?: LogFields): void;
|
|
11
|
+
info(event: string, fields?: LogFields): void;
|
|
12
|
+
warn(event: string, fields?: LogFields): void;
|
|
13
|
+
error(event: string, fields?: LogFields): void;
|
|
14
|
+
}
|
|
15
|
+
export declare function createJsonConsoleLogger(minLevel?: LogLevel): Logger;
|
|
16
|
+
export declare function fromOpenCodeLogLevel(value: unknown): LogLevel | undefined;
|
package/dist/logging.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
export const LOG_LEVEL_PRIORITY = {
|
|
2
|
+
trace: 5,
|
|
3
|
+
debug: 10,
|
|
4
|
+
info: 20,
|
|
5
|
+
warn: 30,
|
|
6
|
+
error: 40
|
|
7
|
+
};
|
|
8
|
+
export const DEFAULT_LOG_LEVEL = "info";
|
|
9
|
+
function redactFields(fields) {
|
|
10
|
+
if (!fields) {
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
const redacted = {};
|
|
14
|
+
for (const [key, value] of Object.entries(fields)) {
|
|
15
|
+
if (/token|secret|password|authorization/i.test(key)) {
|
|
16
|
+
redacted[key] = "[redacted]";
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
redacted[key] = value;
|
|
20
|
+
}
|
|
21
|
+
return redacted;
|
|
22
|
+
}
|
|
23
|
+
export function createJsonConsoleLogger(minLevel = DEFAULT_LOG_LEVEL) {
|
|
24
|
+
const minPriority = LOG_LEVEL_PRIORITY[minLevel];
|
|
25
|
+
const write = (level, event, fields) => {
|
|
26
|
+
if (LOG_LEVEL_PRIORITY[level] < minPriority) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const payload = {
|
|
30
|
+
ts: new Date().toISOString(),
|
|
31
|
+
level,
|
|
32
|
+
event,
|
|
33
|
+
...(redactFields(fields) ?? {})
|
|
34
|
+
};
|
|
35
|
+
const line = JSON.stringify(payload);
|
|
36
|
+
if (level === "error") {
|
|
37
|
+
console.error(line);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (level === "warn") {
|
|
41
|
+
console.warn(line);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
console.log(line);
|
|
45
|
+
};
|
|
46
|
+
return {
|
|
47
|
+
trace: (event, fields) => write("trace", event, fields),
|
|
48
|
+
debug: (event, fields) => write("debug", event, fields),
|
|
49
|
+
info: (event, fields) => write("info", event, fields),
|
|
50
|
+
warn: (event, fields) => write("warn", event, fields),
|
|
51
|
+
error: (event, fields) => write("error", event, fields)
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
export function fromOpenCodeLogLevel(value) {
|
|
55
|
+
if (typeof value !== "string") {
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
58
|
+
switch (value.toUpperCase()) {
|
|
59
|
+
case "DEBUG":
|
|
60
|
+
// Host DEBUG unlocks our most-verbose internal tier (trace).
|
|
61
|
+
return "trace";
|
|
62
|
+
case "INFO":
|
|
63
|
+
return "info";
|
|
64
|
+
case "WARN":
|
|
65
|
+
return "warn";
|
|
66
|
+
case "ERROR":
|
|
67
|
+
return "error";
|
|
68
|
+
default:
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=logging.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logging.js","sourceRoot":"","sources":["../src/logging.ts"],"names":[],"mappings":"AAIA,MAAM,CAAC,MAAM,kBAAkB,GAA6B;IAC1D,KAAK,EAAE,CAAC;IACR,KAAK,EAAE,EAAE;IACT,IAAI,EAAE,EAAE;IACR,IAAI,EAAE,EAAE;IACR,KAAK,EAAE,EAAE;CACV,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAa,MAAM,CAAC;AAclD,SAAS,YAAY,CAAC,MAAkB;IACtC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAClD,IAAI,sCAAsC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACrD,QAAQ,CAAC,GAAG,CAAC,GAAG,YAAY,CAAC;YAC7B,SAAS;QACX,CAAC;QACD,QAAQ,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IACxB,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,WAAqB,iBAAiB;IAC5E,MAAM,WAAW,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IAEjD,MAAM,KAAK,GAAG,CAAC,KAAe,EAAE,KAAa,EAAE,MAAkB,EAAQ,EAAE;QACzE,IAAI,kBAAkB,CAAC,KAAK,CAAC,GAAG,WAAW,EAAE,CAAC;YAC5C,OAAO;QACT,CAAC;QACD,MAAM,OAAO,GAAG;YACd,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YAC5B,KAAK;YACL,KAAK;YACL,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;SAChC,CAAC;QACF,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACrC,IAAI,KAAK,KAAK,OAAO,EAAE,CAAC;YACtB,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACpB,OAAO;QACT,CAAC;QACD,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;YACrB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnB,OAAO;QACT,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACpB,CAAC,CAAC;IAEF,OAAO;QACL,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC;QACvD,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC;QACvD,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC;QACrD,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC;QACrD,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC;KACxD,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAc;IACjD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,QAAQ,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;QAC5B,KAAK,OAAO;YACV,6DAA6D;YAC7D,OAAO,OAAO,CAAC;QACjB,KAAK,MAAM;YACT,OAAO,MAAM,CAAC;QAChB,KAAK,MAAM;YACT,OAAO,MAAM,CAAC;QAChB,KAAK,OAAO;YACV,OAAO,OAAO,CAAC;QACjB;YACE,OAAO,SAAS,CAAC;IACrB,CAAC;AACH,CAAC"}
|