I am using winston
to log throughout my NextJS application. I want these logs to be collected in Azure Application Insights. Microsoft advises to do so using OpenTelemetry. My setup is as follows:
instrumentation.ts
:
import { env } from "~/env";
import { logs } from "@opentelemetry/api-logs";
import { LoggerProvider, SimpleLogRecordProcessor, ConsoleLogRecordExporter } from "@opentelemetry/sdk-logs";
import { BatchSpanProcessor, NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
import { Resource } from "@opentelemetry/resources";
import { registerOTel } from "@vercel/otel";
import { WinstonInstrumentation } from "@opentelemetry/instrumentation-winston";
import { ATTR_SERVICE_NAME } from "@opentelemetry/semantic-conventions";
import { registerInstrumentations } from "@opentelemetry/instrumentation";
export async function register() {
if (
process.env.NEXT_RUNTIME == "nodejs" &&
env.APPLICATIONINSIGHTS_CONNECTION_STRING != null
) {
console.log("Registering Application Insights");
const { AzureMonitorTraceExporter, AzureMonitorLogExporter } =
await import("@azure/monitor-opentelemetry-exporter");
const tracerProvider = new NodeTracerProvider({
resource: new Resource({
[ATTR_SERVICE_NAME]: env.APPLICATIONINSIGHTS_SERVICE_NAME,
}),
});
tracerProvider.register();
const traceExporter = new AzureMonitorTraceExporter({
connectionString: env.APPLICATIONINSIGHTS_CONNECTION_STRING,
});
tracerProvider.addSpanProcessor(
new BatchSpanProcessor(traceExporter, {
maxQueueSize: 10,
scheduledDelayMillis: 5000,
}),
);
const logExporter = new AzureMonitorLogExporter({
connectionString: env.APPLICATIONINSIGHTS_CONNECTION_STRING,
});
// Set up OpenTelemetry logging provider
const loggerProvider = new LoggerProvider();
// Add a log processor that will export the logs
loggerProvider.addLogRecordProcessor(
new SimpleLogRecordProcessor(logExporter),
);
// Add a processor to export log record
loggerProvider.addLogRecordProcessor(
new SimpleLogRecordProcessor(new ConsoleLogRecordExporter()),
);
logs.setGlobalLoggerProvider(loggerProvider);
const instrumentation = new WinstonInstrumentation({
disableLogSending: false,
enabled: true,
disableLogCorrelation: false,
});
registerOTel({
serviceName: env.APPLICATIONINSIGHTS_SERVICE_NAME,
traceExporter,
instrumentations: [instrumentation],
});
registerInstrumentations({
instrumentations: [instrumentation],
});
} else {
}
}
My winston setup is as follows:
import { env } from "~/env";
import winston, { type Logger } from "winston";
import { OpenTelemetryTransportV3 } from "@opentelemetry/winston-transport";
// Create a logger with custom format
const logger: Logger = winston.createLogger({
transports: [
new winston.transports.Console({
level: env.NODE_ENV == "test" ? "error" : "debug",
format: winston.format.simple(),
}),
new OpenTelemetryTransportV3(),
],
});
export default logger;
The application does show that the instrumentation code is being executed, and I do get request time information in Application Insights, but the traces
table in Application Insights remains empty. What am I doing wrong?
To resolve your issue with Winston logs not appearing in Azure Application Insights, follow these steps:
- Check Connection String: Ensure APPLICATIONINSIGHTS_CONNECTION_STRING is correctly set in your environment variables.
- Configure Log Exporter: Make sure AzureMonitorLogExporter is properly set up and added to the LoggerProvider.
- Persist User State: Verify that userType and token are stored and retrieved from local storage.
const logExporter = new AzureMonitorLogExporter({
connectionString: env.APPLICATIONINSIGHTS_CONNECTION_STRING,
});
const loggerProvider = new LoggerProvider();
loggerProvider.addLogRecordProcessor(new SimpleLogRecordProcessor(logExporter));
logs.setGlobalLoggerProvider(loggerProvider);
Zahir HANICHE is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
1