zario 0.3.1 → 0.3.5

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 (35) hide show
  1. package/README.md +161 -1
  2. package/dist/cjs/aggregation/LogAggregator.js +110 -0
  3. package/dist/cjs/aggregation/index.js +17 -0
  4. package/dist/cjs/core/Logger.js +106 -2
  5. package/dist/cjs/filters/Filter.js +56 -0
  6. package/dist/cjs/filters/SpecificFilters.js +71 -0
  7. package/dist/cjs/filters/index.js +18 -0
  8. package/dist/cjs/index.js +18 -1
  9. package/dist/cjs/structured/StructuredExtensions.js +112 -0
  10. package/dist/cjs/structured/index.js +17 -0
  11. package/dist/cjs/transports/FilterableTransport.js +39 -0
  12. package/dist/cjs/transports/index.js +1 -0
  13. package/dist/esm/aggregation/LogAggregator.d.ts +60 -0
  14. package/dist/esm/aggregation/LogAggregator.js +104 -0
  15. package/dist/esm/aggregation/index.d.ts +1 -0
  16. package/dist/esm/aggregation/index.js +1 -0
  17. package/dist/esm/core/Logger.d.ts +33 -0
  18. package/dist/esm/core/Logger.js +106 -2
  19. package/dist/esm/filters/Filter.d.ts +47 -0
  20. package/dist/esm/filters/Filter.js +49 -0
  21. package/dist/esm/filters/SpecificFilters.d.ts +41 -0
  22. package/dist/esm/filters/SpecificFilters.js +64 -0
  23. package/dist/esm/filters/index.d.ts +2 -0
  24. package/dist/esm/filters/index.js +2 -0
  25. package/dist/esm/index.d.ts +6 -3
  26. package/dist/esm/index.js +11 -2
  27. package/dist/esm/structured/StructuredExtensions.d.ts +31 -0
  28. package/dist/esm/structured/StructuredExtensions.js +74 -0
  29. package/dist/esm/structured/index.d.ts +1 -0
  30. package/dist/esm/structured/index.js +1 -0
  31. package/dist/esm/transports/FilterableTransport.d.ts +14 -0
  32. package/dist/esm/transports/FilterableTransport.js +35 -0
  33. package/dist/esm/transports/index.d.ts +1 -0
  34. package/dist/esm/transports/index.js +1 -0
  35. package/package.json +8 -4
package/README.md CHANGED
@@ -2,6 +2,17 @@
2
2
 
3
3
  A minimal, fast logging library for Node.js with TypeScript support.
4
4
 
5
+ ## What's New in 0.3.5
6
+
7
+ - Added advanced filtering capabilities with LevelFilter, PrefixFilter, MetadataFilter, CompositeFilter, OrFilter, and PredicateFilter
8
+ - Added structured logging extensions with LogEnrichmentPipeline and MetadataEnricher
9
+ - Added TimeBasedAggregator.stop() method for proper timer cleanup
10
+ - Improved error handling for aggregators and filters with try-catch protection
11
+ - Enhanced thread safety with defensive copying of filters during iteration
12
+ - Fixed enricher inheritance in child loggers
13
+ - Added documentation for empty array behavior in CompositeFilter (allows all) and OrFilter (blocks all)
14
+ - Added note about strict equality in MetadataFilter for complex objects
15
+
5
16
  ## What's New in 0.2.11
6
17
 
7
18
  - Added HTTP transport support with new HttpTransport class
@@ -46,6 +57,9 @@ logger.error("❌ Database connection failed", { code: 500 });
46
57
  | **transports** | `array` | Where logs are written (with transport-specific options like `path`, `maxSize`, `maxFiles`, `compression`, `batchInterval`, `compressOldFiles` for file transport) |
47
58
  | **customLevels** | `object` | Define custom log levels and their priorities |
48
59
  | **customColors** | `object` | Assign colors to custom log levels |
60
+ | **filters** | `Filter[]` | Array of filters to apply before logging (LevelFilter, PrefixFilter, MetadataFilter, CompositeFilter, OrFilter, PredicateFilter) |
61
+ | **aggregators** | `LogAggregator[]` | Array of log aggregators (BatchAggregator, TimeBasedAggregator, CompositeAggregator) |
62
+ | **enrichers** | `LogEnrichmentPipeline` | Pipeline for structured logging extensions |
49
63
 
50
64
  ### Log Levels
51
65
 
@@ -112,16 +126,162 @@ const logger = new Logger({
112
126
  });
113
127
  ```
114
128
 
129
+ ### Advanced Filtering
130
+
131
+ Filter logs based on various criteria using built-in filter classes:
132
+
133
+ ```js
134
+ import {
135
+ Logger,
136
+ ConsoleTransport,
137
+ LevelFilter,
138
+ PrefixFilter,
139
+ MetadataFilter,
140
+ CompositeFilter,
141
+ OrFilter,
142
+ PredicateFilter
143
+ } from "zario";
144
+
145
+ // Level filter - only allow specific log levels
146
+ const levelFilter = new LevelFilter(['info', 'error']);
147
+
148
+ // Prefix filter - only allow logs with specific prefixes
149
+ const prefixFilter = new PrefixFilter(['[API]', '[DB]']);
150
+
151
+ // Metadata filter - only allow logs with specific metadata
152
+ const metadataFilter = new MetadataFilter({ userId: 123 });
153
+
154
+ // Composite filter - combines multiple filters with AND logic
155
+ // Note: With an empty array, CompositeFilter allows all logs (vacuous truth)
156
+ const compositeFilter = new CompositeFilter([levelFilter, prefixFilter]);
157
+
158
+ // Or filter - combines multiple filters with OR logic
159
+ // Note: With an empty array, OrFilter blocks all logs (no matching conditions)
160
+ const orFilter = new OrFilter([levelFilter, metadataFilter]);
161
+
162
+ // Predicate filter - custom filtering function
163
+ const predicateFilter = new PredicateFilter((logData) => {
164
+ return logData.level !== 'debug'; // Filter out debug messages
165
+ });
166
+
167
+ // Create logger with filters
168
+ const filteredLogger = new Logger({
169
+ level: 'debug',
170
+ transports: [new ConsoleTransport()],
171
+ filters: [compositeFilter, predicateFilter] // Apply multiple filters
172
+ });
173
+ ```
174
+
175
+ ### Structured Logging Extensions
176
+
177
+ Enhance your logs with additional metadata using structured logging extensions:
178
+
179
+ ```js
180
+ import {
181
+ Logger,
182
+ ConsoleTransport,
183
+ LogEnrichmentPipeline,
184
+ MetadataEnricher
185
+ } from "zario";
186
+
187
+ // Create enrichers to add metadata to logs
188
+ const staticEnricher = MetadataEnricher.addStaticFields({
189
+ service: 'user-service',
190
+ version: '1.0.0'
191
+ });
192
+
193
+ const dynamicEnricher = MetadataEnricher.addDynamicFields(() => ({
194
+ processId: process.pid,
195
+ memoryUsage: process.memoryUsage().heapUsed
196
+ }));
197
+
198
+ const processEnricher = MetadataEnricher.addProcessInfo();
199
+ const envEnricher = MetadataEnricher.addEnvironmentInfo();
200
+
201
+ // Create a pipeline with multiple enrichers
202
+ const enricherPipeline = new LogEnrichmentPipeline([
203
+ staticEnricher,
204
+ dynamicEnricher,
205
+ processEnricher,
206
+ envEnricher
207
+ ]);
208
+
209
+ // Create logger with enrichers
210
+ const enrichedLogger = new Logger({
211
+ level: 'info',
212
+ transports: [new ConsoleTransport()],
213
+ enrichers: enricherPipeline
214
+ });
215
+
216
+ enrichedLogger.info('User login', { userId: 123 });
217
+ // Output will include additional metadata fields
218
+
219
+ // Add enrichers dynamically
220
+ enrichedLogger.addEnricher((logData) => {
221
+ return {
222
+ ...logData,
223
+ timestamp: new Date().toISOString(),
224
+ additionalField: 'some-value'
225
+ };
226
+ });
227
+ ```
228
+
229
+ ### Log Aggregation
230
+
231
+ Aggregate logs in batches or based on time intervals:
232
+
233
+ ```js
234
+ import {
235
+ Logger,
236
+ ConsoleTransport,
237
+ BatchAggregator,
238
+ TimeBasedAggregator,
239
+ CompositeAggregator
240
+ } from "zario";
241
+
242
+ // Batch aggregator - flushes when batch size is reached
243
+ const batchAggregator = new BatchAggregator(10, (logs) => {
244
+ // Process batch of 10 logs
245
+ console.log(`Processing ${logs.length} logs`);
246
+ });
247
+
248
+ // Time-based aggregator - flushes after time interval
249
+ const timeAggregator = new TimeBasedAggregator(5000, (logs) => {
250
+ // Process logs every 5 seconds
251
+ console.log(`Processing ${logs.length} logs`);
252
+ });
253
+
254
+ // Create logger with aggregators
255
+ const aggregatedLogger = new Logger({
256
+ level: 'info',
257
+ transports: [new ConsoleTransport()],
258
+ aggregators: [batchAggregator]
259
+ });
260
+
261
+ // Manually flush aggregators
262
+ aggregatedLogger.flushAggregators();
263
+
264
+ // Stop time-based aggregator timer
265
+ // timeAggregator.stop(); // Available for TimeBasedAggregator
266
+ ```
267
+
115
268
  ### Methods
116
269
 
117
270
  - `logger.debug(message, metadata?)` - Debug level logging
118
- - `logger.info(message, metadata?)` - Info level logging
271
+ - `logger.info(message, metadata?)` - Info level logging
119
272
  - `logger.warn(message, metadata?)` - Warning level logging
120
273
  - `logger.error(message, metadata?)` - Error level logging
121
274
  - `logger.logWithLevel(level, message, metadata?)` - Log a message at an arbitrary/custom level
122
275
  - `logger.createChild(options)` - Creates a child logger with inherited settings
123
276
  - `logger.setLevel(level)` - Change the logger level at runtime
124
277
  - `logger.setFormat(format)` - Set the output format to text or json
278
+ - `logger.addFilter(filter)` - Add a filter to the logger (LevelFilter, PrefixFilter, MetadataFilter, etc.)
279
+ - `logger.removeFilter(filter)` - Remove a filter from the logger
280
+ - `logger.addAggregator(aggregator)` - Add an aggregator to the logger (BatchAggregator, TimeBasedAggregator, etc.)
281
+ - `logger.removeAggregator(aggregator)` - Remove an aggregator from the logger
282
+ - `logger.flushAggregators()` - Manually flush all aggregators
283
+ - `logger.addEnricher(enricher)` - Add an enricher to the logger for structured logging
284
+ - `logger.startTimer(name)` - Create a performance timer
125
285
 
126
286
  ## Usage Examples
127
287
 
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CompositeAggregator = exports.TimeBasedAggregator = exports.BatchAggregator = void 0;
4
+ /**
5
+ * Aggregates logs in memory and flushes them in batches
6
+ */
7
+ class BatchAggregator {
8
+ constructor(maxSize = 100, flushCallback) {
9
+ this.logs = [];
10
+ this.maxSize = maxSize;
11
+ this.flushCallback = flushCallback;
12
+ }
13
+ aggregate(logData, formatter) {
14
+ this.logs.push({ logData, formatter });
15
+ if (this.logs.length >= this.maxSize) {
16
+ const result = this.flush();
17
+ // Handle the case where flush returns a Promise (async flushCallback)
18
+ if (result instanceof Promise) {
19
+ result.catch(error => {
20
+ console.error('Error in BatchAggregator flush callback:', error);
21
+ });
22
+ }
23
+ }
24
+ }
25
+ flush() {
26
+ if (this.logs.length > 0) {
27
+ const logsToFlush = [...this.logs];
28
+ this.logs = [];
29
+ return this.flushCallback(logsToFlush);
30
+ }
31
+ }
32
+ }
33
+ exports.BatchAggregator = BatchAggregator;
34
+ /**
35
+ * Aggregates logs based on a time interval
36
+ */
37
+ class TimeBasedAggregator {
38
+ constructor(flushInterval, // in milliseconds
39
+ flushCallback) {
40
+ this.logs = [];
41
+ this.timer = null;
42
+ this.flushInterval = flushInterval;
43
+ this.flushCallback = flushCallback;
44
+ }
45
+ aggregate(logData, formatter) {
46
+ this.logs.push({ logData, formatter });
47
+ // Start the timer if it's not already running
48
+ if (!this.timer) {
49
+ this.timer = setTimeout(() => {
50
+ const result = this.flush();
51
+ // Handle the case where flush returns a Promise (async flushCallback)
52
+ if (result instanceof Promise) {
53
+ result.catch(error => {
54
+ console.error('Error in TimeBasedAggregator flush callback:', error);
55
+ });
56
+ }
57
+ }, this.flushInterval);
58
+ }
59
+ }
60
+ flush() {
61
+ if (this.logs.length > 0) {
62
+ // Clear the timer if it exists
63
+ if (this.timer) {
64
+ clearTimeout(this.timer);
65
+ this.timer = null;
66
+ }
67
+ const logsToFlush = [...this.logs];
68
+ this.logs = [];
69
+ return this.flushCallback(logsToFlush);
70
+ }
71
+ }
72
+ /**
73
+ * Stop the aggregator and cancel any pending timer without flushing
74
+ */
75
+ stop() {
76
+ if (this.timer) {
77
+ clearTimeout(this.timer);
78
+ this.timer = null;
79
+ }
80
+ }
81
+ }
82
+ exports.TimeBasedAggregator = TimeBasedAggregator;
83
+ /**
84
+ * Combines multiple aggregators
85
+ */
86
+ class CompositeAggregator {
87
+ constructor(aggregators) {
88
+ this.aggregators = aggregators;
89
+ }
90
+ aggregate(logData, formatter) {
91
+ for (const aggregator of this.aggregators) {
92
+ aggregator.aggregate(logData, formatter);
93
+ }
94
+ }
95
+ flush() {
96
+ const results = [];
97
+ for (const aggregator of this.aggregators) {
98
+ const result = aggregator.flush();
99
+ if (result) {
100
+ results.push(result);
101
+ }
102
+ }
103
+ // If any aggregator returns a promise, wait for all of them
104
+ if (results.some(r => r instanceof Promise)) {
105
+ const promiseResults = results.filter(r => r instanceof Promise);
106
+ return Promise.all(promiseResults).then(() => { });
107
+ }
108
+ }
109
+ }
110
+ exports.CompositeAggregator = CompositeAggregator;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./LogAggregator.js"), exports);
@@ -3,14 +3,20 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Logger = void 0;
4
4
  const Formatter_js_1 = require("./Formatter.js");
5
5
  const ConsoleTransport_js_1 = require("../transports/ConsoleTransport.js");
6
+ const StructuredExtensions_js_1 = require("../structured/StructuredExtensions.js");
6
7
  class Logger {
7
8
  constructor(options = {}) {
8
9
  this.transports = [];
9
- const { level, colorize, json, transports = [], timestampFormat = "YYYY-MM-DD HH:mm:ss", prefix, timestamp, context = {}, parent, asyncMode, customLevels = {}, customColors = {}, } = options;
10
+ this.filters = [];
11
+ this.aggregators = [];
12
+ const { level, colorize, json, transports = [], timestampFormat = "YYYY-MM-DD HH:mm:ss", prefix, timestamp, context = {}, parent, asyncMode, customLevels = {}, customColors = {}, filters = [], aggregators = [], enrichers, } = options;
10
13
  this.parent = parent; // Set parent
11
14
  this.context = { ...context }; // Init context
12
15
  this.customLevels = customLevels; // custom log store
13
16
  this.asyncMode = false;
17
+ this.filters = [...filters]; // Copy filters
18
+ this.aggregators = [...aggregators]; // Copy aggregators
19
+ this.enrichers = enrichers ?? new StructuredExtensions_js_1.LogEnrichmentPipeline(); // Set enrichers, default to new instance
14
20
  if (this.parent) {
15
21
  this.level = level ?? this.parent.level;
16
22
  this.prefix = prefix ?? this.parent.prefix;
@@ -36,6 +42,21 @@ class Logger {
36
42
  this.context = { ...this.parent.context, ...this.context };
37
43
  // Merge custom levels with parent's custom levels
38
44
  this.customLevels = { ...this.parent.customLevels, ...customLevels };
45
+ // Merge filters with parent's filters
46
+ this.filters = [...this.parent.filters, ...filters];
47
+ // Merge aggregators with parent's aggregators
48
+ this.aggregators = [...this.parent.aggregators, ...aggregators];
49
+ // If child logger doesn't provide its own enrichers, use parent's
50
+ // If child logger provides enrichers, merge parent and child enrichers
51
+ if (enrichers) {
52
+ // Create a new pipeline that combines parent and child enrichers
53
+ const parentEnrichers = this.parent.enrichers.getEnrichers();
54
+ const childEnrichers = enrichers.getEnrichers();
55
+ this.enrichers = new StructuredExtensions_js_1.LogEnrichmentPipeline([...parentEnrichers, ...childEnrichers]);
56
+ }
57
+ else {
58
+ this.enrichers = this.parent.enrichers;
59
+ }
39
60
  }
40
61
  else {
41
62
  // Auto-configure based on environment
@@ -140,7 +161,7 @@ class Logger {
140
161
  finalMetadata = metadata;
141
162
  }
142
163
  // Only add metadata if it's not empty after merging
143
- const logData = {
164
+ let logData = {
144
165
  level,
145
166
  message,
146
167
  timestamp,
@@ -149,6 +170,17 @@ class Logger {
149
170
  : undefined,
150
171
  prefix: this.prefix,
151
172
  };
173
+ // Apply enrichers to the log data
174
+ logData = this.enrichers.process(logData);
175
+ // Check if the log should be emitted based on filters
176
+ // Use a copy to prevent concurrent modification issues if filters are modified during logging
177
+ const currentFilters = [...this.filters];
178
+ if (currentFilters.length > 0) {
179
+ const shouldEmit = currentFilters.every(filter => filter.shouldEmit(logData));
180
+ if (!shouldEmit) {
181
+ return; // Don't emit if any filter rejects the log
182
+ }
183
+ }
152
184
  if (this.asyncMode) {
153
185
  for (const transport of this.transports) {
154
186
  if (transport.writeAsync) {
@@ -168,6 +200,17 @@ class Logger {
168
200
  transport.write(logData, this.formatter);
169
201
  }
170
202
  }
203
+ // Send to aggregators if any exist
204
+ if (this.aggregators.length > 0) {
205
+ for (const aggregator of this.aggregators) {
206
+ try {
207
+ aggregator.aggregate(logData, this.formatter);
208
+ }
209
+ catch (error) {
210
+ console.error('Error in aggregator:', error);
211
+ }
212
+ }
213
+ }
171
214
  }
172
215
  debug(message, metadata) {
173
216
  this.log("debug", message, metadata);
@@ -221,6 +264,67 @@ class Logger {
221
264
  const { Timer } = require("../utils/Timerutil");
222
265
  return new Timer(name, (message) => this.info(message));
223
266
  }
267
+ /**
268
+ * Add a filter to the logger
269
+ */
270
+ addFilter(filter) {
271
+ this.filters.push(filter);
272
+ }
273
+ /**
274
+ * Remove a filter from the logger
275
+ */
276
+ removeFilter(filter) {
277
+ const index = this.filters.indexOf(filter);
278
+ if (index !== -1) {
279
+ this.filters.splice(index, 1);
280
+ return true;
281
+ }
282
+ return false;
283
+ }
284
+ /**
285
+ * Add an aggregator to the logger
286
+ */
287
+ addAggregator(aggregator) {
288
+ this.aggregators.push(aggregator);
289
+ }
290
+ /**
291
+ * Remove an aggregator from the logger
292
+ */
293
+ removeAggregator(aggregator) {
294
+ const index = this.aggregators.indexOf(aggregator);
295
+ if (index !== -1) {
296
+ this.aggregators.splice(index, 1);
297
+ return true;
298
+ }
299
+ return false;
300
+ }
301
+ /**
302
+ * Add an enricher to the logger
303
+ */
304
+ addEnricher(enricher) {
305
+ this.enrichers.add(enricher);
306
+ }
307
+ /**
308
+ * Flush all aggregators
309
+ */
310
+ async flushAggregators() {
311
+ const flushPromises = [];
312
+ for (const aggregator of this.aggregators) {
313
+ try {
314
+ const result = aggregator.flush();
315
+ if (result instanceof Promise) {
316
+ // Wrap the promise to catch and log rejections, so one failure doesn't stop others
317
+ flushPromises.push(result.catch(error => {
318
+ console.error('Error flushing aggregator:', error);
319
+ }));
320
+ }
321
+ }
322
+ catch (error) {
323
+ console.error('Error flushing aggregator:', error);
324
+ }
325
+ }
326
+ await Promise.all(flushPromises);
327
+ }
224
328
  }
225
329
  exports.Logger = Logger;
226
330
  Logger.defaultTransportsFactory = null;
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PredicateFilter = exports.NotFilter = exports.OrFilter = exports.CompositeFilter = void 0;
4
+ /**
5
+ * A filter that combines multiple filters with AND logic
6
+ * Note: With an empty array of filters, this returns true (allows all logs).
7
+ * This follows the mathematical concept of vacuous truth - "all" conditions
8
+ * are satisfied when there are no conditions to check.
9
+ */
10
+ class CompositeFilter {
11
+ constructor(filters) {
12
+ this.filters = filters;
13
+ }
14
+ shouldEmit(logData) {
15
+ return this.filters.every(filter => filter.shouldEmit(logData));
16
+ }
17
+ }
18
+ exports.CompositeFilter = CompositeFilter;
19
+ /**
20
+ * A filter that combines multiple filters with OR logic
21
+ * Note: With an empty array of filters, this returns false (blocks all logs).
22
+ * This is because there are no matching conditions when the filter array is empty.
23
+ */
24
+ class OrFilter {
25
+ constructor(filters) {
26
+ this.filters = filters;
27
+ }
28
+ shouldEmit(logData) {
29
+ return this.filters.some(filter => filter.shouldEmit(logData));
30
+ }
31
+ }
32
+ exports.OrFilter = OrFilter;
33
+ /**
34
+ * A filter that negates another filter
35
+ */
36
+ class NotFilter {
37
+ constructor(filter) {
38
+ this.filter = filter;
39
+ }
40
+ shouldEmit(logData) {
41
+ return !this.filter.shouldEmit(logData);
42
+ }
43
+ }
44
+ exports.NotFilter = NotFilter;
45
+ /**
46
+ * A filter based on a predicate function
47
+ */
48
+ class PredicateFilter {
49
+ constructor(predicate) {
50
+ this.predicate = predicate;
51
+ }
52
+ shouldEmit(logData) {
53
+ return this.predicate(logData);
54
+ }
55
+ }
56
+ exports.PredicateFilter = PredicateFilter;
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FieldFilter = exports.MetadataFilter = exports.PrefixFilter = exports.LevelFilter = void 0;
4
+ /**
5
+ * A filter that allows logs based on their log level
6
+ */
7
+ class LevelFilter {
8
+ constructor(allowedLevels) {
9
+ this.allowedLevels = new Set(allowedLevels);
10
+ }
11
+ shouldEmit(logData) {
12
+ return this.allowedLevels.has(logData.level);
13
+ }
14
+ }
15
+ exports.LevelFilter = LevelFilter;
16
+ /**
17
+ * A filter that allows logs based on their prefix/namespace
18
+ */
19
+ class PrefixFilter {
20
+ constructor(allowedPrefixes) {
21
+ this.allowedPrefixes = new Set(allowedPrefixes);
22
+ }
23
+ shouldEmit(logData) {
24
+ if (!logData.prefix) {
25
+ // If no prefix exists, only allow if empty string is in allowed prefixes
26
+ return this.allowedPrefixes.has('');
27
+ }
28
+ return this.allowedPrefixes.has(logData.prefix);
29
+ }
30
+ }
31
+ exports.PrefixFilter = PrefixFilter;
32
+ /**
33
+ * A filter that allows logs based on specific metadata fields
34
+ * Note: Uses strict equality (===) for comparison, which means objects and arrays
35
+ * will only match if they are the same reference. For deep comparison of complex
36
+ * values, consider implementing a custom filter.
37
+ */
38
+ class MetadataFilter {
39
+ constructor(requiredMetadata) {
40
+ this.requiredMetadata = requiredMetadata;
41
+ }
42
+ shouldEmit(logData) {
43
+ if (!logData.metadata) {
44
+ // If no metadata exists but we require some, return false
45
+ return Object.keys(this.requiredMetadata).length === 0;
46
+ }
47
+ for (const [key, value] of Object.entries(this.requiredMetadata)) {
48
+ if (logData.metadata[key] !== value) {
49
+ return false;
50
+ }
51
+ }
52
+ return true;
53
+ }
54
+ }
55
+ exports.MetadataFilter = MetadataFilter;
56
+ /**
57
+ * A filter that allows logs based on a custom field in metadata
58
+ */
59
+ class FieldFilter {
60
+ constructor(fieldName, expectedValue) {
61
+ this.fieldName = fieldName;
62
+ this.expectedValue = expectedValue;
63
+ }
64
+ shouldEmit(logData) {
65
+ if (!logData.metadata) {
66
+ return false;
67
+ }
68
+ return logData.metadata[this.fieldName] === this.expectedValue;
69
+ }
70
+ }
71
+ exports.FieldFilter = FieldFilter;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./Filter.js"), exports);
18
+ __exportStar(require("./SpecificFilters.js"), exports);
package/dist/cjs/index.js CHANGED
@@ -1,12 +1,29 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.HttpTransport = exports.FileTransport = exports.ConsoleTransport = exports.Logger = void 0;
3
+ exports.LogEnrichmentPipeline = exports.MetadataEnricher = exports.CompositeAggregator = exports.TimeBasedAggregator = exports.BatchAggregator = exports.FieldFilter = exports.MetadataFilter = exports.PrefixFilter = exports.LevelFilter = exports.PredicateFilter = exports.NotFilter = exports.OrFilter = exports.CompositeFilter = exports.FilterableTransport = exports.HttpTransport = exports.FileTransport = exports.ConsoleTransport = exports.Logger = void 0;
4
4
  const Logger_js_1 = require("./core/Logger.js");
5
5
  Object.defineProperty(exports, "Logger", { enumerable: true, get: function () { return Logger_js_1.Logger; } });
6
6
  const index_js_1 = require("./transports/index.js");
7
7
  Object.defineProperty(exports, "ConsoleTransport", { enumerable: true, get: function () { return index_js_1.ConsoleTransport; } });
8
8
  Object.defineProperty(exports, "FileTransport", { enumerable: true, get: function () { return index_js_1.FileTransport; } });
9
9
  Object.defineProperty(exports, "HttpTransport", { enumerable: true, get: function () { return index_js_1.HttpTransport; } });
10
+ Object.defineProperty(exports, "FilterableTransport", { enumerable: true, get: function () { return index_js_1.FilterableTransport; } });
11
+ const index_js_2 = require("./filters/index.js");
12
+ Object.defineProperty(exports, "CompositeFilter", { enumerable: true, get: function () { return index_js_2.CompositeFilter; } });
13
+ Object.defineProperty(exports, "OrFilter", { enumerable: true, get: function () { return index_js_2.OrFilter; } });
14
+ Object.defineProperty(exports, "NotFilter", { enumerable: true, get: function () { return index_js_2.NotFilter; } });
15
+ Object.defineProperty(exports, "PredicateFilter", { enumerable: true, get: function () { return index_js_2.PredicateFilter; } });
16
+ Object.defineProperty(exports, "LevelFilter", { enumerable: true, get: function () { return index_js_2.LevelFilter; } });
17
+ Object.defineProperty(exports, "PrefixFilter", { enumerable: true, get: function () { return index_js_2.PrefixFilter; } });
18
+ Object.defineProperty(exports, "MetadataFilter", { enumerable: true, get: function () { return index_js_2.MetadataFilter; } });
19
+ Object.defineProperty(exports, "FieldFilter", { enumerable: true, get: function () { return index_js_2.FieldFilter; } });
20
+ const index_js_3 = require("./aggregation/index.js");
21
+ Object.defineProperty(exports, "BatchAggregator", { enumerable: true, get: function () { return index_js_3.BatchAggregator; } });
22
+ Object.defineProperty(exports, "TimeBasedAggregator", { enumerable: true, get: function () { return index_js_3.TimeBasedAggregator; } });
23
+ Object.defineProperty(exports, "CompositeAggregator", { enumerable: true, get: function () { return index_js_3.CompositeAggregator; } });
24
+ const index_js_4 = require("./structured/index.js");
25
+ Object.defineProperty(exports, "MetadataEnricher", { enumerable: true, get: function () { return index_js_4.MetadataEnricher; } });
26
+ Object.defineProperty(exports, "LogEnrichmentPipeline", { enumerable: true, get: function () { return index_js_4.LogEnrichmentPipeline; } });
10
27
  // Configure default transports to maintain backward compatibility
11
28
  Logger_js_1.Logger.defaultTransportsFactory = (isProd) => {
12
29
  if (isProd) {