@steve31415/log-logger-ts 1.0.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 ADDED
@@ -0,0 +1,128 @@
1
+ # @steve31415/log-logger-ts
2
+
3
+ Lightweight logging library for Cloudflare Workers and browsers with automatic batching and dual logging (console + backend).
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @steve31415/log-logger-ts
9
+ ```
10
+
11
+ ## Features
12
+
13
+ - **Dual logging**: Logs to console immediately and batches for backend delivery
14
+ - **Automatic batching**: Flushes on 10 events, 1 second timeout, or any ERROR (whichever first)
15
+ - **Timeout-based flush**: `flushWithTimeout(ms)` for Workers with `ctx.waitUntil`
16
+ - **Best-effort delivery**: `flushSync()` uses `sendBeacon` for browser page unload
17
+
18
+ ## Usage
19
+
20
+ ### Cloudflare Workers (fetch handler)
21
+
22
+ ```typescript
23
+ import { Logger, FetchDeliveryAdapter } from '@steve31415/log-logger-ts';
24
+
25
+ const INGEST_ENDPOINT = 'https://log-ingest.example.com/v1/logs:ingest';
26
+
27
+ export default {
28
+ async fetch(request, env, ctx) {
29
+ const logger = new Logger(
30
+ { app: 'my-app', context: 'worker_http' },
31
+ new FetchDeliveryAdapter(INGEST_ENDPOINT)
32
+ );
33
+
34
+ try {
35
+ logger.info('Request received', { url: request.url });
36
+ // ... handle request
37
+ return new Response('OK');
38
+ } finally {
39
+ ctx.waitUntil(logger.flushWithTimeout(3000));
40
+ }
41
+ }
42
+ }
43
+ ```
44
+
45
+ ### Cloudflare Workers (cron/queue)
46
+
47
+ ```typescript
48
+ import { Logger, FetchDeliveryAdapter } from '@steve31415/log-logger-ts';
49
+
50
+ const INGEST_ENDPOINT = 'https://log-ingest.example.com/v1/logs:ingest';
51
+
52
+ async scheduled(event, env, ctx) {
53
+ const logger = new Logger(
54
+ { app: 'my-app', context: 'worker_cron', runId: crypto.randomUUID() },
55
+ new FetchDeliveryAdapter(INGEST_ENDPOINT)
56
+ );
57
+
58
+ try {
59
+ logger.info('Cron started');
60
+ // ... do work
61
+ logger.info('Cron completed');
62
+ } finally {
63
+ await logger.flushWithTimeout(3000);
64
+ }
65
+ }
66
+ ```
67
+
68
+ ### Browser
69
+
70
+ ```typescript
71
+ import { Logger, BrowserDeliveryAdapter } from '@steve31415/log-logger-ts';
72
+
73
+ const logger = new Logger(
74
+ { app: 'my-app', context: 'web_frontend' },
75
+ new BrowserDeliveryAdapter('/api/logs')
76
+ );
77
+
78
+ // Flush on page visibility change (uses sendBeacon for reliability)
79
+ document.addEventListener('visibilitychange', () => {
80
+ if (document.visibilityState === 'hidden') {
81
+ logger.flushSync();
82
+ }
83
+ });
84
+ ```
85
+
86
+ ## API
87
+
88
+ ### Logger Options
89
+
90
+ | Option | Type | Default | Description |
91
+ |--------|------|---------|-------------|
92
+ | `app` | string | required | Application name |
93
+ | `context` | string | required | Execution context (e.g., `worker_http`, `web_frontend`) |
94
+ | `runId` | string | optional | Correlation ID for invocation/session |
95
+ | `logger` | string | optional | Module/subsystem name |
96
+ | `batchSize` | number | 10 | Max events before flush |
97
+ | `batchTimeoutMs` | number | 1000 | Max time before flush (ms) |
98
+ | `consoleLog` | boolean | true | Enable console logging |
99
+ | `minLevel` | LogLevel | 'DEBUG' | Minimum level to log |
100
+
101
+ ### Log Levels
102
+
103
+ - `logger.debug(message, meta?)` - DEBUG level
104
+ - `logger.info(message, meta?)` - INFO level
105
+ - `logger.warn(message, meta?)` - WARN level
106
+ - `logger.error(message, meta?)` - ERROR level (triggers immediate flush)
107
+
108
+ ### Child Loggers
109
+
110
+ ```typescript
111
+ const logger = new Logger({ app: 'my-app', context: 'worker_http' }, adapter);
112
+ const dbLogger = logger.child('database');
113
+ const authLogger = logger.child('auth');
114
+
115
+ dbLogger.info('Query executed'); // Logs as [my-app:database]
116
+ authLogger.warn('Token expired'); // Logs as [my-app:auth]
117
+ ```
118
+
119
+ ### Flush Methods
120
+
121
+ - `flush()` - Async flush of buffered events
122
+ - `flushWithTimeout(ms)` - Flush with timeout, falls back to `sendBeacon` if available
123
+ - `flushSync()` - Synchronous best-effort flush using `sendBeacon` (for page unload)
124
+ - `close()` - Flush and prevent further logging
125
+
126
+ ## License
127
+
128
+ MIT
@@ -0,0 +1,14 @@
1
+ import type { DeliveryAdapter, IngestPayload } from '../types';
2
+ /**
3
+ * Browser-based delivery adapter with sendBeacon fallback
4
+ */
5
+ export declare class BrowserDeliveryAdapter implements DeliveryAdapter {
6
+ private endpoint;
7
+ constructor(endpoint: string);
8
+ deliver(payload: IngestPayload): Promise<boolean>;
9
+ /**
10
+ * Best-effort delivery using sendBeacon for page unload scenarios
11
+ */
12
+ deliverBestEffort(payload: IngestPayload): boolean;
13
+ }
14
+ //# sourceMappingURL=browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../src/adapters/browser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAkB,MAAM,UAAU,CAAC;AAE/E;;GAEG;AACH,qBAAa,sBAAuB,YAAW,eAAe;IAChD,OAAO,CAAC,QAAQ;gBAAR,QAAQ,EAAE,MAAM;IAE9B,OAAO,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC;IA6BvD;;OAEG;IACH,iBAAiB,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO;CAanD"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Browser-based delivery adapter with sendBeacon fallback
3
+ */
4
+ export class BrowserDeliveryAdapter {
5
+ constructor(endpoint) {
6
+ this.endpoint = endpoint;
7
+ }
8
+ async deliver(payload) {
9
+ try {
10
+ const response = await fetch(this.endpoint, {
11
+ method: 'POST',
12
+ headers: {
13
+ 'Content-Type': 'application/json',
14
+ },
15
+ body: JSON.stringify(payload),
16
+ // keepalive allows the request to outlive the page
17
+ keepalive: true,
18
+ });
19
+ if (!response.ok) {
20
+ const text = await response.text();
21
+ console.error(`[Logger] Delivery failed: ${response.status} ${text}`);
22
+ return false;
23
+ }
24
+ const result = await response.json();
25
+ if (result.rejected > 0) {
26
+ console.warn(`[Logger] ${result.rejected} events rejected:`, result.errors);
27
+ }
28
+ return true;
29
+ }
30
+ catch (error) {
31
+ console.error('[Logger] Delivery error:', error);
32
+ return false;
33
+ }
34
+ }
35
+ /**
36
+ * Best-effort delivery using sendBeacon for page unload scenarios
37
+ */
38
+ deliverBestEffort(payload) {
39
+ if (typeof navigator !== 'undefined' && navigator.sendBeacon) {
40
+ const blob = new Blob([JSON.stringify(payload)], {
41
+ type: 'application/json',
42
+ });
43
+ const success = navigator.sendBeacon(this.endpoint, blob);
44
+ if (!success) {
45
+ console.error('[Logger] sendBeacon failed');
46
+ }
47
+ return success;
48
+ }
49
+ return false;
50
+ }
51
+ }
52
+ //# sourceMappingURL=browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.js","sourceRoot":"","sources":["../../src/adapters/browser.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,OAAO,sBAAsB;IACjC,YAAoB,QAAgB;QAAhB,aAAQ,GAAR,QAAQ,CAAQ;IAAG,CAAC;IAExC,KAAK,CAAC,OAAO,CAAC,OAAsB;QAClC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE;gBAC1C,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;iBACnC;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;gBAC7B,mDAAmD;gBACnD,SAAS,EAAE,IAAI;aAChB,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;gBACnC,OAAO,CAAC,KAAK,CAAC,6BAA6B,QAAQ,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC,CAAC;gBACtE,OAAO,KAAK,CAAC;YACf,CAAC;YAED,MAAM,MAAM,GAAmB,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACrD,IAAI,MAAM,CAAC,QAAQ,GAAG,CAAC,EAAE,CAAC;gBACxB,OAAO,CAAC,IAAI,CAAC,YAAY,MAAM,CAAC,QAAQ,mBAAmB,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;YAC9E,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,KAAK,CAAC,CAAC;YACjD,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED;;OAEG;IACH,iBAAiB,CAAC,OAAsB;QACtC,IAAI,OAAO,SAAS,KAAK,WAAW,IAAI,SAAS,CAAC,UAAU,EAAE,CAAC;YAC7D,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,EAAE;gBAC/C,IAAI,EAAE,kBAAkB;aACzB,CAAC,CAAC;YACH,MAAM,OAAO,GAAG,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YAC1D,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,OAAO,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC;YAC9C,CAAC;YACD,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;CACF"}
@@ -0,0 +1,10 @@
1
+ import type { DeliveryAdapter, IngestPayload } from '../types';
2
+ /**
3
+ * Fetch-based delivery adapter for Cloudflare Workers and Node.js environments
4
+ */
5
+ export declare class FetchDeliveryAdapter implements DeliveryAdapter {
6
+ private endpoint;
7
+ constructor(endpoint: string);
8
+ deliver(payload: IngestPayload): Promise<boolean>;
9
+ }
10
+ //# sourceMappingURL=fetch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/adapters/fetch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAkB,MAAM,UAAU,CAAC;AAE/E;;GAEG;AACH,qBAAa,oBAAqB,YAAW,eAAe;IAC9C,OAAO,CAAC,QAAQ;gBAAR,QAAQ,EAAE,MAAM;IAE9B,OAAO,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC;CA0BxD"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Fetch-based delivery adapter for Cloudflare Workers and Node.js environments
3
+ */
4
+ export class FetchDeliveryAdapter {
5
+ constructor(endpoint) {
6
+ this.endpoint = endpoint;
7
+ }
8
+ async deliver(payload) {
9
+ try {
10
+ const response = await fetch(this.endpoint, {
11
+ method: 'POST',
12
+ headers: {
13
+ 'Content-Type': 'application/json',
14
+ },
15
+ body: JSON.stringify(payload),
16
+ });
17
+ if (!response.ok) {
18
+ const text = await response.text();
19
+ console.error(`[Logger] Delivery failed: ${response.status} ${text}`);
20
+ return false;
21
+ }
22
+ const result = await response.json();
23
+ if (result.rejected > 0) {
24
+ console.warn(`[Logger] ${result.rejected} events rejected:`, result.errors);
25
+ }
26
+ return true;
27
+ }
28
+ catch (error) {
29
+ console.error('[Logger] Delivery error:', error);
30
+ return false;
31
+ }
32
+ }
33
+ }
34
+ //# sourceMappingURL=fetch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch.js","sourceRoot":"","sources":["../../src/adapters/fetch.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,OAAO,oBAAoB;IAC/B,YAAoB,QAAgB;QAAhB,aAAQ,GAAR,QAAQ,CAAQ;IAAG,CAAC;IAExC,KAAK,CAAC,OAAO,CAAC,OAAsB;QAClC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE;gBAC1C,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;iBACnC;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;aAC9B,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;gBACnC,OAAO,CAAC,KAAK,CAAC,6BAA6B,QAAQ,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC,CAAC;gBACtE,OAAO,KAAK,CAAC;YACf,CAAC;YAED,MAAM,MAAM,GAAmB,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACrD,IAAI,MAAM,CAAC,QAAQ,GAAG,CAAC,EAAE,CAAC;gBACxB,OAAO,CAAC,IAAI,CAAC,YAAY,MAAM,CAAC,QAAQ,mBAAmB,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;YAC9E,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,KAAK,CAAC,CAAC;YACjD,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,3 @@
1
+ export { FetchDeliveryAdapter } from './fetch';
2
+ export { BrowserDeliveryAdapter } from './browser';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { FetchDeliveryAdapter } from './fetch';
2
+ export { BrowserDeliveryAdapter } from './browser';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * @steve31415/log-logger-ts - Lightweight logging library for Cloudflare Workers and browsers
3
+ *
4
+ * Features:
5
+ * - Dual logging: console + backend delivery
6
+ * - Automatic batching (10 events, 1 second, or on ERROR)
7
+ * - Timeout-based flush for Workers
8
+ * - Best-effort sendBeacon for browser page unload
9
+ *
10
+ * @example Workers fetch handler
11
+ * ```typescript
12
+ * import { Logger, FetchDeliveryAdapter } from '@steve31415/log-logger-ts';
13
+ *
14
+ * const INGEST_ENDPOINT = 'https://log-ingest.example.com/v1/logs:ingest';
15
+ *
16
+ * export default {
17
+ * async fetch(request, env, ctx) {
18
+ * const logger = new Logger(
19
+ * { app: 'my-app', context: 'worker_http' },
20
+ * new FetchDeliveryAdapter(INGEST_ENDPOINT)
21
+ * );
22
+ * try {
23
+ * logger.info('Request received', { url: request.url });
24
+ * // ... handle request
25
+ * return new Response('OK');
26
+ * } finally {
27
+ * ctx.waitUntil(logger.flushWithTimeout(3000));
28
+ * }
29
+ * }
30
+ * }
31
+ * ```
32
+ *
33
+ * @example Browser
34
+ * ```typescript
35
+ * import { Logger, BrowserDeliveryAdapter } from '@steve31415/log-logger-ts';
36
+ *
37
+ * const logger = new Logger(
38
+ * { app: 'my-app', context: 'web_frontend' },
39
+ * new BrowserDeliveryAdapter('/api/logs')
40
+ * );
41
+ *
42
+ * // Flush on page unload
43
+ * document.addEventListener('visibilitychange', () => {
44
+ * if (document.visibilityState === 'hidden') {
45
+ * logger.flushSync();
46
+ * }
47
+ * });
48
+ * ```
49
+ */
50
+ export { Logger } from './logger';
51
+ export { FetchDeliveryAdapter, BrowserDeliveryAdapter } from './adapters';
52
+ export type { LogLevel, LogEvent, LoggerConfig, DeliveryAdapter, ConsoleAdapter, IngestPayload, IngestResponse, } from './types';
53
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAC1E,YAAY,EACV,QAAQ,EACR,QAAQ,EACR,YAAY,EACZ,eAAe,EACf,cAAc,EACd,aAAa,EACb,cAAc,GACf,MAAM,SAAS,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,52 @@
1
+ /**
2
+ * @steve31415/log-logger-ts - Lightweight logging library for Cloudflare Workers and browsers
3
+ *
4
+ * Features:
5
+ * - Dual logging: console + backend delivery
6
+ * - Automatic batching (10 events, 1 second, or on ERROR)
7
+ * - Timeout-based flush for Workers
8
+ * - Best-effort sendBeacon for browser page unload
9
+ *
10
+ * @example Workers fetch handler
11
+ * ```typescript
12
+ * import { Logger, FetchDeliveryAdapter } from '@steve31415/log-logger-ts';
13
+ *
14
+ * const INGEST_ENDPOINT = 'https://log-ingest.example.com/v1/logs:ingest';
15
+ *
16
+ * export default {
17
+ * async fetch(request, env, ctx) {
18
+ * const logger = new Logger(
19
+ * { app: 'my-app', context: 'worker_http' },
20
+ * new FetchDeliveryAdapter(INGEST_ENDPOINT)
21
+ * );
22
+ * try {
23
+ * logger.info('Request received', { url: request.url });
24
+ * // ... handle request
25
+ * return new Response('OK');
26
+ * } finally {
27
+ * ctx.waitUntil(logger.flushWithTimeout(3000));
28
+ * }
29
+ * }
30
+ * }
31
+ * ```
32
+ *
33
+ * @example Browser
34
+ * ```typescript
35
+ * import { Logger, BrowserDeliveryAdapter } from '@steve31415/log-logger-ts';
36
+ *
37
+ * const logger = new Logger(
38
+ * { app: 'my-app', context: 'web_frontend' },
39
+ * new BrowserDeliveryAdapter('/api/logs')
40
+ * );
41
+ *
42
+ * // Flush on page unload
43
+ * document.addEventListener('visibilitychange', () => {
44
+ * if (document.visibilityState === 'hidden') {
45
+ * logger.flushSync();
46
+ * }
47
+ * });
48
+ * ```
49
+ */
50
+ export { Logger } from './logger';
51
+ export { FetchDeliveryAdapter, BrowserDeliveryAdapter } from './adapters';
52
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,72 @@
1
+ import type { LogLevel, LoggerConfig, DeliveryAdapter, ConsoleAdapter } from './types';
2
+ /**
3
+ * Logger class with batching and multi-environment support
4
+ */
5
+ export declare class Logger {
6
+ private config;
7
+ private adapter;
8
+ private console;
9
+ private buffer;
10
+ private flushTimer;
11
+ private firstEventTime;
12
+ private closed;
13
+ private flushPromise;
14
+ private inFlightPayload;
15
+ constructor(config: LoggerConfig, adapter: DeliveryAdapter, consoleAdapter?: ConsoleAdapter);
16
+ /**
17
+ * Create a child logger with a different logger name
18
+ */
19
+ child(loggerName: string): Logger;
20
+ /**
21
+ * Log at DEBUG level
22
+ */
23
+ debug(message: string, meta?: Record<string, unknown>): void;
24
+ /**
25
+ * Log at INFO level
26
+ */
27
+ info(message: string, meta?: Record<string, unknown>): void;
28
+ /**
29
+ * Log at WARN level
30
+ */
31
+ warn(message: string, meta?: Record<string, unknown>): void;
32
+ /**
33
+ * Log at ERROR level
34
+ */
35
+ error(message: string, meta?: Record<string, unknown>): void;
36
+ /**
37
+ * Log at a specific level
38
+ */
39
+ log(level: LogLevel, message: string, meta?: Record<string, unknown>): void;
40
+ /**
41
+ * Schedule a flush after the batch timeout
42
+ */
43
+ private scheduleFlush;
44
+ /**
45
+ * Clear the scheduled flush timer
46
+ */
47
+ private clearFlushTimer;
48
+ /**
49
+ * Flush buffered events to the backend
50
+ */
51
+ flush(): Promise<void>;
52
+ /**
53
+ * Deliver payload with a single retry on failure
54
+ */
55
+ private deliverWithRetry;
56
+ /**
57
+ * Flush with a timeout - useful for Workers and end-of-task scenarios
58
+ * @param timeoutMs Maximum time to wait for flush to complete
59
+ * @returns Promise that resolves when flush completes or times out
60
+ */
61
+ flushWithTimeout(timeoutMs: number): Promise<void>;
62
+ /**
63
+ * Close the logger - flushes remaining events and prevents further logging
64
+ */
65
+ close(): Promise<void>;
66
+ /**
67
+ * Best-effort flush using sendBeacon (for page unload scenarios)
68
+ * Call this from visibilitychange or pagehide event handlers
69
+ */
70
+ flushSync(): void;
71
+ }
72
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,QAAQ,EAER,YAAY,EACZ,eAAe,EACf,cAAc,EAEf,MAAM,SAAS,CAAC;AAqBjB;;GAEG;AACH,qBAAa,MAAM;IACjB,OAAO,CAAC,MAAM,CAAyG;IACvH,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,OAAO,CAAiB;IAEhC,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,UAAU,CAA8C;IAChE,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,YAAY,CAA8B;IAClD,OAAO,CAAC,eAAe,CAA8B;gBAGnD,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,eAAe,EACxB,cAAc,GAAE,cAAwB;IAgB1C;;OAEG;IACH,KAAK,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM;IAQjC;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI5D;;OAEG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI3D;;OAEG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI3D;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI5D;;OAEG;IACH,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAkD3E;;OAEG;IACH,OAAO,CAAC,aAAa;IAUrB;;OAEG;IACH,OAAO,CAAC,eAAe;IAOvB;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAmC5B;;OAEG;YACW,gBAAgB;IAe9B;;;;OAIG;IACG,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA6BxD;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAS5B;;;OAGG;IACH,SAAS,IAAI,IAAI;CAmBlB"}
package/dist/logger.js ADDED
@@ -0,0 +1,251 @@
1
+ const LEVEL_PRIORITY = {
2
+ DEBUG: 0,
3
+ INFO: 1,
4
+ WARN: 2,
5
+ ERROR: 3,
6
+ };
7
+ const DEFAULT_BATCH_SIZE = 10;
8
+ const DEFAULT_BATCH_TIMEOUT_MS = 1000;
9
+ /**
10
+ * Generate a simple unique ID for log events
11
+ */
12
+ function generateId() {
13
+ const timestamp = Date.now().toString(36);
14
+ const random = Math.random().toString(36).substring(2, 10);
15
+ return `${timestamp}-${random}`;
16
+ }
17
+ /**
18
+ * Logger class with batching and multi-environment support
19
+ */
20
+ export class Logger {
21
+ constructor(config, adapter, consoleAdapter = console) {
22
+ this.buffer = [];
23
+ this.flushTimer = null;
24
+ this.firstEventTime = null;
25
+ this.closed = false;
26
+ this.flushPromise = null;
27
+ this.inFlightPayload = null;
28
+ this.config = {
29
+ app: config.app,
30
+ context: config.context,
31
+ runId: config.runId,
32
+ logger: config.logger,
33
+ batchSize: config.batchSize ?? DEFAULT_BATCH_SIZE,
34
+ batchTimeoutMs: config.batchTimeoutMs ?? DEFAULT_BATCH_TIMEOUT_MS,
35
+ consoleLog: config.consoleLog ?? true,
36
+ minLevel: config.minLevel ?? 'DEBUG',
37
+ };
38
+ this.adapter = adapter;
39
+ this.console = consoleAdapter;
40
+ }
41
+ /**
42
+ * Create a child logger with a different logger name
43
+ */
44
+ child(loggerName) {
45
+ return new Logger({ ...this.config, logger: loggerName }, this.adapter, this.console);
46
+ }
47
+ /**
48
+ * Log at DEBUG level
49
+ */
50
+ debug(message, meta) {
51
+ this.log('DEBUG', message, meta);
52
+ }
53
+ /**
54
+ * Log at INFO level
55
+ */
56
+ info(message, meta) {
57
+ this.log('INFO', message, meta);
58
+ }
59
+ /**
60
+ * Log at WARN level
61
+ */
62
+ warn(message, meta) {
63
+ this.log('WARN', message, meta);
64
+ }
65
+ /**
66
+ * Log at ERROR level
67
+ */
68
+ error(message, meta) {
69
+ this.log('ERROR', message, meta);
70
+ }
71
+ /**
72
+ * Log at a specific level
73
+ */
74
+ log(level, message, meta) {
75
+ if (this.closed) {
76
+ this.console.warn('[Logger] Attempted to log after close');
77
+ return;
78
+ }
79
+ // Check minimum level
80
+ if (LEVEL_PRIORITY[level] < LEVEL_PRIORITY[this.config.minLevel]) {
81
+ return;
82
+ }
83
+ const timestamp = Date.now();
84
+ // Log to native console immediately
85
+ if (this.config.consoleLog) {
86
+ const prefix = this.config.logger
87
+ ? `[${this.config.app}:${this.config.logger}]`
88
+ : `[${this.config.app}]`;
89
+ const consoleFn = this.console[level.toLowerCase()];
90
+ if (meta && Object.keys(meta).length > 0) {
91
+ consoleFn(`${prefix} ${message}`, meta);
92
+ }
93
+ else {
94
+ consoleFn(`${prefix} ${message}`);
95
+ }
96
+ }
97
+ // Create event for batching
98
+ const event = {
99
+ id: generateId(),
100
+ level,
101
+ message,
102
+ time_generated_client_ms: timestamp,
103
+ logger: this.config.logger,
104
+ meta,
105
+ };
106
+ this.buffer.push(event);
107
+ // Track first event time for batch timeout
108
+ if (this.firstEventTime === null) {
109
+ this.firstEventTime = timestamp;
110
+ this.scheduleFlush();
111
+ }
112
+ // Flush immediately on ERROR or when batch size reached
113
+ if (level === 'ERROR' || this.buffer.length >= this.config.batchSize) {
114
+ this.flush();
115
+ }
116
+ }
117
+ /**
118
+ * Schedule a flush after the batch timeout
119
+ */
120
+ scheduleFlush() {
121
+ if (this.flushTimer !== null) {
122
+ return;
123
+ }
124
+ this.flushTimer = setTimeout(() => {
125
+ this.flushTimer = null;
126
+ this.flush();
127
+ }, this.config.batchTimeoutMs);
128
+ }
129
+ /**
130
+ * Clear the scheduled flush timer
131
+ */
132
+ clearFlushTimer() {
133
+ if (this.flushTimer !== null) {
134
+ clearTimeout(this.flushTimer);
135
+ this.flushTimer = null;
136
+ }
137
+ }
138
+ /**
139
+ * Flush buffered events to the backend
140
+ */
141
+ async flush() {
142
+ // If already flushing, wait for it
143
+ if (this.flushPromise) {
144
+ await this.flushPromise;
145
+ return;
146
+ }
147
+ this.clearFlushTimer();
148
+ if (this.buffer.length === 0) {
149
+ return;
150
+ }
151
+ // Take current buffer
152
+ const events = this.buffer;
153
+ this.buffer = [];
154
+ this.firstEventTime = null;
155
+ const payload = {
156
+ app: this.config.app,
157
+ context: this.config.context,
158
+ run_id: this.config.runId,
159
+ events,
160
+ };
161
+ this.inFlightPayload = payload;
162
+ this.flushPromise = this.deliverWithRetry(payload);
163
+ try {
164
+ await this.flushPromise;
165
+ }
166
+ finally {
167
+ this.flushPromise = null;
168
+ this.inFlightPayload = null;
169
+ }
170
+ }
171
+ /**
172
+ * Deliver payload with a single retry on failure
173
+ */
174
+ async deliverWithRetry(payload) {
175
+ let success = await this.adapter.deliver(payload);
176
+ if (!success) {
177
+ // Single retry
178
+ this.console.warn('[Logger] Retrying delivery...');
179
+ success = await this.adapter.deliver(payload);
180
+ if (!success) {
181
+ this.console.error(`[Logger] CRITICAL: Failed to deliver ${payload.events.length} log events after retry`);
182
+ // Events are lost at this point - we don't re-queue to avoid memory growth
183
+ }
184
+ }
185
+ }
186
+ /**
187
+ * Flush with a timeout - useful for Workers and end-of-task scenarios
188
+ * @param timeoutMs Maximum time to wait for flush to complete
189
+ * @returns Promise that resolves when flush completes or times out
190
+ */
191
+ async flushWithTimeout(timeoutMs) {
192
+ const flushPromise = this.flush();
193
+ const timeoutPromise = new Promise((_, reject) => {
194
+ setTimeout(() => {
195
+ reject(new Error(`Flush timed out after ${timeoutMs}ms`));
196
+ }, timeoutMs);
197
+ });
198
+ try {
199
+ await Promise.race([flushPromise, timeoutPromise]);
200
+ }
201
+ catch (error) {
202
+ this.console.error('[Logger] Flush timeout:', error);
203
+ // Attempt best-effort delivery if adapter supports it
204
+ // Use in-flight payload if flush took the buffer, otherwise use current buffer
205
+ const payload = this.inFlightPayload ?? (this.buffer.length > 0 ? {
206
+ app: this.config.app,
207
+ context: this.config.context,
208
+ run_id: this.config.runId,
209
+ events: this.buffer,
210
+ } : null);
211
+ if (payload && this.adapter.deliverBestEffort) {
212
+ this.adapter.deliverBestEffort(payload);
213
+ this.buffer = [];
214
+ }
215
+ }
216
+ }
217
+ /**
218
+ * Close the logger - flushes remaining events and prevents further logging
219
+ */
220
+ async close() {
221
+ if (this.closed) {
222
+ return;
223
+ }
224
+ this.closed = true;
225
+ this.clearFlushTimer();
226
+ await this.flush();
227
+ }
228
+ /**
229
+ * Best-effort flush using sendBeacon (for page unload scenarios)
230
+ * Call this from visibilitychange or pagehide event handlers
231
+ */
232
+ flushSync() {
233
+ if (this.buffer.length === 0) {
234
+ return;
235
+ }
236
+ if (this.adapter.deliverBestEffort) {
237
+ const payload = {
238
+ app: this.config.app,
239
+ context: this.config.context,
240
+ run_id: this.config.runId,
241
+ events: this.buffer,
242
+ };
243
+ const success = this.adapter.deliverBestEffort(payload);
244
+ if (success) {
245
+ this.buffer = [];
246
+ this.firstEventTime = null;
247
+ }
248
+ }
249
+ }
250
+ }
251
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Log level types
3
+ */
4
+ export type LogLevel = 'DEBUG' | 'INFO' | 'WARN' | 'ERROR';
5
+ /**
6
+ * A single log event to be delivered to the backend
7
+ */
8
+ export interface LogEvent {
9
+ id: string;
10
+ level: LogLevel;
11
+ message: string;
12
+ time_generated_client_ms: number;
13
+ logger?: string;
14
+ meta?: Record<string, unknown>;
15
+ }
16
+ /**
17
+ * The payload sent to the ingest API
18
+ */
19
+ export interface IngestPayload {
20
+ app: string;
21
+ context: string;
22
+ run_id?: string;
23
+ events: LogEvent[];
24
+ }
25
+ /**
26
+ * Response from the ingest API
27
+ */
28
+ export interface IngestResponse {
29
+ accepted: number;
30
+ rejected: number;
31
+ errors?: string[];
32
+ }
33
+ /**
34
+ * Configuration for the logger
35
+ */
36
+ export interface LoggerConfig {
37
+ /** Application name (required) */
38
+ app: string;
39
+ /** Execution context: web_frontend, worker_http, worker_cron, etc. */
40
+ context: string;
41
+ /** @deprecated Endpoint is now specified in the DeliveryAdapter constructor */
42
+ endpoint?: string;
43
+ /** Optional run/session ID for correlation */
44
+ runId?: string;
45
+ /** Optional default logger name (subsystem) */
46
+ logger?: string;
47
+ /** Batch size threshold (default: 10) */
48
+ batchSize?: number;
49
+ /** Batch time threshold in ms (default: 1000) */
50
+ batchTimeoutMs?: number;
51
+ /** Whether to log to console in addition to backend (default: true) */
52
+ consoleLog?: boolean;
53
+ /** Minimum level to log (default: DEBUG) */
54
+ minLevel?: LogLevel;
55
+ }
56
+ /**
57
+ * Delivery adapter interface for different environments
58
+ */
59
+ export interface DeliveryAdapter {
60
+ /**
61
+ * Send a batch of events to the backend
62
+ * @returns true if delivery succeeded, false otherwise
63
+ */
64
+ deliver(payload: IngestPayload): Promise<boolean>;
65
+ /**
66
+ * Attempt to deliver using best-effort methods (e.g., sendBeacon)
67
+ * Used during page unload or service worker termination
68
+ */
69
+ deliverBestEffort?(payload: IngestPayload): boolean;
70
+ }
71
+ /**
72
+ * Native console interface for logging
73
+ */
74
+ export interface ConsoleAdapter {
75
+ debug(message: string, ...args: unknown[]): void;
76
+ info(message: string, ...args: unknown[]): void;
77
+ warn(message: string, ...args: unknown[]): void;
78
+ error(message: string, ...args: unknown[]): void;
79
+ }
80
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAE3D;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,QAAQ,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,wBAAwB,EAAE,MAAM,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,QAAQ,EAAE,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,kCAAkC;IAClC,GAAG,EAAE,MAAM,CAAC;IAEZ,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAC;IAEhB,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,8CAA8C;IAC9C,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,+CAA+C;IAC/C,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,yCAAyC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,iDAAiD;IACjD,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,uEAAuE;IACvE,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,OAAO,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAElD;;;OAGG;IACH,iBAAiB,CAAC,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC;CACrD;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IACjD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;CAClD"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@steve31415/log-logger-ts",
3
+ "version": "1.0.0",
4
+ "description": "Lightweight logging library for Cloudflare Workers and browsers",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "module": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "README.md"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsc",
21
+ "prepublishOnly": "npm run build",
22
+ "test": "vitest"
23
+ },
24
+ "keywords": [
25
+ "logging",
26
+ "cloudflare",
27
+ "workers",
28
+ "browser"
29
+ ],
30
+ "license": "MIT",
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "https://github.com/plasticine-apps/log.git",
34
+ "directory": "libs/logger-ts"
35
+ },
36
+ "devDependencies": {
37
+ "typescript": "^5.0.0",
38
+ "vitest": "^2.1.9"
39
+ }
40
+ }