The SDK includes a built-in logging system to help debug requests, monitor errors, and track retry behavior.
Log Levels
The SDK supports four log levels defined in the LogLevel enum:
import { LogLevel } from '@notionhq/client'
enum LogLevel {
DEBUG = "debug", // Most verbose - logs everything
INFO = "info", // Request lifecycle events
WARN = "warn", // Warnings and errors (default)
ERROR = "error", // Only errors
}
Log Level Hierarchy
Levels are ordered by severity:
- DEBUG (20) - Logs all messages including request/response bodies
- INFO (40) - Logs request start, success, retries
- WARN (60) - Logs request failures and warnings (default)
- ERROR (80) - Logs only critical errors
When you set a log level, all messages at that level and higher are logged.
Basic Configuration
Set the log level when creating the client:
import { Client, LogLevel } from '@notionhq/client'
const notion = new Client({
auth: process.env.NOTION_API_KEY,
logLevel: LogLevel.INFO,
})
Default Logging (WARN)
By default, only warnings and errors are logged:
const notion = new Client({
auth: process.env.NOTION_API_KEY,
// logLevel: LogLevel.WARN (default)
})
// Console output:
// @notionhq/client warn: request fail { code: 'object_not_found', ... }
Verbose Logging (DEBUG)
Enable debug logging to see all request details:
const notion = new Client({
auth: process.env.NOTION_API_KEY,
logLevel: LogLevel.DEBUG,
})
// Console output:
// @notionhq/client info: request start { method: 'get', path: 'pages/...' }
// @notionhq/client debug: failed response body { body: '{"object": ...}' }
// @notionhq/client info: request success { method: 'get', path: '...' }
Silent Logging (ERROR)
Only log critical errors:
const notion = new Client({
auth: process.env.NOTION_API_KEY,
logLevel: LogLevel.ERROR,
})
// Only errors are logged, successful requests are silent
What Gets Logged
INFO Level Messages
Request Start:
// @notionhq/client info: request start {
// method: 'post',
// path: 'pages'
// }
Request Success:
// @notionhq/client info: request success {
// method: 'post',
// path: 'pages',
// requestId: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890'
// }
Retry Attempt:
// @notionhq/client info: retrying request {
// method: 'get',
// path: 'pages/page-id',
// attempt: 1,
// delayMs: 1234
// }
WARN Level Messages
Request Failure:
// @notionhq/client warn: request fail {
// code: 'object_not_found',
// message: 'Could not find page with ID: ...',
// attempt: 0,
// requestId: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890'
// }
Unknown Parameters:
// @notionhq/client warn: unknown parameters were ignored {
// unknownParams: ['page_size'],
// knownParams: ['block_id', 'start_cursor', 'page_size']
// }
DEBUG Level Messages
Failed Response Body:
// @notionhq/client debug: failed response body {
// body: '{"object": "error", "status": 404, ...}'
// }
Custom Logger
Provide a custom logger function to send logs to your own logging system:
import { Client, LogLevel, Logger } from '@notionhq/client'
const customLogger: Logger = (level, message, extraInfo) => {
// Send to your logging service
console.log(JSON.stringify({
timestamp: new Date().toISOString(),
level,
message,
...extraInfo,
}))
}
const notion = new Client({
auth: process.env.NOTION_API_KEY,
logLevel: LogLevel.INFO,
logger: customLogger,
})
Logger Type
The Logger type is a function that receives three arguments:
type Logger = (
level: LogLevel,
message: string,
extraInfo: Record<string, unknown>
) => void
The log level for this message (DEBUG, INFO, WARN, or ERROR).
A short description of the event (e.g., "request start", "request fail").
Additional context as a key-value object (method, path, error codes, etc.).
Custom Logger Examples
Structured JSON Logging
import { Logger, LogLevel } from '@notionhq/client'
const jsonLogger: Logger = (level, message, extraInfo) => {
const log = {
timestamp: Date.now(),
service: 'notion-sdk',
level,
message,
...extraInfo,
}
console.log(JSON.stringify(log))
}
const notion = new Client({
auth: process.env.NOTION_API_KEY,
logger: jsonLogger,
logLevel: LogLevel.INFO,
})
Pino Logger
import pino from 'pino'
import { Logger } from '@notionhq/client'
const logger = pino()
const pinoLogger: Logger = (level, message, extraInfo) => {
logger[level]({ ...extraInfo }, message)
}
const notion = new Client({
auth: process.env.NOTION_API_KEY,
logger: pinoLogger,
logLevel: LogLevel.INFO,
})
Winston Logger
import winston from 'winston'
import { Logger } from '@notionhq/client'
const logger = winston.createLogger({
transports: [new winston.transports.Console()],
})
const winstonLogger: Logger = (level, message, extraInfo) => {
logger.log(level, message, extraInfo)
}
const notion = new Client({
auth: process.env.NOTION_API_KEY,
logger: winstonLogger,
logLevel: LogLevel.INFO,
})
Filter Sensitive Data
import { Logger } from '@notionhq/client'
const sanitizingLogger: Logger = (level, message, extraInfo) => {
const sanitized = { ...extraInfo }
// Remove sensitive fields
delete sanitized.auth
delete sanitized.authorization
// Redact request IDs in production
if (process.env.NODE_ENV === 'production') {
if (sanitized.requestId) {
sanitized.requestId = '[redacted]'
}
}
console[level](`notion-sdk ${level}:`, message, sanitized)
}
const notion = new Client({
auth: process.env.NOTION_API_KEY,
logger: sanitizingLogger,
})
Only Log Errors
import { Logger, LogLevel } from '@notionhq/client'
const errorOnlyLogger: Logger = (level, message, extraInfo) => {
if (level === LogLevel.ERROR || level === LogLevel.WARN) {
console.error('Notion SDK error:', message, extraInfo)
}
}
const notion = new Client({
auth: process.env.NOTION_API_KEY,
logger: errorOnlyLogger,
logLevel: LogLevel.WARN,
})
Production Best Practices
Development vs Production
import { Client, LogLevel } from '@notionhq/client'
const isDevelopment = process.env.NODE_ENV === 'development'
const notion = new Client({
auth: process.env.NOTION_API_KEY,
logLevel: isDevelopment ? LogLevel.DEBUG : LogLevel.WARN,
})
Sampling High-Volume Logs
import { Logger, LogLevel } from '@notionhq/client'
let logCounter = 0
const SAMPLE_RATE = 0.1 // Log 10% of INFO messages
const samplingLogger: Logger = (level, message, extraInfo) => {
if (level === LogLevel.INFO) {
logCounter++
if (Math.random() > SAMPLE_RATE) {
return // Skip this log
}
}
console[level](`notion-sdk ${level}:`, message, {
...extraInfo,
sampleNumber: logCounter,
})
}
const notion = new Client({
auth: process.env.NOTION_API_KEY,
logger: samplingLogger,
logLevel: LogLevel.INFO,
})
Log Aggregation
import { Logger } from '@notionhq/client'
const aggregatingLogger: Logger = (level, message, extraInfo) => {
// Send to log aggregation service
fetch('https://logs.example.com/ingest', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
timestamp: Date.now(),
source: 'notion-sdk',
level,
message,
metadata: extraInfo,
}),
}).catch(console.error)
}
const notion = new Client({
auth: process.env.NOTION_API_KEY,
logger: aggregatingLogger,
logLevel: LogLevel.WARN,
})
Debugging Tips
Enable Debug Logs Temporarily
import { Client, LogLevel } from '@notionhq/client'
const DEBUG = process.env.DEBUG_NOTION === 'true'
const notion = new Client({
auth: process.env.NOTION_API_KEY,
logLevel: DEBUG ? LogLevel.DEBUG : LogLevel.WARN,
})
// Run with: DEBUG_NOTION=true node app.js
Log Request IDs
Request IDs are automatically included in success and failure logs when available:
// @notionhq/client info: request success {
// method: 'get',
// path: 'pages/page-id',
// requestId: 'a1b2c3d4-...' // Use this for Notion support
// }
Include these IDs when contacting Notion support.
Monitor Retry Patterns
Set logLevel: LogLevel.INFO to see retry attempts:
const notion = new Client({
auth: process.env.NOTION_API_KEY,
logLevel: LogLevel.INFO,
})
// @notionhq/client info: retrying request {
// method: 'get',
// path: 'pages/page-id',
// attempt: 1,
// delayMs: 2341
// }
Frequent retries may indicate rate limiting or API issues.
Default Console Logger
The SDK uses a simple console logger by default:
import { Logger, LogLevel } from '@notionhq/client'
export function makeConsoleLogger(name: string): Logger {
return (level, message, extraInfo) => {
console[level](`${name} ${level}:`, message, extraInfo)
}
}
// Default logger output format:
// @notionhq/client info: request start { method: 'get', path: '...' }
This logger writes to console.debug, console.info, console.warn, and console.error.