@qlever-llc/trellis 0.10.11 → 0.10.12

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 (110) hide show
  1. package/esm/errors/TrellisError.d.ts +3 -3
  2. package/esm/errors/TrellisError.js +3 -3
  3. package/esm/server/internal_jobs/job-manager.d.ts.map +1 -1
  4. package/esm/server/internal_jobs/job-manager.js +32 -1
  5. package/esm/server/runtime.d.ts +3 -0
  6. package/esm/server/runtime.d.ts.map +1 -1
  7. package/esm/server/service.d.ts +15 -0
  8. package/esm/server/service.d.ts.map +1 -1
  9. package/esm/server/service.js +8 -0
  10. package/esm/server.d.ts.map +1 -1
  11. package/esm/server.js +54 -6
  12. package/esm/service/deno.d.ts +1 -1
  13. package/esm/service/deno.d.ts.map +1 -1
  14. package/esm/service/mod.d.ts +1 -1
  15. package/esm/service/mod.d.ts.map +1 -1
  16. package/esm/service/node.d.ts +1 -1
  17. package/esm/service/node.d.ts.map +1 -1
  18. package/esm/service/outbox_inbox.d.ts.map +1 -1
  19. package/esm/service/outbox_inbox.js +14 -0
  20. package/esm/telemetry/core.d.ts.map +1 -1
  21. package/esm/telemetry/core.js +1 -1
  22. package/esm/telemetry/env.d.ts.map +1 -1
  23. package/esm/telemetry/env.js +6 -1
  24. package/esm/telemetry/init.d.ts +3 -0
  25. package/esm/telemetry/init.d.ts.map +1 -0
  26. package/esm/telemetry/init.js +7 -0
  27. package/esm/telemetry/metrics.d.ts +34 -0
  28. package/esm/telemetry/metrics.d.ts.map +1 -0
  29. package/esm/telemetry/metrics.js +181 -0
  30. package/esm/telemetry/mod.d.ts +3 -0
  31. package/esm/telemetry/mod.d.ts.map +1 -1
  32. package/esm/telemetry/mod.js +2 -0
  33. package/esm/telemetry/runtime.d.ts +2 -0
  34. package/esm/telemetry/runtime.d.ts.map +1 -0
  35. package/esm/telemetry/runtime.js +134 -0
  36. package/esm/telemetry.d.ts +3 -0
  37. package/esm/telemetry.d.ts.map +1 -0
  38. package/esm/telemetry.js +2 -0
  39. package/esm/transfer.d.ts.map +1 -1
  40. package/esm/transfer.js +27 -16
  41. package/esm/trellis.d.ts.map +1 -1
  42. package/esm/trellis.js +460 -56
  43. package/package.json +7 -5
  44. package/script/errors/TrellisError.d.ts +3 -3
  45. package/script/errors/TrellisError.js +3 -3
  46. package/script/server/internal_jobs/job-manager.d.ts.map +1 -1
  47. package/script/server/internal_jobs/job-manager.js +32 -1
  48. package/script/server/runtime.d.ts +3 -0
  49. package/script/server/runtime.d.ts.map +1 -1
  50. package/script/server/service.d.ts +15 -0
  51. package/script/server/service.d.ts.map +1 -1
  52. package/script/server/service.js +8 -0
  53. package/script/server.d.ts.map +1 -1
  54. package/script/server.js +54 -6
  55. package/script/service/deno.d.ts +1 -1
  56. package/script/service/deno.d.ts.map +1 -1
  57. package/script/service/mod.d.ts +1 -1
  58. package/script/service/mod.d.ts.map +1 -1
  59. package/script/service/node.d.ts +1 -1
  60. package/script/service/node.d.ts.map +1 -1
  61. package/script/service/outbox_inbox.d.ts.map +1 -1
  62. package/script/service/outbox_inbox.js +14 -0
  63. package/script/telemetry/core.d.ts.map +1 -1
  64. package/script/telemetry/core.js +1 -1
  65. package/script/telemetry/env.d.ts.map +1 -1
  66. package/script/telemetry/env.js +6 -1
  67. package/script/telemetry/init.d.ts +3 -0
  68. package/script/telemetry/init.d.ts.map +1 -0
  69. package/script/telemetry/init.js +10 -0
  70. package/script/telemetry/metrics.d.ts +34 -0
  71. package/script/telemetry/metrics.d.ts.map +1 -0
  72. package/script/telemetry/metrics.js +186 -0
  73. package/script/telemetry/mod.d.ts +3 -0
  74. package/script/telemetry/mod.d.ts.map +1 -1
  75. package/script/telemetry/mod.js +7 -1
  76. package/script/telemetry/runtime.d.ts +2 -0
  77. package/script/telemetry/runtime.d.ts.map +1 -0
  78. package/script/telemetry/runtime.js +137 -0
  79. package/script/telemetry.d.ts +3 -0
  80. package/script/telemetry.d.ts.map +1 -0
  81. package/script/telemetry.js +18 -0
  82. package/script/transfer.d.ts.map +1 -1
  83. package/script/transfer.js +28 -17
  84. package/script/trellis.d.ts.map +1 -1
  85. package/script/trellis.js +490 -86
  86. package/src/errors/TrellisError.ts +4 -4
  87. package/src/server/internal_jobs/job-manager.ts +35 -5
  88. package/src/server/runtime.ts +4 -0
  89. package/src/server/service.ts +27 -0
  90. package/src/server.ts +66 -11
  91. package/src/service/deno.ts +1 -0
  92. package/src/service/mod.ts +1 -0
  93. package/src/service/node.ts +1 -0
  94. package/src/service/outbox_inbox.ts +14 -0
  95. package/src/telemetry/core.ts +1 -1
  96. package/src/telemetry/env.ts +5 -1
  97. package/src/telemetry/init.ts +8 -0
  98. package/src/telemetry/metrics.ts +294 -0
  99. package/src/telemetry/mod.ts +7 -0
  100. package/src/telemetry/runtime.ts +218 -0
  101. package/src/telemetry.ts +2 -0
  102. package/src/transfer.ts +69 -30
  103. package/src/trellis.ts +487 -88
  104. package/esm/tracing.d.ts +0 -5
  105. package/esm/tracing.d.ts.map +0 -1
  106. package/esm/tracing.js +0 -8
  107. package/script/tracing.d.ts +0 -5
  108. package/script/tracing.d.ts.map +0 -1
  109. package/script/tracing.js +0 -27
  110. package/src/tracing.ts +0 -28
@@ -1 +1 @@
1
- {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../src/telemetry/core.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,OAAO,EACZ,OAAO,EACP,KAAK,IAAI,EACT,QAAQ,EACR,cAAc,EACd,KAAK,EACL,KAAK,MAAM,EACZ,MAAM,oBAAoB,CAAC;AAE5B,wBAAgB,SAAS,CAAC,KAAK,SAAgC,GAAG,MAAM,CAEvE;AAED,wBAAgB,aAAa,IAAI,IAAI,GAAG,SAAS,CAEhD;AAED,wBAAgB,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAEtD;AAED,wBAAsB,aAAa,CAAC,CAAC,EACnC,IAAI,EAAE,IAAI,EACV,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACnB,OAAO,CAAC,CAAC,CAAC,CAEZ;AAED,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC;AACpD,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC"}
1
+ {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../src/telemetry/core.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,OAAO,EACZ,OAAO,EACP,KAAK,IAAI,EACT,QAAQ,EACR,cAAc,EACd,KAAK,EACL,KAAK,MAAM,EACZ,MAAM,oBAAoB,CAAC;AAE5B,wBAAgB,SAAS,CAAC,KAAK,SAAkC,GAAG,MAAM,CAEzE;AAED,wBAAgB,aAAa,IAAI,IAAI,GAAG,SAAS,CAEhD;AAED,wBAAgB,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAEtD;AAED,wBAAsB,aAAa,CAAC,CAAC,EACnC,IAAI,EAAE,IAAI,EACV,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACnB,OAAO,CAAC,CAAC,CAAC,CAEZ;AAED,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC;AACpD,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import { context, SpanKind, SpanStatusCode, trace, } from "@opentelemetry/api";
2
- export function getTracer(scope = "@qlever-llc/trellis/tracing") {
2
+ export function getTracer(scope = "@qlever-llc/trellis/telemetry") {
3
3
  return trace.getTracer(scope);
4
4
  }
5
5
  export function getActiveSpan() {
@@ -1 +1 @@
1
- {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/telemetry/env.ts"],"names":[],"mappings":"AAYA,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAUtD"}
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/telemetry/env.ts"],"names":[],"mappings":"AAYA,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CActD"}
@@ -3,7 +3,12 @@ import * as dntShim from "../_dnt.shims.js";
3
3
  export function getEnv(key) {
4
4
  const deno = dntShim.dntGlobalThis;
5
5
  if (deno.Deno?.env?.get) {
6
- return deno.Deno.env.get(key);
6
+ try {
7
+ return deno.Deno.env.get(key);
8
+ }
9
+ catch {
10
+ return undefined;
11
+ }
7
12
  }
8
13
  const processGlobal = dntShim.dntGlobalThis;
9
14
  return processGlobal.process?.env?.[key];
@@ -0,0 +1,3 @@
1
+ /** Initializes Trellis telemetry for a service runtime. */
2
+ export declare function initTelemetry(serviceName: string): void;
3
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/telemetry/init.ts"],"names":[],"mappings":"AAGA,2DAA2D;AAC3D,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAGvD"}
@@ -0,0 +1,7 @@
1
+ import { configureErrorTraceId } from "./result.js";
2
+ import { initTelemetryRuntime } from "./runtime.js";
3
+ /** Initializes Trellis telemetry for a service runtime. */
4
+ export function initTelemetry(serviceName) {
5
+ configureErrorTraceId();
6
+ initTelemetryRuntime(serviceName);
7
+ }
@@ -0,0 +1,34 @@
1
+ import { type Meter } from "@opentelemetry/api";
2
+ /** Low-cardinality attributes accepted by {@link recordTrellisError}. */
3
+ export type TrellisErrorMetricAttributes = {
4
+ /** Stable Trellis surface name, such as `rpc`, `jobs`, or `operations`. */
5
+ surface?: string;
6
+ /** Stable flow direction such as `client`, `server`, `publish`, or `consume`. */
7
+ direction?: string;
8
+ /** Stable operation kind or method name. Do not pass IDs, subjects, or URLs. */
9
+ operation?: string;
10
+ /** Stable lifecycle phase such as `encode`, `send`, `auth`, or `handler`. */
11
+ phase?: string;
12
+ /** Stable local Trellis error type override when the thrown value does not expose one. */
13
+ errorType?: string;
14
+ /** Stable wrapped remote Trellis error type override. */
15
+ remoteErrorType?: string;
16
+ /** Stable auth failure reason, such as `missing_session_key`. */
17
+ authReason?: string;
18
+ /** Static messaging system name, when already known. */
19
+ messagingSystem?: string;
20
+ /** Static messaging operation name, when already known. */
21
+ messagingOperation?: string;
22
+ };
23
+ /** Returns the shared Trellis OpenTelemetry meter. */
24
+ export declare function getTrellisMeter(): Meter;
25
+ /** Records one Trellis error with only stable, low-cardinality attributes. */
26
+ export declare function recordTrellisError(error: unknown, attributes?: TrellisErrorMetricAttributes): void;
27
+ /**
28
+ * Builds sanitized, low-cardinality attributes for `trellis.errors`.
29
+ *
30
+ * @internal Exported for focused tests; runtime callers should use
31
+ * {@link recordTrellisError}.
32
+ */
33
+ export declare function buildTrellisErrorMetricAttributes(error: unknown, attributes?: TrellisErrorMetricAttributes): Record<string, string>;
34
+ //# sourceMappingURL=metrics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/telemetry/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,KAAK,EAAW,MAAM,oBAAoB,CAAC;AAiDzD,yEAAyE;AACzE,MAAM,MAAM,4BAA4B,GAAG;IACzC,2EAA2E;IAC3E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gFAAgF;IAChF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0FAA0F;IAC1F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iEAAiE;IACjE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wDAAwD;IACxD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AASF,sDAAsD;AACtD,wBAAgB,eAAe,IAAI,KAAK,CAEvC;AAED,8EAA8E;AAC9E,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,OAAO,EACd,UAAU,GAAE,4BAAiC,GAC5C,IAAI,CAWN;AAED;;;;;GAKG;AACH,wBAAgB,iCAAiC,CAC/C,KAAK,EAAE,OAAO,EACd,UAAU,GAAE,4BAAiC,GAC5C,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAsDxB"}
@@ -0,0 +1,181 @@
1
+ import { metrics } from "@opentelemetry/api";
2
+ const TRELLIS_METER_NAME = "@qlever-llc/trellis";
3
+ const MAX_ATTRIBUTE_LENGTH = 96;
4
+ const LOW_CARDINALITY_PATTERN = /^[A-Za-z0-9_.:-]+$/;
5
+ const UUID_PATTERN = /(^|[_.:-])[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}($|[_.:-])/i;
6
+ const ULID_PATTERN = /(^|[_.:-])[0-7][0-9A-HJKMNP-TV-Z]{25}($|[_.:-])/i;
7
+ const LONG_HEX_SEGMENT_PATTERN = /(^|[_.:-])[0-9a-f]{12,}($|[_.:-])/i;
8
+ const TRELLIS_SUBJECT_PREFIX_PATTERN = /^(rpc|events|feeds|operations|jobs|state|kv|store|resources|transfer)\.v\d+\./;
9
+ const AUTH_REASONS = new Set([
10
+ "invalid_request",
11
+ "missing_session_key",
12
+ "missing_proof",
13
+ "session_not_found",
14
+ "session_expired",
15
+ "invalid_signature",
16
+ "user_not_found",
17
+ "user_already_exists",
18
+ "username_taken",
19
+ "identity_already_exists",
20
+ "identity_not_found",
21
+ "user_inactive",
22
+ "unknown_device",
23
+ "device_deployment_not_found",
24
+ "device_deployment_disabled",
25
+ "device_activation_revoked",
26
+ "unknown_service",
27
+ "service_disabled",
28
+ "iat_out_of_range",
29
+ "invalid_binding_token",
30
+ "session_corrupted",
31
+ "session_already_bound",
32
+ "authtoken_already_used",
33
+ "oauth_session_key_mismatch",
34
+ "reply_subject_mismatch",
35
+ "insufficient_permissions",
36
+ "forbidden",
37
+ "last_admin_required",
38
+ "missing_flow_id",
39
+ "device_activation_flow_not_found",
40
+ "device_activation_flow_expired",
41
+ "device_activation_rejected",
42
+ "device_identity_key_mismatch",
43
+ "invalid_device_qr_mac",
44
+ ]);
45
+ /** Returns the shared Trellis OpenTelemetry meter. */
46
+ export function getTrellisMeter() {
47
+ return metrics.getMeter(TRELLIS_METER_NAME);
48
+ }
49
+ /** Records one Trellis error with only stable, low-cardinality attributes. */
50
+ export function recordTrellisError(error, attributes = {}) {
51
+ getTrellisMeter().createCounter("trellis.errors", {
52
+ description: "Trellis errors observed by runtime instrumentation.",
53
+ unit: "{error}",
54
+ }).add(1, buildTrellisErrorMetricAttributes(error, attributes));
55
+ }
56
+ /**
57
+ * Builds sanitized, low-cardinality attributes for `trellis.errors`.
58
+ *
59
+ * @internal Exported for focused tests; runtime callers should use
60
+ * {@link recordTrellisError}.
61
+ */
62
+ export function buildTrellisErrorMetricAttributes(error, attributes = {}) {
63
+ const serializable = serializableErrorData(error);
64
+ const metricAttributes = {
65
+ "exception.type": exceptionType(error),
66
+ "trellis.error.type": trellisErrorType(error, serializable, attributes.errorType),
67
+ };
68
+ const remoteErrorType = lowCardinalityValue(attributes.remoteErrorType) ??
69
+ remoteSerializableErrorType(serializable);
70
+ if (remoteErrorType) {
71
+ metricAttributes["trellis.remote_error.type"] = remoteErrorType;
72
+ }
73
+ setLowCardinalityAttribute(metricAttributes, "trellis.surface", attributes.surface);
74
+ setLowCardinalityAttribute(metricAttributes, "trellis.direction", attributes.direction);
75
+ setLowCardinalityAttribute(metricAttributes, "trellis.operation", attributes.operation);
76
+ setLowCardinalityAttribute(metricAttributes, "trellis.phase", attributes.phase);
77
+ setLowCardinalityAttribute(metricAttributes, "trellis.auth.reason", boundedAuthReason(attributes.authReason) ?? authReason(serializable));
78
+ setLowCardinalityAttribute(metricAttributes, "messaging.system", attributes.messagingSystem);
79
+ setLowCardinalityAttribute(metricAttributes, "messaging.operation", attributes.messagingOperation);
80
+ return metricAttributes;
81
+ }
82
+ function trellisErrorType(error, serializable, override) {
83
+ const overrideType = lowCardinalityValue(override);
84
+ if (overrideType)
85
+ return overrideType;
86
+ const serializableType = lowCardinalityValue(serializable?.type);
87
+ if (serializableType)
88
+ return serializableType;
89
+ const objectType = objectStringProperty(error, "type");
90
+ if (objectType)
91
+ return objectType;
92
+ return exceptionType(error);
93
+ }
94
+ function exceptionType(error) {
95
+ if (error instanceof Error) {
96
+ const name = lowCardinalityValue(error.name);
97
+ if (name)
98
+ return name;
99
+ }
100
+ const objectType = objectStringProperty(error, "type");
101
+ if (objectType)
102
+ return objectType;
103
+ return "unknown";
104
+ }
105
+ function serializableErrorData(error) {
106
+ const toSerializable = safeProperty(error, "toSerializable");
107
+ if (!isSerializableMethod(toSerializable))
108
+ return undefined;
109
+ try {
110
+ const data = toSerializable.call(error);
111
+ return isRecord(data) ? data : undefined;
112
+ }
113
+ catch {
114
+ return undefined;
115
+ }
116
+ }
117
+ function remoteSerializableErrorType(serializable) {
118
+ const remoteError = safeProperty(serializable, "remoteError");
119
+ if (!isRecord(remoteError))
120
+ return undefined;
121
+ return objectStringProperty(remoteError, "type");
122
+ }
123
+ function authReason(serializable) {
124
+ const type = safeProperty(serializable, "type");
125
+ if (type === "AuthError") {
126
+ return boundedAuthReason(safeProperty(serializable, "reason"));
127
+ }
128
+ if (type === "RemoteError") {
129
+ const remoteError = safeProperty(serializable, "remoteError");
130
+ if (isRecord(remoteError) && objectStringProperty(remoteError, "type") ===
131
+ "AuthError") {
132
+ return boundedAuthReason(safeProperty(remoteError, "reason"));
133
+ }
134
+ }
135
+ return undefined;
136
+ }
137
+ function boundedAuthReason(value) {
138
+ const sanitized = lowCardinalityValue(value);
139
+ if (!sanitized || !AUTH_REASONS.has(sanitized))
140
+ return undefined;
141
+ return sanitized;
142
+ }
143
+ function isRecord(value) {
144
+ return value !== null && typeof value === "object" && !Array.isArray(value);
145
+ }
146
+ function isSerializableMethod(value) {
147
+ return typeof value === "function";
148
+ }
149
+ function safeProperty(value, key) {
150
+ if (!isRecord(value))
151
+ return undefined;
152
+ try {
153
+ return value[key];
154
+ }
155
+ catch {
156
+ return undefined;
157
+ }
158
+ }
159
+ function objectStringProperty(value, key) {
160
+ return lowCardinalityValue(safeProperty(value, key));
161
+ }
162
+ function setLowCardinalityAttribute(attributes, key, value) {
163
+ const sanitized = lowCardinalityValue(value);
164
+ if (sanitized)
165
+ attributes[key] = sanitized;
166
+ }
167
+ function lowCardinalityValue(value) {
168
+ if (typeof value !== "string")
169
+ return undefined;
170
+ const trimmed = value.trim();
171
+ if (trimmed.length === 0 ||
172
+ trimmed.length > MAX_ATTRIBUTE_LENGTH ||
173
+ !LOW_CARDINALITY_PATTERN.test(trimmed) ||
174
+ UUID_PATTERN.test(trimmed) ||
175
+ ULID_PATTERN.test(trimmed) ||
176
+ LONG_HEX_SEGMENT_PATTERN.test(trimmed) ||
177
+ TRELLIS_SUBJECT_PREFIX_PATTERN.test(trimmed)) {
178
+ return undefined;
179
+ }
180
+ return trimmed;
181
+ }
@@ -3,6 +3,9 @@ export { createMapCarrier, extractTraceContext, injectTraceContext, } from "./ca
3
3
  export type { Context, Span } from "./core.js";
4
4
  export { context, getActiveSpan, getTracer, SpanKind, SpanStatusCode, trace, withSpan, withSpanAsync, } from "./core.js";
5
5
  export { getEnv } from "./env.js";
6
+ export { initTelemetry } from "./init.js";
7
+ export { buildTrellisErrorMetricAttributes, getTrellisMeter, recordTrellisError, } from "./metrics.js";
8
+ export type { TrellisErrorMetricAttributes } from "./metrics.js";
6
9
  export type { NatsHeadersLike } from "./nats.js";
7
10
  export { createNatsHeaderCarrier } from "./nats.js";
8
11
  export { configureErrorTraceId } from "./result.js";
@@ -1 +1 @@
1
- {"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../../src/telemetry/mod.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,EACL,OAAO,EACP,aAAa,EACb,SAAS,EACT,QAAQ,EACR,cAAc,EACd,KAAK,EACL,QAAQ,EACR,aAAa,GACd,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,YAAY,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,eAAe,GAChB,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../../src/telemetry/mod.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,EACL,OAAO,EACP,aAAa,EACb,SAAS,EACT,QAAQ,EACR,cAAc,EACd,KAAK,EACL,QAAQ,EACR,aAAa,GACd,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EACL,iCAAiC,EACjC,eAAe,EACf,kBAAkB,GACnB,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,4BAA4B,EAAE,MAAM,cAAc,CAAC;AACjE,YAAY,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,eAAe,GAChB,MAAM,cAAc,CAAC"}
@@ -1,6 +1,8 @@
1
1
  export { createMapCarrier, extractTraceContext, injectTraceContext, } from "./carrier.js";
2
2
  export { context, getActiveSpan, getTracer, SpanKind, SpanStatusCode, trace, withSpan, withSpanAsync, } from "./core.js";
3
3
  export { getEnv } from "./env.js";
4
+ export { initTelemetry } from "./init.js";
5
+ export { buildTrellisErrorMetricAttributes, getTrellisMeter, recordTrellisError, } from "./metrics.js";
4
6
  export { createNatsHeaderCarrier } from "./nats.js";
5
7
  export { configureErrorTraceId } from "./result.js";
6
8
  export { getTrellisTracer, startClientSpan, startServerSpan, } from "./trellis.js";
@@ -0,0 +1,2 @@
1
+ export declare function initTelemetryRuntime(serviceName: string): void;
2
+ //# sourceMappingURL=runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/telemetry/runtime.ts"],"names":[],"mappings":"AAmNA,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAM9D"}
@@ -0,0 +1,134 @@
1
+ import { metrics } from "@opentelemetry/api";
2
+ import { getEnv } from "./env.js";
3
+ let initialized = false;
4
+ let provider;
5
+ let metricProvider;
6
+ function runtimeImport(specifier) {
7
+ const load = new Function("specifier", "return import(specifier);");
8
+ return load(specifier);
9
+ }
10
+ async function loadTracingRuntime() {
11
+ const [traceNode, otlp, traceBase, resources, semantic] = await Promise.all([
12
+ runtimeImport(["@opentelemetry", "sdk-trace-node"].join("/")),
13
+ runtimeImport(["@opentelemetry", "exporter-trace-otlp-proto"].join("/")),
14
+ runtimeImport(["@opentelemetry", "sdk-trace-base"].join("/")),
15
+ runtimeImport(["@opentelemetry", "resources"].join("/")),
16
+ runtimeImport(["@opentelemetry", "semantic-conventions"].join("/")),
17
+ ]);
18
+ return {
19
+ NodeTracerProvider: traceNode.NodeTracerProvider,
20
+ OTLPTraceExporter: otlp.OTLPTraceExporter,
21
+ BatchSpanProcessor: traceBase.BatchSpanProcessor,
22
+ ConsoleSpanExporter: traceBase.ConsoleSpanExporter,
23
+ resourceFromAttributes: resources.resourceFromAttributes,
24
+ ATTR_SERVICE_NAME: semantic.ATTR_SERVICE_NAME,
25
+ };
26
+ }
27
+ async function loadMetricsRuntime() {
28
+ const [sdkMetrics, otlp, resources, semantic] = await Promise.all([
29
+ runtimeImport(["@opentelemetry", "sdk-metrics"].join("/")),
30
+ runtimeImport(["@opentelemetry", "exporter-metrics-otlp-proto"].join("/")),
31
+ runtimeImport(["@opentelemetry", "resources"].join("/")),
32
+ runtimeImport(["@opentelemetry", "semantic-conventions"].join("/")),
33
+ ]);
34
+ return {
35
+ MeterProvider: sdkMetrics.MeterProvider,
36
+ PeriodicExportingMetricReader: sdkMetrics.PeriodicExportingMetricReader,
37
+ ConsoleMetricExporter: sdkMetrics.ConsoleMetricExporter,
38
+ OTLPMetricExporter: otlp.OTLPMetricExporter,
39
+ resourceFromAttributes: resources.resourceFromAttributes,
40
+ ATTR_SERVICE_NAME: semantic.ATTR_SERVICE_NAME,
41
+ };
42
+ }
43
+ async function initTracingRuntime(serviceName) {
44
+ const endpoint = getEnv("OTEL_EXPORTER_OTLP_ENDPOINT");
45
+ const consoleTracing = getEnv("OTEL_TRACES_CONSOLE") === "true";
46
+ if (!endpoint && !consoleTracing) {
47
+ return;
48
+ }
49
+ try {
50
+ const runtime = await loadTracingRuntime();
51
+ const spanProcessors = [];
52
+ if (endpoint) {
53
+ spanProcessors.push(new runtime.BatchSpanProcessor(new runtime.OTLPTraceExporter({ url: `${endpoint}/v1/traces` })));
54
+ }
55
+ if (consoleTracing) {
56
+ spanProcessors.push(new runtime.BatchSpanProcessor(new runtime.ConsoleSpanExporter()));
57
+ }
58
+ const nextProvider = new runtime.NodeTracerProvider({
59
+ resource: runtime.resourceFromAttributes({
60
+ [runtime.ATTR_SERVICE_NAME]: serviceName,
61
+ }),
62
+ ...(spanProcessors.length > 0 ? { spanProcessors } : {}),
63
+ });
64
+ provider = nextProvider;
65
+ nextProvider.register();
66
+ }
67
+ catch (error) {
68
+ console.warn("Failed to initialize tracing runtime", error);
69
+ }
70
+ }
71
+ function metricEndpoint() {
72
+ const metricsEndpoint = getEnv("OTEL_EXPORTER_OTLP_METRICS_ENDPOINT");
73
+ if (metricsEndpoint)
74
+ return metricsEndpoint;
75
+ const endpoint = getEnv("OTEL_EXPORTER_OTLP_ENDPOINT");
76
+ if (!endpoint)
77
+ return undefined;
78
+ return `${endpoint.replace(/\/$/, "")}/v1/metrics`;
79
+ }
80
+ function metricExportIntervalMillis() {
81
+ const configured = getEnv("OTEL_METRIC_EXPORT_INTERVAL");
82
+ if (!configured)
83
+ return undefined;
84
+ const parsed = Number(configured);
85
+ if (!Number.isFinite(parsed) || parsed <= 0)
86
+ return undefined;
87
+ return Math.trunc(parsed);
88
+ }
89
+ async function initMetricsRuntime(serviceName) {
90
+ const endpoint = metricEndpoint();
91
+ const consoleMetrics = getEnv("TRELLIS_METRICS_CONSOLE") === "true";
92
+ if (!endpoint && !consoleMetrics) {
93
+ return;
94
+ }
95
+ try {
96
+ const runtime = await loadMetricsRuntime();
97
+ const readers = [];
98
+ const exportIntervalMillis = metricExportIntervalMillis();
99
+ if (endpoint) {
100
+ readers.push(new runtime.PeriodicExportingMetricReader({
101
+ exporter: new runtime.OTLPMetricExporter({ url: endpoint }),
102
+ ...(exportIntervalMillis !== undefined
103
+ ? { exportIntervalMillis }
104
+ : {}),
105
+ }));
106
+ }
107
+ if (consoleMetrics) {
108
+ readers.push(new runtime.PeriodicExportingMetricReader({
109
+ exporter: new runtime.ConsoleMetricExporter(),
110
+ ...(exportIntervalMillis !== undefined
111
+ ? { exportIntervalMillis }
112
+ : {}),
113
+ }));
114
+ }
115
+ const nextMetricProvider = new runtime.MeterProvider({
116
+ resource: runtime.resourceFromAttributes({
117
+ [runtime.ATTR_SERVICE_NAME]: serviceName,
118
+ }),
119
+ ...(readers.length > 0 ? { readers } : {}),
120
+ });
121
+ metricProvider = nextMetricProvider;
122
+ metrics.setGlobalMeterProvider(nextMetricProvider);
123
+ }
124
+ catch (error) {
125
+ console.warn("Failed to initialize metrics runtime", error);
126
+ }
127
+ }
128
+ export function initTelemetryRuntime(serviceName) {
129
+ if (initialized)
130
+ return;
131
+ initialized = true;
132
+ void initTracingRuntime(serviceName);
133
+ void initMetricsRuntime(serviceName);
134
+ }
@@ -0,0 +1,3 @@
1
+ import "./_dnt.polyfills.js";
2
+ export * from "./telemetry/mod.js";
3
+ //# sourceMappingURL=telemetry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAC7B,cAAc,oBAAoB,CAAC"}
@@ -0,0 +1,2 @@
1
+ import "./_dnt.polyfills.js";
2
+ export * from "./telemetry/mod.js";
@@ -1 +1 @@
1
- {"version":3,"file":"transfer.d.ts","sourceRoot":"","sources":["../src/transfer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"transfer.d.ts","sourceRoot":"","sources":["../src/transfer.ts"],"names":[],"mappings":"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"}
package/esm/transfer.js CHANGED
@@ -17,7 +17,7 @@ import { ulid } from "ulid";
17
17
  import { buildProofInput, verifyProof } from "./auth/proof.js";
18
18
  import { base64urlEncode, sha256 } from "./auth/utils.js";
19
19
  import { TransferError } from "./errors/TransferError.js";
20
- import { createNatsHeaderCarrier, injectTraceContext } from "./tracing.js";
20
+ import { createNatsHeaderCarrier, injectTraceContext, recordTrellisError, } from "./telemetry/mod.js";
21
21
  const TRANSFER_SEQUENCE_HEADER = "trellis-transfer-seq";
22
22
  const TRANSFER_EOF_HEADER = "trellis-transfer-eof";
23
23
  export const FileInfoSchema = Type.Object({
@@ -130,7 +130,7 @@ function deserializeTransferError(msg, operation) {
130
130
  try {
131
131
  const value = JSON.parse(msg.string());
132
132
  return new TransferError({
133
- operation: value.operation ?? operation,
133
+ operation,
134
134
  context: value.context,
135
135
  cause: value.message ? new Error(value.message) : undefined,
136
136
  });
@@ -139,6 +139,16 @@ function deserializeTransferError(msg, operation) {
139
139
  return new TransferError({ operation, cause });
140
140
  }
141
141
  }
142
+ function recordTransferError(error, direction, phase) {
143
+ recordTrellisError(error, {
144
+ surface: "transfer",
145
+ direction,
146
+ operation: error.operation ?? direction,
147
+ phase,
148
+ messagingSystem: "nats",
149
+ });
150
+ return error;
151
+ }
142
152
  function receiveStream(sub, timeoutMs) {
143
153
  const iterator = sub[Symbol.asyncIterator]();
144
154
  return new ReadableStream({
@@ -179,9 +189,10 @@ function receiveStream(sub, timeoutMs) {
179
189
  }
180
190
  catch (cause) {
181
191
  sub.unsubscribe();
182
- controller.error(cause instanceof TransferError
192
+ const error = cause instanceof TransferError
183
193
  ? cause
184
- : new TransferError({ operation: "stream", cause }));
194
+ : new TransferError({ operation: "stream", cause });
195
+ controller.error(recordTransferError(error, "receive", "stream"));
185
196
  }
186
197
  },
187
198
  cancel() {
@@ -283,7 +294,7 @@ export class SendTransferHandle extends BaseTransferHandle {
283
294
  return AsyncResult.from((async () => {
284
295
  const valid = this.validateGrant(__classPrivateFieldGet(this, _SendTransferHandle_grant, "f"), "send").take();
285
296
  if (isErr(valid)) {
286
- return Result.err(valid.error);
297
+ return Result.err(recordTransferError(valid.error, "send", "grant"));
287
298
  }
288
299
  let sentBytes = 0;
289
300
  let seq = 0;
@@ -292,14 +303,14 @@ export class SendTransferHandle extends BaseTransferHandle {
292
303
  sentBytes += chunk.length;
293
304
  if (__classPrivateFieldGet(this, _SendTransferHandle_grant, "f").maxBytes !== undefined &&
294
305
  sentBytes > __classPrivateFieldGet(this, _SendTransferHandle_grant, "f").maxBytes) {
295
- return Result.err(new TransferError({
306
+ return Result.err(recordTransferError(new TransferError({
296
307
  operation: "send",
297
308
  context: {
298
309
  reason: "max_bytes_exceeded",
299
310
  maxBytes: __classPrivateFieldGet(this, _SendTransferHandle_grant, "f").maxBytes,
300
311
  attemptedBytes: sentBytes,
301
312
  },
302
- }));
313
+ }), "send", "validation"));
303
314
  }
304
315
  const headers = await this.buildHeaders(__classPrivateFieldGet(this, _SendTransferHandle_grant, "f").subject, chunk, seq, false);
305
316
  const response = await AsyncResult.try(() => this.nc.request(__classPrivateFieldGet(this, _SendTransferHandle_grant, "f").subject, chunk, {
@@ -307,11 +318,11 @@ export class SendTransferHandle extends BaseTransferHandle {
307
318
  headers,
308
319
  })).take();
309
320
  if (isErr(response)) {
310
- return Result.err(new TransferError({ operation: "send", cause: response.error }));
321
+ return Result.err(recordTransferError(new TransferError({ operation: "send", cause: response.error }), "send", "send"));
311
322
  }
312
323
  const ack = parseTransferAck(response, "send").take();
313
324
  if (isErr(ack)) {
314
- return Result.err(ack.error);
325
+ return Result.err(recordTransferError(ack.error, "send", "ack"));
315
326
  }
316
327
  if (ack.status === "complete") {
317
328
  completed = ack.info;
@@ -324,20 +335,20 @@ export class SendTransferHandle extends BaseTransferHandle {
324
335
  headers: finalHeaders,
325
336
  })).take();
326
337
  if (isErr(finalResponse)) {
327
- return Result.err(new TransferError({
338
+ return Result.err(recordTransferError(new TransferError({
328
339
  operation: "send",
329
340
  cause: finalResponse.error,
330
- }));
341
+ }), "send", "send"));
331
342
  }
332
343
  const finalAck = parseTransferAck(finalResponse, "send").take();
333
344
  if (isErr(finalAck)) {
334
- return Result.err(finalAck.error);
345
+ return Result.err(recordTransferError(finalAck.error, "send", "ack"));
335
346
  }
336
347
  if (finalAck.status !== "complete") {
337
- return Result.err(new TransferError({
348
+ return Result.err(recordTransferError(new TransferError({
338
349
  operation: "send",
339
350
  context: { reason: "missing_completion" },
340
- }));
351
+ }), "send", "ack"));
341
352
  }
342
353
  return Result.ok(finalAck.info ?? completed);
343
354
  })());
@@ -354,7 +365,7 @@ export class ReceiveTransferHandle extends BaseTransferHandle {
354
365
  return AsyncResult.from((async () => {
355
366
  const valid = this.validateGrant(__classPrivateFieldGet(this, _ReceiveTransferHandle_grant, "f"), "stream").take();
356
367
  if (isErr(valid)) {
357
- return Result.err(valid.error);
368
+ return Result.err(recordTransferError(valid.error, "receive", "grant"));
358
369
  }
359
370
  const inbox = createInbox(`_INBOX.${this.auth.sessionKey.slice(0, 16)}`);
360
371
  const sub = this.nc.subscribe(inbox);
@@ -369,7 +380,7 @@ export class ReceiveTransferHandle extends BaseTransferHandle {
369
380
  }
370
381
  catch (cause) {
371
382
  sub.unsubscribe();
372
- return Result.err(new TransferError({ operation: "stream", cause }));
383
+ return Result.err(recordTransferError(new TransferError({ operation: "stream", cause }), "receive", "send"));
373
384
  }
374
385
  return Result.ok(receiveStream(sub, this.timeoutMs));
375
386
  })());