@logbrew/sdk 0.1.1 → 0.1.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.
package/README.md CHANGED
@@ -120,7 +120,27 @@ await client.flush(RecordingTransport.alwaysAccept());
120
120
 
121
121
  The helpers validate the W3C `version-traceId-parentSpanId-traceFlags` shape, reject all-zero trace/span ids, normalize valid ids to lowercase, expose the sampled flag from `traceFlags`, and keep span metadata primitive-only. `createTraceparentHeaders()` returns an explicit outbound carrier with only `traceparent`. The helpers do not install OpenTelemetry or patch HTTP clients; use them when you need explicit interop in code you own.
122
122
 
123
- LogBrew severity categories are `info`, `warning`, `error`, and `critical`. The JavaScript SDK accepts common runtime aliases such as `trace`, `debug`, `warn`, and `fatal` for compatibility, then serializes canonical values before queued events are sent.
123
+ LogBrew severity categories are `info`, `warning`, `error`, and `critical`. The JavaScript SDK accepts common runtime aliases such as `trace`, `debug`, `warn`, and `fatal` for compatibility, then serializes canonical values before queued events are sent. The shared mapping is documented in the [LogBrew severity contract](../../docs/severity-contract.md).
124
+
125
+ ## Event Filtering
126
+
127
+ Use `eventFilter` when your app needs a last-mile privacy or sampling gate before events enter the in-memory queue. The filter receives a copy of the already validated event, so severity aliases are already canonical and mutations inside the callback do not alter queued payloads. Return `false` to drop an event; return `true` or nothing to keep it.
128
+
129
+ ```js
130
+ const client = LogBrewClient.create({
131
+ apiKey: "LOGBREW_API_KEY",
132
+ sdkName: "checkout-api",
133
+ sdkVersion: "1.0.0",
134
+ eventFilter(event) {
135
+ if (event.type === "log" && event.attributes.level === "info") {
136
+ return false;
137
+ }
138
+ return true;
139
+ }
140
+ });
141
+ ```
142
+
143
+ Prefer removing sensitive values at the source before calling LogBrew. `eventFilter` is intentionally drop-only: it avoids broad mutable event processing, global scopes, and hidden context that can make observability payloads harder to reason about.
124
144
 
125
145
  ## Agent-Readable Timelines
126
146
 
package/index.cjs CHANGED
@@ -79,13 +79,17 @@ class RecordingTransport {
79
79
  }
80
80
 
81
81
  class LogBrewClient {
82
- static create({ apiKey, sdkName, sdkVersion, maxRetries = 2 }) {
82
+ static create({ apiKey, sdkName, sdkVersion, maxRetries = 2, eventFilter }) {
83
83
  requireNonEmpty("apiKey", apiKey);
84
84
  requireNonEmpty("sdkName", sdkName);
85
85
  requireNonEmpty("sdkVersion", sdkVersion);
86
+ if (eventFilter !== undefined && typeof eventFilter !== "function") {
87
+ throw new SdkError("validation_error", "eventFilter must be a function");
88
+ }
86
89
 
87
90
  return new LogBrewClient({
88
91
  apiKey,
92
+ eventFilter,
89
93
  sdk: {
90
94
  name: sdkName,
91
95
  language: "javascript",
@@ -95,8 +99,9 @@ class LogBrewClient {
95
99
  });
96
100
  }
97
101
 
98
- constructor({ apiKey, sdk, maxRetries }) {
102
+ constructor({ apiKey, sdk, maxRetries, eventFilter }) {
99
103
  this.apiKey = apiKey;
104
+ this.eventFilter = eventFilter;
100
105
  this.sdk = sdk;
101
106
  this.maxRetries = maxRetries;
102
107
  this.events = [];
@@ -161,7 +166,11 @@ class LogBrewClient {
161
166
  }
162
167
  requireNonEmpty("event id", id);
163
168
  requireTimestamp(timestamp);
164
- this.events.push({ type: eventType, id, timestamp, attributes });
169
+ const event = { type: eventType, id, timestamp, attributes };
170
+ if (this.eventFilter && this.eventFilter(cloneEvent(event)) === false) {
171
+ return;
172
+ }
173
+ this.events.push(event);
165
174
  }
166
175
 
167
176
  async #flushInternal(transport) {
@@ -1004,6 +1013,13 @@ function cloneMetadata(metadata) {
1004
1013
  return { ...metadata };
1005
1014
  }
1006
1015
 
1016
+ function cloneEvent(event) {
1017
+ const attributes = event.attributes.metadata === undefined
1018
+ ? { ...event.attributes }
1019
+ : { ...event.attributes, metadata: { ...event.attributes.metadata } };
1020
+ return { ...event, attributes };
1021
+ }
1022
+
1007
1023
  function validateRelease(attributes) {
1008
1024
  requireNonEmpty("release version", attributes.version);
1009
1025
  if (attributes.commit !== undefined) {
package/index.d.cts CHANGED
@@ -241,6 +241,9 @@ export type Event =
241
241
  | { type: "action"; id: string; timestamp: string; attributes: ActionAttributes }
242
242
  | { type: "metric"; id: string; timestamp: string; attributes: MetricAttributes };
243
243
 
244
+ /** Drop-only event filter called after validation and before an event is queued. */
245
+ export type EventFilter = (event: Event) => boolean | void;
246
+
244
247
  /** Stable transport response returned from flush and shutdown operations. */
245
248
  export type TransportResponse = {
246
249
  /** Final HTTP-like status returned by the transport. */
@@ -289,6 +292,7 @@ export declare class LogBrewClient {
289
292
  sdkName: string;
290
293
  sdkVersion: string;
291
294
  maxRetries?: number;
295
+ eventFilter?: EventFilter;
292
296
  }): LogBrewClient;
293
297
  /** Return the queued event count currently buffered in memory. */
294
298
  pendingEvents(): number;
package/index.d.ts CHANGED
@@ -241,6 +241,9 @@ export type Event =
241
241
  | { type: "action"; id: string; timestamp: string; attributes: ActionAttributes }
242
242
  | { type: "metric"; id: string; timestamp: string; attributes: MetricAttributes };
243
243
 
244
+ /** Drop-only event filter called after validation and before an event is queued. */
245
+ export type EventFilter = (event: Event) => boolean | void;
246
+
244
247
  /** Stable transport response returned from flush and shutdown operations. */
245
248
  export type TransportResponse = {
246
249
  /** Final HTTP-like status returned by the transport. */
@@ -289,6 +292,7 @@ export declare class LogBrewClient {
289
292
  sdkName: string;
290
293
  sdkVersion: string;
291
294
  maxRetries?: number;
295
+ eventFilter?: EventFilter;
292
296
  }): LogBrewClient;
293
297
  /** Return the queued event count currently buffered in memory. */
294
298
  pendingEvents(): number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@logbrew/sdk",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Public LogBrew JavaScript SDK for building, validating, and flushing event batches.",
5
5
  "type": "module",
6
6
  "main": "./index.cjs",