Use this checklist when a GCP connection is set up but no topology, metrics, or logs appear in Dynatrace.
This checklist uses dtctl, the Dynatrace command-line tool. Install it and authenticate it against your Dynatrace environment before running the commands — see Create a GCP connection via CLI for setup.
Each command takes your monitoring configuration ID (<mconfig_id>). To find it, run dtctl get gcp monitoring to list your monitoring configurations, or open the connection in the Settings app and copy the Configuration ID from its properties.
dtctl describe gcp monitoring <mconfig_id>
Look for:
Enabled: true — if false, the monitoring config is disabled. Enable it via the Settings app or with dtctl enable gcp monitoring <mconfig_id>.<sa-id>@<project>.iam.gserviceaccount.com) is present and not empty. If only the Dynatrace principal appears and the service account is blank, the connection was never linked to your service account — set it with dtctl update gcp connection --serviceAccountId <sa-email> or enter the email in the Settings app.dtctl get extension com.dynatrace.extension.da-gcp. If it is missing, activate it with dtctl create extension --hub-extension com.dynatrace.extension.da-gcp.Metrics ingest and Smartscape updates — no data is expected for the first few minutes after deployment. If still no data after 15 minutes, continue the checklist.Events — no recent data acquisition events means no errors yet. If error messages appear here, they indicate authentication or permission failures.gcloud iam service-accounts describe <sa-id>@<project>.iam.gserviceaccount.com \--project=<project>
If not found, the service account was not created. Complete the Google Cloud setup steps for your deployment method and verify the service account exists before proceeding.
gcloud projects get-iam-policy <project> \--flatten="bindings[].members" \--filter="bindings.members:serviceAccount:<sa-id>@<project>.iam.gserviceaccount.com" \--format="value(bindings.role)"
Required roles:
roles/monitoring.viewerroles/cloudasset.viewerroles/browserMissing roles mean Dynatrace cannot read metrics or topology. Re-run terraform apply or grant them manually.
roles/browser at folder scope is required for folder filtering. Granting it only at project scope does not enable folder listing.
Find the Dynatrace principal email under Dynatrace > Principal in the output of:
dtctl describe gcp monitoring <mconfig_id>
Dynatrace:Principal ID: <internal-id>Principal: dynatrace-<env-id>-<hash>@dtp-prod-gcp-auth.iam.gserviceaccount.com
Then check it has roles/iam.serviceAccountTokenCreator on your monitoring service account:
gcloud iam service-accounts get-iam-policy <sa-id>@<project>.iam.gserviceaccount.com \--project=<project>
The Dynatrace principal must appear as a member of roles/iam.serviceAccountTokenCreator. If missing, Dynatrace cannot authenticate and no data flows.
Every time Dynatrace polls for metrics, it first exchanges a short-lived token by calling iamcredentials.googleapis.com / GenerateAccessToken on your monitoring service account. This call is visible in Cloud Audit Logs on the service account project and is a reliable signal that the integration is authenticating.
gcloud logging read \'logName="projects/<sa-project>/logs/cloudaudit.googleapis.com%2Fdata_access"AND protoPayload.serviceName="iamcredentials.googleapis.com"AND protoPayload.methodName="GenerateAccessToken"' \--project=<sa-project> \--limit=10 \--format="table(timestamp, protoPayload.authenticationInfo.principalEmail, protoPayload.request.name)"
A successful log entry shows:
principalEmail — the Dynatrace principal.request.name — your monitoring service account being impersonated.authorizationInfo[].granted: true — impersonation succeeded.If no entries appear, either Data Access audit logging is not enabled for iamcredentials.googleapis.com on the project, or Dynatrace has not yet attempted authentication.
gcloud services list --project=<sa-project> --enabled \--format="value(config.name)" \--filter="config.name=(monitoring.googleapis.com OR cloudasset.googleapis.com OR cloudresourcemanager.googleapis.com OR pubsub.googleapis.com OR iam.googleapis.com OR logging.googleapis.com OR dataflow.googleapis.com OR storage.googleapis.com OR secretmanager.googleapis.com)"
The five base APIs must always be listed: monitoring, cloudasset, cloudresourcemanager, pubsub, and iam. If you enabled log forwarding, four more must also appear: logging, dataflow, storage, and secretmanager. Missing APIs cause silent failures. Enable any that are missing:
gcloud services enable <api-name> --project=<sa-project>
This is separate from the service account project. monitoring.googleapis.com must be enabled on every project whose metrics you want to collect. Topology can appear without it — metrics will be silently missing.
gcloud services list --project=<monitored-project> --enabled \--format="value(config.name)" \--filter="config.name=monitoring.googleapis.com"
If the output is empty, the API is disabled on that project. Enable it:
gcloud services enable monitoring.googleapis.com --project=<monitored-project>
Repeat for each project in your monitoring scope.
Neither token is stored in terraform.tfvars; both are passed as environment variables.
TF_VAR_dynatrace_settings_token) — always required. It creates the connection and enables the monitoring configuration.TF_VAR_dynatrace_api_token) — required only when log forwarding is enabled (logs_enabled = true). If it is missing while logs_enabled = true, terraform plan fails with the error dynatrace_api_token must be non-empty when the logs module is enabled. If you are not forwarding logs, an empty ingest token is expected and harmless.The asset inventory feed does not use a Dynatrace token. Its Pub/Sub push subscription authenticates to Dynatrace with a Google-issued OIDC token, so the feed works without the ingest token.
[ -n "$TF_VAR_dynatrace_settings_token" ] && echo "settings token is set" || echo "settings token is NOT set"[ -n "$TF_VAR_dynatrace_api_token" ] && echo "ingest token is set" || echo "ingest token is NOT set" # only relevant when logs_enabled = true
If a required token is empty in your current shell, this was likely the cause. Re-export it and re-run terraform apply:
export TF_VAR_dynatrace_settings_token="<your-settings-token>"export TF_VAR_dynatrace_api_token="<your-ingest-token>" # only when forwarding logsterraform apply
| Signal | First data expected |
|---|---|
Metrics | Within one 5-minute polling cycle after a successful |
Topology (asset inventory) | Within about 15 minutes — Dynatrace scrapes the full inventory when the connection is established |
If dtctl describe shows no data but it has been less than 15 minutes, wait before continuing. After the initial scrape, Dynatrace works from asset feed events (if you enabled the asset feed) and runs a full scrape every hour.
Metrics depend on topology: Dynatrace collects Cloud Monitoring metrics only for resources that already exist as Smartscape entities. Until a resource is discovered in topology, its metrics are not collected — even after the five-minute metric cycle. If metrics are missing while topology is still populating, wait for the initial topology scrape (about 15 minutes) before troubleshooting metrics further. Metrics ingested via Ingest any Google Cloud Monitor metrics are exempt from this requirement only for resource types that are not in the supported services list. For supported resource types, the topology requirement still applies.
gcloud dataflow jobs list --project=<project> --region=<region> \--filter="name~<mconfig_id>" \--format="table(id,name,state,location)"
Use the region that you configured for log forwarding (region in terraform.tfvars).
Look for the job whose name contains your mconfig_id. Its state must be Running. Previous failed or cancelled attempts may also appear — only the current job matters.
If the current job state is FAILED or CANCELLED:
roles/dataflow.admin and roles/logging.admin were granted to the account that ran the setup.Terraform doesn't create log sinks. You create them in each project whose logs you want to forward, so check the sinks in those projects, and the topics in the service account project:
gcloud logging sinks list --project=<source-project> \--filter="destination~dt-logs-"gcloud pubsub topics list --project=<service-account-project> \--filter="labels.dt_created_by=dynatrace"
Expected: in every project whose logs you want to forward, one log sink with a destination that points to the Pub/Sub topic dt-logs-<mconfig_id> in the service account project. If a project has no such sink, its logs aren't forwarded — see Create log sinks. If a sink's FILTER column shows (empty filter), all logs of that project are forwarded.
Expected Pub/Sub topics:
dt-logs-<mconfig_id> — main log ingestion topicdt-logs-dlq-<mconfig_id> — dead-letter queue for failed messagesCheck the subscriptions in the service account project as well:
gcloud pubsub subscriptions list --project=<service-account-project> \--filter="name~dt-logs"
Expected Pub/Sub subscriptions:
dt-logs-sub-<mconfig_id> — main subscription that the Dataflow job readsdt-logs-dlq-sub-<mconfig_id> — dead-letter subscription for inspecting failed messagesdt-logs-dlq-replay-sub-<mconfig_id> — replay subscription that the Dataflow job reads to retry failed messagesThe topics and subscriptions that the Terraform bundle creates carry the label dt_created_by=dynatrace. The asset feed topic dt-asset-feed-<mconfig_id> and its subscription dt-asset-feed-push-<mconfig_id> exist only if you enabled the asset inventory feed. See Asset feed events not arriving.
Missing resources indicate an incomplete setup. Rerun the setup steps for your deployment method.
This label-based audit — and the labels.dt_created_by=dynatrace filter in Step 9 — applies only to resources deployed by the Terraform template, which labels every resource it creates. If you deployed manually with the gcloud CLI, the resources are not labelled; filter by the dt-logs- and dt-asset-feed- name prefixes instead.
All resources created by the Terraform template are labelled with dt_created_by=dynatrace and dt_connection_id=<mconfig_id>. Filter by the connection ID so that the resources of other connections in the same project don't appear. Use this to confirm the deployment is complete:
gcloud asset search-all-resources \--project=<project> \--query="labels.dt_connection_id=<mconfig_id>" \--format="table(assetType,displayName)"
A complete deployment includes: Dataflow job, Compute instance (Dataflow worker), Pub/Sub topics and subscriptions, and GCS buckets (log staging).
Cloud Asset feeds, the Secret Manager secret, the service account, and IAM bindings don't carry labels and don't appear in this list.
If the list is empty or incomplete, Terraform did not apply cleanly. Check terraform.tfstate for errors and re-run terraform apply.
If you enabled the asset inventory feed (asset_feed_enabled = true), verify the feeds separately. List the feeds of each scope you configured; the command lists only the feeds directly under the scope you pass:
gcloud asset feeds list --project=<project>gcloud asset feeds list --folder=<folder-id>gcloud asset feeds list --organization=<organization-id>
Expected: one feed named dt-asset-feed-<mconfig_id> for each project, folder, and organization in the asset feed scope.
PendingA connection shows Pending after creation while Google Cloud setup completes. Status changes to Healthy once Dynatrace successfully authenticates.
While Pending, the Manage and Enable/Disable actions in the menu are disabled. If the connection stays Pending, verify:
Unhealthy| Symptom | Possible cause | Solution |
|---|---|---|
Authentication failed | Service account doesn't exist | Verify service account was created in Google Cloud |
Authentication failed | Dynatrace service account lacks impersonation rights | Grant |
Authentication failed | Domain-restricted sharing blocks Dynatrace | Add the Dynatrace customer identity to allowed domains |
No metrics data | Required APIs not enabled | Enable |
No topology data | Required APIs not enabled | Enable |
Partial data | Service account lacks permissions on some projects | Grant |
Filters may be excluding all projects. Check folder and project filters in connection settings.
If the monitoring configuration is set to collect metrics from scoping projects only, Dynatrace polls only GCP projects whose metrics scope includes other projects. If no such scoping project exists in your environment, zero metrics are collected with no error — the connection stays Healthy. Dynatrace caches scoping project detection, so recent changes to your Google Cloud metrics scopes can take some time to appear.
Check which monitoring configurations use scoping projects mode:
dtctl get gcp monitoring -o yaml | grep -B1 "observabilityscopesenabled: true"
If the output is empty, no monitoring configuration has scoping projects mode enabled. If one or more IDs appear, those configurations collect metrics only from scoping projects.
Check whether any scoping projects exist in your GCP environment:
A scoping project is a GCP project whose Cloud Monitoring metrics scope includes other projects. Check each project's metrics scope via the Cloud Monitoring API:
TOKEN=$(gcloud auth print-access-token)for PROJECT_ID in $(gcloud projects list --format="value(projectId)"); doRESPONSE=$(curl -s \-H "Authorization: Bearer $TOKEN" \"https://monitoring.googleapis.com/v1/projects/${PROJECT_ID}/metricsScopes")COUNT=$(echo "$RESPONSE" | grep -c '"name":')if [ "$COUNT" -gt 1 ]; thenecho "Scoping project: $PROJECT_ID (scope includes $COUNT projects)"echo "$RESPONSE" | grep '"name":' | grep -v "metricsScopes/${PROJECT_ID}\"" | sed 's/.*projects\// - /' | sed 's/".*//'fidone
If the loop finds no scoping projects, switch the affected monitoring configuration to all visible projects:
Settings app: Edit the monitoring configuration and change the metrics collection scope.
dtctl: Export the configuration, disable scoping projects mode, and apply:
dtctl get gcp monitoring <mconfig_id> -o yaml | \sed 's/observabilityscopesenabled: true/observabilityscopesenabled: false/' | \dtctl apply -f -
If metrics are missing or arrive late in large environments, the Cloud Monitoring API quota of the project that holds the monitoring service account may be exhausted. Check the ListTimeSeries quota usage in that project and request an increase if needed. See GCP performance and quotas.
The service may be disabled in the metrics configuration. Go to
Settings > Collect and capture > Cloud and virtualization > Google Cloud, open the connection, select Edit, and enable the service under Google Cloud Monitor metrics.
Dynatrace only collects metrics for resources already discovered in GCP topology. If a resource was recently created or not yet discovered, its metrics are not collected until the entity appears in Smartscape on Grail.
Clouds or via a DQL query in
Notebooks.gce_instance, the restriction still applies.Google Cloud label and tag enrichment is best effort. Due to the eventual consistency of Cloud Asset Inventory, values on Smartscape entities may be briefly out of date after a resource change.
If the asset inventory feed is configured but topology is not updating in near-real time:
Verify the Pub/Sub subscription is in ACTIVE state:
gcloud pubsub subscriptions describe dt-asset-feed-push-${MCONFIG_ID} --project=${PROJECT_ID}
Check for delivery errors in the subscription's error statistics in the Google Cloud Console (Pub/Sub > Subscriptions > your subscription > Monitoring tab).
Verify IAM: The Pub/Sub service agent must have roles/iam.serviceAccountTokenCreator on your monitoring service account. The Cloud Asset service agent must have roles/pubsub.publisher on the Pub/Sub topic: the agent of each project that has a project-scope feed, and the agent of the service account project for folder and organization feeds.
Verify the asset feed exists for each monitored scope:
gcloud asset feeds list --project=${PROJECT_ID}
Check asset types: If a resource type is missing from topology, verify it is in the --asset-types list of the feed. See Update asset feed asset types.
Check the Dataflow job is in Running state (see also Step 8):
gcloud dataflow jobs list --region=${REGION} --project=${PROJECT_ID} \--filter="name~${MCONFIG_ID}" --format='value(state)'
Check the dead-letter queue for permanently failed messages:
gcloud pubsub subscriptions pull dt-logs-dlq-sub-${MCONFIG_ID} \--project=${PROJECT_ID} --limit=5
Without --auto-ack, the messages stay in the subscription. Adding --auto-ack would remove them.
Verify the log sink in each source project routes to the correct Pub/Sub topic and its writer identity has roles/pubsub.publisher on that topic. See Create log sinks.
Token expired: If the Log Ingest token has expired, rotate it — see Rotate Log Ingest token.
If the same Google Cloud project is monitored by more than one connection, its resources are ingested more than once. This produces duplicate metrics, topology, and logs, inflates ingest and cost, and makes the data harder to interpret. Dynatrace detects overlapping visibility and flags it on the connection's Projects tab.
Find projects monitored by more than one connection:
smartscapeEdges "*"| filter source_type == "DA_MONITORING_CONFIGURATION" and type == "monitors" and startsWith(target_type, "GCP")| lookup [smartscapeNodes "GCP*" | fieldsAdd project = gcp.project.id | fields id, project],sourceField:target_id, lookupField:id, prefix:"p."| summarize connections = countDistinct(source_id), by:{ project = p.project }| filter connections > 1
This situation must be resolved so that each project is monitored by exactly one connection. Use one of the following:
roles/monitoring.viewer, roles/cloudasset.viewer, roles/browser) for each project to only one connection's service account.roles/browser binding granted at the folder or organization level that exposes the project.