@superblocksteam/sdk 2.0.128-next.0 → 2.0.128-next.2

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.
@@ -1,4 +1,4 @@
1
1
 
2
- > @superblocksteam/sdk@2.0.128-next.0 build /home/runner/work/superblocks/superblocks/packages/cli/packages/sdk
2
+ > @superblocksteam/sdk@2.0.128-next.2 build /home/runner/work/superblocks/superblocks/packages/cli/packages/sdk
3
3
  > tsc --build
4
4
 
@@ -5,10 +5,22 @@ export interface ErrorMeta {
5
5
  stack?: string;
6
6
  };
7
7
  }
8
+ /**
9
+ * Primitive-only attribute map. Forwarded to OTel log attributes (Datadog
10
+ * facets), so values must stay low-cardinality-friendly (enums/ids/numbers),
11
+ * not free-form text.
12
+ */
13
+ export type LogAttributes = Record<string, string | number | boolean>;
8
14
  export interface Logger {
9
15
  debug: (...messages: unknown[]) => void;
10
16
  info: (...messages: unknown[]) => void;
11
17
  warn: (...messages: unknown[]) => void;
18
+ /**
19
+ * Emit a WARN-level log whose structured attributes are exported as OTel log
20
+ * attributes (Datadog facets) instead of being flattened into the message
21
+ * body. Use for machine-queryable warn events such as stream stalls.
22
+ */
23
+ warnStructured?: (message: string, attributes: LogAttributes) => void;
12
24
  error: (message: string, meta?: ErrorMeta) => void;
13
25
  }
14
26
  export declare function getLogger(loggerOverride?: (...messages: unknown[]) => void): Logger;
@@ -1 +1 @@
1
- {"version":3,"file":"logging.d.ts","sourceRoot":"","sources":["../../src/telemetry/logging.ts"],"names":[],"mappings":"AA6DA,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED,MAAM,WAAW,MAAM;IACrB,KAAK,EAAE,CAAC,GAAG,QAAQ,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACxC,IAAI,EAAE,CAAC,GAAG,QAAQ,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACvC,IAAI,EAAE,CAAC,GAAG,QAAQ,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACvC,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,SAAS,KAAK,IAAI,CAAC;CACpD;AAwDD,wBAAgB,SAAS,CACvB,cAAc,CAAC,EAAE,CAAC,GAAG,QAAQ,EAAE,OAAO,EAAE,KAAK,IAAI,GAChD,MAAM,CAWR;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,CAgBtD"}
1
+ {"version":3,"file":"logging.d.ts","sourceRoot":"","sources":["../../src/telemetry/logging.ts"],"names":[],"mappings":"AA8DA,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;AAEtE,MAAM,WAAW,MAAM;IACrB,KAAK,EAAE,CAAC,GAAG,QAAQ,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACxC,IAAI,EAAE,CAAC,GAAG,QAAQ,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACvC,IAAI,EAAE,CAAC,GAAG,QAAQ,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACvC;;;;OAIG;IACH,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,aAAa,KAAK,IAAI,CAAC;IACtE,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,SAAS,KAAK,IAAI,CAAC;CACpD;AAyED,wBAAgB,SAAS,CACvB,cAAc,CAAC,EAAE,CAAC,GAAG,QAAQ,EAAE,OAAO,EAAE,KAAK,IAAI,GAChD,MAAM,CAiBR;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,CAgBtD"}
@@ -1,6 +1,6 @@
1
1
  import { SeverityNumber } from "@opentelemetry/api-logs";
2
2
  import { createLogger, format, transports } from "winston";
3
- import { sanitizeLogError, sanitizeLogMessage, } from "@superblocksteam/telemetry";
3
+ import { sanitizeLogError, sanitizeLogMessage, sanitizeLogObject, } from "@superblocksteam/telemetry";
4
4
  import { getLogger as getTracedLogger } from "./index.js";
5
5
  import { safeStringify } from "./safe-stringify.js";
6
6
  const activeTransports = [];
@@ -70,6 +70,23 @@ const logger = Object.freeze({
70
70
  });
71
71
  winstonLogger.warn(body);
72
72
  },
73
+ warnStructured: (message, attributes) => {
74
+ const body = sanitizeLogMessage(message);
75
+ // sanitizeLogObject strips secret-named keys and redacts secret values,
76
+ // matching the vite-plugin wrapLogger path so both implementations of this
77
+ // contract enforce the same invariant.
78
+ const safeAttributes = sanitizeLogObject(attributes);
79
+ getTracedLogger().emit({
80
+ severityNumber: SeverityNumber.WARN,
81
+ severityText: "WARN",
82
+ body,
83
+ attributes: safeAttributes,
84
+ });
85
+ // OTel is the canonical sink for the structured attributes; Winston gets
86
+ // the body only (matching warn() above) so attributes are not also shipped
87
+ // to Datadog via stdout log shippers as a second, duplicate copy.
88
+ winstonLogger.warn(body);
89
+ },
73
90
  error: (message, meta) => {
74
91
  const safeMessage = sanitizeLogMessage(message);
75
92
  const safeError = meta?.error
@@ -98,6 +115,11 @@ export function getLogger(loggerOverride) {
98
115
  debug: loggerOverride,
99
116
  info: loggerOverride,
100
117
  warn: loggerOverride,
118
+ // The override path is for test/debug sinks only: like debug/info/warn
119
+ // above, it forwards raw args to the supplied function and does NOT
120
+ // sanitize or emit OTel attributes. Production callers use the default
121
+ // logger (and the vite-plugin wrapLogger) which sanitize before emitting.
122
+ warnStructured: (message, attributes) => loggerOverride(message, attributes),
101
123
  error: loggerOverride,
102
124
  };
103
125
  }
@@ -1 +1 @@
1
- {"version":3,"file":"logging.js","sourceRoot":"","sources":["../../src/telemetry/logging.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"logging.js","sourceRoot":"","sources":["../../src/telemetry/logging.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { beforeEach, describe, expect, it, vi } from "vitest";
2
- const { emitMock, winstonErrorMock, winstonLoggerMock, sanitizeLogMessageMock, sanitizeLogErrorMock, } = vi.hoisted(() => {
2
+ const { emitMock, winstonErrorMock, winstonLoggerMock, sanitizeLogMessageMock, sanitizeLogErrorMock, sanitizeLogObjectMock, } = vi.hoisted(() => {
3
3
  const emitMock = vi.fn();
4
4
  const winstonErrorMock = vi.fn();
5
5
  const winstonLoggerMock = {
@@ -14,17 +14,31 @@ const { emitMock, winstonErrorMock, winstonLoggerMock, sanitizeLogMessageMock, s
14
14
  message: `sanitized-error:${error.message}`,
15
15
  stack: error.stack ? `sanitized-error:${error.stack}` : undefined,
16
16
  }));
17
+ // Faithful stand-in for the real sanitizeLogObject: strips secret-named keys
18
+ // and redacts string values; numbers/booleans pass through.
19
+ const sanitizeLogObjectMock = vi.fn((obj) => {
20
+ const out = {};
21
+ for (const [key, value] of Object.entries(obj)) {
22
+ if (key === "password" || key === "token" || key === "api_key")
23
+ continue;
24
+ out[key] =
25
+ typeof value === "string" ? `sanitized-object:${value}` : value;
26
+ }
27
+ return out;
28
+ });
17
29
  return {
18
30
  emitMock,
19
31
  winstonErrorMock,
20
32
  winstonLoggerMock,
21
33
  sanitizeLogMessageMock,
22
34
  sanitizeLogErrorMock,
35
+ sanitizeLogObjectMock,
23
36
  };
24
37
  });
25
38
  vi.mock("@superblocksteam/telemetry", () => ({
26
39
  sanitizeLogMessage: sanitizeLogMessageMock,
27
40
  sanitizeLogError: sanitizeLogErrorMock,
41
+ sanitizeLogObject: sanitizeLogObjectMock,
28
42
  }));
29
43
  vi.mock("./index.js", () => ({
30
44
  getLogger: vi.fn(() => ({
@@ -101,4 +115,51 @@ describe("telemetry logger error sanitization", () => {
101
115
  expect(winstonErrorMock).toHaveBeenCalledWith("sanitized-message:plain failure");
102
116
  });
103
117
  });
118
+ describe("telemetry logger warnStructured", () => {
119
+ beforeEach(() => {
120
+ vi.clearAllMocks();
121
+ });
122
+ it("emits a WARN record carrying structured attributes (not flattened into the body)", () => {
123
+ const logger = getLogger();
124
+ logger.warnStructured?.("Idle timeout exceeded", {
125
+ event: "stream_stall",
126
+ provider: "snowflake",
127
+ model: "claude-opus-4-6",
128
+ idleMs: 180001,
129
+ attempt: 0,
130
+ });
131
+ expect(emitMock).toHaveBeenCalledWith(expect.objectContaining({
132
+ severityText: "WARN",
133
+ body: "sanitized-message:Idle timeout exceeded",
134
+ attributes: {
135
+ event: "sanitized-object:stream_stall",
136
+ provider: "sanitized-object:snowflake",
137
+ model: "sanitized-object:claude-opus-4-6",
138
+ idleMs: 180001,
139
+ attempt: 0,
140
+ },
141
+ }));
142
+ // Winston gets the body only (structured attributes go to OTel, not also
143
+ // to stdout log shippers as a duplicate).
144
+ expect(winstonLoggerMock.warn).toHaveBeenCalledWith("sanitized-message:Idle timeout exceeded");
145
+ });
146
+ it("strips secret-named attribute keys and leaves numbers untouched", () => {
147
+ const logger = getLogger();
148
+ logger.warnStructured?.("stall", {
149
+ provider: "snowflake",
150
+ password: "sekret",
151
+ idleMs: 42,
152
+ });
153
+ expect(emitMock).toHaveBeenCalledWith(expect.objectContaining({
154
+ attributes: expect.objectContaining({
155
+ provider: "sanitized-object:snowflake",
156
+ idleMs: 42,
157
+ }),
158
+ }));
159
+ // Secret-named keys are dropped before reaching the OTel record.
160
+ expect(emitMock).not.toHaveBeenCalledWith(expect.objectContaining({
161
+ attributes: expect.objectContaining({ password: expect.anything() }),
162
+ }));
163
+ });
164
+ });
104
165
  //# sourceMappingURL=logging.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"logging.test.js","sourceRoot":"","sources":["../../src/telemetry/logging.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"logging.test.js","sourceRoot":"","sources":["../../src/telemetry/logging.test.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@superblocksteam/sdk",
3
- "version": "2.0.128-next.0",
3
+ "version": "2.0.128-next.2",
4
4
  "description": "Superblocks JS SDK",
5
5
  "homepage": "https://www.superblocks.com",
6
6
  "license": "Superblocks Community Software License",
@@ -48,11 +48,11 @@
48
48
  "vite-tsconfig-paths": "^6.0.4",
49
49
  "winston": "^3.17.0",
50
50
  "yaml": "^2.7.1",
51
- "@superblocksteam/library-shared": "2.0.128-next.0",
52
- "@superblocksteam/shared": "0.9590.6",
53
- "@superblocksteam/telemetry": "2.0.128-next.0",
54
- "@superblocksteam/util": "2.0.128-next.0",
55
- "@superblocksteam/vite-plugin-file-sync": "2.0.128-next.0"
51
+ "@superblocksteam/shared": "0.9590.8",
52
+ "@superblocksteam/telemetry": "2.0.128-next.2",
53
+ "@superblocksteam/util": "2.0.128-next.2",
54
+ "@superblocksteam/vite-plugin-file-sync": "2.0.128-next.2",
55
+ "@superblocksteam/library-shared": "2.0.128-next.2"
56
56
  },
57
57
  "devDependencies": {
58
58
  "@eslint/js": "^9.39.2",
@@ -6,6 +6,7 @@ const {
6
6
  winstonLoggerMock,
7
7
  sanitizeLogMessageMock,
8
8
  sanitizeLogErrorMock,
9
+ sanitizeLogObjectMock,
9
10
  } = vi.hoisted(() => {
10
11
  const emitMock = vi.fn();
11
12
  const winstonErrorMock = vi.fn();
@@ -27,18 +28,32 @@ const {
27
28
  }),
28
29
  );
29
30
 
31
+ // Faithful stand-in for the real sanitizeLogObject: strips secret-named keys
32
+ // and redacts string values; numbers/booleans pass through.
33
+ const sanitizeLogObjectMock = vi.fn((obj: Record<string, unknown>) => {
34
+ const out: Record<string, unknown> = {};
35
+ for (const [key, value] of Object.entries(obj)) {
36
+ if (key === "password" || key === "token" || key === "api_key") continue;
37
+ out[key] =
38
+ typeof value === "string" ? `sanitized-object:${value}` : value;
39
+ }
40
+ return out;
41
+ });
42
+
30
43
  return {
31
44
  emitMock,
32
45
  winstonErrorMock,
33
46
  winstonLoggerMock,
34
47
  sanitizeLogMessageMock,
35
48
  sanitizeLogErrorMock,
49
+ sanitizeLogObjectMock,
36
50
  };
37
51
  });
38
52
 
39
53
  vi.mock("@superblocksteam/telemetry", () => ({
40
54
  sanitizeLogMessage: sanitizeLogMessageMock,
41
55
  sanitizeLogError: sanitizeLogErrorMock,
56
+ sanitizeLogObject: sanitizeLogObjectMock,
42
57
  }));
43
58
 
44
59
  vi.mock("./index.js", () => ({
@@ -140,3 +155,65 @@ describe("telemetry logger error sanitization", () => {
140
155
  );
141
156
  });
142
157
  });
158
+
159
+ describe("telemetry logger warnStructured", () => {
160
+ beforeEach(() => {
161
+ vi.clearAllMocks();
162
+ });
163
+
164
+ it("emits a WARN record carrying structured attributes (not flattened into the body)", () => {
165
+ const logger = getLogger();
166
+
167
+ logger.warnStructured?.("Idle timeout exceeded", {
168
+ event: "stream_stall",
169
+ provider: "snowflake",
170
+ model: "claude-opus-4-6",
171
+ idleMs: 180001,
172
+ attempt: 0,
173
+ });
174
+
175
+ expect(emitMock).toHaveBeenCalledWith(
176
+ expect.objectContaining({
177
+ severityText: "WARN",
178
+ body: "sanitized-message:Idle timeout exceeded",
179
+ attributes: {
180
+ event: "sanitized-object:stream_stall",
181
+ provider: "sanitized-object:snowflake",
182
+ model: "sanitized-object:claude-opus-4-6",
183
+ idleMs: 180001,
184
+ attempt: 0,
185
+ },
186
+ }),
187
+ );
188
+ // Winston gets the body only (structured attributes go to OTel, not also
189
+ // to stdout log shippers as a duplicate).
190
+ expect(winstonLoggerMock.warn).toHaveBeenCalledWith(
191
+ "sanitized-message:Idle timeout exceeded",
192
+ );
193
+ });
194
+
195
+ it("strips secret-named attribute keys and leaves numbers untouched", () => {
196
+ const logger = getLogger();
197
+
198
+ logger.warnStructured?.("stall", {
199
+ provider: "snowflake",
200
+ password: "sekret",
201
+ idleMs: 42,
202
+ });
203
+
204
+ expect(emitMock).toHaveBeenCalledWith(
205
+ expect.objectContaining({
206
+ attributes: expect.objectContaining({
207
+ provider: "sanitized-object:snowflake",
208
+ idleMs: 42,
209
+ }),
210
+ }),
211
+ );
212
+ // Secret-named keys are dropped before reaching the OTel record.
213
+ expect(emitMock).not.toHaveBeenCalledWith(
214
+ expect.objectContaining({
215
+ attributes: expect.objectContaining({ password: expect.anything() }),
216
+ }),
217
+ );
218
+ });
219
+ });
@@ -6,6 +6,7 @@ import type winston from "winston";
6
6
  import {
7
7
  sanitizeLogError,
8
8
  sanitizeLogMessage,
9
+ sanitizeLogObject,
9
10
  } from "@superblocksteam/telemetry";
10
11
 
11
12
  import { getLogger as getTracedLogger } from "./index.js";
@@ -67,10 +68,23 @@ export interface ErrorMeta {
67
68
  };
68
69
  }
69
70
 
71
+ /**
72
+ * Primitive-only attribute map. Forwarded to OTel log attributes (Datadog
73
+ * facets), so values must stay low-cardinality-friendly (enums/ids/numbers),
74
+ * not free-form text.
75
+ */
76
+ export type LogAttributes = Record<string, string | number | boolean>;
77
+
70
78
  export interface Logger {
71
79
  debug: (...messages: unknown[]) => void;
72
80
  info: (...messages: unknown[]) => void;
73
81
  warn: (...messages: unknown[]) => void;
82
+ /**
83
+ * Emit a WARN-level log whose structured attributes are exported as OTel log
84
+ * attributes (Datadog facets) instead of being flattened into the message
85
+ * body. Use for machine-queryable warn events such as stream stalls.
86
+ */
87
+ warnStructured?: (message: string, attributes: LogAttributes) => void;
74
88
  error: (message: string, meta?: ErrorMeta) => void;
75
89
  }
76
90
 
@@ -106,6 +120,23 @@ const logger: Logger = Object.freeze({
106
120
  });
107
121
  winstonLogger.warn(body);
108
122
  },
123
+ warnStructured: (message: string, attributes: LogAttributes) => {
124
+ const body = sanitizeLogMessage(message);
125
+ // sanitizeLogObject strips secret-named keys and redacts secret values,
126
+ // matching the vite-plugin wrapLogger path so both implementations of this
127
+ // contract enforce the same invariant.
128
+ const safeAttributes = sanitizeLogObject(attributes);
129
+ getTracedLogger().emit({
130
+ severityNumber: SeverityNumber.WARN,
131
+ severityText: "WARN",
132
+ body,
133
+ attributes: safeAttributes,
134
+ });
135
+ // OTel is the canonical sink for the structured attributes; Winston gets
136
+ // the body only (matching warn() above) so attributes are not also shipped
137
+ // to Datadog via stdout log shippers as a second, duplicate copy.
138
+ winstonLogger.warn(body);
139
+ },
109
140
  error: (message: string, meta?: ErrorMeta) => {
110
141
  const safeMessage = sanitizeLogMessage(message);
111
142
  const safeError = meta?.error
@@ -139,6 +170,12 @@ export function getLogger(
139
170
  debug: loggerOverride,
140
171
  info: loggerOverride,
141
172
  warn: loggerOverride,
173
+ // The override path is for test/debug sinks only: like debug/info/warn
174
+ // above, it forwards raw args to the supplied function and does NOT
175
+ // sanitize or emit OTel attributes. Production callers use the default
176
+ // logger (and the vite-plugin wrapLogger) which sanitize before emitting.
177
+ warnStructured: (message: string, attributes: LogAttributes) =>
178
+ loggerOverride(message, attributes),
142
179
  error: loggerOverride as (message: string, meta?: ErrorMeta) => void,
143
180
  };
144
181
  }