---
title: "Logging"
description: "Logging statements are statements you can add to your algorithm in order to add information to the log file, Cloud Terminal, or stop the algorithm."
canonical: https://www.quantconnect.com/docs/v2/writing-algorithms/logging
markdown: https://www.quantconnect.com/docs/v2/writing-algorithms/logging.md
language: python
source: https://github.com/QuantConnect/Documentation/tree/master/03%20Writing%20Algorithms/38%20Logging
modified: 2026-10-29
index: https://www.quantconnect.com/llms.txt
---

# Logging

[Documentation](https://www.quantconnect.com/docs/v2.md) > [Writing Algorithms](https://www.quantconnect.com/docs/v2/writing-algorithms.md) > Logging

> Code examples are shown in Python. Append `?lang=csharp` to this URL for the C# version of this page.

## Introduction

Algorithms can record string messages ('log statements') to a file for analysis after a backtest is complete, or as a live algorithm is running. These records can assist in debugging logical flow errors in the project code. Consider adding them in the code block of an `if` statement to signify an error has been caught.

It's good practice to add logging statements to live algorithms so you can understand its behavior and keep records to compare against backtest results. If you don't add logging statements to a live algorithm and the algorithm doesn't trade as you expect, it's difficult to evaluate the underlying problem.

## Log Messages

Log statements are added to the log file while your algorithm continues executing. Logging dataset information is not permitted. Use `log` method statements to debug your backtests and live trading algorithms.

If you execute algorithms in QuantConnect Cloud, log length is [capped by organization tier](https://www.quantconnect.com/docs/v2/cloud-platform/organizations/resources.md#09-Log-Quotas). If your organization hits the daily limit, [contact us](https://www.quantconnect.com/contact).

If you log the same content multiple times, only the first instance is added to the log file. To bypass this rate-limit, add a timestamp to your log messages.

For live trading, the log files of each cloud project can store up to 100,000 lines for up to one year. If you log more than 100,000 lines or some lines become older than one year, we remove the oldest lines in the files so your project stays within the quota.

To record the algorithm state when the algorithm stops executing, add log statements to the `on_end_of_algorithm` event handler.

```python
self.log("My log message")
```

## Debug Messages

Debug statements are the same as log statements, but `debug` method statements are orange in the Cloud Terminal. Use these statements when you want to give more attention to a message in the Cloud Terminal. Debug messages can be up to 200 characters in length. If you send multiple debug statements within 1 second, your messages are rate-limited to avoid crashing your browser.

```python
self.debug("My debug message")
```

## Error Messages

Error statements are the same as log statements, but `error` method statements are displayed in red text in the Cloud Terminal. Use these statements when you want to give the most attention to a message in the Cloud Terminal. Error statements are rate-limited like debug statements.

```python
self.error("My error message")
```

## Quit Messages

Quit statements cause your project to stop running and may log some data to the log file and Cloud Terminal. These statements are orange in the Cloud Terminal. When you call the `quit` method method, the program continues executing until the end of the method definition. If you want to quit execution immediately, `return` after you call `quit` method.

```python
self.quit("My quit message")
```

## Best Practices

### Log Sparingly

Every log statement costs execution time and counts against your [log quota](https://www.quantconnect.com/docs/v2/cloud-platform/organizations/resources.md#09-Log-Quotas), so a statement in a handler that runs on every time step can slow an algorithm down and exhaust the quota in a single run. Never log without a bound inside the `on_data` event handler or inside a Scheduled Event that fires often. Log the condition you are investigating, not every pass through the handler.

Use the `log` method rather than the `debug` method for routine records. Debug messages go through the messaging system, which rate limits them to protect your browser and slows the algorithm. Reserve debug statements for the few messages you want to stand out in the terminal.

### Gate Diagnostics Behind a Verbosity Level

Rather than adding and removing diagnostic statements each time you investigate something, route them through one method that checks a verbosity level. You keep the statements in place and turn them off for the runs where you do not need them.

```python
# Log the message only when the algorithm runs at or above the given verbosity level.
def _trace(self, level, message):
    if level <= self._log_level:
        self.log(message)
```

The caller builds the message before the method runs, so string formatting still costs you even when the method discards the result. In the handlers that run on every time step, check the level at the call site so you skip the formatting too.

```python
# Skip building the message when the level is off.
if self._log_level >= 2:
    self._trace(2, f"{self.time}: {symbol} at {price}")
```

### Record Trade Information on the Order

To record why a trade happened, pass a `tag` argument to the order method instead of writing a log statement. The tag travels with the [order](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/order-management/order-tickets.md) and appears in the results, so you keep the context of each trade without the cost of logging it.

```python
# Record the reason for the trade on the order instead of in the log.
self.stop_market_order(symbol, -quantity, stop_price, tag="stop loss")
```

## Get Logs

The following tables describe how to access the logs of your backtests and live algorithms:

| Deployment Target | Execution Mode | Access Tools |
| --- | --- | --- |
| QuantConnect Cloud | Backtest | [Backtest results page](https://www.quantconnect.com/docs/v2/cloud-platform/backtesting/results.md#14-Logs) in the Algorithm Lab [Backtest results page](https://www.quantconnect.com/docs/v2/local-platform/backtesting/results.md#13-Logs) on Local Platform |
| QuantConnect Cloud | Live Trading | [Live results page](https://www.quantconnect.com/docs/v2/cloud-platform/live-trading/results.md#12-Logs) in the Algorithm Lab Live results page on Local Platform [/live/read/log](https://www.quantconnect.com/docs/v2/cloud-platform/api-reference/live-management/read-live-algorithm/logs.md) endpoint |
| Local | Backtest | [Backtest results page](https://www.quantconnect.com/docs/v2/local-platform/backtesting/results.md#13-Logs) on Local Platform `<organizationWorkspace> / <projectName> / backtests / <unixTimestamp> / <algorithmId>-log.txt` [lean logs](https://www.quantconnect.com/docs/v2/lean-cli/api-reference/lean-logs.md) CLI command |
| Local | Live Trading | Live results page on Local Platform `<organizationWorkspace> / <projectName> / live / <timeStamp> / / L-<deploymentId>-log.txt` [lean logs](https://www.quantconnect.com/docs/v2/lean-cli/api-reference/lean-logs.md) CLI command |

## Example

The following examples demonstrate some common practices for logging.

### Example 1: On Events And Trading Logic

The following example trades a simple EMA cross trend-following strategy on SPY. We log or debug messages in event handlers and trading logic changes to get information on any event flow.

```python
class LoggingAlgorithm(QCAlgorithm):
    def initialize(self) -> None:
        self.set_start_date(2024, 9, 12)
        self.set_end_date(2024, 10, 1)
        self.set_cash(1000000)

        # Request SPY data to trade.
        self.spy = self.add_equity("SPY").symbol
        # Create an EMA indicator to generate trade signals.
        self._ema = self.ema(self.spy, 20, Resolution.DAILY)

        # Warm up the algorithm for indicator readiness.
        self.set_warm_up(20, Resolution.DAILY)

    def on_warmup_finished(self) -> None:
        # Signals on warm-up finished.
        self.log("Warm up finished")

    def on_data(self, slice: Slice) -> None:
        bar = None if self.is_warming_up else slice.bars.get(self.spy)
        if bar:
            # Trend-following strategy using price and EMA.
            # If the price is above EMA, SPY is in an uptrend, and we buy it.
            if bar.close > self._ema.current.value and not self.portfolio[self.spy].is_long:
                self.debug("Trend changes to upwards")
                self.set_holdings(self.spy, 1)
            elif bar.close < self._ema.current.value and not self.portfolio[self.spy].is_short:
                self.debug("Trend changes to downwards")
                self.set_holdings(self.spy, -1)

    def on_order_event(self, order_event: OrderEvent) -> None:
        if order_event.status == OrderStatus.FILLED:
            # Log the order details if being filled.
            self.log(f"Order filled - Quantity: {order_event.quantity}")
```
