I’d like to log my messages and use named fields, so that they appear in Kibana available fields menu for an index. The Logstash configuration I use:
input {
file {
path => "/logs/combined.log"
start_position => "beginning"
sincedb_path => "/dev/null"
codec => "json"
}
}
filter {
date {
match => [ "timestamp", "ISO8601" ]
}
}
output {
elasticsearch {
hosts => ["http://elasticsearch:9200"]
index => "application-logs-%{+YYYY.MM.dd}"
}
stdout {
codec => rubydebug
}
}
The nest.js logger definition I use:
import { Injectable, LoggerService } from '@nestjs/common';
import * as logform from 'logform';
import * as winston from 'winston';
const logFormat = logform.format.combine(
logform.format.timestamp(),
logform.format.printf(({ timestamp, level, message, ...meta }) => {
const logObject = {
timestamp,
level: level.toUpperCase(),
message,
...meta,
};
return JSON.stringify(logObject);
}),
);
@Injectable()
export class FileLoggerService implements LoggerService {
private readonly logger: winston.Logger;
constructor() {
this.logger = winston.createLogger({
level: 'info',
format: logFormat,
transports: [
new winston.transports.File({
filename: 'logs/error.log',
level: 'error',
}),
new winston.transports.File({ filename: 'logs/combined.log' }),
],
});
if (process.env.NODE_ENV !== 'production') {
this.logger.add(
new winston.transports.Console({
format: winston.format.simple(),
}),
);
}
}
public log(message: string, meta?: any) {
this.logger.info(message, meta);
}
public error(message: string, trace: string, meta?: any) {
this.logger.error(message, { trace, ...meta });
}
public warn(message: string, meta?: any) {
this.logger.warn(message, meta);
}
public debug(message: string, meta?: any) {
this.logger.debug(message, meta);
}
public verbose(message: string, meta?: any) {
this.logger.verbose(message, meta);
}
}
And finally, how I do the logging in a controller:
this.logger.log(
'Task management webhook invoked with {model}, {webhookEvent}, {externalId}.' +
'The original message was: {request}.',
{
model: entry.model,
event: entry.event,
externalId: entry.entry.id,
request: entry,
},
);
The issue is that new documents get the _jsonparsefailure
tag, and no additional fields are present for selection in Kibana.