---
title: "Logger"
description: "Logger inspired by PHP Monolog, provides a structured logging system with support for channels, handlers, processors, and formatters. Implementation follows PSR-3 principles and the chain of responsibility pattern."
canonical_url: "https://bitrix24.github.io/b24jssdk/docs/working-with-the-rest-api/logger"
last_updated: "2026-05-08"
---
# Logger

> Logger inspired by PHP Monolog, provides a structured logging system with support for channels, handlers, processors, and formatters. Implementation follows PSR-3 principles and the chain of responsibility pattern.

> [!WARNING]
> We are still updating this page. Some data may be missing here — we will complete it shortly.

## Logging Levels

Logging levels are arranged in increasing order of severity — from **detailed debugging** (0) to **critical failures** (7).
Filtering works on an inclusive principle: when a certain level is set, messages of that level and all higher levels are logged.

| Level | Value | When to Use | Practical Example |
| --- | --- | --- | --- |
| **DEBUG** | 0 | Detailed debugging information for developers **Default in development** | `Loaded1523recordsin45ms` |
| **INFO** | 1 | Information about normal application operation Tracking business logic | `User#123addeditemtocart` |
| **NOTICE** | 2 | Important but non-critical events Successful operations with consequences | `Systemsettingschangedbyadministrator` |
| **WARNING** | 3 | Potential issues Application works but requires attention | `Cachealmostfull(95%)` |
| **ERROR** | 4 | Runtime errors requiring intervention Part of functionality unavailable | `Failedtoconnecttodatabase` |
| **CRITICAL** | 5 | Critical component failures Require urgent intervention during working hours | `Paymentgatewayunavailableformorethan5minutes` |
| **ALERT** | 6 | Serious problems requiring immediate resolution | `Diskspaceexhaustedat99%` |
| **EMERGENCY** | 7 | System inoperable Highest level of urgency | `Serverfarmcompletelyunavailable` |

### How Level Filtering Works

```ts
// Example 1: ERROR level
const $logger = new Logger('app');
$logger.pushHandler(new ConsoleHandler(LogLevel.ERROR));

// These logs WILL be output:
$logger.error('Loading error'); // ✓ level 4 >= 4
$logger.critical('Critical error'); // ✓ level 5 >= 4
$logger.alert('Alert'); // ✓ level 6 >= 4
$logger.emergency('Emergency'); // ✓ level 7 >= 4

// These logs WILL NOT be output:
$logger.debug('Debug'); // ✗ level 0 < 4
$logger.info('Info'); // ✗ level 1 < 4
$logger.warning('Warning'); // ✗ level 3 < 4
```

## Main Types and Interfaces

**LogRecord**
Log record structure:

```ts-type
{
  channel: string,              // Logger channel name
  level: LogLevel,              // Numeric level
  levelName: LogLevelName,      // Level name (e.g., 'DEBUG')
  message: string,              // Message text
  context: Record<string, any>, // Contextual data
  extra: Record<string, any>,   // Additional data (added by processors)
  timestamp: Date               // Timestamp
}
```

**LoggerInterface**
Main logger interface:

```ts-type
log(level: LogLevel, message: string, context?: Record<string, any>): Promise<void>
debug(message: string, context?: Record<string, any>): Promise<void>
info(message: string, context?: Record<string, any>): Promise<void>
notice(message: string, context?: Record<string, any>): Promise<void>
warning(message: string, context?: Record<string, any>): Promise<void>
error(message: string, context?: Record<string, any>): Promise<void>
critical(message: string, context?: Record<string, any>): Promise<void>
alert(message: string, context?: Record<string, any>): Promise<void>
emergency(message: string, context?: Record<string, any>): Promise<void>
```

**Handler**
Log handler:

```ts-type
handle(record: LogRecord): Promise<boolean>  // Process record
isHandling(level: LogLevel): boolean         // Check level support
shouldBubble(): boolean                      // Whether to continue chain
setFormatter(formatter: Formatter): void     // Set formatter
getFormatter(): Formatter | null             // Get formatter
```

**Formatter** for converting LogRecord:

```ts-type
format(record: LogRecord): any
```

**Processor** for modifying LogRecord:

```ts-type
(record: LogRecord) => LogRecord
```

## Main Classes

**AbstractLogger**
Abstract base class implementing convenience methods (debug, info, etc.).

**Logger**
Main logger implementation:

```ts-type
constructor(channel: string)                 // Create logger with specified channel
pushHandler(handler: Handler): this          // Add handler
popHandler(): Handler | null                 // Remove last handler
setHandlers(handlers: Handler[]): this       // Set list of handlers
pushProcessor(processor: Processor): this    // Add processor
log(level, message, context): Promise<void>  // Main logging method
```

**NullLogger**
Stub for cases when logging is not required. Performs no operations.

## Logger Factory

**LoggerFactory**
Static methods for creating loggers:

```ts-type
createNullLogger(): LoggerInterface
createForBrowser(channel: string, isDevMode: boolean = false): LoggerInterface
createForBrowserDevelopment(channel: string, level: LogLevel = LogLevel.DEBUG): LoggerInterface
createForBrowserProduction(channel: string, level: LogLevel = LogLevel.ERROR): LoggerInterface
forcedLog(logger, action, message, context): Promise<void>  // Forced logging
```

## Processors

Processors modify log records before processing:

**Built-in processors:**

- `memoryUsageProcessor` - adds memory usage
- `pidProcessor` - adds process ID

**Creating a custom processor:**

```ts
const customProcessor: Processor = (record) => {
  record.extra.customField = 'value'
  return record
}
```

## Formatters

**AbstractFormatter**
Base formatter class with date formatting support.

**LineFormatter**
Formats logs into a string with template support:

```ts
// Default: '[{channel}] {levelName}: {message} {context} {extra} {date}'
new LineFormatter(formatString, dateFormat)
```

*Available placeholders:*

- `{channel}` - channel name
- `{levelName}` - level name
- `{message}` - message
- `{context}` - context in JSON
- `{extra}` - extra data in JSON
- `{timestamp}` - unix timestamp
- `{date}` - date in specified format

**JsonFormatter:** Formats logs into a JSON string.

**TelegramFormatter:** Formats a log entry for [sending to Telegram](https://core.telegram.org/bots/api#html-style). Supports HTML markup with escaped special characters.

## Handlers

**AbstractHandler**
Base handler class with logging level and bubbling support.

**ConsoleHandler**
Outputs logs to browser console with styling support for different levels.

**ConsoleV2Handler**
Improved version of ConsoleHandler with more readable output.

**MemoryHandler**
Stores logs in memory (useful for testing and debugging):

```ts
const handler = new MemoryHandler(LogLevel.DEBUG, { limit: 1000 })
const records = handler.getRecords() // Get all records
handler.clear() // Clear records
```

**ConsolaAdapter**
Adapter for [Consola](https://github.com/unjs/consola).

**WinstonAdapter**
Adapter for [Winston](https://github.com/winstonjs/winston).

**StreamHandler**
Node.js stream handler for writing logs to streams.

**TelegramHandler**[Sends logs](https://bitrix24.github.io/b24jssdk/raw/docs/working-with-the-rest-api/logger-telegram.md) to Telegram chat. The browser displays a warning in the console. In server-side, sends a message via the Telegram Bot API.

## Usage

### Basic Example

```ts
import { LoggerFactory } from '@bitrix24/b24jssdk'

const devMode = typeof import.meta !== 'undefined' && (import.meta.dev || import.meta.env?.DEV)
const $logger = LoggerFactory.createForBrowser('Example:getCrmItem', devMode)
$logger.info('User logged in', { userId: 123 })
```

### Advanced Configuration

```ts
import { Logger, ConsoleV2Handler, LineFormatter } from '@bitrix24/b24jssdk'

const $logger = new Logger('app')
const handler = new ConsoleV2Handler(LogLevel.DEBUG)
handler.setFormatter(new LineFormatter('[{levelName}] {message}'))

$logger
  .pushHandler(handler)
  .pushProcessor(memoryUsageProcessor)
  .pushProcessor(pidProcessor)

$logger.warning('Low memory', { freeMemory: '10MB' })
```

### Creating a Custom Handler

```ts
class CustomHandler extends AbstractHandler {
  async handle(record: LogRecord): Promise<boolean> {
    // Send to server, write to file, etc.
    return true // Returns true if record was processed
  }
}
```

## Features

1. **Asynchronous**: All logging methods return a Promise.
2. **Chain of responsibility**: Handlers are called sequentially.
3. **Bubbling**: If a handler returns `true` and `shouldBubble() === false`, the chain is interrupted.
4. **Channels**: Logs are grouped by channels for filtering.
5. **Context**: Support for structured data via the `context` parameter.

## Usage Recommendations

**Development**

- Use `LoggerFactory.createForBrowserDevelopment` with level `DEBUG`
- Add processors for debugging information

**Production**

- Use `LoggerFactory.createForBrowserProduction` with level `ERROR` or higher
- Limit the number of handlers for performance
- Consider creating custom handlers for sending logs to server

**Context**

```ts
// Good:
$logger.error('Failed to process order', {
  orderId: 123,
  userId: 456,
  error: error.message
})

// Bad:
$logger.error(`Failed to process order ${orderId} for user ${userId}: ${error.message}`)
```

## Sitemap

See the full [sitemap](/b24jssdk/sitemap.md) for all pages.
