@xeonr/telemetry 0.0.0-stage → 0.2.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.
Files changed (56) hide show
  1. package/README.md +128 -2
  2. package/dist/baggage.d.ts +21 -0
  3. package/dist/baggage.d.ts.map +1 -0
  4. package/dist/baggage.js +117 -0
  5. package/dist/baggage.js.map +1 -0
  6. package/dist/boot.d.ts +7 -0
  7. package/dist/boot.d.ts.map +1 -0
  8. package/dist/boot.js +10 -0
  9. package/dist/boot.js.map +1 -0
  10. package/dist/connect.d.ts +63 -0
  11. package/dist/connect.d.ts.map +1 -0
  12. package/dist/connect.js +200 -0
  13. package/dist/connect.js.map +1 -0
  14. package/dist/fetch.d.ts +19 -0
  15. package/dist/fetch.d.ts.map +1 -0
  16. package/dist/fetch.js +41 -0
  17. package/dist/fetch.js.map +1 -0
  18. package/dist/identity.d.ts +79 -0
  19. package/dist/identity.d.ts.map +1 -0
  20. package/dist/identity.js +173 -0
  21. package/dist/identity.js.map +1 -0
  22. package/dist/index.d.ts +22 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +22 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/job.d.ts +38 -0
  27. package/dist/job.d.ts.map +1 -0
  28. package/dist/job.js +107 -0
  29. package/dist/job.js.map +1 -0
  30. package/dist/keys.d.ts +80 -0
  31. package/dist/keys.d.ts.map +1 -0
  32. package/dist/keys.js +90 -0
  33. package/dist/keys.js.map +1 -0
  34. package/dist/keys.json +127 -0
  35. package/dist/log.d.ts +43 -0
  36. package/dist/log.d.ts.map +1 -0
  37. package/dist/log.js +139 -0
  38. package/dist/log.js.map +1 -0
  39. package/dist/processor.d.ts +79 -0
  40. package/dist/processor.d.ts.map +1 -0
  41. package/dist/processor.js +163 -0
  42. package/dist/processor.js.map +1 -0
  43. package/dist/register.d.ts +2 -0
  44. package/dist/register.d.ts.map +1 -0
  45. package/dist/register.js +34 -0
  46. package/dist/register.js.map +1 -0
  47. package/dist/sanitize.d.ts +17 -0
  48. package/dist/sanitize.d.ts.map +1 -0
  49. package/dist/sanitize.js +52 -0
  50. package/dist/sanitize.js.map +1 -0
  51. package/dist/sdk.d.ts +50 -0
  52. package/dist/sdk.d.ts.map +1 -0
  53. package/dist/sdk.js +217 -0
  54. package/dist/sdk.js.map +1 -0
  55. package/package.json +97 -3
  56. package/register.cjs +3 -0
package/dist/fetch.js ADDED
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Outbound HTTP, the Node counterpart of go-platform's
3
+ * telemetry.HTTPTransport: the undici and http instrumentations already make
4
+ * the client span and send `traceparent`; this adds `peer.service` (and the
5
+ * span name `HTTP GET <peer>`) and, toward an in-cluster host only, origin
6
+ * baggage. Any `baggage` header aimed elsewhere is removed.
7
+ */
8
+ import { context } from "@opentelemetry/api";
9
+ import { HEADER_BAGGAGE, inCluster, originBaggage } from "./baggage.js";
10
+ import { withPeer } from "./processor.js";
11
+ /** A `fetch` for one peer. */
12
+ export function fetchWith(opts = {}) {
13
+ const base = opts.fetch ?? ((...args) => globalThis.fetch(...args));
14
+ return (input, init) => {
15
+ const url = input instanceof Request ? input.url : String(input);
16
+ const headers = new Headers(init?.headers ?? (input instanceof Request ? input.headers : undefined));
17
+ const b = opts.baggage === false ? "" : baggageFor(url, opts.inCluster);
18
+ if (b)
19
+ headers.set(HEADER_BAGGAGE, b);
20
+ else
21
+ headers.delete(HEADER_BAGGAGE);
22
+ const call = () => base(input, { ...init, headers });
23
+ return opts.peer ? withPeer(opts.peer, call) : call();
24
+ };
25
+ }
26
+ /**
27
+ * The `baggage` header for a request to `url`: the origin members when the
28
+ * host is in-cluster, else "". For HTTP clients other than fetch (axios,
29
+ * got): set it when non-empty, and run the call inside `withPeer`.
30
+ */
31
+ export function baggageFor(url, isInCluster = inCluster) {
32
+ let host = "";
33
+ try {
34
+ host = new URL(url).host;
35
+ }
36
+ catch {
37
+ return "";
38
+ }
39
+ return isInCluster(host) ? originBaggage(context.active()) : "";
40
+ }
41
+ //# sourceMappingURL=fetch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch.js","sourceRoot":"","sources":["../src/fetch.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACxE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAa1C,8BAA8B;AAC9B,MAAM,UAAU,SAAS,CAAC,OAAqB,EAAE;IAChD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,GAAG,IAA8B,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;IAC9F,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACtB,MAAM,GAAG,GAAG,KAAK,YAAY,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACjE,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,IAAI,EAAE,OAAO,IAAI,CAAC,KAAK,YAAY,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;QACrG,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QACxE,IAAI,CAAC;YAAE,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC;;YACjC,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;QACpC,MAAM,IAAI,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;QACrD,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACvD,CAAC,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,GAAW,EAAE,cAAyC,SAAS;IACzF,IAAI,IAAI,GAAG,EAAE,CAAC;IACd,IAAI,CAAC;QACJ,IAAI,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;IAC1B,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,EAAE,CAAC;IACX,CAAC;IACD,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AACjE,CAAC"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * The request's identity (observability plan §4.2), carried on the
3
+ * OpenTelemetry context as go-platform's telemetry package carries it on
4
+ * context.Context: one mutable record per request or job, so a handler's
5
+ * `setTeam` reaches every span and log line started after it.
6
+ */
7
+ import { type Attributes, type Context, type Span } from "@opentelemetry/api";
8
+ import { type AuthMethod, type SubjectKind } from "./keys.ts";
9
+ /** What the telemetry layer knows about who a request or job acts for. Every value is a full URN or an opaque id, never a name or email. */
10
+ export interface Identity {
11
+ subject?: string;
12
+ subjectKind?: SubjectKind;
13
+ orgId?: string;
14
+ clientId?: string;
15
+ applicationId?: string;
16
+ delegatorApp?: string;
17
+ apiKeyId?: string;
18
+ authMethod?: AuthMethod;
19
+ originSubject?: string;
20
+ originService?: string;
21
+ teamUrn?: string;
22
+ resourceType?: string;
23
+ resourceId?: string;
24
+ resourceUrn?: string;
25
+ /** On the RPC server span only; `attributes()` and `fields()` leave them out. */
26
+ scopes?: string[];
27
+ jobName?: string;
28
+ jobRunId?: string;
29
+ jobTrigger?: string;
30
+ }
31
+ /** The kind of a subject URN, as go-platform's telemetry.SubjectKind derives it. */
32
+ export declare function subjectKind(subject: string | undefined): SubjectKind;
33
+ /** The span attributes for an identity: the §4.2 table, minus scopes. */
34
+ export declare function attributes(id: Identity): Attributes;
35
+ /** The log fields for an identity: the same table, log spelling. */
36
+ export declare function fields(id: Identity): Record<string, string>;
37
+ /** @internal The per-request record. Exported for the package's own modules. */
38
+ export declare class State {
39
+ id: Identity;
40
+ job: boolean;
41
+ originDecided: boolean;
42
+ entry: boolean;
43
+ baggageOrgId: string;
44
+ service: string;
45
+ procedure: string;
46
+ ip: string;
47
+ /** The request's or job's root span, so late team/resource reach it too. */
48
+ root: Span | undefined;
49
+ clone(): State;
50
+ /** The identity with its derived values filled in, as go-platform's state.identity. */
51
+ identity(): Identity;
52
+ merge(id: Identity): void;
53
+ }
54
+ /** @internal */
55
+ export declare function stateFrom(ctx?: Context): State | undefined;
56
+ /** @internal */
57
+ export declare function withState(ctx: Context, s: State): Context;
58
+ /** @internal The context's record, creating one when there is none. */
59
+ export declare function ensureState(ctx?: Context): [Context, State];
60
+ /** The identity of the request or job `ctx` belongs to, or undefined outside one. */
61
+ export declare function identityFrom(ctx?: Context): Identity | undefined;
62
+ /**
63
+ * Records who the caller is. Call it where the service verifies a Xeonr
64
+ * caller itself (its auth interceptor or middleware), the Node counterpart of
65
+ * go-platform's authn.WithPrincipal. It merges into the request's record when
66
+ * there is one (the server interceptor made it) and returns `ctx` unchanged;
67
+ * otherwise it returns a new context carrying a record, to run the rest of
68
+ * the work under with `context.with`.
69
+ */
70
+ export declare function setIdentity(id: Identity, ctx?: Context): Context;
71
+ /**
72
+ * Records the team the request acts on (resource ownership), never the
73
+ * caller's memberships. Spans started after the call carry it, and so do the
74
+ * current span and the request's root span.
75
+ */
76
+ export declare function setTeam(urn: string, ctx?: Context): void;
77
+ /** Records the request's target, as trail's SetTarget names it. */
78
+ export declare function setResource(type: string, id: string, urn: string, ctx?: Context): void;
79
+ //# sourceMappingURL=identity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAoC,KAAK,UAAU,EAAE,KAAK,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAChH,OAAO,EAAiB,KAAK,UAAU,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AAE7E,4IAA4I;AAC5I,MAAM,WAAW,QAAQ;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iFAAiF;IACjF,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AASD,oFAAoF;AACpF,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,WAAW,CAQpE;AAID,yEAAyE;AACzE,wBAAgB,UAAU,CAAC,EAAE,EAAE,QAAQ,GAAG,UAAU,CAQnD;AAED,oEAAoE;AACpE,wBAAgB,MAAM,CAAC,EAAE,EAAE,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAQ3D;AAED,gFAAgF;AAChF,qBAAa,KAAK;IACjB,EAAE,EAAE,QAAQ,CAAM;IAClB,GAAG,UAAS;IACZ,aAAa,UAAS;IACtB,KAAK,UAAS;IACd,YAAY,SAAM;IAClB,OAAO,SAAM;IACb,SAAS,SAAM;IACf,EAAE,SAAM;IACR,4EAA4E;IAC5E,IAAI,EAAE,IAAI,GAAG,SAAS,CAAC;IAEvB,KAAK,IAAI,KAAK;IAcd,uFAAuF;IACvF,QAAQ,IAAI,QAAQ;IAapB,KAAK,CAAC,EAAE,EAAE,QAAQ,GAAG,IAAI;CAMzB;AAID,gBAAgB;AAChB,wBAAgB,SAAS,CAAC,GAAG,GAAE,OAA0B,GAAG,KAAK,GAAG,SAAS,CAE5E;AAED,gBAAgB;AAChB,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,GAAG,OAAO,CAEzD;AAED,uEAAuE;AACvE,wBAAgB,WAAW,CAAC,GAAG,GAAE,OAA0B,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAK7E;AAED,qFAAqF;AACrF,wBAAgB,YAAY,CAAC,GAAG,GAAE,OAA0B,GAAG,QAAQ,GAAG,SAAS,CAElF;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,QAAQ,EAAE,GAAG,GAAE,OAA0B,GAAG,OAAO,CAKlF;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,GAAE,OAA0B,GAAG,IAAI,CAK1E;AAED,mEAAmE;AACnE,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,GAAE,OAA0B,GAAG,IAAI,CASxG"}
@@ -0,0 +1,173 @@
1
+ /**
2
+ * The request's identity (observability plan §4.2), carried on the
3
+ * OpenTelemetry context as go-platform's telemetry package carries it on
4
+ * context.Context: one mutable record per request or job, so a handler's
5
+ * `setTeam` reaches every span and log line started after it.
6
+ */
7
+ import { context, createContextKey, trace } from "@opentelemetry/api";
8
+ import { IDENTITY_KEYS } from "./keys.js";
9
+ const URN_USER = "urn:xeonr:auth:uid:user:";
10
+ const URN_SERVICE_ACCOUNT = "urn:xeonr:auth:uid:service_account:";
11
+ const URN_CLIENT = "urn:xeonr:auth:client:";
12
+ const URN_TEAM = "urn:xeonr:auth:team:";
13
+ const URN_API_KEY = "urn:xeonr:auth:api-key:";
14
+ const URN_AUTOMATION_KEY = "urn:xeonr:auth:automation-key:";
15
+ /** The kind of a subject URN, as go-platform's telemetry.SubjectKind derives it. */
16
+ export function subjectKind(subject) {
17
+ if (!subject)
18
+ return "anonymous";
19
+ if (subject.startsWith(URN_USER))
20
+ return "user";
21
+ if (subject.startsWith(URN_SERVICE_ACCOUNT))
22
+ return "service_account";
23
+ if (subject.startsWith(URN_CLIENT))
24
+ return "client";
25
+ if (subject.startsWith(URN_TEAM))
26
+ return "team";
27
+ if (subject.startsWith(URN_API_KEY) || subject.startsWith(URN_AUTOMATION_KEY))
28
+ return "api_key";
29
+ return "unknown";
30
+ }
31
+ /** The span attributes for an identity: the §4.2 table, minus scopes. */
32
+ export function attributes(id) {
33
+ const out = {};
34
+ for (const k of IDENTITY_KEYS) {
35
+ if (k.rpcServerSpanOnly)
36
+ continue;
37
+ const v = id[k.prop];
38
+ if (v)
39
+ out[k.span] = v;
40
+ }
41
+ return out;
42
+ }
43
+ /** The log fields for an identity: the same table, log spelling. */
44
+ export function fields(id) {
45
+ const out = {};
46
+ for (const k of IDENTITY_KEYS) {
47
+ if (!k.log)
48
+ continue;
49
+ const v = id[k.prop];
50
+ if (v)
51
+ out[k.log] = v;
52
+ }
53
+ return out;
54
+ }
55
+ /** @internal The per-request record. Exported for the package's own modules. */
56
+ export class State {
57
+ id = {};
58
+ job = false;
59
+ originDecided = false;
60
+ entry = false;
61
+ baggageOrgId = "";
62
+ service = "";
63
+ procedure = "";
64
+ ip = "";
65
+ /** The request's or job's root span, so late team/resource reach it too. */
66
+ root;
67
+ clone() {
68
+ const c = new State();
69
+ c.id = { ...this.id, ...(this.id.scopes ? { scopes: [...this.id.scopes] } : {}) };
70
+ c.job = this.job;
71
+ c.originDecided = this.originDecided;
72
+ c.entry = this.entry;
73
+ c.baggageOrgId = this.baggageOrgId;
74
+ c.service = this.service;
75
+ c.procedure = this.procedure;
76
+ c.ip = this.ip;
77
+ c.root = this.root;
78
+ return c;
79
+ }
80
+ /** The identity with its derived values filled in, as go-platform's state.identity. */
81
+ identity() {
82
+ const id = { ...this.id };
83
+ if (this.id.scopes)
84
+ id.scopes = [...this.id.scopes];
85
+ if (!id.subjectKind)
86
+ id.subjectKind = id.subject ? subjectKind(id.subject) : this.job ? "system" : "anonymous";
87
+ if (!id.authMethod && !id.subject && !this.job)
88
+ id.authMethod = "none";
89
+ if (!id.orgId && this.baggageOrgId)
90
+ id.orgId = this.baggageOrgId;
91
+ if (this.entry && !id.originSubject && !id.originService) {
92
+ if (id.subject)
93
+ id.originSubject = id.subject;
94
+ if (this.service)
95
+ id.originService = this.service;
96
+ }
97
+ return id;
98
+ }
99
+ merge(id) {
100
+ for (const [k, v] of Object.entries(id)) {
101
+ if (v === undefined || v === "")
102
+ continue;
103
+ this.id[k] = Array.isArray(v) ? [...v] : v;
104
+ }
105
+ }
106
+ }
107
+ const STATE = createContextKey("xeonr.telemetry.state");
108
+ /** @internal */
109
+ export function stateFrom(ctx = context.active()) {
110
+ return ctx.getValue(STATE);
111
+ }
112
+ /** @internal */
113
+ export function withState(ctx, s) {
114
+ return ctx.setValue(STATE, s);
115
+ }
116
+ /** @internal The context's record, creating one when there is none. */
117
+ export function ensureState(ctx = context.active()) {
118
+ const s = stateFrom(ctx);
119
+ if (s)
120
+ return [ctx, s];
121
+ const n = new State();
122
+ return [withState(ctx, n), n];
123
+ }
124
+ /** The identity of the request or job `ctx` belongs to, or undefined outside one. */
125
+ export function identityFrom(ctx = context.active()) {
126
+ return stateFrom(ctx)?.identity();
127
+ }
128
+ /**
129
+ * Records who the caller is. Call it where the service verifies a Xeonr
130
+ * caller itself (its auth interceptor or middleware), the Node counterpart of
131
+ * go-platform's authn.WithPrincipal. It merges into the request's record when
132
+ * there is one (the server interceptor made it) and returns `ctx` unchanged;
133
+ * otherwise it returns a new context carrying a record, to run the rest of
134
+ * the work under with `context.with`.
135
+ */
136
+ export function setIdentity(id, ctx = context.active()) {
137
+ const [next, s] = ensureState(ctx);
138
+ s.merge(id);
139
+ stamp(s, ctx, attributes(s.identity()));
140
+ return next;
141
+ }
142
+ /**
143
+ * Records the team the request acts on (resource ownership), never the
144
+ * caller's memberships. Spans started after the call carry it, and so do the
145
+ * current span and the request's root span.
146
+ */
147
+ export function setTeam(urn, ctx = context.active()) {
148
+ const s = stateFrom(ctx);
149
+ if (!s || !urn)
150
+ return;
151
+ s.merge({ teamUrn: urn });
152
+ stamp(s, ctx, { "xeonr.team.urn": urn });
153
+ }
154
+ /** Records the request's target, as trail's SetTarget names it. */
155
+ export function setResource(type, id, urn, ctx = context.active()) {
156
+ const s = stateFrom(ctx);
157
+ if (!s)
158
+ return;
159
+ const add = {};
160
+ if (type)
161
+ add.resourceType = type;
162
+ if (id)
163
+ add.resourceId = id;
164
+ if (urn)
165
+ add.resourceUrn = urn;
166
+ s.merge(add);
167
+ stamp(s, ctx, attributes(add));
168
+ }
169
+ function stamp(s, ctx, attrs) {
170
+ trace.getSpan(ctx)?.setAttributes(attrs);
171
+ s.root?.setAttributes(attrs);
172
+ }
173
+ //# sourceMappingURL=identity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.js","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * `@xeonr/telemetry`: the Node mirror of go-platform's telemetry package.
3
+ *
4
+ * Start the process with `node --import @xeonr/telemetry/register app.js`
5
+ * (or `--require` for CommonJS). The app then uses:
6
+ * - `setIdentity` where it verifies a caller, `setTeam` / `setResource` in
7
+ * handlers acting on owned resources;
8
+ * - `startJob` / `runJob` / `detach` for background work;
9
+ * - `fetchWith` / `withPeer` / `baggageFor` for outbound HTTP, and
10
+ * `@xeonr/telemetry/connect` for Connect;
11
+ * - `@xeonr/telemetry/log` for logging;
12
+ * - `shutdown()` last, after its servers and workers have drained.
13
+ */
14
+ export * from "./keys.ts";
15
+ export { attributes, fields, identityFrom, setIdentity, setResource, setTeam, subjectKind, type Identity } from "./identity.ts";
16
+ export { DEFAULT_TRUSTED_PROXY_CIDR, HEADER_BAGGAGE, inCluster, originBaggage, parseOriginBaggage, PeerTrust } from "./baggage.ts";
17
+ export { detach, METRIC_JOB_DURATION, METRIC_JOB_RUNS, runJob, SCOPE, startJob, type Job, type JobOptions } from "./job.ts";
18
+ export { baggageFor, fetchWith, type FetchOptions } from "./fetch.ts";
19
+ export { DynamicSpanProcessor, IdentitySpanProcessor, KEY_LOCAL_EVENT, KEY_PEER_SERVICE, localEvent, METRIC_ROOTLESS_CLIENT_SPANS, ExportGuard, SanitizeSpanProcessor, withPeer, } from "./processor.ts";
20
+ export { sanitize, stripUrl } from "./sanitize.ts";
21
+ export { addSpanProcessor, environment, forceFlush, init, initialised, instrumentations, resolveEndpoint, shutdown, type Endpoint, type InitOptions } from "./sdk.ts";
22
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,cAAc,WAAW,CAAC;AAC1B,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,EAAE,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAC;AAChI,OAAO,EAAE,0BAA0B,EAAE,cAAc,EAAE,SAAS,EAAE,aAAa,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACnI,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,GAAG,EAAE,KAAK,UAAU,EAAE,MAAM,UAAU,CAAC;AAC5H,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AACtE,OAAO,EACN,oBAAoB,EACpB,qBAAqB,EACrB,eAAe,EACf,gBAAgB,EAChB,UAAU,EACV,4BAA4B,EAC5B,WAAW,EACX,qBAAqB,EACrB,QAAQ,GACR,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,gBAAgB,EAAE,eAAe,EAAE,QAAQ,EAAE,KAAK,QAAQ,EAAE,KAAK,WAAW,EAAE,MAAM,UAAU,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,22 @@
1
+ /**
2
+ * `@xeonr/telemetry`: the Node mirror of go-platform's telemetry package.
3
+ *
4
+ * Start the process with `node --import @xeonr/telemetry/register app.js`
5
+ * (or `--require` for CommonJS). The app then uses:
6
+ * - `setIdentity` where it verifies a caller, `setTeam` / `setResource` in
7
+ * handlers acting on owned resources;
8
+ * - `startJob` / `runJob` / `detach` for background work;
9
+ * - `fetchWith` / `withPeer` / `baggageFor` for outbound HTTP, and
10
+ * `@xeonr/telemetry/connect` for Connect;
11
+ * - `@xeonr/telemetry/log` for logging;
12
+ * - `shutdown()` last, after its servers and workers have drained.
13
+ */
14
+ export * from "./keys.js";
15
+ export { attributes, fields, identityFrom, setIdentity, setResource, setTeam, subjectKind } from "./identity.js";
16
+ export { DEFAULT_TRUSTED_PROXY_CIDR, HEADER_BAGGAGE, inCluster, originBaggage, parseOriginBaggage, PeerTrust } from "./baggage.js";
17
+ export { detach, METRIC_JOB_DURATION, METRIC_JOB_RUNS, runJob, SCOPE, startJob } from "./job.js";
18
+ export { baggageFor, fetchWith } from "./fetch.js";
19
+ export { DynamicSpanProcessor, IdentitySpanProcessor, KEY_LOCAL_EVENT, KEY_PEER_SERVICE, localEvent, METRIC_ROOTLESS_CLIENT_SPANS, ExportGuard, SanitizeSpanProcessor, withPeer, } from "./processor.js";
20
+ export { sanitize, stripUrl } from "./sanitize.js";
21
+ export { addSpanProcessor, environment, forceFlush, init, initialised, instrumentations, resolveEndpoint, shutdown } from "./sdk.js";
22
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,cAAc,WAAW,CAAC;AAC1B,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,EAAiB,MAAM,eAAe,CAAC;AAChI,OAAO,EAAE,0BAA0B,EAAE,cAAc,EAAE,SAAS,EAAE,aAAa,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACnI,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAA6B,MAAM,UAAU,CAAC;AAC5H,OAAO,EAAE,UAAU,EAAE,SAAS,EAAqB,MAAM,YAAY,CAAC;AACtE,OAAO,EACN,oBAAoB,EACpB,qBAAqB,EACrB,eAAe,EACf,gBAAgB,EAChB,UAAU,EACV,4BAA4B,EAC5B,WAAW,EACX,qBAAqB,EACrB,QAAQ,GACR,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,gBAAgB,EAAE,eAAe,EAAE,QAAQ,EAAmC,MAAM,UAAU,CAAC"}
package/dist/job.d.ts ADDED
@@ -0,0 +1,38 @@
1
+ import { type Context, type Link, type Span } from "@opentelemetry/api";
2
+ /** The tracer and meter scope, the package as go-platform's is its module path. */
3
+ export declare const SCOPE = "@xeonr/telemetry";
4
+ export declare const METRIC_JOB_RUNS = "xeonr_job_runs_total";
5
+ export declare const METRIC_JOB_DURATION = "xeonr_job_duration_seconds";
6
+ export interface JobOptions {
7
+ /** What started the job: `cron`, `queue`, `request`, `boot`, … (`xeonr.job.trigger`). */
8
+ trigger?: string;
9
+ /** The context to start from. Default: the active one. Its span, if any, becomes a link, never the parent. */
10
+ ctx?: Context;
11
+ /** Extra links, e.g. a queue message's producer span. */
12
+ links?: Link[];
13
+ /** Attributes for the job's root span. Never ids of people or teams: those come from the identity. */
14
+ attributes?: Record<string, string | number | boolean>;
15
+ }
16
+ export interface Job {
17
+ /** The job's context: run the work under it (`context.with(job.ctx, …)`). */
18
+ ctx: Context;
19
+ span: Span;
20
+ /** Ends the job. An error marks it failed (status and a sanitised exception event). Safe to call twice. */
21
+ end(err?: unknown): void;
22
+ }
23
+ /**
24
+ * A context for work that outlives the request that spawned it: the request
25
+ * trace is not held open. It keeps the identity (minus the root span) and
26
+ * remembers the request's span, so the job started from it links to it.
27
+ */
28
+ export declare function detach(ctx?: Context): Context;
29
+ /** Starts a job: a new root span, linked to whatever span `opts.ctx` carried. End it with `job.end(err)`. */
30
+ export declare function startJob(name: string, opts?: JobOptions): Job;
31
+ /**
32
+ * Runs `fn` as a job and returns its result. A thrown error or rejection ends
33
+ * the job failed and is rethrown.
34
+ */
35
+ export declare function runJob<T>(name: string, fn: (ctx: Context) => Promise<T> | T, opts?: JobOptions): Promise<T>;
36
+ /** @internal Marks a span failed with a sanitised exception event, as go-platform does. */
37
+ export declare function recordError(span: Span, err: unknown): void;
38
+ //# sourceMappingURL=job.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"job.d.ts","sourceRoot":"","sources":["../src/job.ts"],"names":[],"mappings":"AAQA,OAAO,EAON,KAAK,OAAO,EACZ,KAAK,IAAI,EACT,KAAK,IAAI,EAET,MAAM,oBAAoB,CAAC;AAI5B,mFAAmF;AACnF,eAAO,MAAM,KAAK,qBAAqB,CAAC;AAExC,eAAO,MAAM,eAAe,yBAAyB,CAAC;AACtD,eAAO,MAAM,mBAAmB,+BAA+B,CAAC;AAIhE,MAAM,WAAW,UAAU;IAC1B,yFAAyF;IACzF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8GAA8G;IAC9G,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,yDAAyD;IACzD,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;IACf,sGAAsG;IACtG,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;CACvD;AAED,MAAM,WAAW,GAAG;IACnB,6EAA6E;IAC7E,GAAG,EAAE,OAAO,CAAC;IACb,IAAI,EAAE,IAAI,CAAC;IACX,2GAA2G;IAC3G,GAAG,CAAC,GAAG,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;CACzB;AAED;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,GAAG,GAAE,OAA0B,GAAG,OAAO,CAW/D;AAED,6GAA6G;AAC7G,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,UAAe,GAAG,GAAG,CA+CjE;AAED;;;GAGG;AACH,wBAAsB,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,IAAI,GAAE,UAAe,GAAG,OAAO,CAAC,CAAC,CAAC,CAUrH;AAED,2FAA2F;AAC3F,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,GAAG,IAAI,CAI1D"}
package/dist/job.js ADDED
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Background work (observability plan §5.9), as go-platform's telemetry
3
+ * StartJob, RunJob and Detach do it: every cron run, queue job, poller pass
4
+ * or handler-spawned task is a root span named after the job, with
5
+ * `xeonr.job.*` and system identity, so none of its database, cache or client
6
+ * spans is ever a trace root (obs.rooted-spans).
7
+ */
8
+ import { randomBytes } from "node:crypto";
9
+ import { context, createContextKey, metrics, SpanKind, SpanStatusCode, trace, } from "@opentelemetry/api";
10
+ import { attributes, State, stateFrom, withState } from "./identity.js";
11
+ import { sanitizeError } from "./sanitize.js";
12
+ /** The tracer and meter scope, the package as go-platform's is its module path. */
13
+ export const SCOPE = "@xeonr/telemetry";
14
+ export const METRIC_JOB_RUNS = "xeonr_job_runs_total";
15
+ export const METRIC_JOB_DURATION = "xeonr_job_duration_seconds";
16
+ const DETACHED = createContextKey("xeonr.telemetry.detached");
17
+ /**
18
+ * A context for work that outlives the request that spawned it: the request
19
+ * trace is not held open. It keeps the identity (minus the root span) and
20
+ * remembers the request's span, so the job started from it links to it.
21
+ */
22
+ export function detach(ctx = context.active()) {
23
+ const link = trace.getSpanContext(ctx);
24
+ let d = trace.deleteSpan(ctx);
25
+ if (link && trace.isSpanContextValid(link))
26
+ d = d.setValue(DETACHED, link);
27
+ const s = stateFrom(ctx);
28
+ if (s) {
29
+ const c = s.clone();
30
+ c.root = undefined;
31
+ d = withState(d, c);
32
+ }
33
+ return d;
34
+ }
35
+ /** Starts a job: a new root span, linked to whatever span `opts.ctx` carried. End it with `job.end(err)`. */
36
+ export function startJob(name, opts = {}) {
37
+ const parent = opts.ctx ?? context.active();
38
+ const start = performance.now();
39
+ const links = [...(opts.links ?? [])];
40
+ const linked = parent.getValue(DETACHED) ?? trace.getSpanContext(parent);
41
+ if (linked && trace.isSpanContextValid(linked))
42
+ links.push({ context: linked });
43
+ const s = new State();
44
+ s.job = true;
45
+ const prev = stateFrom(parent);
46
+ if (prev) {
47
+ const p = prev.clone();
48
+ s.id = p.id;
49
+ s.service = p.service;
50
+ s.entry = p.entry;
51
+ s.originDecided = p.originDecided;
52
+ s.baggageOrgId = p.baggageOrgId;
53
+ }
54
+ s.id.jobName = name;
55
+ s.id.jobRunId = randomBytes(8).toString("hex");
56
+ if (opts.trigger)
57
+ s.id.jobTrigger = opts.trigger;
58
+ const base = withState(trace.deleteSpan(parent).deleteValue(DETACHED), s);
59
+ const span = trace.getTracer(SCOPE).startSpan(name, { root: true, kind: SpanKind.INTERNAL, links, attributes: { ...opts.attributes, ...attributes(s.identity()) } }, base);
60
+ s.root = span;
61
+ const ctx = trace.setSpan(base, span);
62
+ let ended = false;
63
+ return {
64
+ ctx,
65
+ span,
66
+ end(err) {
67
+ if (ended)
68
+ return;
69
+ ended = true;
70
+ let outcome = "ok";
71
+ if (err !== undefined && err !== null) {
72
+ outcome = "error";
73
+ recordError(span, err);
74
+ }
75
+ span.end();
76
+ recordJob(name, outcome, start);
77
+ },
78
+ };
79
+ }
80
+ /**
81
+ * Runs `fn` as a job and returns its result. A thrown error or rejection ends
82
+ * the job failed and is rethrown.
83
+ */
84
+ export async function runJob(name, fn, opts = {}) {
85
+ const job = startJob(name, opts);
86
+ try {
87
+ const out = await context.with(job.ctx, () => fn(job.ctx));
88
+ job.end();
89
+ return out;
90
+ }
91
+ catch (err) {
92
+ job.end(err);
93
+ throw err;
94
+ }
95
+ }
96
+ /** @internal Marks a span failed with a sanitised exception event, as go-platform does. */
97
+ export function recordError(span, err) {
98
+ const { type, message } = sanitizeError(err);
99
+ span.addEvent("exception", { "exception.type": type, "exception.message": message });
100
+ span.setStatus({ code: SpanStatusCode.ERROR, message });
101
+ }
102
+ function recordJob(name, outcome, start) {
103
+ const m = metrics.getMeter(SCOPE);
104
+ m.createCounter(METRIC_JOB_RUNS, { description: "Background job runs by outcome (ok, error)." }).add(1, { job: name, outcome });
105
+ m.createHistogram(METRIC_JOB_DURATION, { unit: "s", description: "Background job run duration." }).record((performance.now() - start) / 1000, { job: name });
106
+ }
107
+ //# sourceMappingURL=job.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"job.js","sourceRoot":"","sources":["../src/job.ts"],"names":[],"mappings":"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"}
package/dist/keys.d.ts ADDED
@@ -0,0 +1,80 @@
1
+ /** One identity key: the span attribute, the log field and the Identity property. */
2
+ export interface IdentityKey {
3
+ readonly field: string;
4
+ readonly prop: string;
5
+ readonly span: string;
6
+ readonly log?: string;
7
+ readonly baggage?: boolean;
8
+ readonly rpcServerSpanOnly?: boolean;
9
+ }
10
+ export declare const VOCABULARY_VERSION = 1;
11
+ /** Subject is the verified principal's full URN (urn:xeonr:auth:uid:user:88, a service account, a client, an API key's owner or the key itself). Never a bare id. */
12
+ export declare const KeySubject = "xeonr.subject";
13
+ export declare const FieldSubject = "subject";
14
+ /** SubjectKind is derived from Subject's URN prefix (SubjectKind func): user, service_account, client, api_key, team; anonymous for an unauthenticated request, system for a job with no caller, unknown for a URN with no recognised prefix. */
15
+ export declare const KeySubjectKind = "xeonr.subject.kind";
16
+ export declare const FieldSubjectKind = "subject_kind";
17
+ /** OrgID is the auth organisation id (Principal.OrganisationID). Not Lantern's org.id resource attribute. */
18
+ export declare const KeyOrgID = "xeonr.org.id";
19
+ export declare const FieldOrgID = "org_id";
20
+ /** ClientID is the OAuth client the token was issued to. */
21
+ export declare const KeyClientID = "xeonr.client.id";
22
+ export declare const FieldClientID = "client_id";
23
+ /** ApplicationID is the auth application the token was minted for. */
24
+ export declare const KeyApplicationID = "xeonr.application.id";
25
+ export declare const FieldApplicationID = "application_id";
26
+ /** DelegatorApp is the product acting for the user on an RFC 8693 exchanged token; empty unless delegated. */
27
+ export declare const KeyDelegatorApp = "xeonr.delegator.app";
28
+ export declare const FieldDelegatorApp = "delegator_app";
29
+ /** APIKeyID is the API key's URN when a key authenticated the request. */
30
+ export declare const KeyAPIKeyID = "xeonr.api_key.id";
31
+ export declare const FieldAPIKeyID = "api_key_id";
32
+ /** AuthMethod is how the caller authenticated: bearer, cookie, api_key, or none. */
33
+ export declare const KeyAuthMethod = "xeonr.auth.method";
34
+ export declare const FieldAuthMethod = "auth_method";
35
+ /** OriginSubject is the subject at the entry of the trace. It survives a service-account hop through baggage from trusted in-cluster peers. */
36
+ export declare const KeyOriginSubject = "xeonr.origin.subject";
37
+ export declare const FieldOriginSubject = "origin_subject";
38
+ /** OriginService is the service.name of the trace's entry service. */
39
+ export declare const KeyOriginService = "xeonr.origin.service";
40
+ export declare const FieldOriginService = "origin_service";
41
+ /** TeamURN is the team the request acts on (resource ownership), set by the handler with SetTeam. Never the caller's membership list. */
42
+ export declare const KeyTeamURN = "xeonr.team.urn";
43
+ export declare const FieldTeamURN = "team_urn";
44
+ /** ResourceType is the kind of the request's target, set with SetResource. */
45
+ export declare const KeyResourceType = "xeonr.resource.type";
46
+ export declare const FieldResourceType = "resource_type";
47
+ /** ResourceID is the target's id, set with SetResource. */
48
+ export declare const KeyResourceID = "xeonr.resource.id";
49
+ export declare const FieldResourceID = "resource_id";
50
+ /** ResourceURN is the target's URN, set with SetResource. */
51
+ export declare const KeyResourceURN = "xeonr.resource.urn";
52
+ export declare const FieldResourceURN = "resource_urn";
53
+ /** Scopes are the token's scopes. They go on the RPC server span only: Attributes and Fields leave them out. */
54
+ export declare const KeyScopes = "xeonr.scopes";
55
+ /** JobName is the background job's name (trail.outbox.flush), set by StartJob. */
56
+ export declare const KeyJobName = "xeonr.job.name";
57
+ export declare const FieldJobName = "job";
58
+ /** JobRunID identifies one run of the job, set by StartJob. */
59
+ export declare const KeyJobRunID = "xeonr.job.run_id";
60
+ export declare const FieldJobRunID = "job_run_id";
61
+ /** JobTrigger is what started the job (cron, queue, request), set by StartJob's Trigger option. */
62
+ export declare const KeyJobTrigger = "xeonr.job.trigger";
63
+ export declare const FieldJobTrigger = "job_trigger";
64
+ /** the Connect procedure of the request a log line belongs to */
65
+ export declare const FieldProcedure = "procedure";
66
+ /** the Connect code of a finished RPC */
67
+ export declare const FieldStatus = "status";
68
+ /** how long the RPC or job took, in milliseconds */
69
+ export declare const FieldDurationMS = "duration_ms";
70
+ /** the resolved client address (connectmw.ClientIPResolver) */
71
+ export declare const FieldIP = "ip";
72
+ /** true on a span whose request or job panicked */
73
+ export declare const KeyPanic = "xeonr.panic";
74
+ /** The §4.2 table in order. */
75
+ export declare const IDENTITY_KEYS: readonly IdentityKey[];
76
+ /** The baggage members, in table order: nothing else ever travels as baggage. */
77
+ export declare const BAGGAGE_KEYS: readonly string[];
78
+ export type SubjectKind = "user" | "service_account" | "client" | "api_key" | "team" | "anonymous" | "system" | "unknown";
79
+ export type AuthMethod = "bearer" | "cookie" | "api_key" | "none";
80
+ //# sourceMappingURL=keys.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../src/keys.ts"],"names":[],"mappings":"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"}