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

# Terraform Logging and Debugging

> Guides Terraform logging setup and usage including TF_LOG and TF_LOG_PATH, interpreting logs, troubleshooting providers and APIs, and securely centralizing log collection

This guide explains how Terraform logging works, how to enable and collect logs, and how to use logs to troubleshoot provider and API issues. It focuses on the two environment variables Terraform uses for logging (`TF_LOG` and `TF_LOG_PATH`), how to interpret common log entries, and best practices for secure log handling and centralized ingestion.

## Key environment variables

Terraform logging is configured with environment variables:

* `TF_LOG` — sets the logging verbosity level Terraform will emit.
* `TF_LOG_PATH` — when set, Terraform writes logs to the specified file instead of streaming verbose logs to the console.

Example — enable the most verbose logging and persist it to a file:

```bash theme={null}
# Set the logging level (TRACE is the most verbose)
export TF_LOG=TRACE

# Persist logs to a file
export TF_LOG_PATH=/tmp/tf.log
```

<Callout icon="lightbulb" color="#1CB2FE">
  If you run Terraform on an Azure VM or build agent, install the Azure Monitor Agent to collect the `TF_LOG` file and send it to a Log Analytics workspace. This enables centralized querying, filtering, and analysis of Terraform logs. See: [https://learn.microsoft.com/azure/azure-monitor/agents/azure-monitor-agent](https://learn.microsoft.com/azure/azure-monitor/agents/azure-monitor-agent)
</Callout>

<Callout icon="warning" color="#FF6B6B">
  Terraform logs at `DEBUG` or `TRACE` levels can contain sensitive data such as secrets or API tokens. Treat files created via `TF_LOG_PATH` as sensitive: restrict access, redact before sharing, and rotate credentials if exposed.
</Callout>

## TF\_LOG levels

Terraform supports these logging levels (from least to most verbose). Setting a level will include that level and all higher-severity messages.

| Level   | When to use                           | What it includes                                                                  |
| ------- | ------------------------------------- | --------------------------------------------------------------------------------- |
| `ERROR` | Production or minimal troubleshooting | Only failure messages and errors.                                                 |
| `WARN`  | Non-fatal potential problems          | Warning messages and errors.                                                      |
| `INFO`  | Normal operational visibility         | High-level events such as plan/apply summaries.                                   |
| `DEBUG` | Troubleshooting provider/API behavior | Detailed internal information and provider API calls.                             |
| `TRACE` | Deep debugging                        | Most verbose output including request/response cycles and fine-grained internals. |

Recommendation: use `DEBUG` for typical troubleshooting. Reserve `TRACE` for deep investigations, and avoid those levels for routine CI runs unless necessary.

## Example Terraform configuration

The following compact example is used throughout this guide. It provisions an Azure resource group and a storage account. A `local-exec` provisioner demonstrates how Terrafrom can execute local commands (note: provisioners and writing secrets to disk have security implications).

```hcl theme={null}
provider "azurerm" {
  features {}
}

resource "azurerm_resource_group" "rg" {
  name     = "rg-local-provisioner"
  location = "canadacentral"
}

resource "azurerm_storage_account" "sa" {
  name                     = "salocalprov2026"
  resource_group_name      = azurerm_resource_group.rg.name
  location                 = azurerm_resource_group.rg.location
  account_tier             = "Standard"
  account_replication_type = "LRS"

  provisioner "local-exec" {
    command = "echo 'CONNECTION_STRING_PLACEHOLDER' > connection_string.txt"
  }
}
```

Note: the `azurerm` provider version and attribute availability can vary. To construct a real connection string, you may need to use provider attributes, data sources, or by retrieving account keys. Avoid writing secrets to disk where possible.

## Running Terraform with logging enabled

Set the environment variables in your terminal or CI agent before running Terraform commands.

Example:

```bash theme={null}
# export environment variables
export TF_LOG=DEBUG
export TF_LOG_PATH=/tmp/tf.log

# run Terraform plan
terraform plan
```

Behavior:

* When `TF_LOG` is set and `TF_LOG_PATH` is unset, verbose logs stream to the console.
* When `TF_LOG_PATH` is set, detailed logs are written to the file and Terraform’s console output remains the normal, succinct Terraform summary (the plan/apply text remains readable).
* For CI systems, prefer writing logs to a file and ingesting that file into your centralized logging.

## Inspecting and filtering the log file

Search and filter the log file to focus on provider API calls or errors. For example, to see provider HTTP GET requests:

```bash theme={null}
# Show provider GET requests in the log
cat /tmp/tf.log | grep GET
```

Representative output:

```plaintext theme={null}
2026-02-13T15:52:17.434Z [DEBUG] provider.terraform-provider-azurerm_v4.60.0_x5: GET https://management.azure.com/subscriptions/1b228746-75d4-46ed-8a6b-6a960d6d3a3/providers?api-version=2022-09-01
2026-02-13T15:52:18.054Z [DEBUG] provider.terraform-provider-azurerm_v4.60.0_x5: GET https://management.azure.com/subscriptions/1b228746-75d4-46ed-8a6b-6a960d6d3a3/resourceGroups/rg-local-provisioner?api-version=2022-09-01
2026-02-13T15:52:14.571Z [DEBUG] provider.terraform-provider-azurerm_v4.60.0_x5: GET https://salocalprov2026.queue.core.windows.net/?comp=properties
```

These entries show provider calls to Azure Resource Manager and storage endpoints. Reviewing these HTTP requests and their timestamps helps diagnose issues like authentication failures, rate limits, incorrect API versions, or missing resources.

## Sample log snippets

A provider plugin error and subsequent plugin exit may appear like this (cleaned and representative):

```plaintext theme={null}
2026-02-13T15:50:44.000+03:00 [DEBUG] plugin: error: code = Unavailable desc = error reading from server: connection reset
2026-02-13T15:50:44.000+03:00 [DEBUG] plugin: process exited: path=/terraform/providers/registry.terraform.io/hashicorp/azurerm/4.60.0/darwin_arm64/terraform-provider-azurerm_v4.60.0_x5
2026-02-13T15:50:44.000+03:00 [INFO] backend/local: plan operation completed!
```

A normal `terraform plan` run (console output remains user-friendly even when `TF_LOG_PATH` is set):

```plaintext theme={null}
No changes. Your infrastructure matches the configuration.

Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.
```

## Reducing verbosity

If `TRACE` or `DEBUG` is too noisy, reduce the level:

```bash theme={null}
export TF_LOG=INFO   # or WARN or ERROR
unset TF_LOG_PATH    # if you no longer want a persistent file
```

Guidance:

* Use `INFO` or `WARN` for routine runs.
* Use `DEBUG` to investigate provider-specific issues.
* Use `TRACE` only when troubleshooting deep internals or when requested by provider maintainers.

## Best practices for secure logging and centralized analysis

* Treat `TF_LOG_PATH` output as sensitive data. Limit permissions and encryption-at-rest where possible.
* Redact or scrub logs before sharing externally or attaching to tickets.
* Rotate credentials if they may have been exposed in logs.
* In production pipelines, send logs to a centralized logging system (e.g., Azure Log Analytics, Splunk, Elastic) and apply retention, access controls, and alerting.
* For Azure-specific ingestion, use the Azure Monitor Agent to forward log files to a Log Analytics workspace for query and correlation.

## Quick reference

| Topic                    | Command / Note                                              |
| ------------------------ | ----------------------------------------------------------- |
| Enable debug logs        | `export TF_LOG=DEBUG`                                       |
| Persist logs to file     | `export TF_LOG_PATH=/tmp/tf.log`                            |
| View provider HTTP calls | `grep GET /tmp/tf.log`                                      |
| Revoke logs or secrets   | Rotate credentials and remove or secure `TF_LOG_PATH` files |

## Summary

* Control Terraform logging with `TF_LOG` and persist logs with `TF_LOG_PATH`.
* `DEBUG` and `TRACE` reveal provider and API interactions—very useful for troubleshooting, but they can expose secrets.
* Centralize `TF_LOG` outputs with logging agents (Azure Monitor Agent → Log Analytics) for better analysis and retention.
* Inspect provider HTTP calls in logs to understand what Terraform requested and how the cloud provider responded.

## Links and references

* Terraform CLI environment variables: [https://developer.hashicorp.com/terraform/cli/config/environment-variables#tf\_log](https://developer.hashicorp.com/terraform/cli/config/environment-variables#tf_log)
* Azure Monitor Agent: [https://learn.microsoft.com/azure/azure-monitor/agents/azure-monitor-agent](https://learn.microsoft.com/azure/azure-monitor/agents/azure-monitor-agent)
* Log Analytics workspace: [https://learn.microsoft.com/azure/azure-monitor/logs/log-analytics-workspace](https://learn.microsoft.com/azure/azure-monitor/logs/log-analytics-workspace)
* azurerm provider docs: [https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs)

<CardGroup>
  <Card title="Watch Video" icon="video" cta="Learn more" href="https://learn.kodekloud.com/user/courses/terraform-on-azure/module/8eb2a0b5-4324-4bba-9e4e-c01dd765911d/lesson/bca84dc3-abf2-4bdc-bbd5-e192250c830e" />
</CardGroup>
