@logbrew/sdk 0.1.2 → 0.1.3

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 CHANGED
@@ -13,6 +13,14 @@ The package supports both ESM `import` and CommonJS `require`.
13
13
  The shipped package also includes `.d.ts` and `.d.cts` declarations so ESM and CommonJS TypeScript consumers can install it directly without a separate build step.
14
14
  The package ships copyable examples under `node_modules/@logbrew/sdk/examples/`. Use the fake `LOGBREW_API_KEY` placeholder in docs, keep the real key in your app configuration, and call `previewJson()` when you want to inspect queued JSON before sending. Type declarations document payload shapes such as `ReleaseAttributes`, `SpanAttributes`, `MetricAttributes`, transport responses, SDK errors, lifecycle helpers, W3C trace helpers, product timeline helpers, console capture, Pino destination, and Winston transport APIs.
15
15
 
16
+ After install, discover and run the packaged examples:
17
+
18
+ ```bash
19
+ node node_modules/@logbrew/sdk/examples/index.mjs --list
20
+ node node_modules/@logbrew/sdk/examples/index.mjs agent-timeline
21
+ npm --prefix node_modules/@logbrew/sdk/examples run agent-timeline
22
+ ```
23
+
16
24
  ## Example
17
25
 
18
26
  ```js
@@ -183,6 +191,13 @@ client.action("evt_payment_api", new Date().toISOString(), createNetworkMileston
183
191
 
184
192
  Timeline helpers keep only primitive metadata, strip query strings and hashes from route templates, normalize HTTP methods, infer failed network milestones from status codes `400` and above, and serialize through the existing `action` event type. Keep metadata low-cardinality, such as `sessionId`, `traceId`, `routeTemplate`, `method`, `statusCode`, `durationMs`, `screen`, `funnel`, and `step`.
185
193
 
194
+ The packaged `agent-timeline` example shows a two-event checkout timeline that an AI assistant can inspect without session replay or payload capture. It combines product action metadata, network milestone metadata, explicit `traceparent` propagation, and a drop-only `eventFilter` that removes low-value info logs:
195
+
196
+ ```bash
197
+ node node_modules/@logbrew/sdk/examples/index.mjs agent-timeline
198
+ node node_modules/@logbrew/sdk/examples/index.mjs agent-timeline:cjs
199
+ ```
200
+
186
201
  ## Console Capture
187
202
 
188
203
  If an app already uses `console.info()`, `console.warn()`, or `console.error()`, install explicit capture on the console object you own:
@@ -0,0 +1,87 @@
1
+ let sdk;
2
+ try {
3
+ sdk = require("@logbrew/sdk");
4
+ } catch (error) {
5
+ if (error && error.code === "MODULE_NOT_FOUND") {
6
+ sdk = require("../index.cjs");
7
+ } else {
8
+ throw error;
9
+ }
10
+ }
11
+
12
+ const {
13
+ createNetworkMilestoneAttributes,
14
+ createProductActionAttributes,
15
+ createTraceparentHeaders,
16
+ LogBrewClient,
17
+ RecordingTransport
18
+ } = sdk;
19
+
20
+ const traceId = "4bf92f3577b34da6a3ce929d0e0e4736";
21
+ const spanId = "b7ad6b7169203331";
22
+ const sessionId = "sess_checkout_001";
23
+ const timestamp = "2026-06-02T10:00:00Z";
24
+
25
+ const client = LogBrewClient.create({
26
+ apiKey: "LOGBREW_API_KEY",
27
+ sdkName: "checkout-agent-timeline",
28
+ sdkVersion: "1.0.0",
29
+ eventFilter(event) {
30
+ return !(event.type === "log" && event.attributes.level === "info");
31
+ }
32
+ });
33
+
34
+ client.action("evt_checkout_started", timestamp, createProductActionAttributes({
35
+ name: "checkout.started",
36
+ status: "success",
37
+ sessionId,
38
+ traceId,
39
+ routeTemplate: "/checkout/:step?coupon=private#payment",
40
+ funnel: "checkout",
41
+ step: "start",
42
+ metadata: { service: "checkout", plan: "pro" }
43
+ }));
44
+
45
+ client.action("evt_payment_api", "2026-06-02T10:00:01Z", createNetworkMilestoneAttributes({
46
+ routeTemplate: "https://api.example.invalid/payments/123?card=private#retry",
47
+ method: "POST",
48
+ statusCode: 503,
49
+ durationMs: 241.5,
50
+ sessionId,
51
+ traceId,
52
+ metadata: { service: "payments", retryable: true }
53
+ }));
54
+
55
+ client.log("evt_debug_noise", "2026-06-02T10:00:02Z", {
56
+ message: "debug heartbeat",
57
+ level: "info",
58
+ logger: "checkout"
59
+ });
60
+
61
+ const headers = createTraceparentHeaders({
62
+ traceId,
63
+ spanId,
64
+ traceFlags: "01"
65
+ });
66
+
67
+ const preview = client.previewJson();
68
+ if (preview.includes("card=private") || preview.includes("coupon=private") || preview.includes("#payment")) {
69
+ throw new Error("agent timeline leaked query or hash metadata");
70
+ }
71
+ if (client.pendingEvents() !== 2) {
72
+ throw new Error(`expected two retained timeline events, got ${client.pendingEvents()}`);
73
+ }
74
+
75
+ console.log(preview);
76
+
77
+ client.shutdown(RecordingTransport.alwaysAccept()).then((response) => {
78
+ console.error(JSON.stringify({
79
+ ok: true,
80
+ events: 2,
81
+ traceparent: headers.traceparent,
82
+ status: response.statusCode
83
+ }));
84
+ }).catch((error) => {
85
+ console.error(error);
86
+ process.exit(1);
87
+ });
@@ -0,0 +1,79 @@
1
+ const sdk = await import("@logbrew/sdk").catch(async (error) => {
2
+ if (error && error.code === "ERR_MODULE_NOT_FOUND") {
3
+ return import("../index.js");
4
+ }
5
+ throw error;
6
+ });
7
+
8
+ const {
9
+ createNetworkMilestoneAttributes,
10
+ createProductActionAttributes,
11
+ createTraceparentHeaders,
12
+ LogBrewClient,
13
+ RecordingTransport
14
+ } = sdk;
15
+
16
+ const traceId = "4bf92f3577b34da6a3ce929d0e0e4736";
17
+ const spanId = "b7ad6b7169203331";
18
+ const sessionId = "sess_checkout_001";
19
+ const timestamp = "2026-06-02T10:00:00Z";
20
+
21
+ const client = LogBrewClient.create({
22
+ apiKey: "LOGBREW_API_KEY",
23
+ sdkName: "checkout-agent-timeline",
24
+ sdkVersion: "1.0.0",
25
+ eventFilter(event) {
26
+ return !(event.type === "log" && event.attributes.level === "info");
27
+ }
28
+ });
29
+
30
+ client.action("evt_checkout_started", timestamp, createProductActionAttributes({
31
+ name: "checkout.started",
32
+ status: "success",
33
+ sessionId,
34
+ traceId,
35
+ routeTemplate: "/checkout/:step?coupon=private#payment",
36
+ funnel: "checkout",
37
+ step: "start",
38
+ metadata: { service: "checkout", plan: "pro" }
39
+ }));
40
+
41
+ client.action("evt_payment_api", "2026-06-02T10:00:01Z", createNetworkMilestoneAttributes({
42
+ routeTemplate: "https://api.example.invalid/payments/123?card=private#retry",
43
+ method: "POST",
44
+ statusCode: 503,
45
+ durationMs: 241.5,
46
+ sessionId,
47
+ traceId,
48
+ metadata: { service: "payments", retryable: true }
49
+ }));
50
+
51
+ client.log("evt_debug_noise", "2026-06-02T10:00:02Z", {
52
+ message: "debug heartbeat",
53
+ level: "info",
54
+ logger: "checkout"
55
+ });
56
+
57
+ const headers = createTraceparentHeaders({
58
+ traceId,
59
+ spanId,
60
+ traceFlags: "01"
61
+ });
62
+
63
+ const preview = client.previewJson();
64
+ if (preview.includes("card=private") || preview.includes("coupon=private") || preview.includes("#payment")) {
65
+ throw new Error("agent timeline leaked query or hash metadata");
66
+ }
67
+ if (client.pendingEvents() !== 2) {
68
+ throw new Error(`expected two retained timeline events, got ${client.pendingEvents()}`);
69
+ }
70
+
71
+ console.log(preview);
72
+
73
+ const response = await client.shutdown(RecordingTransport.alwaysAccept());
74
+ console.error(JSON.stringify({
75
+ ok: true,
76
+ events: 2,
77
+ traceparent: headers.traceparent,
78
+ status: response.statusCode
79
+ }));
@@ -10,6 +10,9 @@ const installedLauncherPrefix = "node node_modules/@logbrew/sdk/examples/index.m
10
10
  const repoLauncherPrefix = "node examples/index.mjs";
11
11
 
12
12
  const examples = {
13
+ "agent-timeline": new URL("./agent-timeline.mjs", import.meta.url),
14
+ "agent-timeline:esm": new URL("./agent-timeline.mjs", import.meta.url),
15
+ "agent-timeline:cjs": new URL("./agent-timeline.cjs", import.meta.url),
13
16
  "readme-example": new URL("./readme-example.mjs", import.meta.url),
14
17
  "readme-example:esm": new URL("./readme-example.mjs", import.meta.url),
15
18
  "readme-example:cjs": new URL("./readme-example.cjs", import.meta.url),
@@ -25,6 +28,9 @@ function isInstalledPackageContext() {
25
28
  function exampleCommands() {
26
29
  if (!isInstalledPackageContext()) {
27
30
  return {
31
+ "agent-timeline": `${repoPrefix} && ${repoLauncherPrefix} agent-timeline`,
32
+ "agent-timeline:esm": `${repoPrefix} && ${repoLauncherPrefix} agent-timeline:esm`,
33
+ "agent-timeline:cjs": `${repoPrefix} && ${repoLauncherPrefix} agent-timeline:cjs`,
28
34
  "readme-example": `${repoPrefix} && ${repoLauncherPrefix} readme-example`,
29
35
  "readme-example:esm": `${repoPrefix} && ${repoLauncherPrefix} readme-example:esm`,
30
36
  "readme-example:cjs": `${repoPrefix} && ${repoLauncherPrefix} readme-example:cjs`,
@@ -36,6 +42,9 @@ function exampleCommands() {
36
42
  }
37
43
 
38
44
  return {
45
+ "agent-timeline": `${installedLauncherPrefix} agent-timeline`,
46
+ "agent-timeline:esm": `${installedLauncherPrefix} agent-timeline:esm`,
47
+ "agent-timeline:cjs": `${installedLauncherPrefix} agent-timeline:cjs`,
39
48
  "readme-example": `${installedLauncherPrefix} readme-example`,
40
49
  "readme-example:esm": `${installedLauncherPrefix} readme-example:esm`,
41
50
  "readme-example:cjs": `${installedLauncherPrefix} readme-example:cjs`,
@@ -49,6 +58,9 @@ function exampleCommands() {
49
58
  function helperCommands() {
50
59
  if (!isInstalledPackageContext()) {
51
60
  return {
61
+ "agent-timeline": `${repoExamplesPrefix} && ${repoNpmHelperPrefix} agent-timeline | ${repoExamplesPrefix} && ${repoPnpmHelperPrefix} agent-timeline`,
62
+ "agent-timeline:esm": `${repoExamplesPrefix} && ${repoNpmHelperPrefix} agent-timeline:esm | ${repoExamplesPrefix} && ${repoPnpmHelperPrefix} agent-timeline:esm`,
63
+ "agent-timeline:cjs": `${repoExamplesPrefix} && ${repoNpmHelperPrefix} agent-timeline:cjs | ${repoExamplesPrefix} && ${repoPnpmHelperPrefix} agent-timeline:cjs`,
52
64
  "readme-example": `${repoExamplesPrefix} && ${repoNpmHelperPrefix} readme-example | ${repoExamplesPrefix} && ${repoPnpmHelperPrefix} readme-example`,
53
65
  "readme-example:esm": `${repoExamplesPrefix} && ${repoNpmHelperPrefix} readme-example:esm | ${repoExamplesPrefix} && ${repoPnpmHelperPrefix} readme-example:esm`,
54
66
  "readme-example:cjs": `${repoExamplesPrefix} && ${repoNpmHelperPrefix} readme-example:cjs | ${repoExamplesPrefix} && ${repoPnpmHelperPrefix} readme-example:cjs`,
@@ -59,6 +71,9 @@ function helperCommands() {
59
71
  }
60
72
 
61
73
  return {
74
+ "agent-timeline": `${installedHelperPrefix} agent-timeline | ${installedPnpmHelperPrefix} agent-timeline`,
75
+ "agent-timeline:esm": `${installedHelperPrefix} agent-timeline:esm | ${installedPnpmHelperPrefix} agent-timeline:esm`,
76
+ "agent-timeline:cjs": `${installedHelperPrefix} agent-timeline:cjs | ${installedPnpmHelperPrefix} agent-timeline:cjs`,
62
77
  "readme-example": `${installedHelperPrefix} readme-example | ${installedPnpmHelperPrefix} readme-example`,
63
78
  "readme-example:esm": `${installedHelperPrefix} readme-example:esm | ${installedPnpmHelperPrefix} readme-example:esm`,
64
79
  "readme-example:cjs": `${installedHelperPrefix} readme-example:cjs | ${installedPnpmHelperPrefix} readme-example:cjs`,
@@ -4,6 +4,9 @@
4
4
  "scripts": {
5
5
  "help": "node ./index.mjs --help",
6
6
  "list": "node ./index.mjs --list",
7
+ "agent-timeline": "node ./index.mjs agent-timeline",
8
+ "agent-timeline:esm": "node ./index.mjs agent-timeline:esm",
9
+ "agent-timeline:cjs": "node ./index.mjs agent-timeline:cjs",
7
10
  "readme-example": "node ./index.mjs readme-example",
8
11
  "readme-example:esm": "node ./index.mjs readme-example:esm",
9
12
  "readme-example:cjs": "node ./index.mjs readme-example:cjs",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@logbrew/sdk",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Public LogBrew JavaScript SDK for building, validating, and flushing event batches.",
5
5
  "type": "module",
6
6
  "main": "./index.cjs",