> ## Documentation Index
> Fetch the complete documentation index at: https://developers.stellar.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Logging

> Debug a smart contract with logs.

The [logging example] demonstrates how to log for the purpose of debugging.

[![Open in Codespaces](https://github.com/codespaces/badge.svg)][open-in-github-codespaces]

[![Open in Codeanywhere](https://codeanywhere.com/img/open-in-codeanywhere-btn.svg)][open-in-code-anywhere]

Logs in contracts are only visible in tests, or when executing contracts using [`stellar-cli`]. Logs are only compiled into the contract if the `debug-assertions` Rust compiler option is enabled.

[open-in-github-codespaces]: https://github.com/codespaces/new?repo=stellar/soroban-examples&editor=web

[open-in-code-anywhere]: https://app.codeanywhere.com/#https://github.com/stellar/soroban-examples

[logging example]: https://github.com/stellar/soroban-examples/tree/v23.0.0/hello_world

> [!TIP]
>
> Logs are not a substitute for step-through debugging. Rust tests for Soroban can be step-through debugged in your Rust-enabled IDE. See \[testing] for more details.

> [!WARNING]
>
> Logs are not accessible by dapps and other applications. See the \[events example] for how to produce structured events.

[testing]: https://developers.stellar.org/docs/build/smart-contracts/getting-started/hello-world.md#run-the-tests

[events example]: https://developers.stellar.org/docs/build/smart-contracts/example-contracts/events.md

## Run the Example

First go through the [Setup] process to get your development environment configured, then clone the `v23.0.0` tag of `soroban-examples` repository:

[setup]: https://developers.stellar.org/docs/build/smart-contracts/getting-started/setup.md

```sh theme={"theme":{"light":"github-light","dark":"github-dark"}}
git clone -b v23.0.0 https://github.com/stellar/soroban-examples
```

Or, skip the development environment setup and open this example in [GitHub Codespaces][open-in-github-codespaces] or [Code Anywhere][open-in-code-anywhere].

To run the tests for the example, navigate to the `logging` directory, and use `cargo test`.

```sh theme={"theme":{"light":"github-light","dark":"github-dark"}}
cd logging
cargo test -- --nocapture
```

You should see the output:

```
running 1 test
[Diagnostic Event] contract:CAAA..., topics:[log], data:["Hello {}", Dev]
[Diagnostic Event] contract:CAAA..., topics:[log], data:["Hello {}", Dev]
Writing test snapshot file for test "test::test" to "test_snapshots/test/test.1.json".
test test::test ... ok
```

## Code

```toml title="logging/Cargo.toml" theme={"theme":{"light":"github-light","dark":"github-dark"}}
[profile.release-with-logs]
inherits = "release"
debug-assertions = true
```

```rust title="logging/src/lib.rs" theme={"theme":{"light":"github-light","dark":"github-dark"}}
#![no_std]
use soroban_sdk::{contract, contractimpl, log, Env, Symbol};

#[contract]
pub struct Contract;

#[contractimpl]
impl Contract {
    pub fn hello(env: Env, value: Symbol) {
        log!(&env, "Hello {}", value);
    }
}
```

Ref: [https://github.com/stellar/soroban-examples/tree/v23.0.0/logging](https://github.com/stellar/soroban-examples/tree/v23.0.0/logging)

## How it Works

The [`log!`] macro logs a string. Any logs that occur during execution are outputted to stdout in [`stellar-cli`] and available for tests to assert on or print.

Logs are only outputted if the contract is built with the `debug-assertions` compiler option enabled. This makes them efficient to leave in code permanently since a regular `release` build will omit them.

Logs are only recorded in Soroban environments that have logging enabled. The only Soroban environments where logging is enabled is in Rust tests, and in the [`stellar-cli`].

Open the files above to follow along.

### `Cargo.toml` Profile

Logs are only outputted if the contract is built with the `debug-assertions` compiler option enabled.

The `test` profile that is activated when running `cargo test` has `debug-assertions` enabled, so when running tests logs are enabled by default.

A new `release-with-logs` profile is added to `Cargo.toml` that inherits from the `release` profile, and enables `debug-assertions`. It can be used to build a `.wasm` file that has logs enabled.

```toml theme={"theme":{"light":"github-light","dark":"github-dark"}}
[profile.release-with-logs]
inherits = "release"
debug-assertions = true
```

To build without logs use the `--release` or `--profile release` option.

To build with logs use the `--profile release-with-logs` option.

### Using the `log!` Macro

The [`log!`] macro builds a string from the format string, and a list of arguments. Arguments are substituted wherever the `{}` value appears in the format string.

```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
log!(&env, "Hello {}", value);
```

The above log will render as follows if `value` is a `Symbol` containing `"Dev"`.

```
Hello Symbol(Dev)
```

> [!WARNING]
>
> The values outputted are currently relatively limited. While primitive values like `u32`, `u64`, `bool`, and `Symbol`s will render clearly in the log output, `Bytes`, `Vec`, `Map`, and custom types will render only their handle number. Logging capabilities are in early development.

## Tests

Open the [`logging/src/test.rs`](https://github.com/stellar/soroban-examples/tree/v23.0.0/logging/src/test.rs) file to follow along.

```rust title="logging/src/test.rs" theme={"theme":{"light":"github-light","dark":"github-dark"}}
extern crate std;

#[test]
fn test() {
    let env = Env::default();

    let addr = Address::from_str(
        &env,
        "CAEAQCAIBAEAQCAIBAEAQCAIBAEAQCAIBAEAQCAIBAEAQCAIBAEAQMCJ",
    );
    let contract_id = env.register_at(&addr, Contract, ());
    let client = ContractClient::new(&env, &contract_id);

    client.hello(&symbol_short!("Dev"));

    let logs = env.logs().all();
    assert_eq!(logs, std::vec!["[Diagnostic Event] contract:CAEAQCAIBAEAQCAIBAEAQCAIBAEAQCAIBAEAQCAIBAEAQCAIBAEAQMCJ, topics:[log], data:[\"Hello {}\", Dev]"]);
    std::println!("{}", logs.join("\n"));
}
```

The `std` crate, which contains the Rust standard library, is imported so that the test can use the `std::vec!` and `std::println!` macros. Since contracts are required to use `#![no_std]`, tests in contracts must manually import `std` to use `std` functionality like printing to stdout.

```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
extern crate std;
```

In any test the first thing that is always required is an `Env`, which is the Soroban environment that the contract will run in.

```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
let env = Env::default();
```

The contract is registered with the environment using the contract type. We're specifying precisely which contract address the contract should be deployed to in the test, using the `env.register_at` function. This makes it easier to ensure the logging output is coming from the relevant contract address.

```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
let addr = Address::from_str(
    &env,
    "CAEAQCAIBAEAQCAIBAEAQCAIBAEAQCAIBAEAQCAIBAEAQCAIBAEAQMCJ",
);
let contract_id = env.register_at(&addr, Contract, ());
```

All public functions within an `impl` block that is annotated with the `#[contractimpl]` attribute have a corresponding function generated in a generated client type. The client type will be named the same as the contract type with `Client` appended. For example, in our contract the contract type is `HelloContract`, and the client is named `HelloContractClient`.

```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
let client = ContractClient::new(&env, &contract_id);
client.hello(&symbol_short!("Dev"));
```

Logs are available in tests via the environment.

```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
let logs = env.logs().all();
```

They can be asserted on like any other value.

```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
assert_eq!(logs, std::vec!["[Diagnostic Event] contract:CAEAQCAIBAEAQCAIBAEAQCAIBAEAQCAIBAEAQCAIBAEAQCAIBAEAQMCJ, topics:[log], data:[\"Hello {}\", Dev]"]);
```

They can also be printed to stdout.

```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
std::println!("{}", logs.join("\n"));
```

## Build the Contract

To build the contract, use the `stellar contract build` command.

### Without Logs

To build the contract without logs, use the `--release` option.

```sh theme={"theme":{"light":"github-light","dark":"github-dark"}}
stellar contract build
```

A `.wasm` file should be outputted in the `target` directory, in the `release` subdirectory:

```
target/wasm32v1-none/release/soroban_logging_contract.wasm
```

### With Logs

To build the contract with logs, use the `--profile release-with-logs` option.

```sh theme={"theme":{"light":"github-light","dark":"github-dark"}}
stellar contract build --profile release-with-logs
```

A `.wasm` file should be outputted in the `target` directory, in the `release-with-logs` subdirectory:

```
target/wasm32v1-none/release-with-logs/soroban_logging_contract.wasm
```

## Run the Contract

If you have [`stellar-cli`] installed, you can deploy the contract and invoke its functions. Specify the `-v` option to enable verbose logs.

### Deploy

**macOS/Linux**

```sh theme={"theme":{"light":"github-light","dark":"github-dark"}}
stellar contract deploy \
    --wasm target/wasm32v1-none/release-with-logs/soroban_logging_contract.wasm \
    --alias logging_example \
    --source-account alice \
    --network testnet
```

**Windows (PowerShell)**

```powershell theme={"theme":{"light":"github-light","dark":"github-dark"}}
stellar contract deploy `
    --wasm target/wasm32v1-none/release-with-logs/soroban_logging_contract.wasm `
    --alias logging_example `
    --source-account alice `
    --network testnet
```

### Invoke

**macOS/Linux**

```sh theme={"theme":{"light":"github-light","dark":"github-dark"}}
stellar -v contract invoke \
    --id logging_example \
    --source-account alice \
    --network testnet \
    -- \
    hello \
    --value friend
```

**Windows (PowerShell)**

```powershell theme={"theme":{"light":"github-light","dark":"github-dark"}}
stellar -v contract invoke `
    --id logging_example `
    --source-account alice `
    --network testnet `
    -- `
    hello `
    --value friend
```

The output should include the following line.

```
📔 CAAA... - Success - Log: {"vec":[{"string":"Hello {}"},{"symbol":"friend"}]}
```

[`log!`]: https://docs.rs/soroban-sdk/latest/soroban_sdk/macro.log.html

[`stellar-cli`]: ../getting-started/setup#install-the-stellar-cli
