Files
ldap-identidy/apps/api/src/application-info-log/application-info-logger.service.ts
Bastian Wagner 5973658582 logging
2026-07-17 15:34:42 +02:00

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];
}