70 lines
2.9 KiB
TypeScript
70 lines
2.9 KiB
TypeScript
import { Injectable, Logger } from '@nestjs/common';
|
|
import { ConfigService } from '@nestjs/config';
|
|
import { InjectRepository } from '@nestjs/typeorm';
|
|
import { hostname } from 'node:os';
|
|
import { Repository } from 'typeorm';
|
|
import { sanitizeContext, sanitizeString } from '../application-error-log/application-error-sanitizer';
|
|
import { RequestContextService } from '../common/request-context.service';
|
|
import { ApplicationInfoLog } from './application-info-log.entity';
|
|
import { ApplicationInfoLogInput } from './application-info-log.types';
|
|
|
|
@Injectable()
|
|
export class ApplicationInfoLoggerService {
|
|
private readonly fallbackLogger = new Logger(ApplicationInfoLoggerService.name);
|
|
|
|
constructor(
|
|
@InjectRepository(ApplicationInfoLog)
|
|
private readonly logs: Repository<ApplicationInfoLog>,
|
|
private readonly config: ConfigService,
|
|
private readonly requestContext: RequestContextService,
|
|
) {}
|
|
|
|
async log(input: ApplicationInfoLogInput): Promise<void> {
|
|
const activeRequest = this.requestContext.get();
|
|
const request = { ...activeRequest, ...input.requestContext };
|
|
|
|
try {
|
|
await this.logs.save(
|
|
this.logs.create({
|
|
level: 'info',
|
|
action: sanitizeString(input.action),
|
|
category: optionalString(input.category),
|
|
outcome: input.outcome ?? 'SUCCESS',
|
|
message: optionalString(input.message),
|
|
actorType: input.actorType,
|
|
actorId: optionalString(input.actorId),
|
|
userId: optionalString(input.userId ?? request.userId),
|
|
clientId: optionalString(input.clientId),
|
|
tenantId: optionalString(input.tenantId ?? request.tenantId),
|
|
backendModule: optionalString(input.backendModule),
|
|
service: optionalString(input.service),
|
|
operation: optionalString(input.operation),
|
|
httpMethod: optionalString(request.method),
|
|
apiPath: optionalString(withoutQuery(request.path)),
|
|
httpStatusCode: input.requestContext?.statusCode,
|
|
correlationId: optionalString(request.correlationId),
|
|
ipAddress: optionalString(input.requestContext?.ipAddress),
|
|
userAgent: optionalString(input.requestContext?.userAgent),
|
|
environment: this.config.get<string>('NODE_ENV') ?? 'development',
|
|
host: hostname(),
|
|
context: sanitizeContext(input.context),
|
|
}),
|
|
);
|
|
} catch (error) {
|
|
const message = error instanceof Error ? error.message : String(error);
|
|
this.fallbackLogger.error(
|
|
`Application info log write failed for ${sanitizeString(input.action)}: ${sanitizeString(message)}`,
|
|
error instanceof Error ? error.stack : undefined,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
function optionalString(value?: string): string | undefined {
|
|
return value ? sanitizeString(value) : undefined;
|
|
}
|
|
|
|
function withoutQuery(value?: string): string | undefined {
|
|
return value?.split('?', 1)[0];
|
|
}
|