> Discover all available pages from the documentation index: https://mastra.ai/llms.txt # Logging Mastra's logging system captures function execution, input data, and output responses in a structured format. When deploying to the Mastra platform, logs are shown in the dashboard. In self-hosted or custom environments, logs can be directed to files or external services depending on the configured transports. **For AI agents:** Run `npx mastra api log list '{"level":"error","page":0,"perPage":50}'` to inspect recent error logs directly instead of opening Studio or writing a temporary script. The command requires a running Mastra server with observability logging configured; start the local server with `npx mastra dev`, or pass the reachable server's base URL with `--url`. Run `npx mastra api log list --schema` before constructing different filters. Install Mastra's skill with `npx skills add mastra-ai/skills --skill mastra` for complete API CLI discovery, targeting, schema, authentication, and error-handling guidance. ## Configuring logs with `PinoLogger` When [initializing a new Mastra project](https://mastra.ai/guides/getting-started/quickstart) using the CLI, `PinoLogger` is included by default. ```typescript import { Mastra } from '@mastra/core/mastra' import { PinoLogger } from '@mastra/loggers' export const mastra = new Mastra({ logger: new PinoLogger({ name: 'Mastra', level: 'info', }), }) ``` Visit [PinoLogger](https://mastra.ai/reference/logging/pino-logger) for all available configuration options. ## Logging to observability storage When [observability](https://mastra.ai/docs/observability/overview) is configured, all logger calls are automatically forwarded to your observability storage. This means every `debug`, `info`, `warn`, `error`, and `trackException` call from your application and from Mastra's internal components is stored alongside your traces. No code changes are required. Mastra wraps the configured logger so that it writes to both the original logger (console, file, or custom transport) and the observability system simultaneously. ### Configuring observability log level You can control which log levels reach observability storage independently from your console logger. Add a `logging` option to your observability instance configuration: ```typescript import { Mastra } from '@mastra/core/mastra' import { PinoLogger } from '@mastra/loggers' import { Observability, MastraStorageExporter } from '@mastra/observability' export const mastra = new Mastra({ logger: new PinoLogger({ name: 'Mastra', level: 'debug' }), observability: new Observability({ configs: { default: { serviceName: 'my-app', exporters: [new MastraStorageExporter()], logging: { enabled: true, // set to false to disable log forwarding level: 'info', // minimum level: 'debug' | 'info' | 'warn' | 'error' | 'fatal' }, }, }, }), }) ``` In this example, the console logger outputs all levels starting from `debug`, but only `info` and above are written to observability storage. This keeps your storage clean while still having verbose console output during development. | Option | Type | Default | Description | | --------- | ---------- | --------- | ---------------------------------------------------------------------- | | `enabled` | `boolean` | `true` | Set to `false` to disable all log forwarding to observability storage. | | `level` | `LogLevel` | `'debug'` | Minimum severity level. Logs below this level are discarded. | ### Querying logs Logs written to observability storage are queryable through the Mastra client SDK: ```typescript import { MastraClient } from '@mastra/client-js' const client = new MastraClient() const logs = await client.listLogsVNext({ filters: { level: 'error' }, pagination: { page: 1, perPage: 50 }, orderBy: { field: 'timestamp', direction: 'desc' }, }) ``` When using a persistent storage backend like DuckDB or ClickHouse, logs survive restarts and are available for historical analysis. ## Customizing logs Mastra provides access to a logger instance via the `mastra.getLogger()` method, available inside both workflow steps and tools. The logger supports standard severity levels: `debug`, `info`, `warn`, and `error`. ### Logging from workflow steps Within a workflow step, access the logger via the `mastra` parameter inside the `execute` function. This allows you to log messages relevant to the step's execution. ```typescript import { createWorkflow, createStep } from "@mastra/core/workflows"; import { z } from "zod"; const step1 = createStep({ execute: async ({ mastra }) => { const logger = mastra.getLogger(); logger.info("workflow info log"); return { output: "" }; } }); export const testWorkflow = createWorkflow({...}) .then(step1) .commit(); ``` ### Logging from tools Similarly, tools have access to the logger instance via the `mastra` parameter. Use this to log tool-specific activity during execution. ```typescript import { createTool } from '@mastra/core/tools' import { z } from 'zod' export const testTool = createTool({ execute: async (inputData, context) => { const logger = context?.mastra.getLogger() logger?.info('tool info log') return { output: '', } }, }) ``` ### Logging with additional data Logger methods accept an optional second argument for additional data. Pass a structured object to make logs filterable in observability storage. ```typescript import { createWorkflow, createStep } from "@mastra/core/workflows"; import { z } from "zod"; const step1 = createStep({ execute: async ({ mastra }) => { const testAgent = mastra.getAgent("testAgent"); const logger = mastra.getLogger(); logger.info("workflow info log", { agent: testAgent }); return { output: "" }; } }); export const testWorkflow = createWorkflow({...}) .then(step1) .commit(); ```