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.

설치로 이동

소스 정보

저장소
dahlia/logtape
최근 소스 활동
2026년 7월 2일 06:35
감지된 SKILL.md 언어
영어
스타
1,997
포크
55

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
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
GitHub에서 보기
이 SKILL.md는 매우 커서 SkillsMP가 여기에는 첫 섹션만 미리 보여줍니다. GitHub에서 보기