@vzn/vx-otel 0.0.638 → 0.0.639
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/README.md +4 -6
- package/package.json +2 -2
- package/src/otlp.ts +0 -2
- package/src/plugin.ts +41 -13
package/README.md
CHANGED
|
@@ -31,7 +31,7 @@ to declare in every environment:
|
|
|
31
31
|
|
|
32
32
|
| Variable | Purpose |
|
|
33
33
|
| ------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
34
|
-
| `OTEL_EXPORTER_OTLP_ENDPOINT` | base collector URL (e.g. `http://localhost:4318`)
|
|
34
|
+
| `OTEL_EXPORTER_OTLP_ENDPOINT` | base collector URL (e.g. `http://localhost:4318`); one with no `http://` or `https://` is refused with a warning |
|
|
35
35
|
| `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` | full traces URL override |
|
|
36
36
|
| `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT` | full metrics URL override |
|
|
37
37
|
| `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` | full logs URL override |
|
|
@@ -93,8 +93,7 @@ otel({
|
|
|
93
93
|
`vcs.ref.head.name`, `vx.command` (the command line; what follows `--`
|
|
94
94
|
is counted, `-- <N arguments>`, never quoted, and a secret value
|
|
95
95
|
before it is `***`), CI provider,
|
|
96
|
-
host/os/arch, vx version,
|
|
97
|
-
`vx.tag.<k>`, and `cicd.pipeline.result` (`success`, `failure`, or
|
|
96
|
+
host/os/arch, vx version, and `cicd.pipeline.result` (`success`, `failure`, or
|
|
98
97
|
`cancellation` for a run stopped with nothing failed); a red run sets
|
|
99
98
|
span status `ERROR`;
|
|
100
99
|
- a child `vx.task` span per task — `cicd.pipeline.task.name`,
|
|
@@ -191,8 +190,7 @@ same CPU live as with one send at the end (median of 10: 815 ms both).
|
|
|
191
190
|
|
|
192
191
|
No send ever holds a task: a task's end only queues its records. A collector
|
|
193
192
|
that never answers holds nothing either: at the end of the run every send
|
|
194
|
-
still in flight is cut at core's teardown deadline (3 s,
|
|
195
|
-
`VX_RUN_TEARDOWN_TIMEOUT`), and the process exits.
|
|
193
|
+
still in flight is cut at core's teardown deadline (3 s), and the process exits.
|
|
196
194
|
|
|
197
195
|
## Behavior note
|
|
198
196
|
|
|
@@ -219,5 +217,5 @@ userinfo and query string replaced by `***`, so an endpoint that carries
|
|
|
219
217
|
its credential in the URL does not leak it into a CI log. The run stays
|
|
220
218
|
green either way; a collector that
|
|
221
219
|
takes too long is cut off by core's end-of-run deadline
|
|
222
|
-
(
|
|
220
|
+
(3 s) with a line saying the buffered
|
|
223
221
|
records were lost.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vzn/vx-otel",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.639",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "OpenTelemetry exporter for vx — a telemetry plugin mapping runs to OTLP traces + metrics (CI/CD + VCS semantic conventions).",
|
|
6
6
|
"keywords": [
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"access": "public"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
|
-
"@vzn/vx": "^0.0.
|
|
37
|
+
"@vzn/vx": "^0.0.639"
|
|
38
38
|
},
|
|
39
39
|
"repository": {
|
|
40
40
|
"type": "git",
|
package/src/otlp.ts
CHANGED
|
@@ -109,7 +109,6 @@ const VX_ATTR = {
|
|
|
109
109
|
version: 'vx.version',
|
|
110
110
|
dirty: 'vx.dirty',
|
|
111
111
|
defaultBranch: 'vx.default_branch',
|
|
112
|
-
tagPrefix: 'vx.tag.',
|
|
113
112
|
// run summary (root span only)
|
|
114
113
|
runStartedAt: 'vx.run.started_at',
|
|
115
114
|
runEndedAt: 'vx.run.ended_at',
|
|
@@ -395,7 +394,6 @@ export function runSpanAttributes(run: RunContextRecord, summary?: RunSummaryRec
|
|
|
395
394
|
if (run.dirty !== null) attrs.push(boolAttr(VX_ATTR.dirty, run.dirty))
|
|
396
395
|
if (run.ciProvider !== null) attrs.push(strAttr(VX_ATTR.ciProvider, run.ciProvider))
|
|
397
396
|
if (run.host !== null) attrs.push(strAttr(VX_ATTR.host, run.host))
|
|
398
|
-
for (const [k, v] of Object.entries(run.tags)) attrs.push(strAttr(`${VX_ATTR.tagPrefix}${k}`, v))
|
|
399
397
|
if (summary !== undefined) {
|
|
400
398
|
attrs.push(
|
|
401
399
|
intAttr(VX_ATTR.runStartedAt, summary.startedAt),
|
package/src/plugin.ts
CHANGED
|
@@ -174,19 +174,47 @@ export function resolveOtelConfig(
|
|
|
174
174
|
env: Record<string, string | undefined>,
|
|
175
175
|
warn?: (m: string) => void,
|
|
176
176
|
): OtelSinkConfig | undefined {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
present(
|
|
181
|
-
(
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
const
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
177
|
+
// Each URL with the setting it came from, so a refusal can name it
|
|
178
|
+
// without printing a value that may hold a credential.
|
|
179
|
+
const from = (option: keyof OtelPluginOptions, envName: string): [string, string] | undefined => {
|
|
180
|
+
const o = present(opts[option] as string | undefined)
|
|
181
|
+
if (o !== undefined) return [o, `the ${option} option`]
|
|
182
|
+
const e = present(env[envName])
|
|
183
|
+
return e === undefined ? undefined : [e, envName]
|
|
184
|
+
}
|
|
185
|
+
const base = from('endpoint', 'OTEL_EXPORTER_OTLP_ENDPOINT')
|
|
186
|
+
const pick = (
|
|
187
|
+
option: keyof OtelPluginOptions,
|
|
188
|
+
envName: string,
|
|
189
|
+
signal: string,
|
|
190
|
+
): [string, string] | undefined =>
|
|
191
|
+
from(option, envName) ??
|
|
192
|
+
(base === undefined ? undefined : [joinSignal(base[0], signal), base[1]])
|
|
193
|
+
const picked = {
|
|
194
|
+
traces: pick('tracesEndpoint', 'OTEL_EXPORTER_OTLP_TRACES_ENDPOINT', 'traces'),
|
|
195
|
+
metrics: pick('metricsEndpoint', 'OTEL_EXPORTER_OTLP_METRICS_ENDPOINT', 'metrics'),
|
|
196
|
+
logs: pick('logsEndpoint', 'OTEL_EXPORTER_OTLP_LOGS_ENDPOINT', 'logs'),
|
|
197
|
+
}
|
|
198
|
+
// An endpoint with no http(s) scheme (`localhost:4318`) parses as a URL
|
|
199
|
+
// of scheme `localhost:`: every export failed "Unable to connect", once
|
|
200
|
+
// per signal, after a second of retries. It is refused here, once per
|
|
201
|
+
// setting, and its signals are not exported.
|
|
202
|
+
const refused = new Map<string, string[]>()
|
|
203
|
+
for (const signal of ['traces', 'metrics', 'logs'] as const) {
|
|
204
|
+
const p = picked[signal]
|
|
205
|
+
if (p === undefined) continue
|
|
206
|
+
const protocol = URL.parse(p[0])?.protocol
|
|
207
|
+
if (protocol === 'http:' || protocol === 'https:') continue
|
|
208
|
+
refused.set(p[1], [...(refused.get(p[1]) ?? []), signal])
|
|
209
|
+
picked[signal] = undefined
|
|
210
|
+
}
|
|
211
|
+
for (const [setting, signals] of refused) {
|
|
212
|
+
const names = signals.length === 3 ? 'traces, metrics and logs' : signals.join(' and ')
|
|
213
|
+
warn?.(`[vx-otel] ${setting} is not an http:// or https:// URL — ${names} are not exported`)
|
|
214
|
+
}
|
|
215
|
+
const tracesUrl = picked.traces?.[0]
|
|
216
|
+
const metricsUrl = picked.metrics?.[0]
|
|
217
|
+
const logsUrl = picked.logs?.[0]
|
|
190
218
|
// Each signal has its own endpoint, as the spec has them: a pipeline that
|
|
191
219
|
// set only a metrics (or logs) endpoint declined whole and exported
|
|
192
220
|
// nothing (F-45). The plugin declines only when no signal has one.
|