@logtail/winston
Version:
Better Stack Winston transport (formerly Logtail)
202 lines • 7.31 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const winston_1 = __importDefault(require("winston"));
const node_1 = require("@logtail/node");
const types_1 = require("@logtail/types");
const winston_2 = require("./winston");
// Sample log message
const message = "Something to do with something";
/**
* Test a Winston level vs. Logtail level
* @param level - Winston log level
* @param logLevel LogLevel - Logtail log level
* @param levels Use custom log levels
*/
async function testLevel(level, logLevel, levels) {
// Sample log
const log = {
level,
message,
};
// Logtail fixtures
const logtail = new node_1.Logtail("test", { throwExceptions: true });
const logged = new Promise((resolve) => {
logtail.setSync(async (logs) => {
resolve(logs);
return logs;
});
});
// Create a Winston logger
const logger = winston_1.default.createLogger({
level,
transports: [new winston_2.LogtailTransport(logtail)],
// use custom levels if passed
levels: levels || winston_1.default.config.npm.levels,
});
// Log it!
logger.log(log);
const logs = await logged;
// Should be exactly one log
expect(logs.length).toBe(1);
// Message should match
expect(logs[0].message).toBe(log.message);
// Log level should be 'logLevel'
expect(logs[0].level).toBe(logLevel);
}
describe("Winston logging tests", () => {
const levels = {
silly: types_1.LogLevel.Silly,
debug: types_1.LogLevel.Debug,
http: types_1.LogLevel.Http,
verbose: types_1.LogLevel.Verbose,
warn: types_1.LogLevel.Warn,
error: types_1.LogLevel.Error,
};
for (const key in levels) {
it(`should log at the '${key}' level`, async () => {
return testLevel(key, levels[key]);
});
}
it("should sync multiple logs", async () => {
// Create multiple log entries
const entries = [
{
level: "info",
message: `${message} 1`,
},
{
level: "debug",
message: `${message} 2`,
},
{
level: "warn",
message: `${message} 3`,
},
{
level: "error",
message: `${message} 4`,
},
];
// Fixtures
const logtail = new node_1.Logtail("test", {
throwExceptions: true,
batchInterval: 1000, // <-- shouldn't be exceeded
batchSize: entries.length,
});
logtail.setSync(async (logs) => {
expect(logs.length).toBe(entries.length);
// Logs should be identical
const isIdentical = logs.every((log) => entries.findIndex((entry) => {
return entry.message == log.message;
}) > -1);
expect(isIdentical).toBe(true);
return logs;
});
// Create a Winston logger
const logger = winston_1.default.createLogger({
level: "debug", // <-- debug and above
transports: [new winston_2.LogtailTransport(logtail)],
});
entries.forEach((entry) => logger.log(entry.level, entry.message));
});
it("should log metadata with the message and level", async () => {
const logtail = new node_1.Logtail("test", { throwExceptions: true });
const logged = new Promise((resolve) => {
logtail.setSync(async (logs) => {
resolve(logs);
return logs;
});
});
// Create a Winston logger
const logger = winston_1.default.createLogger({
level: types_1.LogLevel.Info,
transports: [new winston_2.LogtailTransport(logtail)],
});
// Log it!
logger.log(types_1.LogLevel.Info, "a test message", { request_id: 123 });
const logs = await logged;
// Should be exactly one log
expect(logs.length).toBe(1);
// Message should match
expect(logs[0].message).toBe("a test message");
// Log level should be 'info'
expect(logs[0].level).toBe(types_1.LogLevel.Info);
expect(logs[0]["request_id"]).toBe(123);
});
it("should log defaultMetadata with the message and level", async () => {
const logtail = new node_1.Logtail("test", { throwExceptions: true });
const logged = new Promise((resolve) => {
logtail.setSync(async (logs) => {
resolve(logs);
return logs;
});
});
// Create a Winston logger
const logger = winston_1.default.createLogger({
level: types_1.LogLevel.Info,
transports: [new winston_2.LogtailTransport(logtail)],
defaultMeta: {
component: "server",
},
});
// Log it!
logger.log(types_1.LogLevel.Info, "a test message", { request_id: 123 });
const logs = await logged;
// Should be exactly one log
expect(logs.length).toBe(1);
// Message should match
expect(logs[0].message).toBe("a test message");
// Log level should be 'info'
expect(logs[0].level).toBe(types_1.LogLevel.Info);
expect(logs[0]["request_id"]).toBe(123);
expect(logs[0]["component"]).toBe("server");
});
it("should include correct context fields", async () => {
const logtail = new node_1.Logtail("test", { throwExceptions: true });
const logged = new Promise((resolve) => {
logtail.setSync(async (logs) => {
resolve(logs);
return logs;
});
});
// Create a Winston logger
const logger = winston_1.default.createLogger({
level: types_1.LogLevel.Info,
transports: [new winston_2.LogtailTransport(logtail)],
defaultMeta: {
component: "server",
},
});
logger.info("message with context");
const logs = await logged;
const context = logs[0].context;
expect(context.runtime.file).toMatch("winston.test.ts");
});
it("should flush logtail when the logger is closed", async () => {
let logs = [];
const logtail = new node_1.Logtail("test", { throwExceptions: true });
logtail.setSync(async (_logs) => {
logs.push(..._logs);
return logs;
});
const logger = winston_1.default.createLogger({
level: types_1.LogLevel.Info,
transports: [new winston_2.LogtailTransport(logtail)],
});
const finished = new Promise((resolve) => {
logger.on("finish", resolve);
});
// Act
logger.info("a test message");
logger.end();
await finished;
// Should be exactly one log
expect(logs.length).toBe(1);
// Message should match
expect(logs[0].message).toBe("a test message");
});
});
//# sourceMappingURL=winston.test.js.map