# Understanding the Logging Mechanism in Karakeep: Winston Implementation Guide

> Learn how Karakeep uses Winston for centralized logging. This guide explains the logging mechanism, configuration, and environment variables for streamlined development.

- Repository: [Karakeep App/karakeep](https://github.com/karakeep-app/karakeep)
- Tags: internals
- Published: 2026-07-07

---

**Karakeep implements a centralized logging mechanism using a Winston singleton exported from [`packages/shared/logger.ts`](https://github.com/karakeep-app/karakeep/blob/main/packages/shared/logger.ts), which reads the `LOG_LEVEL` and `LOG_NO_COLOR` environment variables to configure timestamped, optionally colorized console output across the entire monorepo.**

The logging mechanism in Karakeep provides a consistent, configurable approach to observability across workers, API routes, and server components. Built on the Winston library, the system uses a singleton pattern to ensure uniform log formatting while supporting both standard logging and rate-limited logging for high-frequency events.

## Winston Logger Singleton Architecture

The core logging infrastructure resides in [`packages/shared/logger.ts`](https://github.com/karakeep-app/karakeep/blob/main/packages/shared/logger.ts). This file creates a single Winston logger instance configured with a custom format combining timestamps, optional colorization, and printf-style message formatting.

All logs route through a single Console transport, making the setup lightweight and container-friendly:

```typescript
// packages/shared/logger.ts
import winston from "winston";
import serverConfig from "./config";

const logger = winston.createLogger({
  level: serverConfig.logLevel,
  format: winston.format.combine(
    winston.format.timestamp(),
    ...(serverConfig.logNoColor ? [] : [winston.format.colorize()]),
    winston.format.printf(info => `${info.timestamp} ${info.level}: ${info.message}`),
  ),
  transports: [new winston.transports.Console()],
});

```

The logger is exported as the default export, allowing any module in the monorepo to import the same instance via the alias `@karakeep/shared/logger`.

## Environment-Based Configuration

Log behavior is controlled through [`packages/shared/config.ts`](https://github.com/karakeep-app/karakeep/blob/main/packages/shared/config.ts), which validates environment variables using Zod schemas. Two key variables govern logger initialization:

```typescript
// packages/shared/config.ts
export const LOG_LEVEL = z.string().default("debug");
export const LOG_NO_COLOR = stringBool("false");

```

The `LOG_LEVEL` variable defaults to `"debug"` but can be set to `"error"`, `"warn"`, `"info"`, or `"debug"` to filter verbosity. The `LOG_NO_COLOR` variable disables ANSI color codes when set to `"true"`, useful for log aggregation systems that expect plain text.

## Usage Patterns Across the Monorepo

### Standard Logging in Services

Modules import the singleton and call standard Winston methods—`logger.info()`, `logger.warn()`, `logger.error()`, and `logger.debug()`. For example, the admin router in [`packages/trpc/routers/admin.ts`](https://github.com/karakeep-app/karakeep/blob/main/packages/trpc/routers/admin.ts) logs administrative actions for audit trails:

```typescript
// packages/trpc/routers/admin.ts
import logger from "@karakeep/shared/logger";

logger.info(`[admin] Admin ${ctx.user.id} accessed debug info for bookmark ${input.bookmarkId}`);

```

### Throttled Logging for High-Frequency Events

For background workers processing high-volume events, Karakeep exports a `throttledLogger` helper that guarantees a message emits at most once per specified millisecond interval. This prevents log spam while maintaining observability:

```typescript
// packages/shared/logger.ts
export function throttledLogger(periodMs: number) {
  let lastLogTime = 0;
  return (level: string, message: string) => {
    const now = Date.now();
    if (now - lastLogTime >= periodMs) {
      lastLogTime = now;
      logger.log(level, message);
    }
  };
}

```

Workers import both the standard logger and the throttled helper to handle different logging frequencies appropriately.

## Practical Implementation Examples

### Basic Service Logging

Import the singleton and use structured logging levels to track application flow:

```typescript
import logger from "@karakeep/shared/logger";

export async function doSomething() {
  logger.debug("Starting doSomething");
  try {
    // …your logic…
    logger.info("doSomething succeeded");
  } catch (err) {
    logger.error(`doSomething failed: ${(err as Error).message}`);
    throw err;
  }
}

```

### Worker Integration with Throttling

Prevent log flooding in high-throughput workers by wrapping repetitive log calls:

```typescript
import logger, { throttledLogger } from "@karakeep/shared/logger";

const logOncePerSecond = throttledLogger(1000);

export function processEvent(event: any) {
  // This could fire many times per second
  logOncePerSecond("info", `Processing event ${event.id}`);
  // …processing…
}

```

### Runtime Log Level Adjustment

Change verbosity without code changes by setting the environment variable before starting the server:

```bash
LOG_LEVEL=error pnpm web

```

This configuration immediately restricts output to error-level messages only, as the Winston instance reads `serverConfig.logLevel` during initialization.

## Summary

- **Centralized Singleton**: The [`packages/shared/logger.ts`](https://github.com/karakeep-app/karakeep/blob/main/packages/shared/logger.ts) file exports a single Winston instance used across the entire monorepo via the `@karakeep/shared/logger` alias.
- **Environment Control**: Log levels and colorization are configured through `LOG_LEVEL` and `LOG_NO_COLOR` variables defined in [`packages/shared/config.ts`](https://github.com/karakeep-app/karakeep/blob/main/packages/shared/config.ts).
- **Flexible API**: Supports standard Winston methods (`info`, `warn`, `error`, `debug`) plus a `throttledLogger` helper for rate-limiting high-frequency events.
- **Consistent Formatting**: All logs include timestamps and optional colorization, outputting to Console for easy container integration.

## Frequently Asked Questions

### How do I change the log level in Karakeep?

Set the `LOG_LEVEL` environment variable before starting the application. Valid values include `"error"`, `"warn"`, `"info"`, and `"debug"`. The default is `"debug"`, which outputs the most verbose logging. Changes take effect immediately on server restart as the Winston instance reads the configuration during creation.

### What is the throttledLogger used for?

The `throttledLogger` function creates a rate-limited wrapper around the standard Winston logger that emits messages at most once per specified millisecond interval. This prevents log spam in high-frequency contexts like background workers processing webhooks or crawling operations, where standard logging would generate excessive noise.

### Where does Karakeep output its logs?

By default, Karakeep logs to the console only via `winston.transports.Console()`. The logger configuration in [`packages/shared/logger.ts`](https://github.com/karakeep-app/karakeep/blob/main/packages/shared/logger.ts) does not include file transports, making it suitable for containerized environments where stdout aggregation is preferred. You can modify the transports array to add file logging if needed.

### How does Karakeep handle log formatting in production?

The logger uses `winston.format.combine()` to chain formatting rules: timestamps are always included, colorization is applied unless `LOG_NO_COLOR` is set to `"true"`, and a custom printf template renders the final string as `${timestamp} ${level}: ${message}`. This produces consistent, parseable log lines suitable for both human reading in development and machine parsing in production environments.