Cloud Logging
Cloud Logging is a fully managed service for storing, searching, analyzing, and alerting on log data from GCP services, VMs, and applications. It integrates with the Log Router for routing logs to multiple destinations.
Logging Architecture
Cloud Logging Architecture:
┌──────────────┐ ┌──────────────┐ ┌──────────────────┐
│ GCP Services │───▶│ │───▶│ Log Storage │
│ (auto-logs) │ │ │ │ (default bucket) │
├──────────────┤ │ Log │ ├──────────────────┤
│ Ops Agent │───▶│ Router │───▶│ Cloud Storage │
│ (VM logs) │ │ │ │ (archival) │
├──────────────┤ │ (Sinks) │ ├──────────────────┤
│ App Logs │───▶│ │───▶│ BigQuery │
│ (structured) │ │ │ │ (analytics) │
├──────────────┤ │ │ ├──────────────────┤
│ Audit Logs │───▶│ │───▶│ Pub/Sub │
│ (admin/data) │ └──────────────┘ │ (streaming) │
└──────────────┘ └──────────────────┘
Log Types
| Log Type |
Description |
Examples |
| Platform Logs |
Auto-generated by GCP services |
VPC flow, load balancer, GKE |
| Audit Logs |
Admin Activity and Data Access |
API calls, resource changes |
| Agent Logs |
Collected by Ops Agent from VMs |
syslog, app logs, nginx |
| User Logs |
Written by applications |
Custom structured logs |
Writing Logs
Structured Logging (Recommended)
import json
import sys
def log_structured(severity, message, **kwargs):
entry = {
"severity": severity,
"message": message,
**kwargs,
}
print(json.dumps(entry))
# Usage
log_structured("INFO", "Request processed",
httpRequest={"method": "GET", "url": "/api/users", "status": 200},
latency="45ms",
userId="user123",
)
Using the Logging Client Library
import google.cloud.logging
client = google.cloud.logging.Client()
logger = client.logger("my-app")
# Write a text log
logger.log_text("Application started")
# Write a structured log
logger.log_struct({
"event": "user_login",
"userId": "user123",
"ip": "10.0.1.50",
"status": "success",
})
# Write with severity
logger.log_struct(
{"message": "Database connection failed", "retry": 3},
severity="ERROR",
)
Query Logs
# Read recent logs
$ gcloud logging read "resource.type=gce_instance" --limit=10
# Filter by severity
$ gcloud logging read "severity>=ERROR" --limit=20 --format=json
# Filter by time range
$ gcloud logging read 'timestamp>="2026-03-30T00:00:00Z" AND timestamp<="2026-03-30T23:59:59Z"' --limit=50
# Filter by text payload
$ gcloud logging read 'textPayload:"connection refused"' --limit=10
# Filter by JSON payload field
$ gcloud logging read 'jsonPayload.status="error" AND jsonPayload.service="api"' --limit=10
# Read Cloud Run logs
$ gcloud logging read 'resource.type="cloud_run_revision" AND resource.labels.service_name="my-service"' --limit=20
Log-Based Metrics
Convert log patterns into metrics for monitoring and alerting:
# Create a counter metric for error logs
$ gcloud logging metrics create app-errors \
--description="Application error count" \
--log-filter='resource.type="cloud_run_revision" AND severity=ERROR'
# Create a distribution metric for latency
$ gcloud logging metrics create request-latency \
--description="Request latency distribution" \
--log-filter='resource.type="cloud_run_revision" AND jsonPayload.latency_ms:*' \
--bucket-options='{"linearBuckets":{"numFiniteBuckets":20,"width":50,"offset":0}}' \
--value-extractor='EXTRACT(jsonPayload.latency_ms)'
# List log-based metrics
$ gcloud logging metrics list
Log Sinks (Routing)
# Create a sink to Cloud Storage (archival)
$ gcloud logging sinks create archive-sink \
storage.googleapis.com/my-log-archive \
--log-filter='resource.type="gce_instance"'
# Create a sink to BigQuery (analytics)
$ gcloud logging sinks create bq-sink \
bigquery.googleapis.com/projects/my-project/datasets/logs \
--log-filter='resource.type="cloud_run_revision"'
# Create a sink to Pub/Sub (streaming)
$ gcloud logging sinks create pubsub-sink \
pubsub.googleapis.com/projects/my-project/topics/log-events \
--log-filter='severity>=ERROR'
# Create an exclusion filter (reduce costs)
$ gcloud logging sinks update _Default \
--add-exclusion=name=exclude-debug,filter='severity=DEBUG'
# List sinks
$ gcloud logging sinks list
Log Buckets and Retention
# List log buckets
$ gcloud logging buckets list --location=global
# Create a custom bucket with extended retention
$ gcloud logging buckets create security-logs \
--location=global \
--retention-days=365 \
--description="Security audit logs"
# Update retention for the default bucket
$ gcloud logging buckets update _Default \
--location=global \
--retention-days=90
# Route logs to custom bucket
$ gcloud logging sinks create security-sink \
logging.googleapis.com/projects/my-project/locations/global/buckets/security-logs \
--log-filter='logName:"cloudaudit.googleapis.com"'
Audit Logs
| Audit Log Type |
Default |
Content |
| Admin Activity |
Always on (free) |
Resource creation/deletion/modification |
| Data Access |
Off by default |
Read operations on data |
| System Event |
Always on (free) |
Google-initiated actions |
| Policy Denied |
Always on (free) |
Access denials |
# Enable Data Access audit logs
$ gcloud projects get-iam-policy my-project --format=json > policy.json
# Edit policy.json to add auditConfigs, then:
$ gcloud projects set-iam-policy my-project policy.json
Common Mistakes
| Mistake |
Why It’s Wrong |
Fix |
| Unstructured logging |
Hard to query and filter |
Use JSON structured logging |
| No exclusion filters |
Storing DEBUG logs = high cost |
Exclude low-value logs |
| Default retention only |
30 days too short for compliance |
Create custom buckets |
| No log sinks |
Logs not archived |
Route to GCS for long-term |
| Not using log-based metrics |
Missing alerting on patterns |
Create metrics for key events |
Quick Reference
| Command |
Description |
gcloud logging read FILTER |
Read/query logs |
gcloud logging write LOG_NAME MESSAGE |
Write a log entry |
gcloud logging metrics create |
Create log-based metric |
gcloud logging sinks create |
Create log sink |
gcloud logging buckets create |
Create log bucket |
gcloud logging sinks list |
List sinks |
Next → Cloud Trace