@arivlabs/logger 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/CHANGELOG.md ADDED
@@ -0,0 +1,19 @@
1
+ # Changelog
2
+
3
+ All notable changes to `@arivlabs/logger` will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [1.0.0] - 2024-12-23
9
+
10
+ ### Added
11
+
12
+ - Initial release
13
+ - `createLogger()` function for creating structured loggers
14
+ - Domain-specific logging with `logger.domain()`
15
+ - Request context logging with `logger.withContext()`
16
+ - CloudWatch-friendly JSON output
17
+ - Pretty printing for development
18
+ - TypeScript support with full type definitions
19
+ - Support for custom service names and log levels
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 ArivLabs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,115 @@
1
+ # @arivlabs/logger
2
+
3
+ Structured logging for ArivLabs services with CloudWatch support.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pnpm add @arivlabs/logger
9
+
10
+ # Optional: for pretty printing in development
11
+ pnpm add -D pino-pretty
12
+ ```
13
+
14
+ ## Usage
15
+
16
+ ```typescript
17
+ import { createLogger } from '@arivlabs/logger';
18
+
19
+ // Create a logger for your service
20
+ const logger = createLogger({ service: 'api-gateway' });
21
+
22
+ // Basic logging
23
+ logger.info({ msg: 'Server started', port: 3000 });
24
+ logger.error({ msg: 'Something failed', error: err.message });
25
+
26
+ // Domain-specific logging
27
+ const discoveryLog = logger.domain('discovery');
28
+ discoveryLog.info({ msg: 'Job created', jobId: '123' });
29
+
30
+ // Request context logging
31
+ const reqLog = logger.withContext({
32
+ correlationId: 'abc-123',
33
+ tenantId: 'tenant-1',
34
+ domain: 'discovery',
35
+ });
36
+ reqLog.info({ msg: 'Processing request' });
37
+ ```
38
+
39
+ ## CloudWatch Insights Queries
40
+
41
+ ```sql
42
+ -- Filter by service
43
+ fields @timestamp, @message
44
+ | filter service = "api-gateway"
45
+
46
+ -- Filter by domain
47
+ fields @timestamp, @message
48
+ | filter domain = "discovery"
49
+
50
+ -- Filter errors
51
+ fields @timestamp, @message
52
+ | filter level = "error"
53
+
54
+ -- Filter by tenant
55
+ fields @timestamp, @message
56
+ | filter tenant_id = "xxx"
57
+
58
+ -- Combine filters
59
+ fields @timestamp, service, domain, @message
60
+ | filter service = "api-gateway" and domain = "discovery"
61
+ | sort @timestamp desc
62
+ | limit 100
63
+ ```
64
+
65
+ ## Configuration
66
+
67
+ ```typescript
68
+ const logger = createLogger({
69
+ service: 'api-gateway', // Required: service name
70
+ environment: 'production', // Optional: defaults to NODE_ENV
71
+ level: 'info', // Optional: debug, info, warn, error
72
+ pretty: false, // Optional: defaults to true in development
73
+ });
74
+ ```
75
+
76
+ ## Log Format
77
+
78
+ JSON output (production):
79
+
80
+ ```json
81
+ {
82
+ "level": 30,
83
+ "timestamp": "2024-01-15T10:30:00.000Z",
84
+ "service": "api-gateway",
85
+ "environment": "production",
86
+ "domain": "discovery",
87
+ "correlation_id": "abc-123",
88
+ "tenant_id": "tenant-1",
89
+ "msg": "Job created",
90
+ "jobId": "job-456"
91
+ }
92
+ ```
93
+
94
+ Pretty output (development):
95
+
96
+ ```
97
+ 10:30:00 Z [api-gateway:discovery] abc-123 Job created
98
+ ```
99
+
100
+ ## Available Domains
101
+
102
+ - `discovery` - Discovery scanning
103
+ - `auth` - Authentication
104
+ - `connectors` - Cloud connectors
105
+ - `inventory` - Resource inventory
106
+ - `lineage` - Data lineage
107
+ - `onboarding` - Customer onboarding
108
+ - `proxy` - AI proxy
109
+ - `users` - User management
110
+ - `dashboard` - Analytics dashboard
111
+ - `internal` - Internal APIs
112
+ - `storage` - File storage
113
+ - `email` - Email service
114
+ - `queue` - Queue processing
115
+ - `system` - System-level logs
@@ -0,0 +1,9 @@
1
+ declare const pino: jest.Mock & {
2
+ stdSerializers: {
3
+ req: jest.Mock;
4
+ res: jest.Mock;
5
+ err: jest.Mock;
6
+ };
7
+ };
8
+ export default pino;
9
+ //# sourceMappingURL=pino.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pino.d.ts","sourceRoot":"","sources":["../../src/__mocks__/pino.ts"],"names":[],"mappings":"AAYA,QAAA,MAAM,IAAI,EAAgC,IAAI,CAAC,IAAI,GAAG;IACpD,cAAc,EAAE;QACd,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC;QACf,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC;QACf,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC;KAChB,CAAC;CACH,CAAC;AAQF,eAAe,IAAI,CAAC"}
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const mockChild = jest.fn().mockReturnThis();
4
+ const mockLogger = {
5
+ info: jest.fn(),
6
+ warn: jest.fn(),
7
+ error: jest.fn(),
8
+ debug: jest.fn(),
9
+ fatal: jest.fn(),
10
+ trace: jest.fn(),
11
+ child: mockChild,
12
+ };
13
+ const pino = jest.fn(() => mockLogger);
14
+ pino.stdSerializers = {
15
+ req: jest.fn(),
16
+ res: jest.fn(),
17
+ err: jest.fn(),
18
+ };
19
+ exports.default = pino;
20
+ //# sourceMappingURL=pino.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pino.js","sourceRoot":"","sources":["../../src/__mocks__/pino.ts"],"names":[],"mappings":";;AAAA,MAAM,SAAS,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC,cAAc,EAAE,CAAC;AAE7C,MAAM,UAAU,GAAG;IACjB,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE;IACf,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE;IACf,KAAK,EAAE,IAAI,CAAC,EAAE,EAAE;IAChB,KAAK,EAAE,IAAI,CAAC,EAAE,EAAE;IAChB,KAAK,EAAE,IAAI,CAAC,EAAE,EAAE;IAChB,KAAK,EAAE,IAAI,CAAC,EAAE,EAAE;IAChB,KAAK,EAAE,SAAS;CACjB,CAAC;AAEF,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,UAAU,CAMpC,CAAC;AAEF,IAAI,CAAC,cAAc,GAAG;IACpB,GAAG,EAAE,IAAI,CAAC,EAAE,EAAE;IACd,GAAG,EAAE,IAAI,CAAC,EAAE,EAAE;IACd,GAAG,EAAE,IAAI,CAAC,EAAE,EAAE;CACf,CAAC;AAEF,kBAAe,IAAI,CAAC"}
@@ -0,0 +1,84 @@
1
+ import type { Logger as PinoLogger } from 'pino';
2
+ /**
3
+ * Service names for ArivLabs services
4
+ */
5
+ export type ServiceName = 'api-gateway' | 'queue-manager' | 'scanner-result-processor' | 'enrichment-processor' | 'lineage-processor' | 'ai-proxy' | 'control-plane';
6
+ /**
7
+ * Domain names for structured logging
8
+ */
9
+ export type LogDomain = 'discovery' | 'auth' | 'connectors' | 'inventory' | 'lineage' | 'onboarding' | 'proxy' | 'users' | 'dashboard' | 'internal' | 'storage' | 'email' | 'queue' | 'system';
10
+ /**
11
+ * Logger configuration options
12
+ */
13
+ export interface LoggerConfig {
14
+ /** Service name (e.g., 'api-gateway') */
15
+ service: ServiceName | string;
16
+ /** Environment (defaults to NODE_ENV or 'development') */
17
+ environment?: string;
18
+ /** Log level (defaults to 'debug' in dev, 'info' in prod) */
19
+ level?: string;
20
+ /** Enable pretty printing (defaults to true in development) */
21
+ pretty?: boolean;
22
+ }
23
+ /**
24
+ * Extended logger interface with domain support
25
+ */
26
+ export interface ArivLogger extends PinoLogger {
27
+ /** Create a child logger for a specific domain */
28
+ domain: (domain: LogDomain) => PinoLogger;
29
+ /** Create a child logger with request context */
30
+ withContext: (context: RequestContext) => PinoLogger;
31
+ }
32
+ /**
33
+ * Request context for correlation
34
+ */
35
+ export interface RequestContext {
36
+ correlationId: string;
37
+ userId?: string;
38
+ tenantId?: string;
39
+ domain?: LogDomain;
40
+ }
41
+ /**
42
+ * Create a structured logger for an ArivLabs service
43
+ *
44
+ * @example
45
+ * ```typescript
46
+ * import { createLogger } from '@arivlabs/logger';
47
+ *
48
+ * const logger = createLogger({ service: 'api-gateway' });
49
+ *
50
+ * // Basic logging
51
+ * logger.info({ msg: 'Server started', port: 3000 });
52
+ *
53
+ * // Domain-specific logging
54
+ * const discoveryLog = logger.domain('discovery');
55
+ * discoveryLog.info({ msg: 'Job created', jobId: '123' });
56
+ *
57
+ * // Request context logging
58
+ * const reqLog = logger.withContext({
59
+ * correlationId: 'abc-123',
60
+ * tenantId: 'tenant-1',
61
+ * domain: 'discovery'
62
+ * });
63
+ * reqLog.info({ msg: 'Processing request' });
64
+ * ```
65
+ *
66
+ * CloudWatch Insights queries:
67
+ * - Filter by service: `fields @timestamp, @message | filter service = "api-gateway"`
68
+ * - Filter by domain: `fields @timestamp, @message | filter domain = "discovery"`
69
+ * - Filter errors: `fields @timestamp, @message | filter level = "error"`
70
+ * - Filter by tenant: `fields @timestamp, @message | filter tenant_id = "xxx"`
71
+ */
72
+ export declare function createLogger(config: LoggerConfig): ArivLogger;
73
+ /**
74
+ * Create a domain-specific child logger
75
+ * @deprecated Use logger.domain() instead
76
+ */
77
+ export declare function createDomainLogger(logger: PinoLogger, domain: LogDomain): PinoLogger;
78
+ /**
79
+ * Create a child logger with request context
80
+ * @deprecated Use logger.withContext() instead
81
+ */
82
+ export declare function createRequestLogger(logger: PinoLogger, domain: LogDomain, correlationId: string, userId?: string, tenantId?: string): PinoLogger;
83
+ export type { Logger as PinoLogger } from 'pino';
84
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAiB,MAAM,MAAM,CAAC;AAGhE;;GAEG;AACH,MAAM,MAAM,WAAW,GACnB,aAAa,GACb,eAAe,GACf,0BAA0B,GAC1B,sBAAsB,GACtB,mBAAmB,GACnB,UAAU,GACV,eAAe,CAAC;AAEpB;;GAEG;AACH,MAAM,MAAM,SAAS,GACjB,WAAW,GACX,MAAM,GACN,YAAY,GACZ,WAAW,GACX,SAAS,GACT,YAAY,GACZ,OAAO,GACP,OAAO,GACP,WAAW,GACX,UAAU,GACV,SAAS,GACT,OAAO,GACP,OAAO,GACP,QAAQ,CAAC;AAEb;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,yCAAyC;IACzC,OAAO,EAAE,WAAW,GAAG,MAAM,CAAC;IAC9B,0DAA0D;IAC1D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,UAAW,SAAQ,UAAU;IAC5C,kDAAkD;IAClD,MAAM,EAAE,CAAC,MAAM,EAAE,SAAS,KAAK,UAAU,CAAC;IAC1C,iDAAiD;IACjD,WAAW,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,UAAU,CAAC;CACtD;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,SAAS,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,UAAU,CA2D7D;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,GAAG,UAAU,CAEpF;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,SAAS,EACjB,aAAa,EAAE,MAAM,EACrB,MAAM,CAAC,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,MAAM,GAChB,UAAU,CAOZ;AAGD,YAAY,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,MAAM,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createLogger = createLogger;
7
+ exports.createDomainLogger = createDomainLogger;
8
+ exports.createRequestLogger = createRequestLogger;
9
+ const pino_1 = __importDefault(require("pino"));
10
+ /**
11
+ * Create a structured logger for an ArivLabs service
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * import { createLogger } from '@arivlabs/logger';
16
+ *
17
+ * const logger = createLogger({ service: 'api-gateway' });
18
+ *
19
+ * // Basic logging
20
+ * logger.info({ msg: 'Server started', port: 3000 });
21
+ *
22
+ * // Domain-specific logging
23
+ * const discoveryLog = logger.domain('discovery');
24
+ * discoveryLog.info({ msg: 'Job created', jobId: '123' });
25
+ *
26
+ * // Request context logging
27
+ * const reqLog = logger.withContext({
28
+ * correlationId: 'abc-123',
29
+ * tenantId: 'tenant-1',
30
+ * domain: 'discovery'
31
+ * });
32
+ * reqLog.info({ msg: 'Processing request' });
33
+ * ```
34
+ *
35
+ * CloudWatch Insights queries:
36
+ * - Filter by service: `fields @timestamp, @message | filter service = "api-gateway"`
37
+ * - Filter by domain: `fields @timestamp, @message | filter domain = "discovery"`
38
+ * - Filter errors: `fields @timestamp, @message | filter level = "error"`
39
+ * - Filter by tenant: `fields @timestamp, @message | filter tenant_id = "xxx"`
40
+ */
41
+ function createLogger(config) {
42
+ const isDevelopment = config.environment === 'development' || process.env.NODE_ENV === 'development';
43
+ const isLocal = process.env.ENV === 'local';
44
+ const shouldPrettyPrint = config.pretty ?? (isDevelopment || isLocal);
45
+ const pinoOptions = {
46
+ name: config.service,
47
+ level: config.level || process.env.LOG_LEVEL || (isDevelopment ? 'debug' : 'info'),
48
+ // Base fields included in every log
49
+ base: {
50
+ service: config.service,
51
+ environment: config.environment || process.env.ENV || process.env.NODE_ENV || 'development',
52
+ },
53
+ // Timestamp format (CloudWatch-friendly ISO 8601)
54
+ timestamp: () => `,"timestamp":"${new Date().toISOString()}"`,
55
+ // Serializers for common objects
56
+ serializers: {
57
+ req: pino_1.default.stdSerializers.req,
58
+ res: pino_1.default.stdSerializers.res,
59
+ err: pino_1.default.stdSerializers.err,
60
+ },
61
+ };
62
+ // Add pretty printing for development
63
+ if (shouldPrettyPrint) {
64
+ pinoOptions.transport = {
65
+ target: 'pino-pretty',
66
+ options: {
67
+ colorize: true,
68
+ translateTime: 'HH:MM:ss Z',
69
+ ignore: 'pid,hostname',
70
+ messageFormat: '[{service}:{domain}] {correlation_id} {msg}',
71
+ },
72
+ };
73
+ }
74
+ const baseLogger = (0, pino_1.default)(pinoOptions);
75
+ // Extend with domain and context methods
76
+ const logger = baseLogger;
77
+ logger.domain = (domain) => {
78
+ return baseLogger.child({ domain });
79
+ };
80
+ logger.withContext = (context) => {
81
+ return baseLogger.child({
82
+ domain: context.domain,
83
+ correlation_id: context.correlationId,
84
+ user_id: context.userId,
85
+ tenant_id: context.tenantId,
86
+ });
87
+ };
88
+ return logger;
89
+ }
90
+ /**
91
+ * Create a domain-specific child logger
92
+ * @deprecated Use logger.domain() instead
93
+ */
94
+ function createDomainLogger(logger, domain) {
95
+ return logger.child({ domain });
96
+ }
97
+ /**
98
+ * Create a child logger with request context
99
+ * @deprecated Use logger.withContext() instead
100
+ */
101
+ function createRequestLogger(logger, domain, correlationId, userId, tenantId) {
102
+ return logger.child({
103
+ domain,
104
+ correlation_id: correlationId,
105
+ user_id: userId,
106
+ tenant_id: tenantId,
107
+ });
108
+ }
109
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;AAmGA,oCA2DC;AAMD,gDAEC;AAMD,kDAaC;AAxLD,gDAAwB;AAmExB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,SAAgB,YAAY,CAAC,MAAoB;IAC/C,MAAM,aAAa,GACjB,MAAM,CAAC,WAAW,KAAK,aAAa,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,CAAC;IACjF,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,OAAO,CAAC;IAC5C,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,IAAI,CAAC,aAAa,IAAI,OAAO,CAAC,CAAC;IAEtE,MAAM,WAAW,GAAkB;QACjC,IAAI,EAAE,MAAM,CAAC,OAAO;QACpB,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;QAElF,oCAAoC;QACpC,IAAI,EAAE;YACJ,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,aAAa;SAC5F;QAED,kDAAkD;QAClD,SAAS,EAAE,GAAG,EAAE,CAAC,iBAAiB,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,GAAG;QAE7D,iCAAiC;QACjC,WAAW,EAAE;YACX,GAAG,EAAE,cAAI,CAAC,cAAc,CAAC,GAAG;YAC5B,GAAG,EAAE,cAAI,CAAC,cAAc,CAAC,GAAG;YAC5B,GAAG,EAAE,cAAI,CAAC,cAAc,CAAC,GAAG;SAC7B;KACF,CAAC;IAEF,sCAAsC;IACtC,IAAI,iBAAiB,EAAE,CAAC;QACtB,WAAW,CAAC,SAAS,GAAG;YACtB,MAAM,EAAE,aAAa;YACrB,OAAO,EAAE;gBACP,QAAQ,EAAE,IAAI;gBACd,aAAa,EAAE,YAAY;gBAC3B,MAAM,EAAE,cAAc;gBACtB,aAAa,EAAE,6CAA6C;aAC7D;SACF,CAAC;IACJ,CAAC;IAED,MAAM,UAAU,GAAG,IAAA,cAAI,EAAC,WAAW,CAAC,CAAC;IAErC,yCAAyC;IACzC,MAAM,MAAM,GAAG,UAAwB,CAAC;IAExC,MAAM,CAAC,MAAM,GAAG,CAAC,MAAiB,EAAE,EAAE;QACpC,OAAO,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;IACtC,CAAC,CAAC;IAEF,MAAM,CAAC,WAAW,GAAG,CAAC,OAAuB,EAAE,EAAE;QAC/C,OAAO,UAAU,CAAC,KAAK,CAAC;YACtB,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,cAAc,EAAE,OAAO,CAAC,aAAa;YACrC,OAAO,EAAE,OAAO,CAAC,MAAM;YACvB,SAAS,EAAE,OAAO,CAAC,QAAQ;SAC5B,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,SAAgB,kBAAkB,CAAC,MAAkB,EAAE,MAAiB;IACtE,OAAO,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;AAClC,CAAC;AAED;;;GAGG;AACH,SAAgB,mBAAmB,CACjC,MAAkB,EAClB,MAAiB,EACjB,aAAqB,EACrB,MAAe,EACf,QAAiB;IAEjB,OAAO,MAAM,CAAC,KAAK,CAAC;QAClB,MAAM;QACN,cAAc,EAAE,aAAa;QAC7B,OAAO,EAAE,MAAM;QACf,SAAS,EAAE,QAAQ;KACpB,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,176 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const index_1 = require("./index");
4
+ // Use the mock from __mocks__ folder
5
+ jest.mock('pino');
6
+ describe('@arivlabs/logger', () => {
7
+ beforeEach(() => {
8
+ jest.clearAllMocks();
9
+ });
10
+ describe('createLogger', () => {
11
+ it('should create a logger with required service name', () => {
12
+ const logger = (0, index_1.createLogger)({ service: 'api-gateway' });
13
+ expect(logger).toBeDefined();
14
+ expect(typeof logger.info).toBe('function');
15
+ expect(typeof logger.error).toBe('function');
16
+ expect(typeof logger.warn).toBe('function');
17
+ expect(typeof logger.debug).toBe('function');
18
+ });
19
+ it('should accept all valid service names', () => {
20
+ const services = [
21
+ 'api-gateway',
22
+ 'queue-manager',
23
+ 'scanner-result-processor',
24
+ 'enrichment-processor',
25
+ 'lineage-processor',
26
+ 'ai-proxy',
27
+ 'control-plane',
28
+ ];
29
+ services.forEach((service) => {
30
+ const logger = (0, index_1.createLogger)({ service });
31
+ expect(logger).toBeDefined();
32
+ });
33
+ });
34
+ it('should accept custom service names', () => {
35
+ const logger = (0, index_1.createLogger)({ service: 'custom-service' });
36
+ expect(logger).toBeDefined();
37
+ });
38
+ it('should create logger with optional environment', () => {
39
+ const logger = (0, index_1.createLogger)({
40
+ service: 'api-gateway',
41
+ environment: 'production',
42
+ });
43
+ expect(logger).toBeDefined();
44
+ });
45
+ it('should create logger with optional log level', () => {
46
+ const logger = (0, index_1.createLogger)({
47
+ service: 'api-gateway',
48
+ level: 'debug',
49
+ });
50
+ expect(logger).toBeDefined();
51
+ });
52
+ it('should create logger with pretty printing disabled', () => {
53
+ const logger = (0, index_1.createLogger)({
54
+ service: 'api-gateway',
55
+ pretty: false,
56
+ });
57
+ expect(logger).toBeDefined();
58
+ });
59
+ });
60
+ describe('logger.domain()', () => {
61
+ it('should create a child logger with domain', () => {
62
+ const logger = (0, index_1.createLogger)({ service: 'api-gateway' });
63
+ const discoveryLogger = logger.domain('discovery');
64
+ expect(logger.child).toHaveBeenCalledWith({ domain: 'discovery' });
65
+ expect(discoveryLogger).toBeDefined();
66
+ });
67
+ it('should accept all valid domains', () => {
68
+ const logger = (0, index_1.createLogger)({ service: 'api-gateway' });
69
+ const domains = [
70
+ 'discovery',
71
+ 'auth',
72
+ 'connectors',
73
+ 'inventory',
74
+ 'lineage',
75
+ 'onboarding',
76
+ 'proxy',
77
+ 'users',
78
+ 'dashboard',
79
+ 'internal',
80
+ 'storage',
81
+ 'email',
82
+ 'queue',
83
+ 'system',
84
+ ];
85
+ domains.forEach((domain) => {
86
+ logger.domain(domain);
87
+ expect(logger.child).toHaveBeenCalledWith({ domain });
88
+ });
89
+ });
90
+ });
91
+ describe('logger.withContext()', () => {
92
+ it('should create a child logger with full context', () => {
93
+ const logger = (0, index_1.createLogger)({ service: 'api-gateway' });
94
+ const requestLogger = logger.withContext({
95
+ correlationId: 'abc-123',
96
+ userId: 'user-456',
97
+ tenantId: 'tenant-789',
98
+ domain: 'discovery',
99
+ });
100
+ expect(logger.child).toHaveBeenCalledWith({
101
+ domain: 'discovery',
102
+ correlation_id: 'abc-123',
103
+ user_id: 'user-456',
104
+ tenant_id: 'tenant-789',
105
+ });
106
+ expect(requestLogger).toBeDefined();
107
+ });
108
+ it('should create a child logger with minimal context', () => {
109
+ const logger = (0, index_1.createLogger)({ service: 'api-gateway' });
110
+ logger.withContext({
111
+ correlationId: 'abc-123',
112
+ });
113
+ expect(logger.child).toHaveBeenCalledWith({
114
+ domain: undefined,
115
+ correlation_id: 'abc-123',
116
+ user_id: undefined,
117
+ tenant_id: undefined,
118
+ });
119
+ });
120
+ it('should create a child logger with correlation and tenant only', () => {
121
+ const logger = (0, index_1.createLogger)({ service: 'api-gateway' });
122
+ logger.withContext({
123
+ correlationId: 'abc-123',
124
+ tenantId: 'tenant-789',
125
+ });
126
+ expect(logger.child).toHaveBeenCalledWith({
127
+ domain: undefined,
128
+ correlation_id: 'abc-123',
129
+ user_id: undefined,
130
+ tenant_id: 'tenant-789',
131
+ });
132
+ });
133
+ });
134
+ describe('type exports', () => {
135
+ it('should export ServiceName type', () => {
136
+ const service = 'api-gateway';
137
+ expect(service).toBe('api-gateway');
138
+ });
139
+ it('should export LogDomain type', () => {
140
+ const domain = 'discovery';
141
+ expect(domain).toBe('discovery');
142
+ });
143
+ it('should export ArivLogger type', () => {
144
+ const logger = (0, index_1.createLogger)({ service: 'api-gateway' });
145
+ expect(logger).toBeDefined();
146
+ });
147
+ });
148
+ describe('environment defaults', () => {
149
+ const originalEnv = process.env;
150
+ beforeEach(() => {
151
+ process.env = { ...originalEnv };
152
+ });
153
+ afterAll(() => {
154
+ process.env = originalEnv;
155
+ });
156
+ it('should default to debug level in development', () => {
157
+ process.env.NODE_ENV = 'development';
158
+ const logger = (0, index_1.createLogger)({ service: 'api-gateway' });
159
+ expect(logger).toBeDefined();
160
+ });
161
+ it('should default to info level in production', () => {
162
+ process.env.NODE_ENV = 'production';
163
+ const logger = (0, index_1.createLogger)({
164
+ service: 'api-gateway',
165
+ environment: 'production',
166
+ });
167
+ expect(logger).toBeDefined();
168
+ });
169
+ it('should respect LOG_LEVEL env variable', () => {
170
+ process.env.LOG_LEVEL = 'warn';
171
+ const logger = (0, index_1.createLogger)({ service: 'api-gateway' });
172
+ expect(logger).toBeDefined();
173
+ });
174
+ });
175
+ });
176
+ //# sourceMappingURL=index.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,69 @@
1
+ {
2
+ "name": "@arivlabs/logger",
3
+ "version": "1.0.0",
4
+ "description": "Structured logging for Node.js services with CloudWatch support",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "require": "./dist/index.js"
11
+ }
12
+ },
13
+ "files": [
14
+ "dist",
15
+ "README.md",
16
+ "CHANGELOG.md"
17
+ ],
18
+ "sideEffects": false,
19
+ "engines": {
20
+ "node": ">=20"
21
+ },
22
+ "scripts": {
23
+ "build": "tsc",
24
+ "dev": "tsc --watch",
25
+ "clean": "rm -rf dist",
26
+ "test": "jest",
27
+ "test:watch": "jest --watch",
28
+ "test:coverage": "jest --coverage",
29
+ "prepublishOnly": "pnpm run build"
30
+ },
31
+ "publishConfig": {
32
+ "access": "public",
33
+ "registry": "https://registry.npmjs.org/"
34
+ },
35
+ "dependencies": {
36
+ "pino": "^9.6.0"
37
+ },
38
+ "devDependencies": {
39
+ "@types/node": "^22.10.2",
40
+ "typescript": "^5.7.2"
41
+ },
42
+ "peerDependencies": {
43
+ "pino-pretty": "^13.0.0"
44
+ },
45
+ "peerDependenciesMeta": {
46
+ "pino-pretty": {
47
+ "optional": true
48
+ }
49
+ },
50
+ "keywords": [
51
+ "logging",
52
+ "pino",
53
+ "cloudwatch",
54
+ "structured-logging",
55
+ "nodejs",
56
+ "typescript"
57
+ ],
58
+ "author": "ArivLabs <hello@arivlabs.com>",
59
+ "license": "MIT",
60
+ "homepage": "https://github.com/ArivLabs/arivlabs-packages/tree/main/packages/logger#readme",
61
+ "repository": {
62
+ "type": "git",
63
+ "url": "git+https://github.com/ArivLabs/arivlabs-packages.git",
64
+ "directory": "packages/logger"
65
+ },
66
+ "bugs": {
67
+ "url": "https://github.com/ArivLabs/arivlabs-packages/issues"
68
+ }
69
+ }