Skip to content

Commit 036f08a

Browse files
Copilothotlong
andcommitted
Task 1.1: Merge logger.zod.ts into logging.zod.ts with backward compatibility
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent 31f8bcb commit 036f08a

4 files changed

Lines changed: 270 additions & 99 deletions

File tree

packages/spec/src/system/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ export * from './tracing.zod';
2424
export * from './manifest.zod';
2525
export * from './plugin.zod';
2626
export * from './plugin-capability.zod';
27-
export * from './logger.zod';
2827
export * from './context.zod';
2928
export * from './scoped-storage.zod';
3029
export * from './datasource.zod';

packages/spec/src/system/logger.zod.ts

Lines changed: 0 additions & 91 deletions
This file was deleted.

packages/spec/src/system/logging.test.ts

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import { describe, it, expect } from 'vitest';
22
import {
33
LogLevel,
4+
LogFormat,
5+
LoggerConfigSchema,
6+
LogEntrySchema,
47
ExtendedLogLevel,
58
LogDestinationType,
69
ConsoleDestinationConfigSchema,
@@ -11,11 +14,103 @@ import {
1114
LogEnrichmentConfigSchema,
1215
StructuredLogEntrySchema,
1316
LoggingConfigSchema,
17+
type LoggerConfig,
18+
type LogEntry,
1419
type LogDestination,
1520
type StructuredLogEntry,
1621
type LoggingConfig,
1722
} from './logging.zod';
1823

24+
describe('LogLevel', () => {
25+
it('should accept valid log levels', () => {
26+
const levels = ['debug', 'info', 'warn', 'error', 'fatal'];
27+
28+
levels.forEach((level) => {
29+
expect(() => LogLevel.parse(level)).not.toThrow();
30+
});
31+
});
32+
33+
it('should reject invalid log levels', () => {
34+
expect(() => LogLevel.parse('invalid')).toThrow();
35+
expect(() => LogLevel.parse('trace')).toThrow(); // trace is only in ExtendedLogLevel
36+
});
37+
});
38+
39+
describe('LogFormat', () => {
40+
it('should accept valid log formats', () => {
41+
const formats = ['json', 'text', 'pretty'];
42+
43+
formats.forEach((format) => {
44+
expect(() => LogFormat.parse(format)).not.toThrow();
45+
});
46+
});
47+
48+
it('should reject invalid log formats', () => {
49+
expect(() => LogFormat.parse('invalid')).toThrow();
50+
});
51+
});
52+
53+
describe('LoggerConfigSchema', () => {
54+
it('should accept minimal configuration', () => {
55+
const config = LoggerConfigSchema.parse({});
56+
57+
expect(config.level).toBe('info');
58+
expect(config.format).toBe('json');
59+
expect(config.sourceLocation).toBe(false);
60+
});
61+
62+
it('should accept full configuration', () => {
63+
const config: LoggerConfig = {
64+
name: 'my-logger',
65+
level: 'debug',
66+
format: 'pretty',
67+
redact: ['apiKey', 'password'],
68+
sourceLocation: true,
69+
file: '/var/log/app.log',
70+
rotation: {
71+
maxSize: '50m',
72+
maxFiles: 10,
73+
},
74+
};
75+
76+
expect(() => LoggerConfigSchema.parse(config)).not.toThrow();
77+
});
78+
79+
it('should apply defaults', () => {
80+
const config = LoggerConfigSchema.parse({});
81+
82+
expect(config.redact).toEqual(['password', 'token', 'secret', 'key']);
83+
});
84+
});
85+
86+
describe('LogEntrySchema', () => {
87+
it('should accept minimal log entry', () => {
88+
const entry: LogEntry = {
89+
timestamp: '2024-01-15T10:30:00.000Z',
90+
level: 'info',
91+
message: 'Application started',
92+
};
93+
94+
expect(() => LogEntrySchema.parse(entry)).not.toThrow();
95+
});
96+
97+
it('should accept full log entry', () => {
98+
const entry: LogEntry = {
99+
timestamp: '2024-01-15T10:30:00.000Z',
100+
level: 'error',
101+
message: 'Database connection failed',
102+
context: { database: 'postgres', attempt: 3 },
103+
error: { message: 'Connection timeout' },
104+
traceId: 'abc123',
105+
spanId: 'def456',
106+
service: 'api-server',
107+
component: 'database-pool',
108+
};
109+
110+
expect(() => LogEntrySchema.parse(entry)).not.toThrow();
111+
});
112+
});
113+
19114
describe('ExtendedLogLevel', () => {
20115
it('should accept valid log levels', () => {
21116
const levels = ['trace', 'debug', 'info', 'warn', 'error', 'fatal'];
@@ -268,6 +363,54 @@ describe('LoggingConfigSchema', () => {
268363
expect(() => LoggingConfigSchema.parse(config)).not.toThrow();
269364
});
270365

366+
it('should accept configuration with default logger', () => {
367+
const config: LoggingConfig = {
368+
name: 'app_logging',
369+
label: 'Application Logging',
370+
default: {
371+
level: 'info',
372+
format: 'json',
373+
},
374+
destinations: [
375+
{
376+
name: 'console',
377+
type: 'console',
378+
},
379+
],
380+
};
381+
382+
const parsed = LoggingConfigSchema.parse(config);
383+
expect(parsed.default).toBeDefined();
384+
expect(parsed.default?.level).toBe('info');
385+
});
386+
387+
it('should accept configuration with named loggers', () => {
388+
const config: LoggingConfig = {
389+
name: 'multi_logger',
390+
label: 'Multi Logger',
391+
default: {
392+
level: 'info',
393+
},
394+
loggers: {
395+
database: {
396+
level: 'debug',
397+
format: 'json',
398+
},
399+
http: {
400+
level: 'warn',
401+
format: 'text',
402+
},
403+
},
404+
destinations: [],
405+
};
406+
407+
const parsed = LoggingConfigSchema.parse(config);
408+
expect(parsed.loggers).toBeDefined();
409+
expect(parsed.loggers?.database).toBeDefined();
410+
expect(parsed.loggers?.database.level).toBe('debug');
411+
expect(parsed.loggers?.http.level).toBe('warn');
412+
});
413+
271414
it('should apply defaults', () => {
272415
const config = LoggingConfigSchema.parse({
273416
name: 'test_logging',
@@ -287,6 +430,15 @@ describe('LoggingConfigSchema', () => {
287430
label: 'Production Logging',
288431
enabled: true,
289432
level: 'warn',
433+
default: {
434+
level: 'info',
435+
format: 'json',
436+
},
437+
loggers: {
438+
app: {
439+
level: 'debug',
440+
},
441+
},
290442
destinations: [
291443
{
292444
name: 'console_dest',

0 commit comments

Comments
 (0)