@md-oss/observability 0.1.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/LICENSE ADDED
@@ -0,0 +1,5 @@
1
+ Copyright 2026 Mirasaki Development
2
+
3
+ Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
4
+
5
+ THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,308 @@
1
+ # @md-oss/observability
2
+
3
+ Structured logging with Winston for production-ready observability.
4
+
5
+ ## Features
6
+
7
+ - **Structured Logging** - JSON-formatted logs with Winston
8
+ - **Multiple Transports** - Console and file-based logging with automatic rotation
9
+ - **Exception Handling** - Automatic logging of unhandled exceptions and rejections
10
+ - **Child Loggers** - Create contextual loggers with custom metadata
11
+ - **Configurable Levels** - Support for all Winston log levels (error, warn, info, verbose, debug, silly)
12
+ - **Log Rotation** - Automatic file rotation with configurable size limits
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ pnpm add @md-oss/observability
18
+ ```
19
+
20
+ ## Usage
21
+
22
+ ### Basic Logging
23
+
24
+ ```typescript
25
+ import { logger } from '@md-oss/observability';
26
+
27
+ // Log at different levels
28
+ logger.error('Critical error occurred', { userId: 123 });
29
+ logger.warn('Warning message', { action: 'deprecated' });
30
+ logger.info('User logged in', { userId: 456 });
31
+ logger.verbose('Detailed information');
32
+ logger.debug('Debug information');
33
+ logger.silly('Very detailed debug info');
34
+
35
+ // Log errors with stack traces
36
+ try {
37
+ throw new Error('Something went wrong');
38
+ } catch (error) {
39
+ logger.error('Operation failed', { error });
40
+ }
41
+ ```
42
+
43
+ ### Child Loggers
44
+
45
+ Create contextual loggers with custom metadata:
46
+
47
+ ```typescript
48
+ import { createChildLogger } from '@md-oss/observability';
49
+
50
+ // Create a logger for a specific service
51
+ const userServiceLogger = createChildLogger({
52
+ service: 'user-service',
53
+ component: 'authentication'
54
+ });
55
+
56
+ userServiceLogger.info('User authenticated', { userId: 123 });
57
+ // Logs: { service: 'user-service', component: 'authentication', message: 'User authenticated', userId: 123 }
58
+
59
+ // Create a logger for a specific request
60
+ const requestLogger = createChildLogger({
61
+ requestId: 'req-abc-123',
62
+ userId: 456
63
+ });
64
+
65
+ requestLogger.info('Processing request');
66
+ requestLogger.error('Request failed');
67
+ // All logs include requestId and userId
68
+ ```
69
+
70
+ ## Configuration
71
+
72
+ Set environment variables to configure logging behavior:
73
+
74
+ ### Environment Variables
75
+
76
+ ```bash
77
+ # Required
78
+ NODE_ENV=development # or 'production', 'test'
79
+
80
+ # Optional
81
+ LOG_LEVEL=info # error | warn | info | verbose | debug | silly
82
+ LOG_DIR=./logs # Directory for log files (relative to cwd)
83
+ LOG_TO_CONSOLE=true # Enable/disable console logging
84
+ ```
85
+
86
+ ### Log Files
87
+
88
+ When `LOG_DIR` is set, the following files are created:
89
+
90
+ - **`combined.log`** - All logs (max 10MB per file, keeps last 7 files)
91
+ - **`errors.log`** - Error level logs only (max 10MB per file, keeps last 3 files)
92
+ - **`exceptions.log`** - Unhandled exceptions
93
+ - **`rejections.log`** - Unhandled promise rejections
94
+
95
+ ### Example Configuration
96
+
97
+ ```env
98
+ # .env.development
99
+ NODE_ENV=development
100
+ LOG_LEVEL=debug
101
+ LOG_TO_CONSOLE=true
102
+ LOG_DIR=./logs
103
+
104
+ # .env.production
105
+ NODE_ENV=production
106
+ LOG_LEVEL=info
107
+ LOG_TO_CONSOLE=false
108
+ LOG_DIR=/var/log/app
109
+ ```
110
+
111
+ ## Log Format
112
+
113
+ ### Console Output (Development)
114
+
115
+ ```
116
+ 2026-01-27 10:30:45 info: User logged in userId=123
117
+ 2026-01-27 10:30:46 error: Operation failed error=[Error: Something went wrong]
118
+ ```
119
+
120
+ ### File Output (JSON)
121
+
122
+ ```json
123
+ {
124
+ "level": "info",
125
+ "message": "User logged in",
126
+ "timestamp": "2026-01-27 10:30:45",
127
+ "service": "my-app",
128
+ "version": "1.0.0",
129
+ "userId": 123
130
+ }
131
+ ```
132
+
133
+ ## Advanced Usage
134
+
135
+ ### Custom Transports
136
+
137
+ Access the transports array to add custom Winston transports:
138
+
139
+ ```typescript
140
+ import { transports, logger } from '@md-oss/observability';
141
+ import winston from 'winston';
142
+
143
+ // Add a custom transport
144
+ transports.push(
145
+ new winston.transports.Http({
146
+ host: 'log-server.example.com',
147
+ port: 8080
148
+ })
149
+ );
150
+ ```
151
+
152
+ ### Log Level Access
153
+
154
+ ```typescript
155
+ import { logLevel } from '@md-oss/observability';
156
+
157
+ console.log('Current log level:', logLevel); // 'info'
158
+
159
+ // Conditionally log based on level
160
+ if (logLevel === 'debug' || logLevel === 'silly') {
161
+ logger.debug('Detailed debug information');
162
+ }
163
+ ```
164
+
165
+ ### Metadata and Formatting
166
+
167
+ ```typescript
168
+ import { logger } from '@md-oss/observability';
169
+
170
+ // Log with structured metadata
171
+ logger.info('User action', {
172
+ action: 'login',
173
+ userId: 123,
174
+ ip: '192.168.1.1',
175
+ timestamp: Date.now()
176
+ });
177
+
178
+ // String interpolation with metadata
179
+ logger.info('User %s performed %s', 'John', 'login', {
180
+ userId: 123
181
+ });
182
+ ```
183
+
184
+ ## Exception Handling
185
+
186
+ Unhandled exceptions and promise rejections are automatically logged:
187
+
188
+ ```typescript
189
+ // Unhandled exception - automatically logged to exceptions.log
190
+ throw new Error('Unhandled error');
191
+
192
+ // Unhandled promise rejection - automatically logged to rejections.log
193
+ Promise.reject(new Error('Unhandled promise rejection'));
194
+ ```
195
+
196
+ ## Best Practices
197
+
198
+ ### 1. Use Appropriate Log Levels
199
+
200
+ ```typescript
201
+ // Production errors
202
+ logger.error('Payment processing failed', { orderId: 123, error });
203
+
204
+ // Important events
205
+ logger.warn('API rate limit approaching', { usage: 0.9 });
206
+
207
+ // Business logic events
208
+ logger.info('Order created', { orderId: 456, total: 99.99 });
209
+
210
+ // Detailed flow information (development)
211
+ logger.debug('Cache hit', { key: 'user:123', ttl: 300 });
212
+
213
+ // Very detailed debugging (development only)
214
+ logger.silly('Raw request data', { headers, body });
215
+ ```
216
+
217
+ ### 2. Include Context in Logs
218
+
219
+ ```typescript
220
+ // Good - includes context
221
+ logger.error('Database query failed', {
222
+ query: 'SELECT * FROM users',
223
+ error,
224
+ duration: 1500
225
+ });
226
+
227
+ // Bad - lacks context
228
+ logger.error('Query failed');
229
+ ```
230
+
231
+ ### 3. Use Child Loggers for Modules
232
+
233
+ ```typescript
234
+ // api/users.ts
235
+ const userLogger = createChildLogger({ module: 'users' });
236
+
237
+ export function getUser(id: number) {
238
+ userLogger.info('Fetching user', { userId: id });
239
+ // ...
240
+ }
241
+
242
+ // api/orders.ts
243
+ const orderLogger = createChildLogger({ module: 'orders' });
244
+
245
+ export function createOrder(data: Order) {
246
+ orderLogger.info('Creating order', { order: data });
247
+ // ...
248
+ }
249
+ ```
250
+
251
+ ### 4. Structured Logging
252
+
253
+ ```typescript
254
+ // Good - structured and searchable
255
+ logger.info('User login', {
256
+ event: 'user.login',
257
+ userId: 123,
258
+ ip: req.ip,
259
+ userAgent: req.headers['user-agent']
260
+ });
261
+
262
+ // Bad - unstructured string
263
+ logger.info(`User ${userId} logged in from ${ip}`);
264
+ ```
265
+
266
+ ## Performance Considerations
267
+
268
+ - **File I/O**: File transports use buffered writes (minimal overhead)
269
+ - **Log Rotation**: Automatic rotation prevents disk space issues
270
+ - **Conditional Logging**: Check log level before expensive operations
271
+
272
+ ```typescript
273
+ // Avoid expensive serialization if not needed
274
+ if (logLevel === 'debug') {
275
+ logger.debug('Complex object', JSON.stringify(largeObject, null, 2));
276
+ }
277
+ ```
278
+
279
+ ## Types
280
+
281
+ ```typescript
282
+ import type { winston } from '@md-oss/observability';
283
+
284
+ // winston is re-exported from the winston package
285
+ const logger: winston.Logger = createChildLogger({ service: 'my-service' });
286
+ ```
287
+
288
+ ## API Reference
289
+
290
+ ### Logger
291
+
292
+ - `logger.error(message, metadata?)` - Log error level
293
+ - `logger.warn(message, metadata?)` - Log warning level
294
+ - `logger.info(message, metadata?)` - Log info level
295
+ - `logger.verbose(message, metadata?)` - Log verbose level
296
+ - `logger.debug(message, metadata?)` - Log debug level
297
+ - `logger.silly(message, metadata?)` - Log silly level
298
+
299
+ ### Functions
300
+
301
+ - `createChildLogger(metadata)` - Create a contextual logger with default metadata
302
+
303
+ ### Exports
304
+
305
+ - `logger: winston.Logger` - Main logger instance
306
+ - `logLevel: string` - Current log level
307
+ - `transports: winston.transport[]` - Array of active transports
308
+ - `winston: typeof winston` - Winston type exports
package/dist/env.cjs ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";var o=Object.defineProperty;var n=(r,O)=>o(r,"name",{value:O,configurable:!0});var t=require("@t3-oss/env-nextjs"),e=require("zod/v4");const L=n(()=>t.createEnv({server:{NODE_ENV:e.z.enum(["development","production","test"]).default("development"),LOG_LEVEL:e.z.enum(["error","warn","info","verbose","debug","silly"]).default("info"),LOG_DIR:e.z.string().optional(),LOG_TO_CONSOLE:e.z.boolean().default(!0)},client:{},runtimeEnv:{NODE_ENV:"production",LOG_LEVEL:process.env.LOG_LEVEL||"info",LOG_DIR:process.env.LOG_DIR,LOG_TO_CONSOLE:process.env.LOG_TO_CONSOLE!=="false"}}),"env");exports.env=L;
2
+ //# sourceMappingURL=env.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.cjs","sources":["../src/env.ts"],"sourcesContent":["import { createEnv } from '@t3-oss/env-nextjs';\nimport { z } from 'zod/v4';\n\nexport const env = (): Readonly<{\n\tLOG_DIR?: string | undefined;\n\tNODE_ENV: 'development' | 'production' | 'test';\n\tLOG_LEVEL: 'error' | 'warn' | 'info' | 'verbose' | 'debug' | 'silly';\n\tLOG_TO_CONSOLE: boolean;\n}> =>\n\tcreateEnv({\n\t\tserver: {\n\t\t\tNODE_ENV: z\n\t\t\t\t.enum(['development', 'production', 'test'])\n\t\t\t\t.default('development'),\n\t\t\tLOG_LEVEL: z\n\t\t\t\t.enum(['error', 'warn', 'info', 'verbose', 'debug', 'silly'])\n\t\t\t\t.default('info'),\n\t\t\tLOG_DIR: z.string().optional(),\n\t\t\tLOG_TO_CONSOLE: z.boolean().default(true),\n\t\t},\n\t\tclient: {},\n\t\truntimeEnv: {\n\t\t\tNODE_ENV: process.env.NODE_ENV || 'development',\n\t\t\tLOG_LEVEL: process.env.LOG_LEVEL || 'info',\n\t\t\tLOG_DIR: process.env.LOG_DIR,\n\t\t\tLOG_TO_CONSOLE: process.env.LOG_TO_CONSOLE !== 'false',\n\t\t},\n\t});\n"],"names":["env","__name","createEnv","z"],"mappings":"oJAGO,MAAMA,EAAMC,EAAA,IAMlBC,EAAAA,UAAU,CACT,OAAQ,CACP,SAAUC,EAAAA,EACR,KAAK,CAAC,cAAe,aAAc,MAAM,CAAC,EAC1C,QAAQ,aAAa,EACvB,UAAWA,EAAAA,EACT,KAAK,CAAC,QAAS,OAAQ,OAAQ,UAAW,QAAS,OAAO,CAAC,EAC3D,QAAQ,MAAM,EAChB,QAASA,EAAAA,EAAE,OAAA,EAAS,SAAA,EACpB,eAAgBA,EAAAA,EAAE,QAAA,EAAU,QAAQ,EAAI,CAAA,EAEzC,OAAQ,CAAA,EACR,WAAY,CACX,SAAU,aACV,UAAW,QAAQ,IAAI,WAAa,OACpC,QAAS,QAAQ,IAAI,QACrB,eAAgB,QAAQ,IAAI,iBAAmB,OAAA,CAEjD,CAAC,EAxBiB"}
package/dist/env.d.cts ADDED
@@ -0,0 +1,8 @@
1
+ declare const env: () => Readonly<{
2
+ LOG_DIR?: string | undefined;
3
+ NODE_ENV: "development" | "production" | "test";
4
+ LOG_LEVEL: "error" | "warn" | "info" | "verbose" | "debug" | "silly";
5
+ LOG_TO_CONSOLE: boolean;
6
+ }>;
7
+
8
+ export { env };
package/dist/env.d.mts ADDED
@@ -0,0 +1,8 @@
1
+ declare const env: () => Readonly<{
2
+ LOG_DIR?: string | undefined;
3
+ NODE_ENV: "development" | "production" | "test";
4
+ LOG_LEVEL: "error" | "warn" | "info" | "verbose" | "debug" | "silly";
5
+ LOG_TO_CONSOLE: boolean;
6
+ }>;
7
+
8
+ export { env };
package/dist/env.mjs ADDED
@@ -0,0 +1,2 @@
1
+ var O=Object.defineProperty;var o=(n,r)=>O(n,"name",{value:r,configurable:!0});import{createEnv as t}from"@t3-oss/env-nextjs";import{z as e}from"zod/v4";const L=o(()=>t({server:{NODE_ENV:e.enum(["development","production","test"]).default("development"),LOG_LEVEL:e.enum(["error","warn","info","verbose","debug","silly"]).default("info"),LOG_DIR:e.string().optional(),LOG_TO_CONSOLE:e.boolean().default(!0)},client:{},runtimeEnv:{NODE_ENV:"production",LOG_LEVEL:process.env.LOG_LEVEL||"info",LOG_DIR:process.env.LOG_DIR,LOG_TO_CONSOLE:process.env.LOG_TO_CONSOLE!=="false"}}),"env");export{L as env};
2
+ //# sourceMappingURL=env.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.mjs","sources":["../src/env.ts"],"sourcesContent":["import { createEnv } from '@t3-oss/env-nextjs';\nimport { z } from 'zod/v4';\n\nexport const env = (): Readonly<{\n\tLOG_DIR?: string | undefined;\n\tNODE_ENV: 'development' | 'production' | 'test';\n\tLOG_LEVEL: 'error' | 'warn' | 'info' | 'verbose' | 'debug' | 'silly';\n\tLOG_TO_CONSOLE: boolean;\n}> =>\n\tcreateEnv({\n\t\tserver: {\n\t\t\tNODE_ENV: z\n\t\t\t\t.enum(['development', 'production', 'test'])\n\t\t\t\t.default('development'),\n\t\t\tLOG_LEVEL: z\n\t\t\t\t.enum(['error', 'warn', 'info', 'verbose', 'debug', 'silly'])\n\t\t\t\t.default('info'),\n\t\t\tLOG_DIR: z.string().optional(),\n\t\t\tLOG_TO_CONSOLE: z.boolean().default(true),\n\t\t},\n\t\tclient: {},\n\t\truntimeEnv: {\n\t\t\tNODE_ENV: process.env.NODE_ENV || 'development',\n\t\t\tLOG_LEVEL: process.env.LOG_LEVEL || 'info',\n\t\t\tLOG_DIR: process.env.LOG_DIR,\n\t\t\tLOG_TO_CONSOLE: process.env.LOG_TO_CONSOLE !== 'false',\n\t\t},\n\t});\n"],"names":["env","__name","createEnv","z"],"mappings":"yJAGO,MAAMA,EAAMC,EAAA,IAMlBC,EAAU,CACT,OAAQ,CACP,SAAUC,EACR,KAAK,CAAC,cAAe,aAAc,MAAM,CAAC,EAC1C,QAAQ,aAAa,EACvB,UAAWA,EACT,KAAK,CAAC,QAAS,OAAQ,OAAQ,UAAW,QAAS,OAAO,CAAC,EAC3D,QAAQ,MAAM,EAChB,QAASA,EAAE,OAAA,EAAS,SAAA,EACpB,eAAgBA,EAAE,QAAA,EAAU,QAAQ,EAAI,CAAA,EAEzC,OAAQ,CAAA,EACR,WAAY,CACX,SAAU,aACV,UAAW,QAAQ,IAAI,WAAa,OACpC,QAAS,QAAQ,IAAI,QACrB,eAAgB,QAAQ,IAAI,iBAAmB,OAAA,CAEjD,CAAC,EAxBiB"}
package/dist/index.cjs ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";var f=Object.defineProperty;var t=(e,u)=>f(e,"name",{value:u,configurable:!0});var o=require("node:path"),r=require("winston"),d=require("./env.cjs");require("@t3-oss/env-nextjs"),require("zod/v4");const{LOG_DIR:n,LOG_LEVEL:L,LOG_TO_CONSOLE:w}=d.env(),l=10*1024*1024,{combine:c,timestamp:m,json:Y,errors:p,splat:g,colorize:_,simple:j}=r.format,s=[],a=L||"info",i=t(()=>new r.transports.Console({format:c(_(),m({format:"YYYY-MM-DD HH:mm:ss"}),p({stack:!0}),g(),j()),level:a}),"consoleTransport");if(n){const e=o.join(process.cwd(),n);s.push(new r.transports.File({filename:o.join(e,"errors.log"),level:"error",maxsize:l,maxFiles:3,dirname:e}),new r.transports.File({filename:o.join(e,"combined.log"),maxsize:l,maxFiles:7,dirname:e}))}w&&s.push(i());const v=r.createLogger({level:a,format:c(m({format:"YYYY-MM-DD HH:mm:ss"}),p({stack:!0}),g(),Y()),transports:s,defaultMeta:{service:process.env.npm_package_name||"unknown",version:process.env.npm_package_version||"unknown"},exceptionHandlers:[i(),new r.transports.File({filename:o.join(n||"","exceptions.log")})],rejectionHandlers:[i(),new r.transports.File({filename:o.join(n||"","rejections.log")})]}),h=t(e=>v.child(e),"createChildLogger");exports.createChildLogger=h,exports.logLevel=a,exports.logger=v,exports.transports=s;
2
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../src/index.ts"],"sourcesContent":["import path from 'node:path';\nimport winston from 'winston';\nimport { env } from './env';\n\nconst { LOG_DIR, LOG_LEVEL, LOG_TO_CONSOLE } = env();\n\nconst TEN_MEGABYTES = 10 * 1024 * 1024;\nconst { combine, timestamp, json, errors, splat, colorize, simple } =\n\twinston.format;\n\nconst transports: winston.transport[] = [];\nconst logLevel: 'error' | 'warn' | 'info' | 'verbose' | 'debug' | 'silly' =\n\tLOG_LEVEL || 'info';\n\nconst consoleTransport = () =>\n\tnew winston.transports.Console({\n\t\tformat: combine(\n\t\t\tcolorize(),\n\t\t\ttimestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),\n\t\t\terrors({ stack: true }),\n\t\t\tsplat(),\n\t\t\tsimple()\n\t\t),\n\t\tlevel: logLevel,\n\t});\n\nif (LOG_DIR) {\n\tconst resolvedPath = path.join(process.cwd(), LOG_DIR);\n\ttransports.push(\n\t\tnew winston.transports.File({\n\t\t\tfilename: path.join(resolvedPath, 'errors.log'),\n\t\t\tlevel: 'error',\n\t\t\tmaxsize: TEN_MEGABYTES,\n\t\t\tmaxFiles: 3,\n\t\t\tdirname: resolvedPath,\n\t\t}),\n\t\tnew winston.transports.File({\n\t\t\tfilename: path.join(resolvedPath, 'combined.log'),\n\t\t\tmaxsize: TEN_MEGABYTES,\n\t\t\tmaxFiles: 7,\n\t\t\tdirname: resolvedPath,\n\t\t})\n\t);\n}\n\nif (LOG_TO_CONSOLE) {\n\ttransports.push(consoleTransport());\n}\n\nconst logger: winston.Logger = winston.createLogger({\n\tlevel: logLevel,\n\tformat: combine(\n\t\ttimestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),\n\t\terrors({ stack: true }),\n\t\tsplat(),\n\t\tjson()\n\t),\n\ttransports,\n\tdefaultMeta: {\n\t\tservice: process.env.npm_package_name || 'unknown',\n\t\tversion: process.env.npm_package_version || 'unknown',\n\t},\n\texceptionHandlers: [\n\t\tconsoleTransport(),\n\t\tnew winston.transports.File({\n\t\t\tfilename: path.join(LOG_DIR || '', 'exceptions.log'),\n\t\t}),\n\t],\n\trejectionHandlers: [\n\t\tconsoleTransport(),\n\t\tnew winston.transports.File({\n\t\t\tfilename: path.join(LOG_DIR || '', 'rejections.log'),\n\t\t}),\n\t],\n});\n\nconst createChildLogger = (meta: Record<string, unknown>): winston.Logger => {\n\treturn logger.child(meta);\n};\n\nexport { logger, logLevel, type winston, transports, createChildLogger };\n"],"names":["LOG_DIR","LOG_LEVEL","LOG_TO_CONSOLE","env","TEN_MEGABYTES","combine","timestamp","json","errors","splat","colorize","simple","winston","transports","logLevel","consoleTransport","__name","resolvedPath","path","logger","createChildLogger","meta"],"mappings":"mNAIA,KAAM,CAAE,QAAAA,EAAS,UAAAC,EAAW,eAAAC,CAAA,EAAmBC,EAAAA,IAAA,EAEzCC,EAAgB,GAAK,KAAO,KAC5B,CAAE,QAAAC,EAAS,UAAAC,EAAW,KAAAC,EAAM,OAAAC,EAAQ,MAAAC,EAAO,SAAAC,EAAU,OAAAC,GAC1DC,EAAQ,OAEHC,EAAkC,CAAA,EAClCC,EACLb,GAAa,OAERc,EAAmBC,EAAA,IACxB,IAAIJ,EAAQ,WAAW,QAAQ,CAC9B,OAAQP,EACPK,EAAA,EACAJ,EAAU,CAAE,OAAQ,sBAAuB,EAC3CE,EAAO,CAAE,MAAO,GAAM,EACtBC,EAAA,EACAE,EAAA,CAAO,EAER,MAAOG,CACR,CAAC,EAVuB,oBAYzB,GAAId,EAAS,CACZ,MAAMiB,EAAeC,EAAK,KAAK,QAAQ,IAAA,EAAOlB,CAAO,EACrDa,EAAW,KACV,IAAID,EAAQ,WAAW,KAAK,CAC3B,SAAUM,EAAK,KAAKD,EAAc,YAAY,EAC9C,MAAO,QACP,QAASb,EACT,SAAU,EACV,QAASa,CAAA,CACT,EACD,IAAIL,EAAQ,WAAW,KAAK,CAC3B,SAAUM,EAAK,KAAKD,EAAc,cAAc,EAChD,QAASb,EACT,SAAU,EACV,QAASa,CAAA,CACT,CAAA,CAEH,CAEIf,GACHW,EAAW,KAAKE,GAAkB,EAGnC,MAAMI,EAAyBP,EAAQ,aAAa,CACnD,MAAOE,EACP,OAAQT,EACPC,EAAU,CAAE,OAAQ,sBAAuB,EAC3CE,EAAO,CAAE,MAAO,GAAM,EACtBC,EAAA,EACAF,EAAA,CAAK,EAEN,WAAAM,EACA,YAAa,CACZ,QAAS,QAAQ,IAAI,kBAAoB,UACzC,QAAS,QAAQ,IAAI,qBAAuB,SAAA,EAE7C,kBAAmB,CAClBE,EAAA,EACA,IAAIH,EAAQ,WAAW,KAAK,CAC3B,SAAUM,EAAK,KAAKlB,GAAW,GAAI,gBAAgB,CAAA,CACnD,CAAA,EAEF,kBAAmB,CAClBe,EAAA,EACA,IAAIH,EAAQ,WAAW,KAAK,CAC3B,SAAUM,EAAK,KAAKlB,GAAW,GAAI,gBAAgB,CAAA,CACnD,CAAA,CAEH,CAAC,EAEKoB,EAAoBJ,EAACK,GACnBF,EAAO,MAAME,CAAI,EADC"}
@@ -0,0 +1,9 @@
1
+ import winston from 'winston';
2
+ export { default as winston } from 'winston';
3
+
4
+ declare const transports: winston.transport[];
5
+ declare const logLevel: 'error' | 'warn' | 'info' | 'verbose' | 'debug' | 'silly';
6
+ declare const logger: winston.Logger;
7
+ declare const createChildLogger: (meta: Record<string, unknown>) => winston.Logger;
8
+
9
+ export { createChildLogger, logLevel, logger, transports };
@@ -0,0 +1,9 @@
1
+ import winston from 'winston';
2
+ export { default as winston } from 'winston';
3
+
4
+ declare const transports: winston.transport[];
5
+ declare const logLevel: 'error' | 'warn' | 'info' | 'verbose' | 'debug' | 'silly';
6
+ declare const logger: winston.Logger;
7
+ declare const createChildLogger: (meta: Record<string, unknown>) => winston.Logger;
8
+
9
+ export { createChildLogger, logLevel, logger, transports };
package/dist/index.mjs ADDED
@@ -0,0 +1,2 @@
1
+ var d=Object.defineProperty;var t=(e,v)=>d(e,"name",{value:v,configurable:!0});import n from"node:path";import o from"winston";import{env as w}from"./env.mjs";import"@t3-oss/env-nextjs";import"zod/v4";const{LOG_DIR:r,LOG_LEVEL:L,LOG_TO_CONSOLE:Y}=w(),m=10*1024*1024,{combine:l,timestamp:c,json:_,errors:p,splat:f,colorize:j,simple:u}=o.format,s=[],i=L||"info",a=t(()=>new o.transports.Console({format:l(j(),c({format:"YYYY-MM-DD HH:mm:ss"}),p({stack:!0}),f(),u()),level:i}),"consoleTransport");if(r){const e=n.join(process.cwd(),r);s.push(new o.transports.File({filename:n.join(e,"errors.log"),level:"error",maxsize:m,maxFiles:3,dirname:e}),new o.transports.File({filename:n.join(e,"combined.log"),maxsize:m,maxFiles:7,dirname:e}))}Y&&s.push(a());const g=o.createLogger({level:i,format:l(c({format:"YYYY-MM-DD HH:mm:ss"}),p({stack:!0}),f(),_()),transports:s,defaultMeta:{service:process.env.npm_package_name||"unknown",version:process.env.npm_package_version||"unknown"},exceptionHandlers:[a(),new o.transports.File({filename:n.join(r||"","exceptions.log")})],rejectionHandlers:[a(),new o.transports.File({filename:n.join(r||"","rejections.log")})]}),x=t(e=>g.child(e),"createChildLogger");export{x as createChildLogger,i as logLevel,g as logger,s as transports};
2
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sources":["../src/index.ts"],"sourcesContent":["import path from 'node:path';\nimport winston from 'winston';\nimport { env } from './env';\n\nconst { LOG_DIR, LOG_LEVEL, LOG_TO_CONSOLE } = env();\n\nconst TEN_MEGABYTES = 10 * 1024 * 1024;\nconst { combine, timestamp, json, errors, splat, colorize, simple } =\n\twinston.format;\n\nconst transports: winston.transport[] = [];\nconst logLevel: 'error' | 'warn' | 'info' | 'verbose' | 'debug' | 'silly' =\n\tLOG_LEVEL || 'info';\n\nconst consoleTransport = () =>\n\tnew winston.transports.Console({\n\t\tformat: combine(\n\t\t\tcolorize(),\n\t\t\ttimestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),\n\t\t\terrors({ stack: true }),\n\t\t\tsplat(),\n\t\t\tsimple()\n\t\t),\n\t\tlevel: logLevel,\n\t});\n\nif (LOG_DIR) {\n\tconst resolvedPath = path.join(process.cwd(), LOG_DIR);\n\ttransports.push(\n\t\tnew winston.transports.File({\n\t\t\tfilename: path.join(resolvedPath, 'errors.log'),\n\t\t\tlevel: 'error',\n\t\t\tmaxsize: TEN_MEGABYTES,\n\t\t\tmaxFiles: 3,\n\t\t\tdirname: resolvedPath,\n\t\t}),\n\t\tnew winston.transports.File({\n\t\t\tfilename: path.join(resolvedPath, 'combined.log'),\n\t\t\tmaxsize: TEN_MEGABYTES,\n\t\t\tmaxFiles: 7,\n\t\t\tdirname: resolvedPath,\n\t\t})\n\t);\n}\n\nif (LOG_TO_CONSOLE) {\n\ttransports.push(consoleTransport());\n}\n\nconst logger: winston.Logger = winston.createLogger({\n\tlevel: logLevel,\n\tformat: combine(\n\t\ttimestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),\n\t\terrors({ stack: true }),\n\t\tsplat(),\n\t\tjson()\n\t),\n\ttransports,\n\tdefaultMeta: {\n\t\tservice: process.env.npm_package_name || 'unknown',\n\t\tversion: process.env.npm_package_version || 'unknown',\n\t},\n\texceptionHandlers: [\n\t\tconsoleTransport(),\n\t\tnew winston.transports.File({\n\t\t\tfilename: path.join(LOG_DIR || '', 'exceptions.log'),\n\t\t}),\n\t],\n\trejectionHandlers: [\n\t\tconsoleTransport(),\n\t\tnew winston.transports.File({\n\t\t\tfilename: path.join(LOG_DIR || '', 'rejections.log'),\n\t\t}),\n\t],\n});\n\nconst createChildLogger = (meta: Record<string, unknown>): winston.Logger => {\n\treturn logger.child(meta);\n};\n\nexport { logger, logLevel, type winston, transports, createChildLogger };\n"],"names":["LOG_DIR","LOG_LEVEL","LOG_TO_CONSOLE","env","TEN_MEGABYTES","combine","timestamp","json","errors","splat","colorize","simple","winston","transports","logLevel","consoleTransport","__name","resolvedPath","path","logger","createChildLogger","meta"],"mappings":"yMAIA,KAAM,CAAE,QAAAA,EAAS,UAAAC,EAAW,eAAAC,CAAA,EAAmBC,EAAA,EAEzCC,EAAgB,GAAK,KAAO,KAC5B,CAAE,QAAAC,EAAS,UAAAC,EAAW,KAAAC,EAAM,OAAAC,EAAQ,MAAAC,EAAO,SAAAC,EAAU,OAAAC,GAC1DC,EAAQ,OAEHC,EAAkC,CAAA,EAClCC,EACLb,GAAa,OAERc,EAAmBC,EAAA,IACxB,IAAIJ,EAAQ,WAAW,QAAQ,CAC9B,OAAQP,EACPK,EAAA,EACAJ,EAAU,CAAE,OAAQ,sBAAuB,EAC3CE,EAAO,CAAE,MAAO,GAAM,EACtBC,EAAA,EACAE,EAAA,CAAO,EAER,MAAOG,CACR,CAAC,EAVuB,oBAYzB,GAAId,EAAS,CACZ,MAAMiB,EAAeC,EAAK,KAAK,QAAQ,IAAA,EAAOlB,CAAO,EACrDa,EAAW,KACV,IAAID,EAAQ,WAAW,KAAK,CAC3B,SAAUM,EAAK,KAAKD,EAAc,YAAY,EAC9C,MAAO,QACP,QAASb,EACT,SAAU,EACV,QAASa,CAAA,CACT,EACD,IAAIL,EAAQ,WAAW,KAAK,CAC3B,SAAUM,EAAK,KAAKD,EAAc,cAAc,EAChD,QAASb,EACT,SAAU,EACV,QAASa,CAAA,CACT,CAAA,CAEH,CAEIf,GACHW,EAAW,KAAKE,GAAkB,EAGnC,MAAMI,EAAyBP,EAAQ,aAAa,CACnD,MAAOE,EACP,OAAQT,EACPC,EAAU,CAAE,OAAQ,sBAAuB,EAC3CE,EAAO,CAAE,MAAO,GAAM,EACtBC,EAAA,EACAF,EAAA,CAAK,EAEN,WAAAM,EACA,YAAa,CACZ,QAAS,QAAQ,IAAI,kBAAoB,UACzC,QAAS,QAAQ,IAAI,qBAAuB,SAAA,EAE7C,kBAAmB,CAClBE,EAAA,EACA,IAAIH,EAAQ,WAAW,KAAK,CAC3B,SAAUM,EAAK,KAAKlB,GAAW,GAAI,gBAAgB,CAAA,CACnD,CAAA,EAEF,kBAAmB,CAClBe,EAAA,EACA,IAAIH,EAAQ,WAAW,KAAK,CAC3B,SAAUM,EAAK,KAAKlB,GAAW,GAAI,gBAAgB,CAAA,CACnD,CAAA,CAEH,CAAC,EAEKoB,EAAoBJ,EAACK,GACnBF,EAAO,MAAME,CAAI,EADC"}
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "@md-oss/observability",
3
+ "version": "0.1.0",
4
+ "private": false,
5
+ "publishConfig": {
6
+ "access": "public",
7
+ "registry": "https://registry.npmjs.org/"
8
+ },
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+ssh://git@github.com/Mirasaki-OSS/monorepo-template.git",
12
+ "directory": "vendor/observability"
13
+ },
14
+ "type": "module",
15
+ "description": "Structured logging with Winston",
16
+ "license": "ISC",
17
+ "main": "./dist/index.cjs",
18
+ "module": "./dist/index.mjs",
19
+ "types": "./dist/index.d.cts",
20
+ "files": [
21
+ "dist/**/*",
22
+ "README.md",
23
+ "LICENSE"
24
+ ],
25
+ "exports": {
26
+ ".": {
27
+ "require": {
28
+ "types": "./dist/index.d.cts",
29
+ "default": "./dist/index.cjs"
30
+ },
31
+ "import": {
32
+ "types": "./dist/index.d.mts",
33
+ "default": "./dist/index.mjs"
34
+ }
35
+ },
36
+ "./env": {
37
+ "require": {
38
+ "types": "./dist/env.d.cts",
39
+ "default": "./dist/env.cjs"
40
+ },
41
+ "import": {
42
+ "types": "./dist/env.d.mts",
43
+ "default": "./dist/env.mjs"
44
+ }
45
+ }
46
+ },
47
+ "dependencies": {
48
+ "@t3-oss/env-nextjs": "^0.13.10",
49
+ "winston": "^3.19.0",
50
+ "zod": "^4.3.6",
51
+ "@md-oss/config": "^0.1.0"
52
+ },
53
+ "devDependencies": {
54
+ "@types/node": "^25.0.9",
55
+ "pkgroll": "^2.21.5",
56
+ "typescript": "^5.9.3"
57
+ },
58
+ "scripts": {
59
+ "build": "pkgroll --minify --clean-dist --sourcemap --define.process.env.NODE_ENV='\"production\"' --define.DEBUG=false",
60
+ "clean": "git clean -xdf .turbo dist node_modules tsconfig.tsbuildinfo",
61
+ "dev": "tsc --watch",
62
+ "typecheck": "tsc --noEmit"
63
+ }
64
+ }