Google Cloud Run logging

Start shipping logs and traces in 10 minutes

Ship logs and traces from your Cloud Run service to Better Stack using the Google-built OpenTelemetry collector as a sidecar.

Your app sends logs and metrics to the collector on localhost as OpenTelemtry, and the collector forwards everything to Better Stack.

Before you begin

Enable Google Run and SecretsManager APIs:

Enable the required APIs
gcloud services enable run.googleapis.com secretmanager.googleapis.com

Create the OpenTelemetry source

  1. Create an OpenTelemetry source and give it a name.
  2. Keep that tab open. You'll need the Source token and Ingesting host later.

Create the collector config

Save the following config as config.yaml:

Forward logs and traces Also forward metrics
receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
      http:
        endpoint: 0.0.0.0:4318

processors:
  batch:

exporters:
  otlp_http/betterstack:
    endpoint: "https://$INGESTING_HOST"
    headers:
      Authorization: "Bearer $SOURCE_TOKEN"
    compression: gzip

extensions:
  health_check:
    endpoint: 0.0.0.0:13133

service:
  extensions: [health_check]
  pipelines:
    logs/betterstack:
      receivers: [otlp]
      processors: [batch]
      exporters: [otlp_http/betterstack]
    traces/betterstack:
      receivers: [otlp]
      processors: [batch]
      exporters: [otlp_http/betterstack]
receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
      http:
        endpoint: 0.0.0.0:4318

processors:
  batch:

exporters:
  otlp_http/betterstack:
    endpoint: "https://$INGESTING_HOST"
    headers:
      Authorization: "Bearer $SOURCE_TOKEN"
    compression: gzip

extensions:
  health_check:
    endpoint: 0.0.0.0:13133

service:
  extensions: [health_check]
  pipelines:
    logs/betterstack:
      receivers: [otlp]
      processors: [batch]
      exporters: [otlp_http/betterstack]
    traces/betterstack:
      receivers: [otlp]
      processors: [batch]
      exporters: [otlp_http/betterstack]
    metrics/betterstack:
      receivers: [otlp]
      processors: [batch]
      exporters: [otlp_http/betterstack]


Store the config as a secret so Cloud Run can mount it into the collector:

Store the config as a secret
gcloud secrets create betterstack-otel-config --data-file=config.yaml

Grant access to the secret to the Cloud Run runtime:

Allow Cloud Run to read the secret
gcloud secrets add-iam-policy-binding betterstack-otel-config \
  --member="serviceAccount:PROJECT_NUMBER-compute@developer.gserviceaccount.com" \
  --role="roles/secretmanager.secretAccessor"

Get your project number

Get your PROJECT_NUMBER using gcloud projects describe PROJECT_ID --format='value(projectNumber)'. If you're using a custom service account, grant the role to that account instead of the default compute one.

Add the collector sidecar to your service

Save your service manifest as service.yaml. The container-dependencies annotation starts the collector before your app, and the app sends OTLP to the collector on localhost:4317:

service.yaml
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: my-service
  annotations:
    run.googleapis.com/launch-stage: BETA
spec:
  template:
    metadata:
      annotations:
        run.googleapis.com/container-dependencies: '{"app":["collector"]}'
        run.googleapis.com/secrets: "betterstack-otel-config:projects/PROJECT_ID/secrets/betterstack-otel-config"
    spec:
      containers:
        - name: app
          image: REGION-docker.pkg.dev/PROJECT_ID/REPO/my-app:latest
          ports:
            - containerPort: 8080
          env:
            - name: OTEL_EXPORTER_OTLP_ENDPOINT
              value: "http://localhost:4317"
            - name: OTEL_EXPORTER_OTLP_PROTOCOL
              value: "grpc"
        - name: collector
          image: "us-docker.pkg.dev/cloud-ops-agents-artifacts/google-cloud-opentelemetry-collector/otelcol-google:0.151.0"
          args:
            - --config=/etc/otelcol-google/config.yaml
          startupProbe:
            httpGet:
              path: /
              port: 13133
            timeoutSeconds: 30
            periodSeconds: 30
          livenessProbe:
            httpGet:
              path: /
              port: 13133
            timeoutSeconds: 30
            periodSeconds: 30
          volumeMounts:
            - name: config
              mountPath: /etc/otelcol-google/
      volumes:
        - name: config
          secret:
            secretName: betterstack-otel-config
            items:
              - key: latest
                path: config.yaml

Replace my-service, image, PROJECT_ID, PROJECT_NUMBER, and REGION with your own values. The image is your full Artifact Registry path. Then deploy:

Deploy your service
gcloud run services replace service.yaml --region=REGION

Customizing OTLP protocol

Port 4317 is the collector's gRPC endpoint, so the app sets OTEL_EXPORTER_OTLP_PROTOCOL=grpc. To use HTTP instead, point OTEL_EXPORTER_OTLP_ENDPOINT at http://localhost:4318 and drop the protocol variable.

Instrument your app

Instrument your app with the OpenTelemetry SDK for your language so it emits OTLP logs and traces. SDKs are available for JavaScript, Python, Go, and Java. Use the OTEL_EXPORTER_OTLP_ENDPOINT environment variable to point the SDK to the collector.

You should see your logs and traces in Better Stack → Live tail.

Not seeing any logs?

Cloud Run scales to zero, so send a request to your service URL to wake your instance.

Collect metrics

Collect metrics for Google Cloud Run and other Google Cloud services. Deploy Google Cloud integration into your GCP project via ready-to-use script. Start by creating a GCP source.

Read more about Better Stack Google Cloud integration.

Need help?

Please let us know at hello@betterstack.com.
We're happy to help! 🙏