-
Notifications
You must be signed in to change notification settings - Fork 1.3k
docs: add custom logger guide #3470
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: v4
Are you sure you want to change the base?
Changes from 5 commits
c1a3055
5ebf19c
69e3096
51172dd
dd1a614
f4d9164
7b6239a
3d163e9
885ab37
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,60 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| --- | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| id: custom-logger | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| title: Using a custom logger | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| description: Replace Crawlee's default logger with Winston, Pino, or any logging library | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| --- | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import CodeBlock from '@theme/CodeBlock'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import ImplementationSource from '!!raw-loader!./implementation.ts'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import UsageSource from '!!raw-loader!./usage.ts'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| By default, Crawlee uses `@apify/log` for all internal logging. Starting with v4, you can | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| replace this with any logger that suits your infrastructure — Winston, Pino, Bunyan, a | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| custom JSON sink, or whatever you already use in production. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| This is useful when you want centralized structured logs, ship logs to an external service | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (e.g. Datadog, ELK, CloudWatch), or enforce a consistent log format across your entire | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| application. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ## The `CrawleeLogger` interface | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Crawlee expects a logger that satisfies the `CrawleeLogger` interface. The easiest way to | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| build one is to extend the `BaseCrawleeLogger` abstract class and implement two methods: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - **`log(level, message, data?)`** — the core dispatch method called for every log entry. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - **`_createChild(options)`** — returns a new logger instance scoped to a prefix (e.g. the crawler name). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| All other methods (`info`, `debug`, `warning`, `error`, `warningOnce`, etc.) are provided | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for free by `BaseCrawleeLogger`. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ## Example: Winston adapter | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| The following adapter wraps a standard Winston logger: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <CodeBlock language="ts">{ImplementationSource}</CodeBlock> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ### Wiring the adapter into a crawler | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Pass a new instance of your adapter to `Configuration` via the `loggerProvider` option, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| then hand that `Configuration` object to your crawler: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <CodeBlock language="ts">{UsageSource}</CodeBlock> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| The `log` object available inside `requestHandler` is a child logger scoped to the | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| crawler, so prefix-tagged entries like `[CheerioCrawler] Processing ...` appear in your | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Winston output automatically. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ## Using a different logging library | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| The same pattern works for any library. Create a class that extends `BaseCrawleeLogger`, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| map the numeric `level` argument (0 = error, 1 = warning, 3 = info, 5 = debug) to your | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| library's level constants inside `log()`, and delegate child-logger creation in | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| `_createChild()`. You only need those two methods — everything else is handled for you. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ## Controlling log level | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| When using the default `@apify/log`, the `logLevel` option in `Configuration` (or the | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| `CRAWLEE_LOG_LEVEL` environment variable) controls verbosity. When you supply your own | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| logger via `loggerProvider`, Crawlee delegates level filtering entirely to your logger, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| so configure it there. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ## The `CrawleeLogger` interface | |
| Crawlee expects a logger that satisfies the `CrawleeLogger` interface. The easiest way to | |
| build one is to extend the `BaseCrawleeLogger` abstract class and implement two methods: | |
| - **`log(level, message, data?)`** — the core dispatch method called for every log entry. | |
| - **`_createChild(options)`** — returns a new logger instance scoped to a prefix (e.g. the crawler name). | |
| All other methods (`info`, `debug`, `warning`, `error`, `warningOnce`, etc.) are provided | |
| for free by `BaseCrawleeLogger`. | |
| ## Example: Winston adapter | |
| The following adapter wraps a standard Winston logger: | |
| <CodeBlock language="ts">{ImplementationSource}</CodeBlock> | |
| ### Wiring the adapter into a crawler | |
| Pass a new instance of your adapter to `Configuration` via the `loggerProvider` option, | |
| then hand that `Configuration` object to your crawler: | |
| <CodeBlock language="ts">{UsageSource}</CodeBlock> | |
| The `log` object available inside `requestHandler` is a child logger scoped to the | |
| crawler, so prefix-tagged entries like `[CheerioCrawler] Processing ...` appear in your | |
| Winston output automatically. | |
| ## Using a different logging library | |
| The same pattern works for any library. Create a class that extends `BaseCrawleeLogger`, | |
| map the numeric `level` argument (0 = error, 1 = warning, 3 = info, 5 = debug) to your | |
| library's level constants inside `log()`, and delegate child-logger creation in | |
| `_createChild()`. You only need those two methods — everything else is handled for you. | |
| ## Controlling log level | |
| When using the default `@apify/log`, the `logLevel` option in `Configuration` (or the | |
| `CRAWLEE_LOG_LEVEL` environment variable) controls verbosity. When you supply your own | |
| logger via `loggerProvider`, Crawlee delegates level filtering entirely to your logger, | |
| so configure it there. | |
| ## Crawlee's logging API | |
| Crawlee uses [`@apify/log`](https://github.com/apify/apify-js/tree/master/packages/log) internally. | |
| In crawling contexts (for example, inside `requestHandler`), the `log` object you receive is | |
| an instance of `@apify/log`’s `Log` class. | |
| This logger exposes familiar methods such as `info`, `debug`, `warning`, `error`, | |
| `exception`, and `warningOnce`, as well as a generic `log(level, message, data?)` method. | |
| You can use it directly, or wrap/forward its calls into another logging system (e.g. Winston, | |
| Pino, or your centralized logging pipeline). | |
| ## Example: Winston adapter | |
| The following adapter shows one way to integrate Crawlee’s logging with a standard Winston logger: | |
| <CodeBlock language="ts">{ImplementationSource}</CodeBlock> | |
| ### Wiring the adapter into a crawler | |
| Use the adapter inside your crawler code (for example, in `requestHandler`) to forward | |
| messages from Crawlee’s `log` (or from your own code) into Winston: | |
| <CodeBlock language="ts">{UsageSource}</CodeBlock> | |
| In crawling contexts, the `log` object made available by Crawlee is already scoped to the | |
| crawler (for example, it may prefix entries with `[CheerioCrawler]`), so those tags will | |
| appear automatically in your Winston output when you forward messages through the adapter. | |
| ## Using a different logging library | |
| The same pattern works for any library. Create a small adapter that accepts Crawlee’s | |
| log calls (or an `@apify/log` `Log` instance), map the numeric log `level` values | |
| (0 = error, 1 = warning, 3 = info, 5 = debug) to your library’s levels, and delegate | |
| to your library’s logging methods. You typically only need to handle the level mapping | |
| and any additional metadata/formatting your logger expects. | |
| ## Controlling log level | |
| When using the default `@apify/log`, you can control verbosity with the | |
| `CRAWLEE_LOG_LEVEL` environment variable (or by configuring `@apify/log` directly in | |
| your application). If you also use an external logger (such as Winston), configure that | |
| logger’s own level filtering and formatting according to its documentation. |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,55 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import winston from 'winston'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { BaseCrawleeLogger } from 'crawlee'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import type { CrawleeLogger, CrawleeLoggerOptions } from 'crawlee'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+2
to
+4
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { BaseCrawleeLogger } from 'crawlee'; | |
| import type { CrawleeLogger, CrawleeLoggerOptions } from 'crawlee'; | |
| // Minimal local definitions mirroring Crawlee's logger abstraction, | |
| // so this example is self-contained and does not rely on unexported symbols. | |
| export interface CrawleeLoggerOptions { | |
| prefix?: string; | |
| } | |
| export abstract class BaseCrawleeLogger { | |
| private readonly options: CrawleeLoggerOptions; | |
| protected constructor(options?: Partial<CrawleeLoggerOptions>) { | |
| this.options = { ...options }; | |
| } | |
| protected getOptions(): CrawleeLoggerOptions { | |
| return this.options; | |
| } | |
| protected abstract log(level: number, message: string, data?: Record<string, unknown>): void; | |
| protected abstract _createChild(options: Partial<CrawleeLoggerOptions>): CrawleeLogger; | |
| child(options: Partial<CrawleeLoggerOptions>): CrawleeLogger { | |
| return this._createChild(options); | |
| } | |
| } | |
| export type CrawleeLogger = BaseCrawleeLogger; |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,25 @@ | ||||||
| import { CheerioCrawler, Configuration } from 'crawlee'; | ||||||
| import { WinstonAdapter, winstonLogger } from './implementation'; | ||||||
|
|
||||||
| // Wrap your Winston logger in the adapter and pass it to Configuration | ||||||
| const config = new Configuration({ | ||||||
| loggerProvider: new WinstonAdapter(winstonLogger), | ||||||
|
||||||
| loggerProvider: new WinstonAdapter(winstonLogger), | |
| logger: new WinstonAdapter(winstonLogger), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Configuration({ loggerProvider })is not a valid API in this repo:ConfigurationOptions(packages/core/src/configuration.ts) has nologgerProviderfield, so this wiring example won’t typecheck/work. Please update the docs to the actual injection point used by the logger abstraction, or adjust the code changes so thatConfigurationaccepts a custom logger provider as documented.