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)
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216import { assertEquals } from "jsr:/@std/assert@^0.222.1/assert-equals"; import { assertRejects } from "jsr:/@std/assert@^0.222.1/assert-rejects"; import { assertStrictEquals } from "jsr:/@std/assert@^0.222.1/assert-strict-equals"; import { type Config, ConfigError, configure, getConfig, reset, } from "./config.ts"; import type { Filter } from "./filter.ts"; import { LoggerImpl } from "./logger.ts"; import type { LogRecord } from "./record.ts"; import type { Sink } from "./sink.ts"; Deno.test("configure()", async (t) => { let disposed = 0; await t.step("test", async () => { const aLogs: LogRecord[] = []; const a: Sink & AsyncDisposable = (record) => aLogs.push(record); a[Symbol.asyncDispose] = () => { ++disposed; return Promise.resolve(); }; const bLogs: LogRecord[] = []; const b: Sink & Disposable = (record) => bLogs.push(record); b[Symbol.dispose] = () => ++disposed; const cLogs: LogRecord[] = []; const c: Sink = cLogs.push.bind(cLogs); const x: Filter & AsyncDisposable = () => true; x[Symbol.asyncDispose] = () => { ++disposed; return Promise.resolve(); }; const y: Filter & Disposable = () => true; y[Symbol.dispose] = () => ++disposed; const config: Config<string, string> = { sinks: { a, b, c }, filters: { x, y, debug: "debug" }, loggers: [ { category: "my-app", sinks: ["a"], filters: ["x"], }, { category: ["my-app", "foo"], sinks: ["b"], parentSinks: "override", filters: ["y"], }, { category: ["my-app", "bar"], sinks: ["c"], filters: ["debug"], level: "info", }, ], }; await configure(config); const logger = LoggerImpl.getLogger("my-app"); assertEquals(logger.sinks, [a]); assertEquals(logger.filters, [x]); const foo = LoggerImpl.getLogger(["my-app", "foo"]); assertEquals(foo.sinks, [b]); assertEquals(foo.filters, [y]); const bar = LoggerImpl.getLogger(["my-app", "bar"]); assertEquals(bar.sinks, [c]); bar.debug("ignored"); assertEquals(aLogs, []); assertEquals(bLogs, []); assertEquals(cLogs, []); foo.warn("logged"); assertEquals(aLogs, []); assertEquals(bLogs, [ { level: "warning", category: ["my-app", "foo"], message: ["logged"], rawMessage: "logged", properties: {}, timestamp: bLogs[0].timestamp, }, ]); assertEquals(cLogs, []); bar.info("logged"); assertEquals(aLogs, [ { level: "info", category: ["my-app", "bar"], message: ["logged"], rawMessage: "logged", properties: {}, timestamp: cLogs[0].timestamp, }, ]); assertEquals(bLogs, [ { level: "warning", category: ["my-app", "foo"], message: ["logged"], rawMessage: "logged", properties: {}, timestamp: bLogs[0].timestamp, }, ]); assertEquals(cLogs, [ { level: "info", category: ["my-app", "bar"], message: ["logged"], rawMessage: "logged", properties: {}, timestamp: cLogs[0].timestamp, }, ]); assertStrictEquals(getConfig(), config); }); await t.step("reconfigure", async () => { await assertRejects( () => configure({ sinks: {}, loggers: [{ category: "my-app" }], }), ConfigError, "Already configured", ); assertEquals(disposed, 0); // No exception if reset is true: const config = { sinks: {}, loggers: [{ category: "my-app" }], reset: true, }; await configure(config); assertEquals(disposed, 4); assertStrictEquals(getConfig(), config); }); await t.step("tear down", async () => { await reset(); assertStrictEquals(getConfig(), null); }); await t.step("misconfiguration", async () => { await assertRejects( () => configure({ // deno-lint-ignore no-explicit-any sinks: {} as any, loggers: [ { category: "my-app", sinks: ["invalid"], }, ], reset: true, }), ConfigError, "Sink not found: invalid", ); assertStrictEquals(getConfig(), null); await assertRejects( () => configure({ sinks: {}, // deno-lint-ignore no-explicit-any filters: {} as any, loggers: [ { category: "my-app", filters: ["invalid"], }, ], reset: true, }), ConfigError, "Filter not found: invalid", ); assertStrictEquals(getConfig(), null); }); const metaCategories = [[], ["logtape"], ["logtape", "meta"]]; for (const metaCategory of metaCategories) { await t.step( "meta configuration: " + JSON.stringify(metaCategory), async () => { const config = { sinks: {}, loggers: [ { category: metaCategory, sinks: [], filters: [], }, ], }; await configure(config); assertEquals(LoggerImpl.getLogger(["logger", "meta"]).sinks, []); assertStrictEquals(getConfig(), config); }, ); await t.step("tear down", async () => { await reset(); assertStrictEquals(getConfig(), null); }); } });