Skip to main content

logtape

Use this skill when writing any code that uses LogTape for logging in JavaScript or TypeScript. Covers getting loggers, the structured message syntax, configuration, library author rules, context, lazy evaluation, testing, and common mistakes to avoid. Trigger whenever the user is adding logging to a project, debugging log output, or integrating LogTape with a framework.

Ir a la instalación

Datos de origen

Repositorio
dahlia/logtape
Última actividad en el origen
2 de julio de 2026 a las 06:35
Idioma detectado de SKILL.md
inglés
Estrellas
1997
Forks
55

Opciones de instalación

De forma predeterminada está seleccionado el prompt que primero revisa el origen. Puedes cambiar a un comando directo o descargar una copia local.

Revisa los archivos de origen

Lee SKILL.md y los archivos complementarios que muestra SkillsMP antes de decidir si quieres instalarlo.

Mostrando SKILL.md

SKILL.md
Instrucciones de origen · Vista previa de solo lectura
name
logtape
description
Use this skill when writing any code that uses LogTape for logging in JavaScript or TypeScript. Covers getting loggers, the structured message syntax, configuration, library author rules, context, lazy evaluation, testing, and common mistakes to avoid. Trigger whenever the user is adding logging to a project, debugging log output, or integrating LogTape with a framework.
license
MIT
LogTape skill for AI coding assistants ====================================== LogTape is a zero-dependency, library-first logging framework for JavaScript and TypeScript that works across Deno, Node.js, Bun, browsers, and edge functions. Full documentation: <https://logtape.org/> Getting a logger ---------------- Always use `getLogger()` with an **array** category to enable hierarchical filtering. The hierarchy works like a path: a parent category's configuration applies to all children. ~~~~ typescript import { getLogger } from "@logtape/logtape"; // Good: array form enables hierarchical filtering const logger = getLogger(["my-app", "users", "auth"]); // Acceptable shorthand for a single-segment category const rootLogger = getLogger("my-app"); ~~~~ Choose category segments that reflect your module structure so that operators can selectively enable/disable logging per subsystem. Use `logger.getChild("sub")` to derive a child logger without repeating the full category: ~~~~ typescript const dbLogger = logger.getChild("database"); // category = ["my-app", "users", "auth", "database"] ~~~~ See <https://logtape.org/manual/categories.md> for details. Structured messages ------------------- Use **named placeholders** with a properties object. This keeps messages parseable and properties searchable: ~~~~ typescript // Correct: structured message with named placeholders logger.info("User {userId} logged in from {ip}", { userId, ip }); // Correct: structured data without a message logger.info({ userId, ip, action: "login" }); // Nested property access (since 1.2.0) logger.info("Name: {user.name}", { user: { name: "Alice" } }); ~~~~ Template literal syntax is available for quick debug logging but does **not** produce structured data: ~~~~ typescript // Template literal: convenient but not structured logger.debug`User ${userId} logged in`; ~~~~ See <https://logtape.org/manual/struct.md> for full structured logging details. Severity levels --------------- LogTape provides six levels, from most to least verbose: | Level | Use for | | --------- | ----------------------------------------------------- | | `trace` | Very fine-grained diagnostic output | | `debug` | Developer-facing diagnostic messages | | `info` | Normal operational events (startup, shutdown, etc.) | | `warning` | Unexpected but recoverable situations | | `error` | Errors that affect a single operation | | `fatal` | Unrecoverable errors that require process termination | Use the lowest appropriate level. Reserve `error`/`fatal` for actual failures; avoid using them for expected conditions like validation errors. See <https://logtape.org/manual/levels.md> for details. Configuration ------------- ### Async configuration (most common) `configure()` is **application-only**. It must be `await`ed and called **exactly once** at startup (e.g., in your entry point): ~~~~ typescript import { configure, getConsoleSink } from "@logtape/logtape"; await configure({ sinks: { console: getConsoleSink(), }, loggers: [ { category: "my-app", lowestLevel: "debug", sinks: ["console"], }, ], }); ~~~~ ### Synchronous configuration Use `configureSync()` when you cannot use `await` (e.g., top-level in CommonJS, or in a synchronous startup path): ~~~~ typescript import { configureSync, getConsoleSink } from "@logtape/logtape"; configureSync({ sinks: { console: getConsoleSink(), }, loggers: [ { category: "my-app", lowestLevel: "debug", sinks: ["console"], }, ], }); ~~~~ > **Limitation:** `configureSync()` cannot use `AsyncDisposable` sinks such as > `getStreamSink()` or sinks created with `fromAsyncSink()`. ### Key rules - `configure()` returns a `Promise`; always `await` it. - `configureSync()` returns `void`; do not `await` it. - Call either one **once**. Calling again without resetting first throws `ConfigError`. - Do **not** mix async and sync: if you used `configure()`, reset with `await reset()`; if you used `configureSync()`, reset with `resetSync()`. - For tests, call `await reset()` (or `resetSync()`) in teardown. ### Framework-specific patterns - **React**: configure **before** `createRoot()`. - **Vue**: configure **before** `app.mount()`. - **Next.js**: use *instrumentation.js* (server) or *instrumentation-client.js* (client). - **SvelteKit**: configure in *hooks.server.ts*. See <https://logtape.org/manual/config.md> for all options. Library author rule ------------------- **Never call `configure()` or `configureSync()` in library code.** Libraries should only call `getLogger()` and log messages. The application that depends on your library decides how (or whether) to configure sinks and levels. ~~~~ typescript // my-lib/src/client.ts — library code import { getLogger } from "@logtape/logtape"; // Good: just get a logger, don't configure const logger = getLogger(["my-lib", "client"]); export function fetchData(url: string) { logger.debug("Fetching {url}", { url }); // ... } ~~~~ If your library wraps other LogTape-using libraries, use `withCategoryPrefix()` to nest their logs under your category: ~~~~ typescript import { withCategoryPrefix } from "@logtape/logtape"; export function myOperation() { return withCategoryPrefix(["my-lib"], () => { // Logs from inner libraries appear as ["my-lib", ...their-category] innerLib.doWork(); }); } ~~~~ > **Note:** `withCategoryPrefix()` requires `contextLocalStorage` to be > configured by the application. See <https://logtape.org/manual/library.md> for the full guide. Context with `with()` and lazy evaluation ----------------------------------------- ### Adding explicit context Use `logger.with()` to create a child logger that attaches properties to every subsequent log call: ~~~~ typescript const reqLogger = logger.with({ requestId, userId }); reqLogger.info("Processing order {orderId}", { orderId }); // Log record will contain requestId, userId, AND orderId ~~~~ ### Implicit context (request tracing) Use `withContext()` to propagate context across an entire call stack without threading loggers manually. Requires `contextLocalStorage` in configuration: ~~~~ typescript import { configure, getConsoleSink, withContext } from "@logtape/logtape"; import { AsyncLocalStorage } from "node:async_hooks"; await configure({ sinks: { console: getConsoleSink() }, loggers: [{ category: "app", sinks: ["console"] }], contextLocalStorage: new AsyncLocalStorage(), }); function handleRequest(req: Request) { withContext({ requestId: crypto.randomUUID() }, () => { // All logs inside this callback automatically include requestId processRequest(req); }); } ~~~~ > **Note:** Implicit contexts are not available in browsers yet. ### Lazy evaluation Wrap expensive computations with `lazy()` so they only run when the level is enabled: ~~~~ typescript import { getLogger, lazy } from "@logtape/logtape"; const logger = getLogger(["my-app"]); logger.debug("System state: {state}", { state: lazy(() => JSON.stringify(getExpensiveState())), }); ~~~~ For structured data, pass a callback as the second argument: ~~~~ typescript logger.debug("Diagnostics", () => ({ heap: process.memoryUsage().heapUsed, uptime: process.uptime(), })); ~~~~ For **async** lazy evaluation, pass an async callback and `await` the result: ~~~~ typescript await logger.info("User details", async () => ({ user: await fetchUserDetails(), })); ~~~~ For multiple expensive log calls, use `isEnabledFor()`: ~~~~ typescript if (logger.isEnabledFor("debug")) { const snapshot = await captureExpensiveSnapshot(); logger.debug("Snapshot: {data}", { data: snapshot }); } ~~~~ See <https://logtape.org/manual/lazy.md> and <https://logtape.org/manual/contexts.md> for details. Logging errors -------------- Pass `Error` objects directly to `error()` or `fatal()`. You can attach extra properties as a second argument: ~~~~ typescript try { await riskyOperation(); } catch (error) { logger.error(error, { operation: "riskyOperation", userId }); } ~~~~ Sinks and formatters -------------------- ### Built-in sinks ~~~~ typescript import { configure, getConsoleSink, getStreamSink, } from "@logtape/logtape"; await configure({ sinks: { console: getConsoleSink(), stderr: getStreamSink(Writable.toWeb(process.stderr)), }, loggers: [{ category: "app", sinks: ["console"] }], }); ~~~~ ### Sink filters Use `withFilter()` to route different levels to different sinks: ~~~~ typescript import { configure, getConsoleSink, withFilter } from "@logtape/logtape"; await configure({ sinks: { errorsOnly: withFilter(getConsoleSink(), "error"), allLevels: getConsoleSink(), }, loggers: [ { category: "app", sinks: ["allLevels", "errorsOnly"] }, ], }); ~~~~ ### Formatters ~~~~ typescript import { configure, getAnsiColorFormatter, getConsoleSink, getJsonLinesFormatter, getLogfmtFormatter, } from "@logtape/logtape"; // Pretty ANSI-colored output for development getConsoleSink({ formatter: getAnsiColorFormatter() }); // JSON Lines for production / log aggregation getConsoleSink({ formatter: getJsonLinesFormatter() }); // logfmt for readable structured logs getConsoleSink({ formatter: getLogfmtFormatter() }); ~~~~ For even nicer development output, use `@logtape/pretty`: ~~~~ typescript import { getPrettyFormatter } from "@logtape/pretty"; getConsoleSink({ formatter: getPrettyFormatter() }); ~~~~ ### Disposal Non-blocking sinks and stream sinks hold resources. In **edge functions** or short-lived processes, explicitly dispose before exit: ~~~~ typescript
Ver en GitHub
Este SKILL.md es muy grande, por eso SkillsMP muestra aqui solo la primera seccion. Ver en GitHub