@rawnodes/logger 2.4.0 → 2.5.0

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
@@ -272,7 +272,6 @@ const logger = Logger.create({
272
272
  console: { format: 'plain' },
273
273
  cloudwatch: {
274
274
  logGroupName: '/app/my-service',
275
- logStreamName: `${hostname}-${Date.now()}`,
276
275
  region: 'us-east-1',
277
276
  accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
278
277
  secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
@@ -284,6 +283,91 @@ const logger = Logger.create({
284
283
  });
285
284
  ```
286
285
 
286
+ #### Log Stream Name
287
+
288
+ The `logStreamName` field is optional and supports multiple configuration formats:
289
+
290
+ ```typescript
291
+ // Option 1: Static string
292
+ cloudwatch: {
293
+ logGroupName: '/app/my-service',
294
+ logStreamName: 'my-static-stream',
295
+ // ...
296
+ }
297
+
298
+ // Option 2: Predefined pattern
299
+ cloudwatch: {
300
+ logGroupName: '/app/my-service',
301
+ logStreamName: { pattern: 'hostname-date' },
302
+ // ...
303
+ }
304
+
305
+ // Option 3: Custom template
306
+ cloudwatch: {
307
+ logGroupName: '/app/my-service',
308
+ logStreamName: { template: '{hostname}/{env}/{date}' },
309
+ // ...
310
+ }
311
+
312
+ // Option 4: Omit for default (hostname)
313
+ cloudwatch: {
314
+ logGroupName: '/app/my-service',
315
+ // logStreamName defaults to hostname
316
+ // ...
317
+ }
318
+ ```
319
+
320
+ **Available patterns:**
321
+
322
+ | Pattern | Example Output |
323
+ |---------|----------------|
324
+ | `hostname` | `my-server` |
325
+ | `hostname-date` | `my-server/2025-01-15` |
326
+ | `hostname-uuid` | `my-server-a1b2c3d4` |
327
+ | `date` | `2025-01-15` |
328
+ | `uuid` | `a1b2c3d4-e5f6-7890-abcd` |
329
+
330
+ **Template variables:**
331
+
332
+ | Variable | Description |
333
+ |----------|-------------|
334
+ | `{hostname}` | Server hostname (config.hostname → HOSTNAME env → os.hostname()) |
335
+ | `{date}` | Current date (YYYY-MM-DD) |
336
+ | `{datetime}` | Current datetime (YYYY-MM-DD-HH-mm-ss) |
337
+ | `{uuid}` | 8-char UUID (generated once at startup) |
338
+ | `{pid}` | Process ID |
339
+ | `{env}` | NODE_ENV (default: "development") |
340
+
341
+ **Hostname resolution priority:**
342
+ 1. `config.hostname` (from logger config)
343
+ 2. `process.env.HOSTNAME` (useful in Docker/Kubernetes)
344
+ 3. `os.hostname()`
345
+
346
+ **Examples:**
347
+
348
+ ```typescript
349
+ // Kubernetes-friendly: pod name as stream
350
+ cloudwatch: {
351
+ logGroupName: '/app/my-service/production',
352
+ logStreamName: { pattern: 'hostname' }, // -> "my-app-pod-abc123"
353
+ // ...
354
+ }
355
+
356
+ // Daily rotation with hostname
357
+ cloudwatch: {
358
+ logGroupName: '/app/my-service',
359
+ logStreamName: { pattern: 'hostname-date' }, // -> "my-server/2025-01-15"
360
+ // ...
361
+ }
362
+
363
+ // Custom format with environment
364
+ cloudwatch: {
365
+ logGroupName: '/app/my-service',
366
+ logStreamName: { template: '{env}/{hostname}/{date}' }, // -> "production/my-server/2025-01-15"
367
+ // ...
368
+ }
369
+ ```
370
+
287
371
  ### Transport Options
288
372
 
289
373
  All external transports support:
package/dist/index.d.mts CHANGED
@@ -64,9 +64,19 @@ interface TelegramConfig extends HttpTransportBaseConfig {
64
64
  threadId?: number;
65
65
  replyToMessageId?: number;
66
66
  }
67
+ type LogStreamPattern = 'hostname' | 'hostname-date' | 'hostname-uuid' | 'date' | 'uuid';
68
+ interface LogStreamPatternConfig {
69
+ pattern: LogStreamPattern;
70
+ }
71
+ interface LogStreamTemplateConfig {
72
+ /** Custom template with variables: {hostname}, {date}, {datetime}, {uuid}, {pid}, {env} */
73
+ template: string;
74
+ }
75
+ type LogStreamName = string | LogStreamPatternConfig | LogStreamTemplateConfig;
67
76
  interface CloudWatchConfig extends HttpTransportBaseConfig {
68
77
  logGroupName: string;
69
- logStreamName: string;
78
+ /** Log stream name - string, pattern config, or template config. Defaults to hostname pattern */
79
+ logStreamName?: LogStreamName;
70
80
  region: string;
71
81
  accessKeyId: string;
72
82
  secretAccessKey: string;
@@ -240,7 +250,8 @@ declare class CloudWatchTransport extends BaseHttpTransport {
240
250
  private sequenceToken;
241
251
  private initialized;
242
252
  private initPromise;
243
- constructor(config: CloudWatchConfig);
253
+ private resolvedLogStreamName;
254
+ constructor(config: CloudWatchConfig, configHostname?: string);
244
255
  protected sendBatch(messages: BufferedMessage[]): Promise<void>;
245
256
  private ensureInitialized;
246
257
  private initialize;
@@ -296,6 +307,10 @@ declare const FileConfigSchema: z.ZodType<FileConfig>;
296
307
  declare const HttpTransportBaseConfigSchema: z.ZodType<HttpTransportBaseConfig>;
297
308
  declare const DiscordConfigSchema: z.ZodType<DiscordConfig>;
298
309
  declare const TelegramConfigSchema: z.ZodType<TelegramConfig>;
310
+ declare const LogStreamPatternSchema: z.ZodType<LogStreamPattern>;
311
+ declare const LogStreamPatternConfigSchema: z.ZodType<LogStreamPatternConfig>;
312
+ declare const LogStreamTemplateConfigSchema: z.ZodType<LogStreamTemplateConfig>;
313
+ declare const LogStreamNameSchema: z.ZodType<LogStreamName>;
299
314
  declare const CloudWatchConfigSchema: z.ZodType<CloudWatchConfig>;
300
315
  declare const LevelConfigObjectSchema: z.ZodType<LevelConfigObject>;
301
316
  declare const LevelConfigSchema: z.ZodType<LevelConfig>;
@@ -322,4 +337,4 @@ declare function safeValidateConfig(config: unknown): z.ZodSafeParseResult<{
322
337
  hostname?: string | undefined;
323
338
  }>;
324
339
 
325
- export { BaseHttpTransport, type BaseHttpTransportOptions, type BufferOptions, type BufferedMessage, type CallerConfig, CallerConfigSchema, type CallerInfo, type CloudWatchConfig, CloudWatchConfigSchema, CloudWatchTransport, type ConsoleConfig, ConsoleConfigSchema, type DiscordConfig, DiscordConfigSchema, DiscordTransport, type FileConfig, FileConfigSchema, type HttpTransportBaseConfig, HttpTransportBaseConfigSchema, LOG_LEVELS, type LevelConfig, type LevelConfigObject, LevelConfigObjectSchema, LevelConfigSchema, type LevelOverride, type LevelOverrideMatch, type LevelRule, LevelRuleSchema, type LogFormat, LogFormatSchema, type LogLevel, LogLevelSchema, Logger, type LoggerConfig, LoggerConfigSchema, type LoggerContext, LoggerStore, type MaskSecretsOptions, MessageBuffer, type Meta, type RequestIdOptions, type SingletonLogger, type TelegramConfig, TelegramConfigSchema, TelegramTransport, type TimingResult, assertLogLevel, createMasker, createSingletonLogger, extractRequestId, flattenObject, formatCallerInfo, formatLogfmt, formatLogfmtValue, generateRequestId, getCallerInfo, getOrGenerateRequestId, isValidLogLevel, maskSecrets, matchesContext, measureAsync, measureSync, safeValidateConfig, validateConfig };
340
+ export { BaseHttpTransport, type BaseHttpTransportOptions, type BufferOptions, type BufferedMessage, type CallerConfig, CallerConfigSchema, type CallerInfo, type CloudWatchConfig, CloudWatchConfigSchema, CloudWatchTransport, type ConsoleConfig, ConsoleConfigSchema, type DiscordConfig, DiscordConfigSchema, DiscordTransport, type FileConfig, FileConfigSchema, type HttpTransportBaseConfig, HttpTransportBaseConfigSchema, LOG_LEVELS, type LevelConfig, type LevelConfigObject, LevelConfigObjectSchema, LevelConfigSchema, type LevelOverride, type LevelOverrideMatch, type LevelRule, LevelRuleSchema, type LogFormat, LogFormatSchema, type LogLevel, LogLevelSchema, type LogStreamName, LogStreamNameSchema, type LogStreamPattern, type LogStreamPatternConfig, LogStreamPatternConfigSchema, LogStreamPatternSchema, type LogStreamTemplateConfig, LogStreamTemplateConfigSchema, Logger, type LoggerConfig, LoggerConfigSchema, type LoggerContext, LoggerStore, type MaskSecretsOptions, MessageBuffer, type Meta, type RequestIdOptions, type SingletonLogger, type TelegramConfig, TelegramConfigSchema, TelegramTransport, type TimingResult, assertLogLevel, createMasker, createSingletonLogger, extractRequestId, flattenObject, formatCallerInfo, formatLogfmt, formatLogfmtValue, generateRequestId, getCallerInfo, getOrGenerateRequestId, isValidLogLevel, maskSecrets, matchesContext, measureAsync, measureSync, safeValidateConfig, validateConfig };
package/dist/index.d.ts CHANGED
@@ -64,9 +64,19 @@ interface TelegramConfig extends HttpTransportBaseConfig {
64
64
  threadId?: number;
65
65
  replyToMessageId?: number;
66
66
  }
67
+ type LogStreamPattern = 'hostname' | 'hostname-date' | 'hostname-uuid' | 'date' | 'uuid';
68
+ interface LogStreamPatternConfig {
69
+ pattern: LogStreamPattern;
70
+ }
71
+ interface LogStreamTemplateConfig {
72
+ /** Custom template with variables: {hostname}, {date}, {datetime}, {uuid}, {pid}, {env} */
73
+ template: string;
74
+ }
75
+ type LogStreamName = string | LogStreamPatternConfig | LogStreamTemplateConfig;
67
76
  interface CloudWatchConfig extends HttpTransportBaseConfig {
68
77
  logGroupName: string;
69
- logStreamName: string;
78
+ /** Log stream name - string, pattern config, or template config. Defaults to hostname pattern */
79
+ logStreamName?: LogStreamName;
70
80
  region: string;
71
81
  accessKeyId: string;
72
82
  secretAccessKey: string;
@@ -240,7 +250,8 @@ declare class CloudWatchTransport extends BaseHttpTransport {
240
250
  private sequenceToken;
241
251
  private initialized;
242
252
  private initPromise;
243
- constructor(config: CloudWatchConfig);
253
+ private resolvedLogStreamName;
254
+ constructor(config: CloudWatchConfig, configHostname?: string);
244
255
  protected sendBatch(messages: BufferedMessage[]): Promise<void>;
245
256
  private ensureInitialized;
246
257
  private initialize;
@@ -296,6 +307,10 @@ declare const FileConfigSchema: z.ZodType<FileConfig>;
296
307
  declare const HttpTransportBaseConfigSchema: z.ZodType<HttpTransportBaseConfig>;
297
308
  declare const DiscordConfigSchema: z.ZodType<DiscordConfig>;
298
309
  declare const TelegramConfigSchema: z.ZodType<TelegramConfig>;
310
+ declare const LogStreamPatternSchema: z.ZodType<LogStreamPattern>;
311
+ declare const LogStreamPatternConfigSchema: z.ZodType<LogStreamPatternConfig>;
312
+ declare const LogStreamTemplateConfigSchema: z.ZodType<LogStreamTemplateConfig>;
313
+ declare const LogStreamNameSchema: z.ZodType<LogStreamName>;
299
314
  declare const CloudWatchConfigSchema: z.ZodType<CloudWatchConfig>;
300
315
  declare const LevelConfigObjectSchema: z.ZodType<LevelConfigObject>;
301
316
  declare const LevelConfigSchema: z.ZodType<LevelConfig>;
@@ -322,4 +337,4 @@ declare function safeValidateConfig(config: unknown): z.ZodSafeParseResult<{
322
337
  hostname?: string | undefined;
323
338
  }>;
324
339
 
325
- export { BaseHttpTransport, type BaseHttpTransportOptions, type BufferOptions, type BufferedMessage, type CallerConfig, CallerConfigSchema, type CallerInfo, type CloudWatchConfig, CloudWatchConfigSchema, CloudWatchTransport, type ConsoleConfig, ConsoleConfigSchema, type DiscordConfig, DiscordConfigSchema, DiscordTransport, type FileConfig, FileConfigSchema, type HttpTransportBaseConfig, HttpTransportBaseConfigSchema, LOG_LEVELS, type LevelConfig, type LevelConfigObject, LevelConfigObjectSchema, LevelConfigSchema, type LevelOverride, type LevelOverrideMatch, type LevelRule, LevelRuleSchema, type LogFormat, LogFormatSchema, type LogLevel, LogLevelSchema, Logger, type LoggerConfig, LoggerConfigSchema, type LoggerContext, LoggerStore, type MaskSecretsOptions, MessageBuffer, type Meta, type RequestIdOptions, type SingletonLogger, type TelegramConfig, TelegramConfigSchema, TelegramTransport, type TimingResult, assertLogLevel, createMasker, createSingletonLogger, extractRequestId, flattenObject, formatCallerInfo, formatLogfmt, formatLogfmtValue, generateRequestId, getCallerInfo, getOrGenerateRequestId, isValidLogLevel, maskSecrets, matchesContext, measureAsync, measureSync, safeValidateConfig, validateConfig };
340
+ export { BaseHttpTransport, type BaseHttpTransportOptions, type BufferOptions, type BufferedMessage, type CallerConfig, CallerConfigSchema, type CallerInfo, type CloudWatchConfig, CloudWatchConfigSchema, CloudWatchTransport, type ConsoleConfig, ConsoleConfigSchema, type DiscordConfig, DiscordConfigSchema, DiscordTransport, type FileConfig, FileConfigSchema, type HttpTransportBaseConfig, HttpTransportBaseConfigSchema, LOG_LEVELS, type LevelConfig, type LevelConfigObject, LevelConfigObjectSchema, LevelConfigSchema, type LevelOverride, type LevelOverrideMatch, type LevelRule, LevelRuleSchema, type LogFormat, LogFormatSchema, type LogLevel, LogLevelSchema, type LogStreamName, LogStreamNameSchema, type LogStreamPattern, type LogStreamPatternConfig, LogStreamPatternConfigSchema, LogStreamPatternSchema, type LogStreamTemplateConfig, LogStreamTemplateConfigSchema, Logger, type LoggerConfig, LoggerConfigSchema, type LoggerContext, LoggerStore, type MaskSecretsOptions, MessageBuffer, type Meta, type RequestIdOptions, type SingletonLogger, type TelegramConfig, TelegramConfigSchema, TelegramTransport, type TimingResult, assertLogLevel, createMasker, createSingletonLogger, extractRequestId, flattenObject, formatCallerInfo, formatLogfmt, formatLogfmtValue, generateRequestId, getCallerInfo, getOrGenerateRequestId, isValidLogLevel, maskSecrets, matchesContext, measureAsync, measureSync, safeValidateConfig, validateConfig };
package/dist/index.js CHANGED
@@ -8,9 +8,9 @@ var promises = require('fs/promises');
8
8
  var rotatingFileStream = require('rotating-file-stream');
9
9
  var events = require('events');
10
10
  var clientCloudwatchLogs = require('@aws-sdk/client-cloudwatch-logs');
11
+ var crypto = require('crypto');
11
12
  var zod = require('zod');
12
13
  var path = require('path');
13
- var crypto = require('crypto');
14
14
 
15
15
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
16
16
 
@@ -422,13 +422,50 @@ var TelegramTransport = class extends BaseHttpTransport {
422
422
  return text.replace(/[&<>"']/g, (c) => entities[c] || c);
423
423
  }
424
424
  };
425
+ var instanceUuid = crypto.randomUUID().slice(0, 8);
426
+ function formatDate() {
427
+ return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
428
+ }
429
+ function formatDateTime() {
430
+ return (/* @__PURE__ */ new Date()).toISOString().slice(0, 19).replace(/[T:]/g, "-");
431
+ }
432
+ function resolveLogStreamName(config, configHostname) {
433
+ const hostname = configHostname || process.env.HOSTNAME || os.hostname();
434
+ if (!config) {
435
+ return hostname;
436
+ }
437
+ if (typeof config === "string") {
438
+ return config;
439
+ }
440
+ if ("pattern" in config) {
441
+ switch (config.pattern) {
442
+ case "hostname":
443
+ return hostname;
444
+ case "hostname-date":
445
+ return `${hostname}/${formatDate()}`;
446
+ case "hostname-uuid":
447
+ return `${hostname}-${instanceUuid}`;
448
+ case "date":
449
+ return formatDate();
450
+ case "uuid":
451
+ return crypto.randomUUID();
452
+ default:
453
+ return hostname;
454
+ }
455
+ }
456
+ if ("template" in config) {
457
+ return config.template.replace(/\{hostname\}/g, hostname).replace(/\{date\}/g, formatDate()).replace(/\{datetime\}/g, formatDateTime()).replace(/\{uuid\}/g, instanceUuid).replace(/\{pid\}/g, String(process.pid)).replace(/\{env\}/g, process.env.NODE_ENV || "development");
458
+ }
459
+ return hostname;
460
+ }
425
461
  var CloudWatchTransport = class extends BaseHttpTransport {
426
462
  config;
427
463
  client;
428
464
  sequenceToken;
429
465
  initialized = false;
430
466
  initPromise = null;
431
- constructor(config) {
467
+ resolvedLogStreamName;
468
+ constructor(config, configHostname) {
432
469
  super({
433
470
  batchSize: config.batchSize ?? 100,
434
471
  flushInterval: config.flushInterval ?? 1e3,
@@ -436,6 +473,7 @@ var CloudWatchTransport = class extends BaseHttpTransport {
436
473
  retryDelay: config.retryDelay
437
474
  });
438
475
  this.config = config;
476
+ this.resolvedLogStreamName = resolveLogStreamName(config.logStreamName, configHostname);
439
477
  this.client = new clientCloudwatchLogs.CloudWatchLogsClient({
440
478
  region: config.region,
441
479
  credentials: {
@@ -458,7 +496,7 @@ var CloudWatchTransport = class extends BaseHttpTransport {
458
496
  logEvents.sort((a, b) => (a.timestamp ?? 0) - (b.timestamp ?? 0));
459
497
  const command = new clientCloudwatchLogs.PutLogEventsCommand({
460
498
  logGroupName: this.config.logGroupName,
461
- logStreamName: this.config.logStreamName,
499
+ logStreamName: this.resolvedLogStreamName,
462
500
  logEvents,
463
501
  sequenceToken: this.sequenceToken
464
502
  });
@@ -470,7 +508,7 @@ var CloudWatchTransport = class extends BaseHttpTransport {
470
508
  await this.fetchSequenceToken();
471
509
  const retryCommand = new clientCloudwatchLogs.PutLogEventsCommand({
472
510
  logGroupName: this.config.logGroupName,
473
- logStreamName: this.config.logStreamName,
511
+ logStreamName: this.resolvedLogStreamName,
474
512
  logEvents,
475
513
  sequenceToken: this.sequenceToken
476
514
  });
@@ -516,7 +554,7 @@ var CloudWatchTransport = class extends BaseHttpTransport {
516
554
  await this.client.send(
517
555
  new clientCloudwatchLogs.CreateLogStreamCommand({
518
556
  logGroupName: this.config.logGroupName,
519
- logStreamName: this.config.logStreamName
557
+ logStreamName: this.resolvedLogStreamName
520
558
  })
521
559
  );
522
560
  } catch (error) {
@@ -529,11 +567,11 @@ var CloudWatchTransport = class extends BaseHttpTransport {
529
567
  const response = await this.client.send(
530
568
  new clientCloudwatchLogs.DescribeLogStreamsCommand({
531
569
  logGroupName: this.config.logGroupName,
532
- logStreamNamePrefix: this.config.logStreamName,
570
+ logStreamNamePrefix: this.resolvedLogStreamName,
533
571
  limit: 1
534
572
  })
535
573
  );
536
- const stream = response.logStreams?.find((s) => s.logStreamName === this.config.logStreamName);
574
+ const stream = response.logStreams?.find((s) => s.logStreamName === this.resolvedLogStreamName);
537
575
  this.sequenceToken = stream?.uploadSequenceToken;
538
576
  }
539
577
  isResourceAlreadyExistsError(error) {
@@ -713,7 +751,7 @@ function createStreams(config, store) {
713
751
  });
714
752
  }
715
753
  for (const cloudwatchConfig of toArray(config.cloudwatch)) {
716
- const transport = new CloudWatchTransport(cloudwatchConfig);
754
+ const transport = new CloudWatchTransport(cloudwatchConfig, config.hostname);
717
755
  const cwStream = createHttpTransportStream(transport, cloudwatchConfig.level, cloudwatchConfig.rules, store);
718
756
  streams.push({
719
757
  level: "trace",
@@ -927,6 +965,24 @@ var TelegramConfigSchema = zod.z.object({
927
965
  threadId: zod.z.number().int().optional(),
928
966
  replyToMessageId: zod.z.number().int().optional()
929
967
  });
968
+ var LogStreamPatternSchema = zod.z.enum([
969
+ "hostname",
970
+ "hostname-date",
971
+ "hostname-uuid",
972
+ "date",
973
+ "uuid"
974
+ ]);
975
+ var LogStreamPatternConfigSchema = zod.z.object({
976
+ pattern: LogStreamPatternSchema
977
+ });
978
+ var LogStreamTemplateConfigSchema = zod.z.object({
979
+ template: zod.z.string().min(1, "template is required")
980
+ });
981
+ var LogStreamNameSchema = zod.z.union([
982
+ zod.z.string().min(1, "logStreamName string must not be empty"),
983
+ LogStreamPatternConfigSchema,
984
+ LogStreamTemplateConfigSchema
985
+ ]);
930
986
  var CloudWatchConfigSchema = zod.z.object({
931
987
  level: LogLevelSchema.optional(),
932
988
  rules: zod.z.array(LevelRuleSchema).optional(),
@@ -935,7 +991,7 @@ var CloudWatchConfigSchema = zod.z.object({
935
991
  maxRetries: zod.z.number().int().nonnegative().optional(),
936
992
  retryDelay: zod.z.number().int().positive().optional(),
937
993
  logGroupName: zod.z.string().min(1, "logGroupName is required"),
938
- logStreamName: zod.z.string().min(1, "logStreamName is required"),
994
+ logStreamName: LogStreamNameSchema.optional(),
939
995
  region: zod.z.string().min(1, "region is required"),
940
996
  accessKeyId: zod.z.string().min(1, "accessKeyId is required"),
941
997
  secretAccessKey: zod.z.string().min(1, "secretAccessKey is required"),
@@ -1402,6 +1458,10 @@ exports.LevelConfigSchema = LevelConfigSchema;
1402
1458
  exports.LevelRuleSchema = LevelRuleSchema;
1403
1459
  exports.LogFormatSchema = LogFormatSchema;
1404
1460
  exports.LogLevelSchema = LogLevelSchema;
1461
+ exports.LogStreamNameSchema = LogStreamNameSchema;
1462
+ exports.LogStreamPatternConfigSchema = LogStreamPatternConfigSchema;
1463
+ exports.LogStreamPatternSchema = LogStreamPatternSchema;
1464
+ exports.LogStreamTemplateConfigSchema = LogStreamTemplateConfigSchema;
1405
1465
  exports.Logger = Logger;
1406
1466
  exports.LoggerConfigSchema = LoggerConfigSchema;
1407
1467
  exports.LoggerStore = LoggerStore;