This guide shows how to forward logs from an existing Winston setup to KloudMate with OpenTelemetry.
- A Node.js application that already uses Winston
- A KloudMate private key
- The ability to install additional npm packages
Assume your Express application already writes logs with Winston:
index.ts
import express from 'express'
import { createLogger, transports } from 'winston'
const logger = createLogger({
transports: [new transports.Console()],
})
const app = express()
const port = 5000
app.get('/', (req: any, res: any) => {
logger.info({ msg: 'received request', query: req.query })
res.send('hello world')
})
app.listen(port, () => {
logger.info(`Server is running at http://localhost:${port}`)
})
Install the packages required to emit OpenTelemetry logs:
npm i @opentelemetry/exporter-logs-otlp-http \
@opentelemetry/sdk-logs \
@opentelemetry/resources \
@opentelemetry/semantic-conventions
Create a customLogger.ts file that forwards Winston logs to KloudMate and still writes them to the console.
import { createLogger, transports } from 'winston'
import { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http'
import {
LoggerProvider,
BatchLogRecordProcessor,
} from '@opentelemetry/sdk-logs'
import { Resource } from '@opentelemetry/resources'
import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions'
import { SeverityNumber } from '@opentelemetry/api-logs'
const resource = Resource.default().merge(
new Resource({
[SemanticResourceAttributes.SERVICE_NAME]: 'my-app',
[SemanticResourceAttributes.SERVICE_VERSION]: '0.1.0',
})
)
const loggerProvider = new LoggerProvider({
resource: resource,
})
const logExporter = new OTLPLogExporter({
url: `https://otel.kloudmate.com:4318/v1/logs`,
headers: {
Authorization: 'KM_PRIVATE_KEY',
},
})
const logProcessor = new BatchLogRecordProcessor(logExporter)
loggerProvider.addLogRecordProcessor(logProcessor)
const formatLog = (args: any) =>
typeof args === 'string' ? args : JSON.stringify(args)
const consoleTransport = new transports.Console()
const logger = createLogger({
transports: [consoleTransport],
})
export const customLogger = {
...logger,
info: (args: any) => {
loggerProvider
.getLogger('otel-logger')
.emit({ body: formatLog(args), severityNumber: SeverityNumber.INFO })
return logger.info(args)
},
error: (args: any) => {
loggerProvider
.getLogger('otel-logger')
.emit({ body: formatLog(args), severityNumber: SeverityNumber.ERROR })
return logger.error(args)
},
}
Replace KM_PRIVATE_KEY with your KloudMate workspace private key.
Update index.ts to use the wrapped logger:
import { customLogger as logger } from './customLogger'
// ...same code as before
Start the application and generate a few requests. You should then see the emitted Winston logs in Log Explorer.