洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hollo.social

LogTape 1.1.0 is out! This release brings “fingers crossed” logging—buffer debug logs quietly, then get the full context when errors occur. Plus a new emit() API for integrating external log sources. Check it out:

https://hackers.pub/@hongminhee/2025/logtape-110

洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@hongminhee@hackers.pub

LogTape 1.1.0 is here, and it focuses on making your logging smarter and more flexible. This release introduces two major features we think you'll love.

Introducing fingers crossed logging

Tired of noisy production logs? Wish you had the full story when an error finally pops up? Our new “fingers crossed” logging pattern was built for exactly that.

With fingers crossed logging, LogTape buffers your debug and low-level logs in memory instead of immediately outputting them. When an error occurs, it flushes the entire buffer—giving you the complete sequence of events leading up to the problem. Once the error is logged, subsequent logs pass through normally until the next trigger event.

import { configure, fingersCrossed, getConsoleSink } from "@logtape/logtape";

await configure({
  sinks: {
    console: fingersCrossed(getConsoleSink(), {
      triggerLevel: "error",  // Buffer until an error occurs
      maxBufferSize: 500,     // Keep last 500 records
    }),
  },
  loggers: [
    { category: [], sinks: ["console"], lowestLevel: "debug" },
  ],
});

It's the best of both worlds: clean logs when things are running smoothly, and rich, detailed context the moment an issue occurs. Stop choosing between too much noise and not enough information.

Category isolation for complex applications

For applications with multiple modules or services, the new category isolation feature prevents one component's errors from flushing unrelated logs:

fingersCrossed(getConsoleSink(), {
  isolateByCategory: "descendant",  // Only flush related categories
})

You can choose how categories relate to each other—flush child categories when a parent triggers, parent categories when a child triggers, or both. This surgical precision keeps your logs focused and relevant.

Direct log emission for external systems

Integrating logs from external systems just got a lot easier. With the new Logger.emit() method, you can now feed logs from Kafka, legacy applications, or any other source directly into LogTape while preserving their original timestamps and metadata.

const logger = getLogger(["my-app", "integration"]);

// Preserve the original timestamp from an external system
logger.emit({
  timestamp: kafkaMessage.originalTimestamp,
  level: "info",
  message: [kafkaMessage.content],
  rawMessage: kafkaMessage.content,
  properties: {
    source: "kafka",
    partition: kafkaMessage.partition,
    offset: kafkaMessage.offset,
  },
});

This new low-level API gives you full control over the log record, allowing you to leverage LogTape's powerful filtering, formatting, and sink ecosystem for any log source. It's particularly valuable for:

  • Migrating from other logging systems while preserving historical context
  • Aggregating logs from multiple sources with accurate timestamps
  • Building custom adapters for specialized logging scenarios

Bug fixes and improvements

Beyond the headline features, we've strengthened LogTape's reliability across the ecosystem. Check out the full changelog for complete details.

@logtape/file

  • Fixed potential data loss during high-volume logging by ensuring all buffered logs are fully written before disposal
  • Changed getStreamFileSink() to properly implement AsyncDisposable for cleaner resource management

@logtape/sentry

  • Improved cross-runtime compatibility by introducing a structural interface that avoids type conflicts
  • Fixed template metadata preservation for better Sentry breadcrumb formatting
  • Removed unnecessary Node.js dependencies for broader runtime support

@logtape/pretty

  • Added support for displaying structured data properties directly in pretty-formatted output (thanks to Matthias Feist for the contribution)

Why upgrade?

Upgrading to 1.1.0 is a no-brainer. It's fully backward-compatible and makes your setup more powerful. The fingers crossed feature alone will change how you debug in production. Imagine getting a complete stack trace with full context for every error, without the performance hit of constant verbose logging.

If you're new to LogTape, this release shows what we're all about: building tools that solve real-world problems. We don't think you should have to choose between noisy logs and insufficient context. LogTape adapts to what you need, buffering logs when things are quiet and providing rich detail when it matters most.

Getting started

Upgrade to LogTape 1.1.0:

npm update @logtape/logtape
# or
deno add jsr:@logtape/logtape@^1.1.0

The new features are opt-in, so your existing configuration continues working exactly as before. When you're ready, explore fingers crossed logging for cleaner production logs or use emit() for advanced integration scenarios.

Let us know what you think of the new features! We're always active in our GitHub discussions and would love to hear your feedback.