Dynatrace ingests Google Cloud logs and audit events from Cloud Logging using a forwarding pipeline deployed to your Google Cloud environment. The pipeline runs in your own infrastructure, giving you full control over what is forwarded and at what cost.
Log and event forwarding uses the following pipeline:
Cloud Logging → log sink → Pub/Sub topic → Dataflow job → Grail
| Component | Role |
|---|---|
| Cloud Logging log sink | Routes matching log entries from Cloud Logging to a Pub/Sub topic. You create a sink in each project whose logs you want to forward, and control what is forwarded using the sink's inclusion and exclusion filters. |
| Pub/Sub topic | Buffers forwarded log entries for reliable, scalable delivery to the Dataflow job. |
| Dataflow job | Reads log entries from Pub/Sub, transforms and enriches them, and forwards them to Dynatrace Grail (Dynatrace's data lakehouse) for storage and analysis. |
| Grail | Stores ingested logs for querying, alerting, and analysis in Dynatrace. |
The onboarding Terraform deploys the Pub/Sub topic and subscriptions, the supporting Secret Manager secret and Cloud Storage buckets, and the Dataflow job, and connects them to Dynatrace. It does not create log sinks. You create the log sinks yourself and point them at the Pub/Sub topic. For step-by-step deployment instructions, see Via Terraform or Via gcloud CLI and dtctl.
The Dataflow job runs as a streaming job in your Google Cloud project and incurs costs (see Cost considerations). It sends logs to your environment's data acquisition endpoint, https://<environment-id>.da.dynatrace.com. If you restrict outbound traffic from your Google Cloud network, allow this host.
Log forwarding must be enabled when configuring or editing your GCP connection. If you did not enable it during initial setup, you can enable it later by editing the connection and re-running Terraform to deploy the required infrastructure. No logs reach Dynatrace until you create at least one log sink.
Dynatrace collects the following log types from Cloud Logging:
| Log type | Description |
|---|---|
| Platform logs | Logs generated by Google Cloud services (for example, GKE cluster logs, Cloud Run request logs, Cloud SQL logs) |
| Admin Activity audit logs | Records API calls that modify the configuration or metadata of Google Cloud resources. Always enabled, cannot be disabled. |
| Data Access audit logs | Records API calls that read resource configurations or user-provided data. Must be explicitly enabled per service in Google Cloud. |
| System Event audit logs | Records Google Cloud administrative actions that modify configurations. Generated automatically by Google Cloud. |
| Application logs | Logs written to Cloud Logging by your own applications using the Cloud Logging API or client libraries. |
Data Access audit logs generate high log volume and can significantly increase costs. Enable them only for the services and projects where you need detailed data access visibility.
Dynatrace does not accept log records with a timestamp older than 24 hours at ingest time.
See OpenPipeline limits for the full timestamp acceptance window by signal type.
A log sink routes log entries from Cloud Logging to the Pub/Sub topic. Dynatrace doesn't create log sinks for you. You create a project-level sink in each project whose logs you want to forward, and point it at the Pub/Sub topic dt-logs-<id>, where <id> is the ID of your monitoring configuration. The topic lives in the service account project. Sinks in other monitored projects can use the same topic, and Dynatrace accepts the logs they send.
A project-level sink exports only the logs of its own project. The pipeline doesn't forward the logs of a project that has no sink, even if you monitor that project.
Run the following steps for each project whose logs you want to forward. Replace the placeholders:
SA_PROJECT: the service account project, where the Terraform bundle deployed the Pub/Sub topic.SOURCE_PROJECT: the project whose logs you want to forward. It can be the same project as SA_PROJECT.MCONFIG_ID: the ID of your monitoring configuration (run dtctl get gcp monitoring to find it).You need roles/logging.configWriter on SOURCE_PROJECT, and permission to change the IAM policy of the topic in SA_PROJECT (for example, roles/pubsub.admin).
Find the Pub/Sub topic. Its name is dt-logs-<MCONFIG_ID> unless you changed dataflow_job_name:
gcloud pubsub topics list --project=SA_PROJECT --filter="name~dt-logs-"
Create the sink. Use --log-filter to limit what you forward. Without it, the sink forwards all logs of the project:
gcloud logging sinks create dt-logs-sink-MCONFIG_ID \pubsub.googleapis.com/projects/SA_PROJECT/topics/dt-logs-MCONFIG_ID \--project=SOURCE_PROJECT \--log-filter='severity>=WARNING'
Data Access audit logs generate high log volume. Include them in the filter only for the services where you need them.
Grant the sink's writer identity permission to publish to the topic. Read the identity from the sink. For a project sink, it is the Cloud Logging service agent of that project. Without this grant, the sink exports nothing:
WRITER=$(gcloud logging sinks describe dt-logs-sink-MCONFIG_ID \--project=SOURCE_PROJECT --format='value(writerIdentity)')gcloud pubsub topics add-iam-policy-binding dt-logs-MCONFIG_ID \--project=SA_PROJECT \--member="$WRITER" \--role="roles/pubsub.publisher"
Verify the sink and the grant:
gcloud logging sinks list --project=SOURCE_PROJECT --filter="name~dt-logs-sink"gcloud pubsub topics get-iam-policy dt-logs-MCONFIG_ID \--project=SA_PROJECT \--flatten="bindings[].members" \--filter="bindings.role=roles/pubsub.publisher" \--format="value(bindings.members)"
The writer identity from step 3 must appear in the output. Logs appear in Dynatrace after the Dataflow job processes them, usually within a few minutes. For further checks, see Troubleshoot GCP connections.
To change what a sink forwards, update its inclusion filter in the Google Cloud Console or with gcloud logging sinks update. Don't change the sink destination (the Pub/Sub topic), because that breaks the forwarding pipeline.
Terraform doesn't know about your sinks, so terraform destroy doesn't remove them. If you remove the forwarding pipeline, also remove your sinks. Otherwise a sink keeps writing to a topic that no longer exists.
The onboarding Terraform creates all log forwarding resources in the service account project. The pipeline requires the following IAM bindings. Terraform creates all of them except the first one, which you grant when you create a log sink:
| Principal | Role | Scope |
|---|---|---|
| Cloud Logging service account (log sink writer identity) | roles/pubsub.publisher | Pub/Sub topic |
| Monitoring service account (Dataflow worker) | roles/dataflow.worker | Project |
| Monitoring service account (Dataflow worker) | roles/pubsub.subscriber | Pub/Sub subscription |
| Monitoring service account (Dataflow worker) | roles/storage.objectAdmin | Dataflow temp bucket |
| Monitoring service account (Dataflow worker) | roles/storage.objectViewer | Dataflow template bucket |
| Monitoring service account (Dataflow worker) | roles/pubsub.viewer | Pub/Sub subscription |
| Monitoring service account (Dataflow worker) | roles/pubsub.subscriber and roles/pubsub.viewer | Pub/Sub replay subscription |
| Monitoring service account (Dataflow worker) | roles/pubsub.publisher | Pub/Sub dead-letter topic |
| Monitoring service account (Dataflow worker) | roles/secretmanager.secretAccessor | Project |
| Monitoring service account (Dataflow worker) | roles/logging.logWriter | Project |
| Dataflow service agent | roles/iam.serviceAccountUser | Monitoring service account |
The bundle grants roles/secretmanager.secretAccessor on the project instead of on the single secret that holds the Log Ingest token. Granting it on the secret would require the account that runs Terraform to hold roles/secretmanager.admin.
If you need to rotate the Dynatrace Log Ingest token used by the Dataflow job, update the token in your deployed Dataflow configuration and re-run Terraform. See Manage your GCP connections for details.
Query GCP logs via DQL in
Notebooks or
Logs.
fetch logs| filter cloud.provider == "gcp"| sort timestamp desc| limit 50
fetch logs| filter cloud.provider == "gcp"and gcp.project.id == "my-project-id"and contains(gcp.log.id, "cloudaudit")| sort timestamp desc
fetch logs| filter cloud.provider == "gcp"and gcp.log.id == "cloudaudit.googleapis.com/activity"| fields timestamp, gcp.project.id, gcp.resource.type, content| sort timestamp desc
fetch logs| filter cloud.provider == "gcp"and gcp.log.id == "cloudaudit.googleapis.com/data_access"| fields timestamp, gcp.project.id, audit.identity, audit.action, audit.result, service.name| sort timestamp desc
fetch logs| filter cloud.provider == "gcp"and loglevel == "ERROR"| summarize count=count(), by: {gcp.project.id, gcp.resource.type}| sort count desc
Logs carry these attributes:
| Attribute | Description |
|---|---|
cloud.provider | Always gcp. |
gcp.project.id | ID of the Google Cloud project. |
gcp.resource.type | Google Cloud resource type that generated the log (for example, gce_instance, k8s_container). |
gcp.log.id | Log type without the project prefix (for example, cloudaudit.googleapis.com/data_access, GCEGuestAgent). |
gcp.logName | Full log name (for example, projects/my-project/logs/cloudaudit.googleapis.com%2Factivity). |
gcp.location, gcp.region, gcp.zone | Location of the resource that generated the log. |
gcp.labels.<key> | Resource label. Present when label enrichment is configured on the connection. |
gcp.tags.<key> | Resource tag. Present when tag enrichment is configured on the connection. |
dt.openpipeline.source | Always da-gcp-pubsub for logs ingested via this pipeline. |
dt.smartscape_source.id | ID of the Dynatrace topology entity this log belongs to (for example, GCP_COMPUTE_GOOGLEAPIS_COM_INSTANCE-A1B2C3D4E5F6G7H8). See Smartscape on Grail. |
dt.smartscape_source.type | Type of the linked entity (for example, GCP_COMPUTE_GOOGLEAPIS_COM_INSTANCE). |
Example log record (GCE guest agent):
{"timestamp": "2026-09-14T12:51:23.053000000Z","cloud.provider": "gcp","gcp.project.id": "my-project","gcp.resource.type": "gce_instance","gcp.log.id": "GCEGuestAgent","gcp.logName": "projects/my-project/logs/GCEGuestAgent","gcp.location": "europe-central2-c","gcp.region": "europe-central2","gcp.zone": "europe-central2-c","gcp.resource_labels.instance_id": "8969141140234854598","gcp.resource_labels.project_id": "my-project","gcp.resource_labels.zone": "europe-central2-c","severity": "INFO","loglevel": "INFO","status": "INFO","message": "Completed adding/removing routes for aliases, forwarded IP and target-instance IPs","content": "{\"localTimestamp\":\"2026-09-14T12:51:23.0539Z\",\"message\":\"Completed adding/removing routes for aliases, forwarded IP and target-instance IPs\"}","dt.openpipeline.source": "da-gcp-pubsub","dt.smartscape_source.id": "GCP_COMPUTE_GOOGLEAPIS_COM_INSTANCE-A1B2C3D4E5F6G7H8","dt.smartscape_source.type": "GCP_COMPUTE_GOOGLEAPIS_COM_INSTANCE"}
Enrichment requires the resource to be already discovered with up-to-date label and tag data. Logs arriving before discovery or before the latest labels and tags are available are ingested without enrichment. Label changes propagate within minutes; tag changes can take up to one hour. Use OpenPipeline rules to set defaults for missing attributes or drop unenriched records.
Ingested logs count toward your Dynatrace log ingest consumption. See the Dynatrace rate card for current log ingest rates.
The log forwarding pipeline runs in your Google Cloud project and can cause charges for the following Google Cloud services:
For details and current rates, see the Google Cloud pricing pages.
To reduce cost, use the inclusion and exclusion filters of your log sinks to keep high-volume, low-value logs out of the pipeline.
Data Access audit logs in particular can generate very high volume—enable them only where needed.