Try it free

Manual onboarding reference (Preview)

  • Latest Dynatrace
  • How-to guide
  • Preview

This page explains how to manually set up GCP monitoring in Dynatrace using:

  • Google Cloud (gcloud) CLI: Manual GCP configuration
  • dtctl: Manual Dynatrace configuration

Use gcloud CLI for GCP setup and dtctl for Dynatrace configuration. For quick tool reference, see the table below.

Stepgcloud CLIdtctl

1. Create GCP connection in Dynatrace

-

Applicable

2. Enable Google Cloud APIs

Applicable

-

3. Create service account

Applicable

-

4. Grant permissions

Applicable

-

5. Grant impersonation rights

Applicable

-

6. Link service account to Dynatrace

-

Applicable

7. Create monitoring configuration

-

Applicable

8. Customize monitoring (optional)

-

Applicable

9. Set up asset inventory feed (optional)

Applicable

-

10. Set up log forwarding (optional)

Applicable

-

Prerequisites

First-time setup: activate the extension

If this is the first time you are setting up GCP Cloud Platform Monitoring in this Dynatrace environment, activate the extension before proceeding. The UI wizard does this automatically — manual setup requires an explicit activation.

curl -X POST "${DT_TENANT_URL}/api/v2/hub/extensions2/com.dynatrace.extension.da-gcp" \
--header "Authorization: Api-Token ${DT_API_TOKEN}" \
--header "Accept: application/json"

DT_API_TOKEN requires hub:read and hub:write permissions.

1. Environment variables

Set these variables before running the commands. They're used throughout all examples.

# Your GCP project ID
PROJECT_ID="my-project-id"
# Service account name (will be created)
CUSTOMER_SA_NAME="dynatrace-monitoring"
# Full service account email (derived from above)
CUSTOMER_SA_EMAIL="${CUSTOMER_SA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com"
# Dynatrace connection name (holds service account credentials)
GCP_CONNECTION_NAME="my-gcp-connection"
# Dynatrace monitoring configuration name (holds metric/filter settings; references the connection)
GCP_MONITORING_NAME="my-gcp-monitoring"
# Dynatrace environment details — needed for asset feed and log forwarding
TENANT_ID="my-tenant-id" # Dynatrace environment ID (e.g. abc12345)
DT_TENANT_URL="https://${TENANT_ID}.da.dynatrace.com"
REGION="us-central1" # GCP region for infrastructure deployment
# Monitoring configuration ID — printed by 'dtctl create gcp monitoring' in step 7
MCONFIG_ID="<monitoring-config-id>"

2. Retrieve your Dynatrace service account

The Dynatrace service account is required for service account impersonation. Retrieve it before starting.

dtctl get gcp connection principal

Example output:

dynatrace-abc12345@dtp-prod-gcp-auth.iam.gserviceaccount.com

Go to Settings Settings > Collect and capture > Cloud and virtualization > Google Cloud (Preview) and start the connection wizard. The principal email is displayed in the setup instructions.

Set the Dynatrace service account in your environment:

DT_SERVICE_ACCOUNT="dynatrace-abc12345@dtp-prod-gcp-auth.iam.gserviceaccount.com"

3. Required permissions

The user running the setup must have these permissions:

ForRolePurpose

GCP

roles/iam.serviceAccountAdmin

Create and manage service accounts

GCP

roles/serviceusage.serviceUsageAdmin

Enable Google Cloud APIs

GCP

roles/resourcemanager.projectIamAdmin

Grant IAM roles at project level

GCP

roles/resourcemanager.folderIamAdmin

Grant IAM roles at folder level (if applicable)

GCP

roles/resourcemanager.organizationIamAdmin

Grant IAM roles at organization level (if applicable)

Dynatrace

IAM user assigned the Data-Acquisition Cloud Integrations All and Standard User policies

Authenticate dtctl and manage Cloud Integrations settings

Dynatrace

API token with settings:objects:read, settings:objects:write, extensions:configurations:read, extensions:configurations:write

Manage connections and monitoring configs (only needed for token-based dtctl authentication)

Create a GCP connection in Dynatrace

1. Create a connection object in Dynatrace

This connection will be linked to your GCP service account later.

dtctl create gcp connection --name "$GCP_CONNECTION_NAME"

Verify the connection was created:

dtctl get gcp connections

2. Enable Google Cloud APIs

Enable the required APIs in your GCP project.

APIPurpose

compute.googleapis.com

Access to zones and regions information

cloudresourcemanager.googleapis.com

Access to projects, folders, and organizations

cloudasset.googleapis.com

Access to asset inventory

monitoring.googleapis.com

Access to metrics

gcloud services enable \
compute.googleapis.com \
cloudresourcemanager.googleapis.com \
cloudasset.googleapis.com \
monitoring.googleapis.com \
--project=$PROJECT_ID

3. Create a service account

Create a service account in your GCP project. Dynatrace will impersonate this account to access your resources.

gcloud iam service-accounts create $CUSTOMER_SA_NAME \
--display-name="Dynatrace monitoring account" \
--project=$PROJECT_ID

Verify the service account was created:

gcloud iam service-accounts list --project=$PROJECT_ID

4. Grant permissions to the service account

Grant the service account the following permissions. These are the exact permissions Dynatrace requires. If your organization restricts broad predefined roles such as roles/viewer, create a custom role with these permissions instead.

PermissionPurpose

compute.zones.list

List availability zones

compute.regions.list

List regions

resourcemanager.organizations.get

List organizations

resourcemanager.folders.get

List folders

resourcemanager.projects.get

List projects

cloudasset.assets.searchAllResources

List assets from a scope

monitoring.metricDescriptors.list

List metric descriptors

monitoring.timeSeries.list

Retrieve time series data

Project-level access

Grant viewer permissions to each project you want to monitor.

gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$CUSTOMER_SA_EMAIL" \
--role="roles/viewer"

For multiple projects:

for PROJECT in project-1 project-2 project-3; do
gcloud projects add-iam-policy-binding $PROJECT \
--member="serviceAccount:$CUSTOMER_SA_EMAIL" \
--role="roles/viewer"
done

Folder-level access Optional

Grant folder viewer permissions if you want to monitor entire folders.

gcloud resource-manager folders add-iam-policy-binding FOLDER_ID \
--member="serviceAccount:$CUSTOMER_SA_EMAIL" \
--role="roles/resourcemanager.folderViewer"

Organization-level access Optional

Grant organization viewer permissions for organization-wide monitoring.

gcloud organizations add-iam-policy-binding ORG_ID \
--member="serviceAccount:$CUSTOMER_SA_EMAIL" \
--role="roles/resourcemanager.organizationViewer"

5. Grant Dynatrace impersonation rights

This is the critical step that establishes trust. Grant the Dynatrace service account the roles/iam.serviceAccountTokenCreator role on your service account. This allows Dynatrace to impersonate your service account without storing long-lived credentials.

gcloud iam service-accounts add-iam-policy-binding $CUSTOMER_SA_EMAIL \
--member="serviceAccount:$DT_SERVICE_ACCOUNT" \
--role="roles/iam.serviceAccountTokenCreator"

If your organization restricts broad predefined roles, create a custom role with the single exact permission this role grants:

PermissionPurpose

iam.serviceAccounts.getAccessToken

Allows Dynatrace to obtain short-lived access tokens by impersonating your service account

Troubleshooting

If you get PERMISSION_DENIED with iam.serviceAccounts.getIamPolicy, your account is missing permissions to update IAM policy on the service account. Ask your GCP admin for the roles/iam.serviceAccountAdmin role.

6. Link the service account to Dynatrace

Update the Dynatrace connection with your service account details. This enables Dynatrace to use service account impersonation.

Wait a minute for IAM changes to propagate, then run:

dtctl update gcp connection \
--name "$GCP_CONNECTION_NAME" \
--serviceAccountId "$CUSTOMER_SA_EMAIL"

Verify the connection:

dtctl get gcp connections

7. Create the monitoring configuration

Create the monitoring configuration to start collecting data from GCP.

Create with defaults (all locations, all essential feature sets):

dtctl create gcp monitoring \
--name "$GCP_MONITORING_NAME" \
--credentials "$GCP_CONNECTION_NAME"

Enable monitoring. The service account was already linked in the previous step, so --serviceAccountId is not needed here:

dtctl enable gcp monitoring \
--name "$GCP_MONITORING_NAME"

You can combine the previous step and this one. Skip the dtctl update gcp connection call above and instead pass --serviceAccountId directly to enable—it updates the linked connection and enables monitoring in a single command:

dtctl enable gcp monitoring \
--name "$GCP_MONITORING_NAME" \
--serviceAccountId "$CUSTOMER_SA_EMAIL"

Verify the configuration:

dtctl describe gcp monitoring $GCP_MONITORING_NAME

8. Customize monitoringOptional

After initial setup, you can customize which regions and services to monitor.

Discover available options

List available GCP regions:

dtctl get gcp monitoring-locations

List available feature sets (services to monitor):

dtctl get gcp monitoring-feature-sets

Update the monitoring configuration

To modify a monitoring configuration, export it as YAML, edit the file, and apply the changes.

  1. Export the current configuration:

    # Get the configuration ID
    dtctl get gcp monitoring
    # Export to YAML (replace with your configuration ID)
    dtctl get gcp monitoring <configuration-id> -o yaml > config.yaml
  2. Edit config.yaml to update properties. Example structure:

    objectid: 0e184789-2f81-34ed-9358-c6b4e47f0def
    scope: integration-gcp
    value:
    enabled: true
    description: my-gcp-monitoring
    googlecloud:
    locationfiltering:
    - us-central1
    - us-east1
    - europe-west1
    projectfiltering: []
    folderfiltering: []
    # ... other properties
    featuresets:
    - compute_engine_essential
    - cloud_run_essential
    - cloud_sql_essential
  3. Apply the updated configuration:

    dtctl apply -f config.yaml

Custom resources and metrics

Ingest metrics from Google Cloud resources not covered by the default feature sets, or collect additional metrics beyond the recommended set.

To add custom resources, export your configuration to YAML, add the resources section under value.googlecloud, and apply. Example:

value:
googlecloud:
# ... existing configuration ...
resources:
# Auto-discovery: collect all available metrics
- resourcetype: gcs_bucket
autodiscoveryenabled: true
# Specific metrics only
- resourcetype: pubsub_topic
autodiscoveryenabled: false
metrics:
- name: pubsub.googleapis.com/topic/send_request_count
type: CUSTOM
- name: pubsub.googleapis.com/topic/message_sizes
type: CUSTOM
# Auto-discovery with exclusions
- resourcetype: gce_instance
autodiscoveryenabled: true
autodiscoveryexcludemetrictype:
- compute.googleapis.com/instance/disk/*
FieldDescription

resourcetype

Google Cloud monitored resource type (for example, gcs_bucket, gce_instance)

autodiscoveryenabled

true to collect all available metrics, false to specify metrics manually

metrics

List of specific metrics to collect (when auto-discovery is off)

autodiscoveryexcludemetrictype

Metric prefixes to exclude (when auto-discovery is on)

9. Set up the asset inventory feedOptional

The asset inventory feed delivers real-time topology change events from Google Cloud Asset Inventory to Dynatrace. It uses a Pub/Sub push subscription with OIDC authentication—no Dynatrace API token is required.

Enable required APIs:

gcloud services enable pubsub.googleapis.com iam.googleapis.com \
--project=$PROJECT_ID

Get the project number (needed for the Pub/Sub service agent):

PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')

Create the Pub/Sub topic:

gcloud pubsub topics create dt-asset-feed-$MCONFIG_ID \
--project=$PROJECT_ID \
--message-retention-duration=3600s

Grant the Pub/Sub service agent token creator rights on the customer service account. This allows the push subscription to generate OIDC tokens:

gcloud iam service-accounts add-iam-policy-binding $CUSTOMER_SA_EMAIL \
--member="serviceAccount:service-${PROJECT_NUMBER}@gcp-sa-pubsub.iam.gserviceaccount.com" \
--role="roles/iam.serviceAccountTokenCreator" \
--project=$PROJECT_ID

Create the push subscription with OIDC authentication:

gcloud pubsub subscriptions create dt-asset-feed-push-$MCONFIG_ID \
--topic=dt-asset-feed-$MCONFIG_ID \
--project=$PROJECT_ID \
--push-endpoint="${DT_TENANT_URL}/api/gcp/assetfeed/v1/events" \
--push-auth-service-account="$CUSTOMER_SA_EMAIL" \
--push-auth-token-audience="dt:gcp:assetfeed:${TENANT_ID}:${MCONFIG_ID}" \
--push-no-wrapper \
--ack-deadline=30 \
--message-retention-duration=3600s \
--min-retry-delay=10s \
--max-retry-delay=120s

Create the asset feed for your monitoring scope. The --asset-types list controls which resource types trigger change events.

ASSET_TYPES="alloydb.googleapis.com/Cluster,alloydb.googleapis.com/Instance,apigee.googleapis.com/Instance,apigee.googleapis.com/Organization,appengine.googleapis.com/Application,bigquery.googleapis.com/Dataset,bigquery.googleapis.com/Model,bigquerydatatransfer.googleapis.com/TransferConfig,bigtableadmin.googleapis.com/Backup,bigtableadmin.googleapis.com/Cluster,bigtableadmin.googleapis.com/Table,cloudfunctions.googleapis.com/CloudFunction,cloudresourcemanager.googleapis.com/TagBinding,cloudtasks.googleapis.com/Queue,composer.googleapis.com/Environment,compute.googleapis.com/Autoscaler,compute.googleapis.com/BackendService,compute.googleapis.com/Disk,compute.googleapis.com/Instance,compute.googleapis.com/Interconnect,compute.googleapis.com/InterconnectAttachment,compute.googleapis.com/Network,compute.googleapis.com/Router,compute.googleapis.com/ServiceAttachment,compute.googleapis.com/VpnGateway,compute.googleapis.com/VpnTunnel,container.googleapis.com/Cluster,dataflow.googleapis.com/Job,dataproc.googleapis.com/Batch,dataproc.googleapis.com/Cluster,dataproc.googleapis.com/Job,dataproc.googleapis.com/Session,file.googleapis.com/Instance,k8s.io/Node,k8s.io/Pod,k8s.io/Service,logging.googleapis.com/LogSink,netapp.googleapis.com/Volume,pubsub.googleapis.com/Snapshot,pubsub.googleapis.com/Subscription,pubsub.googleapis.com/Topic,recaptchaenterprise.googleapis.com/Key,redis.googleapis.com/Cluster,redis.googleapis.com/Instance,run.googleapis.com/Job,run.googleapis.com/Revision,spanner.googleapis.com/Instance,storage.googleapis.com/Bucket"
gcloud asset feeds create dt-asset-feed-$MCONFIG_ID \
--project=$PROJECT_ID \
--pubsub-topic=projects/$PROJECT_ID/topics/dt-asset-feed-$MCONFIG_ID \
--content-type=RESOURCE \
--asset-types="$ASSET_TYPES"

Replace FOLDER_ID with your numeric folder ID (for example, 178078973866).

ASSET_TYPES="alloydb.googleapis.com/Cluster,alloydb.googleapis.com/Instance,apigee.googleapis.com/Instance,apigee.googleapis.com/Organization,appengine.googleapis.com/Application,bigquery.googleapis.com/Dataset,bigquery.googleapis.com/Model,bigquerydatatransfer.googleapis.com/TransferConfig,bigtableadmin.googleapis.com/Backup,bigtableadmin.googleapis.com/Cluster,bigtableadmin.googleapis.com/Table,cloudfunctions.googleapis.com/CloudFunction,cloudresourcemanager.googleapis.com/TagBinding,cloudtasks.googleapis.com/Queue,composer.googleapis.com/Environment,compute.googleapis.com/Autoscaler,compute.googleapis.com/BackendService,compute.googleapis.com/Disk,compute.googleapis.com/Instance,compute.googleapis.com/Interconnect,compute.googleapis.com/InterconnectAttachment,compute.googleapis.com/Network,compute.googleapis.com/Router,compute.googleapis.com/ServiceAttachment,compute.googleapis.com/VpnGateway,compute.googleapis.com/VpnTunnel,container.googleapis.com/Cluster,dataflow.googleapis.com/Job,dataproc.googleapis.com/Batch,dataproc.googleapis.com/Cluster,dataproc.googleapis.com/Job,dataproc.googleapis.com/Session,file.googleapis.com/Instance,k8s.io/Node,k8s.io/Pod,k8s.io/Service,logging.googleapis.com/LogSink,netapp.googleapis.com/Volume,pubsub.googleapis.com/Snapshot,pubsub.googleapis.com/Subscription,pubsub.googleapis.com/Topic,recaptchaenterprise.googleapis.com/Key,redis.googleapis.com/Cluster,redis.googleapis.com/Instance,run.googleapis.com/Job,run.googleapis.com/Revision,spanner.googleapis.com/Instance,storage.googleapis.com/Bucket"
gcloud asset feeds create dt-asset-feed-$MCONFIG_ID \
--folder=FOLDER_ID \
--billing-project=$PROJECT_ID \
--pubsub-topic=projects/$PROJECT_ID/topics/dt-asset-feed-$MCONFIG_ID \
--content-type=RESOURCE \
--asset-types="$ASSET_TYPES"

Replace ORG_ID with your numeric organization ID.

ASSET_TYPES="alloydb.googleapis.com/Cluster,alloydb.googleapis.com/Instance,apigee.googleapis.com/Instance,apigee.googleapis.com/Organization,appengine.googleapis.com/Application,bigquery.googleapis.com/Dataset,bigquery.googleapis.com/Model,bigquerydatatransfer.googleapis.com/TransferConfig,bigtableadmin.googleapis.com/Backup,bigtableadmin.googleapis.com/Cluster,bigtableadmin.googleapis.com/Table,cloudfunctions.googleapis.com/CloudFunction,cloudresourcemanager.googleapis.com/TagBinding,cloudtasks.googleapis.com/Queue,composer.googleapis.com/Environment,compute.googleapis.com/Autoscaler,compute.googleapis.com/BackendService,compute.googleapis.com/Disk,compute.googleapis.com/Instance,compute.googleapis.com/Interconnect,compute.googleapis.com/InterconnectAttachment,compute.googleapis.com/Network,compute.googleapis.com/Router,compute.googleapis.com/ServiceAttachment,compute.googleapis.com/VpnGateway,compute.googleapis.com/VpnTunnel,container.googleapis.com/Cluster,dataflow.googleapis.com/Job,dataproc.googleapis.com/Batch,dataproc.googleapis.com/Cluster,dataproc.googleapis.com/Job,dataproc.googleapis.com/Session,file.googleapis.com/Instance,k8s.io/Node,k8s.io/Pod,k8s.io/Service,logging.googleapis.com/LogSink,netapp.googleapis.com/Volume,pubsub.googleapis.com/Snapshot,pubsub.googleapis.com/Subscription,pubsub.googleapis.com/Topic,recaptchaenterprise.googleapis.com/Key,redis.googleapis.com/Cluster,redis.googleapis.com/Instance,run.googleapis.com/Job,run.googleapis.com/Revision,spanner.googleapis.com/Instance,storage.googleapis.com/Bucket"
gcloud asset feeds create dt-asset-feed-$MCONFIG_ID \
--organization=ORG_ID \
--billing-project=$PROJECT_ID \
--pubsub-topic=projects/$PROJECT_ID/topics/dt-asset-feed-$MCONFIG_ID \
--content-type=RESOURCE \
--asset-types="$ASSET_TYPES"

The Terraform deployment applies a JavaScript message transform that strips the priorAsset field from feed events to reduce message size and egress cost. This is not configurable via gcloud CLI. Without it, events include priorAsset, which increases message size but does not affect functionality.

10. Set up log forwardingOptional

Log forwarding uses the pipeline: Cloud Logging sink → Pub/Sub → Dataflow streaming job → Dynatrace Log Ingest API.

Set additional environment variables:

LOG_JOB_NAME="dynatrace-log-forwarder"
DATAFLOW_IMAGE_TAG="0.0.35"
TEMPLATE_BUCKET="${PROJECT_ID}-${LOG_JOB_NAME}"
TEMP_BUCKET="${PROJECT_ID}-dataflow-temp"
DT_LOG_INGEST_TOKEN="<your-logs.ingest-token>"

Enable required APIs:

gcloud services enable \
logging.googleapis.com \
dataflow.googleapis.com \
storage.googleapis.com \
secretmanager.googleapis.com \
--project=$PROJECT_ID

Create Pub/Sub topics (main + dead-letter queue):

gcloud pubsub topics create $LOG_JOB_NAME --project=$PROJECT_ID
gcloud pubsub topics create ${LOG_JOB_NAME}-dlq --project=$PROJECT_ID

Create subscriptions:

# Main subscription (consumed by Dataflow)
gcloud pubsub subscriptions create ${LOG_JOB_NAME}-sub \
--topic=$LOG_JOB_NAME \
--project=$PROJECT_ID \
--ack-deadline=120 \
--message-retention-duration=604800s
# Dead-letter queue subscription (for inspection)
gcloud pubsub subscriptions create ${LOG_JOB_NAME}-dlq-sub \
--topic=${LOG_JOB_NAME}-dlq \
--project=$PROJECT_ID \
--ack-deadline=120 \
--message-retention-duration=604800s
# Replay subscription (filtered to non-permanent failures; consumed in-pipeline)
gcloud pubsub subscriptions create ${LOG_JOB_NAME}-dlq-replay-sub \
--topic=${LOG_JOB_NAME}-dlq \
--project=$PROJECT_ID \
--ack-deadline=120 \
--message-retention-duration=604800s \
--message-filter='attributes.dt-dlq-permanent = "false"'

Create a Cloud Logging sink and grant its writer identity publisher access on the main topic:

gcloud logging sinks create ${LOG_JOB_NAME}-sink \
pubsub.googleapis.com/projects/${PROJECT_ID}/topics/${LOG_JOB_NAME} \
--project=$PROJECT_ID
SINK_WRITER=$(gcloud logging sinks describe ${LOG_JOB_NAME}-sink \
--project=$PROJECT_ID --format='value(writerIdentity)')
gcloud pubsub topics add-iam-policy-binding $LOG_JOB_NAME \
--project=$PROJECT_ID \
--member="$SINK_WRITER" \
--role="roles/pubsub.publisher"

Grant the service account the required roles:

# Publish failed messages to the dead-letter topic
gcloud pubsub topics add-iam-policy-binding ${LOG_JOB_NAME}-dlq \
--project=$PROJECT_ID \
--member="serviceAccount:$CUSTOMER_SA_EMAIL" \
--role="roles/pubsub.publisher"
# Subscribe to main and replay subscriptions
for SUB in "${LOG_JOB_NAME}-sub" "${LOG_JOB_NAME}-dlq-replay-sub"; do
gcloud pubsub subscriptions add-iam-policy-binding $SUB \
--project=$PROJECT_ID \
--member="serviceAccount:$CUSTOMER_SA_EMAIL" \
--role="roles/pubsub.subscriber"
gcloud pubsub subscriptions add-iam-policy-binding $SUB \
--project=$PROJECT_ID \
--member="serviceAccount:$CUSTOMER_SA_EMAIL" \
--role="roles/pubsub.viewer"
done
# Project-level roles
for ROLE in roles/dataflow.worker roles/logging.logWriter roles/secretmanager.secretAccessor; do
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$CUSTOMER_SA_EMAIL" \
--role="$ROLE"
done

Create GCS buckets (Dataflow flex template spec and temp storage):

gcloud storage buckets create gs://$TEMPLATE_BUCKET \
--project=$PROJECT_ID --location=$REGION --uniform-bucket-level-access
gcloud storage buckets create gs://$TEMP_BUCKET \
--project=$PROJECT_ID --location=$REGION --uniform-bucket-level-access
gcloud storage buckets add-iam-policy-binding gs://$TEMP_BUCKET \
--member="serviceAccount:$CUSTOMER_SA_EMAIL" \
--role="roles/storage.objectAdmin"
gcloud storage buckets add-iam-policy-binding gs://$TEMPLATE_BUCKET \
--member="serviceAccount:$CUSTOMER_SA_EMAIL" \
--role="roles/storage.objectViewer"

Store the Log Ingest token in Secret Manager:

echo -n "$DT_LOG_INGEST_TOKEN" | \
gcloud secrets create ${LOG_JOB_NAME}-dynatrace-api-token \
--project=$PROJECT_ID \
--data-file=-

Grant the Dataflow service agent roles/iam.serviceAccountUser on the customer service account:

PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')
DATAFLOW_AGENT="service-${PROJECT_NUMBER}@dataflow-service-account-prod.iam.gserviceaccount.com"
gcloud iam service-accounts add-iam-policy-binding $CUSTOMER_SA_EMAIL \
--member="serviceAccount:$DATAFLOW_AGENT" \
--role="roles/iam.serviceAccountUser" \
--project=$PROJECT_ID

Upload the Dataflow flex template spec to GCS:

cat > /tmp/dt-flex-template-spec.json <<EOF
{
"image": "docker.io/dynatrace/dynatrace-gcp-dataflow-template:${DATAFLOW_IMAGE_TAG}",
"sdkInfo": {"language": "JAVA"},
"metadata": {
"name": "Dynatrace Log Forwarder",
"description": "Reads messages from a Pub/Sub subscription and forwards them to the Dynatrace log ingest endpoint.",
"parameters": [
{"name": "subscription", "label": "Pub/Sub Subscription", "isOptional": false},
{"name": "dynatraceUrl", "label": "Dynatrace Log Ingest URL", "isOptional": false},
{"name": "dynatraceApiTokenSecret", "label": "Dynatrace API Token Secret", "isOptional": false},
{"name": "deadLetterTopic", "label": "Dead-Letter Pub/Sub Topic", "isOptional": false},
{"name": "monitoringConfigurationId", "label": "Monitoring Configuration ID", "isOptional": false},
{"name": "windowSeconds", "label": "Window Duration (seconds)", "isOptional": true, "defaultValue": "10"},
{"name": "batchSize", "label": "Batch Size", "isOptional": true, "defaultValue": "1000"},
{"name": "maxBatchBytes", "label": "Max Batch Bytes", "isOptional": true, "defaultValue": "10485760"},
{"name": "maxReplayAttempts", "label": "Max Replay Attempts", "isOptional": true, "defaultValue": "5"},
{"name": "replaySubscription", "label": "Replay Subscription", "isOptional": true},
{"name": "replayBatchSize", "label": "Replay Batch Size", "isOptional": true, "defaultValue": "50"}
]
}
}
EOF
gcloud storage cp /tmp/dt-flex-template-spec.json \
gs://$TEMPLATE_BUCKET/templates/dynatrace-log-forwarder.json

Launch the Dataflow flex template job:

JOB_NAME="${LOG_JOB_NAME}-${DATAFLOW_IMAGE_TAG//./-}"
gcloud dataflow flex-template run $JOB_NAME \
--project=$PROJECT_ID \
--region=$REGION \
--template-file-gcs-location=gs://$TEMPLATE_BUCKET/templates/dynatrace-log-forwarder.json \
--service-account-email=$CUSTOMER_SA_EMAIL \
--temp-location=gs://$TEMP_BUCKET/tmp \
--enable-streaming-engine \
--parameters="subscription=projects/${PROJECT_ID}/subscriptions/${LOG_JOB_NAME}-sub" \
--parameters="dynatraceUrl=${DT_TENANT_URL}/api/gcp/pubsub/v1/logs" \
--parameters="dynatraceApiTokenSecret=projects/${PROJECT_ID}/secrets/${LOG_JOB_NAME}-dynatrace-api-token/versions/latest" \
--parameters="deadLetterTopic=projects/${PROJECT_ID}/topics/${LOG_JOB_NAME}-dlq" \
--parameters="monitoringConfigurationId=${MCONFIG_ID}" \
--parameters="replaySubscription=projects/${PROJECT_ID}/subscriptions/${LOG_JOB_NAME}-dlq-replay-sub"

Verify the job started:

gcloud dataflow jobs list \
--region=$REGION \
--project=$PROJECT_ID \
--filter="name:$JOB_NAME"

Monitoring configuration reference

This section provides a complete reference of all available configuration properties.

See configuration properties

Properties are located under value.googlecloud in the YAML configuration:

PropertyTypeDescription

locationfiltering

list of strings

GCP regions to monitor (for example, us-central1, europe-west1)

projectfiltering

list of strings

Project IDs to monitor

folderfiltering

list of strings

Folder IDs to monitor

labelfiltering

list of key/value/condition

Include or exclude resources by label

tagfiltering

list of key/value/condition

Include or exclude resources by tag

labelenrichment

list of strings

Label keys to forward to signals

tagenrichment

list of strings

Tag keys to forward to signals

resources

list of objects

Custom resources and metrics to collect

Feature sets are located under value.featuresets as a list of strings.

See available locations

For a complete list of available Google Cloud regions, see the official Google Cloud documentation:

  • Google Cloud locations—overview of all regions and zones
  • Compute Engine regions and zones—detailed region codes and descriptions

Use region codes (for example, us-central1, europe-west1, asia-east1) when configuring location filtering.

Cleanup

To remove the GCP monitoring setup

If you deployed log forwarding or asset inventory feed infrastructure using Terraform, run terraform destroy in that directory first to remove the Pub/Sub topics, Dataflow jobs, and related resources before deleting the Dynatrace objects below.

1. Remove Dynatrace resources

  1. Delete monitoring configuration first.
dtctl delete gcp monitoring $GCP_MONITORING_NAME
  1. Then delete the connection.
dtctl delete gcp connection $GCP_CONNECTION_NAME

2. Remove GCP resources

  1. Remove IAM bindings.

    # Remove impersonation rights
    gcloud iam service-accounts remove-iam-policy-binding $CUSTOMER_SA_EMAIL \
    --member="serviceAccount:$DT_SERVICE_ACCOUNT" \
    --role="roles/iam.serviceAccountTokenCreator"
    # Remove viewer role
    gcloud projects remove-iam-policy-binding $PROJECT_ID \
    --member="serviceAccount:$CUSTOMER_SA_EMAIL" \
    --role="roles/viewer"
  2. Delete the service account.

    gcloud iam service-accounts delete $CUSTOMER_SA_EMAIL --project=$PROJECT_ID

3. Remove asset inventory feed resourcesOptional

# Delete the asset feed (use the scope where you created it)
gcloud asset feeds delete dt-asset-feed-$MCONFIG_ID --project=$PROJECT_ID
# Delete the Pub/Sub subscription and topic
gcloud pubsub subscriptions delete dt-asset-feed-push-$MCONFIG_ID --project=$PROJECT_ID
gcloud pubsub topics delete dt-asset-feed-$MCONFIG_ID --project=$PROJECT_ID

4. Remove log forwarding resourcesOptional

# Cancel the Dataflow job
JOB_ID=$(gcloud dataflow jobs list \
--region=$REGION --project=$PROJECT_ID \
--filter="name:${LOG_JOB_NAME}" \
--format='value(id)' | head -1)
gcloud dataflow jobs cancel $JOB_ID --region=$REGION --project=$PROJECT_ID
# Delete Pub/Sub subscriptions and topics
gcloud pubsub subscriptions delete \
${LOG_JOB_NAME}-sub \
${LOG_JOB_NAME}-dlq-sub \
${LOG_JOB_NAME}-dlq-replay-sub \
--project=$PROJECT_ID
gcloud pubsub topics delete $LOG_JOB_NAME ${LOG_JOB_NAME}-dlq --project=$PROJECT_ID
# Delete the log sink
gcloud logging sinks delete ${LOG_JOB_NAME}-sink --project=$PROJECT_ID
# Delete Secret Manager secret
gcloud secrets delete ${LOG_JOB_NAME}-dynatrace-api-token --project=$PROJECT_ID
# Delete GCS buckets
gcloud storage rm -r gs://$TEMPLATE_BUCKET
gcloud storage rm -r gs://$TEMP_BUCKET
Related tags
Infrastructure Observability