logging
This commit is contained in:
@@ -1,12 +1,14 @@
|
||||
import type { AnalyticsService } from './analytics/analytics-service';
|
||||
import type { CacheService } from './cache/cache-service';
|
||||
import type { ErrorReportingService } from './errors/error-reporting-service';
|
||||
import type { LoggerService } from './logging/logger-service';
|
||||
|
||||
// Simple constructor-based DI container.
|
||||
export class AppServices {
|
||||
constructor(
|
||||
public readonly analytics: AnalyticsService,
|
||||
public readonly errors: ErrorReportingService,
|
||||
public readonly cache: CacheService
|
||||
public readonly cache: CacheService,
|
||||
public readonly logger: LoggerService
|
||||
) {}
|
||||
}
|
||||
|
||||
8
lib/services/cache/redis-cache-service.ts
vendored
8
lib/services/cache/redis-cache-service.ts
vendored
@@ -1,5 +1,6 @@
|
||||
import { createClient, type RedisClientType } from 'redis';
|
||||
import type { CacheService, CacheSetOptions } from './cache-service';
|
||||
import { getServerAppServices } from '../create-services.server';
|
||||
|
||||
export type RedisCacheServiceOptions = {
|
||||
url: string;
|
||||
@@ -17,7 +18,12 @@ export class RedisCacheService implements CacheService {
|
||||
this.keyPrefix = options.keyPrefix ?? '';
|
||||
|
||||
// Fire-and-forget connect.
|
||||
this.client.connect().catch(() => undefined);
|
||||
this.client.connect().catch((err) => {
|
||||
// We can't use getServerAppServices() here because it might cause a circular dependency
|
||||
// during initialization. But we can log to console as a fallback or use a global logger if we had one.
|
||||
// For now, let's just use console.error as this is a low-level service.
|
||||
console.error('Redis connection error:', err);
|
||||
});
|
||||
}
|
||||
|
||||
private k(key: string) {
|
||||
|
||||
@@ -7,6 +7,7 @@ import { MemoryCacheService } from './cache/memory-cache-service';
|
||||
import { RedisCacheService } from './cache/redis-cache-service';
|
||||
import { GlitchtipErrorReportingService } from './errors/glitchtip-error-reporting-service';
|
||||
import { NoopErrorReportingService } from './errors/noop-error-reporting-service';
|
||||
import { PinoLoggerService } from './logging/pino-logger-service';
|
||||
|
||||
let singleton: AppServices | undefined;
|
||||
|
||||
@@ -32,7 +33,9 @@ export function getServerAppServices(): AppServices {
|
||||
})
|
||||
: new MemoryCacheService();
|
||||
|
||||
singleton = new AppServices(analytics, errors, cache);
|
||||
const logger = new PinoLoggerService('server');
|
||||
|
||||
singleton = new AppServices(analytics, errors, cache, logger);
|
||||
return singleton;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ import { UmamiAnalyticsService } from './analytics/umami-analytics-service';
|
||||
import { MemoryCacheService } from './cache/memory-cache-service';
|
||||
import { GlitchtipErrorReportingService } from './errors/glitchtip-error-reporting-service';
|
||||
import { NoopErrorReportingService } from './errors/noop-error-reporting-service';
|
||||
import { NoopLoggerService } from './logging/noop-logger-service';
|
||||
import { PinoLoggerService } from './logging/pino-logger-service';
|
||||
|
||||
/**
|
||||
* Singleton instance of AppServices.
|
||||
@@ -93,7 +95,12 @@ export function getAppServices(): AppServices {
|
||||
// Use [`getServerAppServices()`](lib/services/create-services.server.ts:1) on the server.
|
||||
const cache = new MemoryCacheService();
|
||||
|
||||
const logger =
|
||||
typeof window === 'undefined'
|
||||
? new PinoLoggerService('server')
|
||||
: new NoopLoggerService();
|
||||
|
||||
// Create and cache the singleton
|
||||
singleton = new AppServices(analytics, errors, cache);
|
||||
singleton = new AppServices(analytics, errors, cache, logger);
|
||||
return singleton;
|
||||
}
|
||||
|
||||
11
lib/services/logging/logger-service.ts
Normal file
11
lib/services/logging/logger-service.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
export type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal';
|
||||
|
||||
export interface LoggerService {
|
||||
trace(msg: string, ...args: any[]): void;
|
||||
debug(msg: string, ...args: any[]): void;
|
||||
info(msg: string, ...args: any[]): void;
|
||||
warn(msg: string, ...args: any[]): void;
|
||||
error(msg: string, ...args: any[]): void;
|
||||
fatal(msg: string, ...args: any[]): void;
|
||||
child(bindings: Record<string, any>): LoggerService;
|
||||
}
|
||||
13
lib/services/logging/noop-logger-service.ts
Normal file
13
lib/services/logging/noop-logger-service.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import type { LoggerService } from './logger-service';
|
||||
|
||||
export class NoopLoggerService implements LoggerService {
|
||||
trace() {}
|
||||
debug() {}
|
||||
info() {}
|
||||
warn() {}
|
||||
error() {}
|
||||
fatal() {}
|
||||
child() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
58
lib/services/logging/pino-logger-service.ts
Normal file
58
lib/services/logging/pino-logger-service.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import pino, { Logger as PinoLogger } from 'pino';
|
||||
import type { LoggerService } from './logger-service';
|
||||
|
||||
export class PinoLoggerService implements LoggerService {
|
||||
private readonly logger: PinoLogger;
|
||||
|
||||
constructor(name?: string, parent?: PinoLogger) {
|
||||
if (parent) {
|
||||
this.logger = parent.child({ name });
|
||||
} else {
|
||||
this.logger = pino({
|
||||
name: name || 'app',
|
||||
level: process.env.LOG_LEVEL || 'info',
|
||||
transport:
|
||||
process.env.NODE_ENV !== 'production'
|
||||
? {
|
||||
target: 'pino-pretty',
|
||||
options: {
|
||||
colorize: true,
|
||||
},
|
||||
}
|
||||
: undefined,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
trace(msg: string, ...args: any[]) {
|
||||
this.logger.trace(msg, ...args);
|
||||
}
|
||||
|
||||
debug(msg: string, ...args: any[]) {
|
||||
this.logger.debug(msg, ...args);
|
||||
}
|
||||
|
||||
info(msg: string, ...args: any[]) {
|
||||
this.logger.info(msg, ...args);
|
||||
}
|
||||
|
||||
warn(msg: string, ...args: any[]) {
|
||||
this.logger.warn(msg, ...args);
|
||||
}
|
||||
|
||||
error(msg: string, ...args: any[]) {
|
||||
this.logger.error(msg, ...args);
|
||||
}
|
||||
|
||||
fatal(msg: string, ...args: any[]) {
|
||||
this.logger.fatal(msg, ...args);
|
||||
}
|
||||
|
||||
child(bindings: Record<string, any>): LoggerService {
|
||||
const childPino = this.logger.child(bindings);
|
||||
const service = new PinoLoggerService();
|
||||
// @ts-ignore - accessing private member for child creation
|
||||
service.logger = childPino;
|
||||
return service;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user