@rawnodes/logger 2.10.0 → 2.12.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/dist/index.d.mts CHANGED
@@ -218,20 +218,24 @@ declare class TelegramTransport extends BaseHttpTransport {
218
218
  declare class CloudWatchTransport extends BaseHttpTransport {
219
219
  private config;
220
220
  private client;
221
- private sequenceToken;
222
221
  private initialized;
223
222
  private initPromise;
223
+ private initFailures;
224
+ private nextInitAttempt;
224
225
  private resolvedLogStreamName;
225
226
  private maskReplacer;
227
+ private static readonly INIT_BACKOFF_BASE_MS;
228
+ private static readonly INIT_BACKOFF_MAX_MS;
226
229
  constructor(config: CloudWatchConfig, configHostname?: string, maskReplacerFn?: MaskReplacer);
227
230
  protected sendBatch(messages: BufferedMessage[]): Promise<void>;
231
+ private putLogEvents;
228
232
  private ensureInitialized;
229
233
  private initialize;
230
234
  private createLogGroupIfNotExists;
231
235
  private createLogStreamIfNotExists;
232
- private fetchSequenceToken;
233
236
  private isResourceAlreadyExistsError;
234
- private isInvalidSequenceTokenError;
237
+ private isResourceNotFoundError;
238
+ private isAwsErrorNamed;
235
239
  }
236
240
 
237
241
  declare class ZohoCliqTransport extends BaseHttpTransport {
@@ -313,6 +317,12 @@ interface HttpErrorData {
313
317
  url?: string;
314
318
  /** HTTP method (GET, POST, etc.) */
315
319
  method?: string;
320
+ /** Request query params */
321
+ params?: unknown;
322
+ /** Request body */
323
+ requestData?: unknown;
324
+ /** Request headers */
325
+ requestHeaders?: unknown;
316
326
  /** Error code (e.g., ECONNREFUSED, ETIMEDOUT) */
317
327
  code?: string;
318
328
  }
package/dist/index.d.ts CHANGED
@@ -218,20 +218,24 @@ declare class TelegramTransport extends BaseHttpTransport {
218
218
  declare class CloudWatchTransport extends BaseHttpTransport {
219
219
  private config;
220
220
  private client;
221
- private sequenceToken;
222
221
  private initialized;
223
222
  private initPromise;
223
+ private initFailures;
224
+ private nextInitAttempt;
224
225
  private resolvedLogStreamName;
225
226
  private maskReplacer;
227
+ private static readonly INIT_BACKOFF_BASE_MS;
228
+ private static readonly INIT_BACKOFF_MAX_MS;
226
229
  constructor(config: CloudWatchConfig, configHostname?: string, maskReplacerFn?: MaskReplacer);
227
230
  protected sendBatch(messages: BufferedMessage[]): Promise<void>;
231
+ private putLogEvents;
228
232
  private ensureInitialized;
229
233
  private initialize;
230
234
  private createLogGroupIfNotExists;
231
235
  private createLogStreamIfNotExists;
232
- private fetchSequenceToken;
233
236
  private isResourceAlreadyExistsError;
234
- private isInvalidSequenceTokenError;
237
+ private isResourceNotFoundError;
238
+ private isAwsErrorNamed;
235
239
  }
236
240
 
237
241
  declare class ZohoCliqTransport extends BaseHttpTransport {
@@ -313,6 +317,12 @@ interface HttpErrorData {
313
317
  url?: string;
314
318
  /** HTTP method (GET, POST, etc.) */
315
319
  method?: string;
320
+ /** Request query params */
321
+ params?: unknown;
322
+ /** Request body */
323
+ requestData?: unknown;
324
+ /** Request headers */
325
+ requestHeaders?: unknown;
316
326
  /** Error code (e.g., ECONNREFUSED, ETIMEDOUT) */
317
327
  code?: string;
318
328
  }
package/dist/index.js CHANGED
@@ -651,14 +651,21 @@ function resolveLogStreamName(config, configHostname) {
651
651
  }
652
652
  return hostname;
653
653
  }
654
- var CloudWatchTransport = class extends BaseHttpTransport {
654
+ var CloudWatchTransport = class _CloudWatchTransport extends BaseHttpTransport {
655
655
  config;
656
656
  client;
657
- sequenceToken;
658
657
  initialized = false;
659
658
  initPromise = null;
659
+ initFailures = 0;
660
+ nextInitAttempt = 0;
660
661
  resolvedLogStreamName;
661
662
  maskReplacer;
663
+ // Backoff bounds for repeated init failures (e.g. IAM not yet propagated,
664
+ // throttling). Without this, a sustained outage makes every flush re-run
665
+ // initialize() back-to-back and hammer the CloudWatch control-plane APIs,
666
+ // which only deepens the throttling.
667
+ static INIT_BACKOFF_BASE_MS = 1e3;
668
+ static INIT_BACKOFF_MAX_MS = 3e4;
662
669
  constructor(config, configHostname, maskReplacerFn) {
663
670
  super({
664
671
  batchSize: config.batchSize ?? 100,
@@ -694,36 +701,46 @@ var CloudWatchTransport = class extends BaseHttpTransport {
694
701
  }, replacer)
695
702
  }));
696
703
  logEvents.sort((a, b) => (a.timestamp ?? 0) - (b.timestamp ?? 0));
697
- const command = new clientCloudwatchLogs.PutLogEventsCommand({
698
- logGroupName: this.config.logGroupName,
699
- logStreamName: this.resolvedLogStreamName,
700
- logEvents,
701
- sequenceToken: this.sequenceToken
702
- });
703
704
  try {
704
- const response = await this.client.send(command);
705
- this.sequenceToken = response.nextSequenceToken;
705
+ await this.putLogEvents(logEvents);
706
706
  } catch (error) {
707
- if (this.isInvalidSequenceTokenError(error)) {
708
- await this.fetchSequenceToken();
709
- const retryCommand = new clientCloudwatchLogs.PutLogEventsCommand({
710
- logGroupName: this.config.logGroupName,
711
- logStreamName: this.resolvedLogStreamName,
712
- logEvents,
713
- sequenceToken: this.sequenceToken
714
- });
715
- const response = await this.client.send(retryCommand);
716
- this.sequenceToken = response.nextSequenceToken;
707
+ if (this.isResourceNotFoundError(error)) {
708
+ this.initialized = false;
709
+ this.initPromise = null;
710
+ await this.ensureInitialized();
711
+ await this.putLogEvents(logEvents);
717
712
  } else {
718
713
  throw error;
719
714
  }
720
715
  }
721
716
  }
717
+ // PutLogEvents no longer requires a sequence token: since 2023 CloudWatch
718
+ // Logs ignores the `sequenceToken` field for sequential writes, so we omit it
719
+ // entirely. This also removes the need for DescribeLogStreams (and the
720
+ // logs:DescribeLogStreams IAM permission) on the hot path.
721
+ async putLogEvents(logEvents) {
722
+ await this.client.send(
723
+ new clientCloudwatchLogs.PutLogEventsCommand({
724
+ logGroupName: this.config.logGroupName,
725
+ logStreamName: this.resolvedLogStreamName,
726
+ logEvents
727
+ })
728
+ );
729
+ }
722
730
  async ensureInitialized() {
723
731
  if (this.initialized) return;
732
+ if (!this.initPromise && Date.now() < this.nextInitAttempt) {
733
+ throw new Error("CloudWatch transport initialization is backing off");
734
+ }
724
735
  if (!this.initPromise) {
725
736
  this.initPromise = this.initialize().catch((err) => {
726
737
  this.initPromise = null;
738
+ this.initFailures += 1;
739
+ const delay = Math.min(
740
+ _CloudWatchTransport.INIT_BACKOFF_MAX_MS,
741
+ _CloudWatchTransport.INIT_BACKOFF_BASE_MS * 2 ** (this.initFailures - 1)
742
+ );
743
+ this.nextInitAttempt = Date.now() + delay;
727
744
  throw err;
728
745
  });
729
746
  }
@@ -736,8 +753,9 @@ var CloudWatchTransport = class extends BaseHttpTransport {
736
753
  if (this.config.createLogStream !== false) {
737
754
  await this.createLogStreamIfNotExists();
738
755
  }
739
- await this.fetchSequenceToken();
740
756
  this.initialized = true;
757
+ this.initFailures = 0;
758
+ this.nextInitAttempt = 0;
741
759
  }
742
760
  async createLogGroupIfNotExists() {
743
761
  try {
@@ -766,22 +784,14 @@ var CloudWatchTransport = class extends BaseHttpTransport {
766
784
  }
767
785
  }
768
786
  }
769
- async fetchSequenceToken() {
770
- const response = await this.client.send(
771
- new clientCloudwatchLogs.DescribeLogStreamsCommand({
772
- logGroupName: this.config.logGroupName,
773
- logStreamNamePrefix: this.resolvedLogStreamName,
774
- limit: 1
775
- })
776
- );
777
- const stream = response.logStreams?.find((s) => s.logStreamName === this.resolvedLogStreamName);
778
- this.sequenceToken = stream?.uploadSequenceToken;
779
- }
780
787
  isResourceAlreadyExistsError(error) {
781
- return typeof error === "object" && error !== null && "name" in error && error.name === "ResourceAlreadyExistsException";
788
+ return this.isAwsErrorNamed(error, "ResourceAlreadyExistsException");
789
+ }
790
+ isResourceNotFoundError(error) {
791
+ return this.isAwsErrorNamed(error, "ResourceNotFoundException");
782
792
  }
783
- isInvalidSequenceTokenError(error) {
784
- return typeof error === "object" && error !== null && "name" in error && error.name === "InvalidSequenceTokenException";
793
+ isAwsErrorNamed(error, name) {
794
+ return typeof error === "object" && error !== null && "name" in error && error.name === name;
785
795
  }
786
796
  };
787
797
 
@@ -1688,13 +1698,22 @@ function extractAxiosHttpData(error) {
1688
1698
  }
1689
1699
  }
1690
1700
  if (error.config) {
1691
- const { url, baseURL, method } = error.config;
1701
+ const { url, baseURL, method, params, data, headers } = error.config;
1692
1702
  if (url) {
1693
1703
  httpData.url = baseURL && !url.startsWith("http") ? `${baseURL}${url}` : url;
1694
1704
  }
1695
1705
  if (method) {
1696
1706
  httpData.method = method.toUpperCase();
1697
1707
  }
1708
+ if (params !== void 0) {
1709
+ httpData.params = sanitizeResponseData(params);
1710
+ }
1711
+ if (data !== void 0) {
1712
+ httpData.requestData = sanitizeResponseData(data);
1713
+ }
1714
+ if (headers !== void 0) {
1715
+ httpData.requestHeaders = sanitizeResponseData(headers);
1716
+ }
1698
1717
  }
1699
1718
  return httpData;
1700
1719
  }
@@ -1732,6 +1751,18 @@ function extractGenericHttpData(error) {
1732
1751
  httpData.method = config.method.toUpperCase();
1733
1752
  hasData = true;
1734
1753
  }
1754
+ if (config.params !== void 0) {
1755
+ httpData.params = sanitizeResponseData(config.params);
1756
+ hasData = true;
1757
+ }
1758
+ if (config.data !== void 0) {
1759
+ httpData.requestData = sanitizeResponseData(config.data);
1760
+ hasData = true;
1761
+ }
1762
+ if (config.headers !== void 0) {
1763
+ httpData.requestHeaders = sanitizeResponseData(config.headers);
1764
+ hasData = true;
1765
+ }
1735
1766
  }
1736
1767
  return hasData ? httpData : void 0;
1737
1768
  }