This release is 2 versions behind 0.8.1 — the latest version of @logtape/logtape. Jump to latest
Built and signed on GitHub ActionsBuilt and signed on GitHub Actions
Built and signed on GitHub Actions
Simple logging library with zero dependencies for Deno/Node.js/Bun/browsers
This package works with Cloudflare Workers, Node.js, Deno, Bun, Browsers




JSR Score
100%
Published
3 months ago (0.7.1)
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189import { assertEquals } from "jsr:/@std/assert@^0.222.1/assert-equals"; import { delay } from "jsr:/@std/async@^0.222.1/delay"; import { AsyncLocalStorage } from "node:async_hooks"; import { configure, reset } from "./config.ts"; import { withContext } from "./context.ts"; import { getLogger } from "./logger.ts"; import type { LogRecord } from "./record.ts"; Deno.test("withContext()", async (t) => { const buffer: LogRecord[] = []; await t.step("set up", async () => { await configure({ sinks: { buffer: buffer.push.bind(buffer), }, loggers: [ { category: "my-app", sinks: ["buffer"], level: "debug" }, { category: ["logtape", "meta"], sinks: [], level: "warning" }, ], contextLocalStorage: new AsyncLocalStorage(), reset: true, }); }); await t.step("test", () => { getLogger("my-app").debug("hello", { foo: 1, bar: 2 }); assertEquals(buffer, [ { category: ["my-app"], level: "debug", message: ["hello"], rawMessage: "hello", properties: { foo: 1, bar: 2 }, timestamp: buffer[0].timestamp, }, ]); buffer.pop(); const rv = withContext({ foo: 3, baz: 4 }, () => { getLogger("my-app").debug("world", { foo: 1, bar: 2 }); return 123; }); assertEquals(rv, 123); assertEquals(buffer, [ { category: ["my-app"], level: "debug", message: ["world"], rawMessage: "world", properties: { foo: 1, bar: 2, baz: 4 }, timestamp: buffer[0].timestamp, }, ]); buffer.pop(); getLogger("my-app").debug("hello", { foo: 1, bar: 2 }); assertEquals(buffer, [ { category: ["my-app"], level: "debug", message: ["hello"], rawMessage: "hello", properties: { foo: 1, bar: 2 }, timestamp: buffer[0].timestamp, }, ]); }); await t.step("nesting", () => { while (buffer.length > 0) buffer.pop(); withContext({ foo: 1, bar: 2 }, () => { withContext({ foo: 3, baz: 4 }, () => { getLogger("my-app").debug("hello"); }); }); assertEquals(buffer, [ { category: ["my-app"], level: "debug", message: ["hello"], rawMessage: "hello", properties: { foo: 3, bar: 2, baz: 4 }, timestamp: buffer[0].timestamp, }, ]); }); await t.step("concurrent runs", async () => { while (buffer.length > 0) buffer.pop(); await Promise.all([ (async () => { await delay(Math.random() * 100); withContext({ foo: 1 }, () => { getLogger("my-app").debug("foo"); }); })(), (async () => { await delay(Math.random() * 100); withContext({ bar: 2 }, () => { getLogger("my-app").debug("bar"); }); })(), (async () => { await delay(Math.random() * 100); withContext({ baz: 3 }, () => { getLogger("my-app").debug("baz"); }); })(), (async () => { await delay(Math.random() * 100); withContext({ qux: 4 }, () => { getLogger("my-app").debug("qux"); }); })(), ]); assertEquals(buffer.length, 4); for (const log of buffer) { if (log.message[0] === "foo") { assertEquals(log.properties, { foo: 1 }); } else if (log.message[0] === "bar") { assertEquals(log.properties, { bar: 2 }); } else if (log.message[0] === "baz") { assertEquals(log.properties, { baz: 3 }); } else { assertEquals(log.properties, { qux: 4 }); } } }); await t.step("tear down", async () => { await reset(); }); const metaBuffer: LogRecord[] = []; await t.step("set up", async () => { await configure({ sinks: { buffer: buffer.push.bind(buffer), metaBuffer: metaBuffer.push.bind(metaBuffer), }, loggers: [ { category: "my-app", sinks: ["buffer"], level: "debug" }, { category: ["logtape", "meta"], sinks: ["metaBuffer"], level: "warning", }, ], reset: true, }); }); await t.step("without settings", () => { while (buffer.length > 0) buffer.pop(); const rv = withContext({ foo: 1 }, () => { getLogger("my-app").debug("hello", { bar: 2 }); return 123; }); assertEquals(rv, 123); assertEquals(buffer, [ { category: ["my-app"], level: "debug", message: ["hello"], rawMessage: "hello", properties: { bar: 2 }, timestamp: buffer[0].timestamp, }, ]); assertEquals(metaBuffer, [ { category: ["logtape", "meta"], level: "warning", message: [ "Context-local storage is not configured. " + "Specify contextLocalStorage option in the configure() function.", ], properties: {}, rawMessage: "Context-local storage is not configured. " + "Specify contextLocalStorage option in the configure() function.", timestamp: metaBuffer[0].timestamp, }, ]); }); await t.step("tear down", async () => { await reset(); }); });