Azure Telemetry Module
This OpenTofu module provisions an OpenTelemetry collector as a container app inside an existing Container App Environment. When Grafana Cloud is enabled it also provisions the Azure Monitor data source and the subscription-scoped role assignment, and points the collector's OTLP exporter at the stack.
Features
- OpenTelemetry collector container app deployed into an existing ACA environment (internal gRPC/HTTP OTLP ingress).
- Grafana Cloud logs, metrics, and traces pipelines via an access policy token — gated by
enable_grafana. - Grafana Azure Monitor data source provisioned through the Grafana provider.
- Optional subscription-scoped Monitoring Reader role assignment for the Grafana service principal (
create_subscription_role_assignment). - Grafana-optional: with
enable_grafana = falsethe collector still deploys (exporting todebug) and no Grafana credentials or provider are required — everygrafana_*andservice_principal_*input becomes optional. - Fail-fast: when
enable_grafana = true, a missing credential aborts the plan up front via aterraform_dataprecondition rather than surfacing as a provider 401 during refresh. - Configurable workload profile and collector image for FIPS builds.
Requirements
| Name | Version |
|---|---|
| azapi | 2.7.0 |
| azuread | ~> 3.0 |
| azurerm | ~> 4.0 |
| grafana | ~> 4.0 |
Providers
| Name | Version |
|---|---|
| azurerm | 4.81.0 |
| grafana | 4.45.2 |
| terraform | n/a |
Modules
No modules.
Resources
| Name | Type |
|---|---|
| azurerm_container_app.otel_gateway | resource |
| azurerm_role_assignment.grafana_monitoring_reader | resource |
| grafana_data_source.azure_monitor | resource |
| terraform_data.grafana_credentials_check | resource |
| azurerm_subscription.current | data source |
| grafana_cloud_stack.this | data source |
Inputs
| Name | Description | Type | Default | Required |
|---|---|---|---|---|
| acr_login_server | The login server URL of the ACR (e.g., myacr.azurecr.io) for pulling the OTel collector image | string |
n/a | yes |
| container_app_environment_id [d] | The container app environment id to install the collector in | string |
n/a | yes |
| create_subscription_role_assignment | Whether or not to create the grafana role assignment for this subscription | bool |
true |
no |
| enable_grafana | Whether to wire this environment to Grafana Cloud. When false the module deploys only the OTel collector container app and reads no Grafana credentials, so this subscription's telemetry stays in-environment. When true (the default) every grafana_ and service_principal_ input is required and the grafana provider must be configured by the caller. |
bool |
true |
no |
| grafana_cloud_stack_slug | Our grafana cloud stack name. Required when var.enable_grafana is true. | string |
null |
no |
| grafana_cloud_token | Grafana Cloud Access Policy Token (must have logs:write, metrics:write, traces:write). Required when var.enable_grafana is true. | string |
null |
no |
| grafana_data_source_name | The name of the grafana data source | string |
"Azure Monitor" |
no |
| grafana_instance_id | Grafana Cloud Instance ID. Required when var.enable_grafana is true. | string |
null |
no |
| otel_collector_image | The container image for the OpenTelemetry collector (defaults to the upstream contrib image) | string |
"acrmerkalis2b65.azurecr.io/minimus/opentelemetry-collector-contrib-fips:0.156.0" |
no |
| registry_identity_id | Resource ID of the user-assigned managed identity used for ACR authentication | string |
n/a | yes |
| resource_group_name [d] | The name of the resource group the container app env is in | string |
n/a | yes |
| service_principal_client_id | The grafana service principal's client id. Required when var.enable_grafana is true. | string |
null |
no |
| service_principal_client_secret | The grafana service principal's client secret. Required when var.enable_grafana is true. | string |
null |
no |
| service_principal_id [d] | The grafana service principal's id. Required when var.enable_grafana is true. | string |
null |
no |
| subscription_id [d] | The azure subscription id | string |
n/a | yes |
| tenant_id | The grafana service principal's tenant id. Required when var.enable_grafana is true. | string |
null |
no |
| workload_profile_name | Workload profile name assigned to the OTel gateway container app | string |
"Consumption" |
no |
[d] Destructive: changing this input forces one or more resources to be destroyed and recreated (an OpenTofu/Terraform replacement) rather than updated in place.
Outputs
| Name | Description |
|---|---|
| grafana_datasource_uid | UID of the Grafana Azure Monitor data source (null when var.enable_grafana is false) |
Example Usage
With Grafana Cloud (default)
module "telemetry" {
source = "oci://acrmerkalisdist0c66.azurecr.io/modules/azure/telemetry?tag=<module-version>"
resource_group_name = "rg-prod-observability"
container_app_environment_id = module.compute.container_app_environment_id
subscription_id = data.azurerm_client_config.current.subscription_id
tenant_id = var.grafana_tenant_id
acr_login_server = "myacr.azurecr.io"
registry_identity_id = module.compute.identity_id
otel_collector_image = "<hardened-opentelemetry-collector-image>"
grafana_cloud_stack_slug = "my-stack"
grafana_instance_id = "123456"
grafana_cloud_token = "<access-policy-token>"
service_principal_id = "<sp-object-id>"
service_principal_client_id = "<sp-client-id>"
service_principal_client_secret = "<sp-secret>"
}
Without Grafana credentials
Deploys only the collector; it exports to debug and never touches the Grafana
provider. Set enable_grafana = false and omit every grafana_* and
service_principal_* input:
module "telemetry" {
source = "oci://acrmerkalisdist0c66.azurecr.io/modules/azure/telemetry?tag=<module-version>"
resource_group_name = "rg-dev-observability"
container_app_environment_id = module.compute.container_app_environment_id
subscription_id = data.azurerm_client_config.current.subscription_id
acr_login_server = "myacr.azurecr.io"
registry_identity_id = module.compute.identity_id
otel_collector_image = "<hardened-opentelemetry-collector-contrib-image>"
enable_grafana = false
}
Notes
1.
grafana_cloud_tokenandservice_principal_client_secretare sensitive and must never be committed to version control.2.
<hardened-opentelemetry-collector-contrib-image>can be pulled from various specialized providers and stored in your local Azure Container Registry.
Available versions
v0.9.1