Logging and viewing logs in Cloud Run

This page describes the logs available when using Cloud Run, and how to view and write logs.

Cloud Run has two types of logs, and these are automatically sent to Cloud Logging:

  • Request logs (services only): logs of requests sent to Cloud Run services. These logs are created automatically.
  • Container logs (services and jobs): logs emitted from the instances, typically from your own code, written to supported locations as described in Writing container logs.

View logs

You can view logs for your service or job in several ways:

Both of the console methods of viewing logs examine the same logs stored in Cloud Logging, but the Cloud Logging Logs Explorer provides more details and more filtering capabilities.

View logs in Cloud Run

You can view logs for services and jobs in the corresponding service and jobs pages.

View logs for a service

To view service logs in the Cloud Run page:

  1. Go to Cloud Run

  2. Click the desired service in the displayed list.

  3. Click the LOGS tab to get the request and container logs for all revisions of this service. You can filter by log severity level.

View logs for a job

To view job logs in the Cloud Run page:

  1. Go to Cloud Run

  2. Click the JOBS tab.

  3. Locate the job in the jobs list, and click on it.

  4. Click the LOGS tab to get the container logs for all executions of this job. You can filter by log severity level.

  5. Alternatively, if you want to see the logs pre-filtered for a specific job execution, click on the job execution and then click the LOGS tab.

View service logs using Google Cloud CLI

You can use Google Cloud CLI to view tailing logs or read existing logs for a Cloud Run service in the command line By default, the logs are formatted in a single-line format optimized for the console.

To tail logs, you need to install the log-streaming component in Google Cloud CLI. If the component isn't installed, you will be prompted to install it when required.

View tailing logs in the command line

For a Cloud Run service, you can tail logs in real-time from your Cloud Run service directly in the command-line:

gcloud beta run services logs tail SERVICE --project PROJECT-ID

Replace

  • SERVICE with the name of the Cloud Run service
  • PROJECT-ID with the Google Cloud project ID. You can view your project ID by running the command gcloud config get-value project.

Read logs in the command line

For a Cloud Run service, you can read existing logs in either of two ways:

  • In a console-optimized format:
    gcloud run services logs read SERVICE --limit=10 --project PROJECT-ID
    
  • Directly from Cloud Logging:
    gcloud logging read "resource.type=cloud_run_revision AND resource.labels.service_name=SERVICE" --project PROJECT-ID --limit 10

Replace

  • SERVICE with the name of the Cloud Run service
  • PROJECT-ID with the Google Cloud project ID. You can view your project ID by running the command gcloud config get-value project.

View logs in Cloud Logging

To view your Cloud Run logs in the Cloud Logging Logs Explorer:

  1. Go to the Logs Explorer page in the Google Cloud console:

    Go to the Logs Explorer page

  2. Select an existing Google Cloud project at the top of the page, or create a new project.

  3. Using the drop-down menus, select the resource Cloud Run Revision for a service, or Cloud Run Job for a job.

For more information, see Using the Logs Explorer.

View service logs in Cloud Code

To view your logs in Cloud Code, read the IntelliJ and Visual Studio Code guides.

Read logs programmatically

If you want to read the logs programmatically, you can use one of these methods:

Write container logs

When you write logs from your service or job, they will be picked up automatically by Cloud Logging so long as the logs are written to any of these locations:

Most developers are expected to write logs using standard output and standard error.

The container logs written to these supported locations are automatically associated with the Cloud Run service, revision, and location, or with the Cloud Run job. Exceptions contained in these logs are captured by and reported in Error Reporting.

The integrated logging balances reliability and resource usage, and should work for most applications. Writing log entries using integrated logging does not consume quota for the number of entries.write requests per minute of the Cloud Logging API.

If your application has requirements for higher volume or reliability, we recommend using the Cloud Logging API directly, either as a library within your application or as a separate sidecar container.

Use simple text vs structured JSON in logs

When you write logs, you can send a simple text string or send a single line of serialized JSON, also called "structured" data. This is picked up and parsed by Cloud Logging and is placed into jsonPayload. In contrast, the simple text message is placed in textPayload.

Write structured logs

The following snippet shows how to write structured log entries. It also shows how to correlate log messages with the corresponding request log.

Node.js


// Uncomment and populate this variable in your code:
// const project = 'The project ID of your function or Cloud Run service';

// Build structured log messages as an object.
const globalLogFields = {};

// Add log correlation to nest all log messages beneath request log in Log Viewer.
// (This only works for HTTP-based invocations where `req` is defined.)
if (typeof req !== 'undefined') {
  const traceHeader = req.header('X-Cloud-Trace-Context');
  if (traceHeader && project) {
    const [trace] = traceHeader.split('/');
    globalLogFields['logging.googleapis.com/trace'] =
      `projects/${project}/traces/${trace}`;
  }
}

// Complete a structured log entry.
const entry = Object.assign(
  {
    severity: 'NOTICE',
    message: 'This is the default display field.',
    // Log viewer accesses 'component' as 'jsonPayload.component'.
    component: 'arbitrary-property',
  },
  globalLogFields
);

// Serialize to a JSON string and output.
console.log(JSON.stringify(entry));

Python

# Uncomment and populate this variable in your code:
# PROJECT = 'The project ID of your Cloud Run service';

# Build structured log messages as an object.
global_log_fields = {}

# Add log correlation to nest all log messages.
# This is only relevant in HTTP-based contexts, and is ignored elsewhere.
# (In particular, non-HTTP-based Cloud Functions.)
request_is_defined = "request" in globals() or "request" in locals()
if request_is_defined and request:
    trace_header = request.headers.get("X-Cloud-Trace-Context")

    if trace_header and PROJECT:
        trace = trace_header.split("/")
        global_log_fields[
            "logging.googleapis.com/trace"
        ] = f"projects/{PROJECT}/traces/{trace[0]}"

# Complete a structured log entry.
entry = dict(
    severity="NOTICE",
    message="This is the default display field.",
    # Log viewer accesses 'component' as jsonPayload.component'.
    component="arbitrary-property",
    **global_log_fields,
)

print(json.dumps(entry))

Go

The structure for each log entry is provided by an Entry type:


// Entry defines a log entry.
type Entry struct {
	Message  string `json:"message"`
	Severity string `json:"severity,omitempty"`
	Trace    string `json:"logging.googleapis.com/trace,omitempty"`

	// Logs Explorer allows filtering and display of this as `jsonPayload.component`.
	Component string `json:"component,omitempty"`
}

// String renders an entry structure to the JSON format expected by Cloud Logging.
func (e Entry) String() string {
	if e.Severity == "" {
		e.Severity = "INFO"
	}
	out, err := json.Marshal(e)
	if err != nil {
		log.Printf("json.Marshal: %v", err)
	}
	return string(out)
}

When an Entry struct is logged, the String method is called to marshal it to the JSON format expected by Cloud Logging:


func init() {
	// Disable log prefixes such as the default timestamp.
	// Prefix text prevents the message from being parsed as JSON.
	// A timestamp is added when shipping logs to Cloud Logging.
	log.SetFlags(0)
}

func indexHandler(w http.ResponseWriter, r *http.Request) {
	// Uncomment and populate this variable in your code:
	// projectID = "The project ID of your Cloud Run service"

	// Derive the traceID associated with the current request.
	var trace string
	if projectID != "" {
		traceHeader := r.Header.Get("X-Cloud-Trace-Context")
		traceParts := strings.Split(traceHeader, "/")
		if len(traceParts) > 0 && len(traceParts[0]) > 0 {
			trace = fmt.Sprintf("projects/%s/traces/%s", projectID, traceParts[0])
		}
	}

	log.Println(Entry{
		Severity:  "NOTICE",
		Message:   "This is the default display field.",
		Component: "arbitrary-property",
		Trace:     trace,
	})

	fmt.Fprintln(w, "Hello Logger!")
}

Java

Enable JSON logging with Logback and SLF4J by enabling the Logstash JSON Encoder in your logback.xml configuration.

// Build structured log messages as an object.
Object globalLogFields = null;

// Add log correlation to nest all log messages beneath request log in Log Viewer.
// TODO(developer): delete this code if you're creating a Cloud
//                  Function and it is *NOT* triggered by HTTP.
String traceHeader = req.headers("x-cloud-trace-context");
if (traceHeader != null && project != null) {
  String trace = traceHeader.split("/")[0];
  globalLogFields =
      kv(
          "logging.googleapis.com/trace",
          String.format("projects/%s/traces/%s", project, trace));
}
// -- End log correlation code --

// Create a structured log entry using key value pairs.
// For instantiating the "logger" variable, see
// https://cloud.google.com/run/docs/logging#run_manual_logging-java
logger.error(
    "This is the default display field.",
    kv("component", "arbitrary-property"),
    kv("severity", "NOTICE"),
    globalLogFields);

Customize standard field names to exclude unwanted content from ingestion in the logs payload. For a list of field names and expected data formats see Use the logging agent.

<configuration>
  <appender name="jsonConsoleAppender" class="ch.qos.logback.core.ConsoleAppender">
    <encoder class="net.logstash.logback.encoder.LogstashEncoder">
      <!-- Ignore default logging fields -->
      <fieldNames>
        <timestamp>[ignore]</timestamp>
        <version>[ignore]</version>
        <logger>[ignore]</logger>
        <thread>[ignore]</thread>
        <level>[ignore]</level>
        <levelValue>[ignore]</levelValue>
      </fieldNames>
    </encoder>
  </appender>
  <root level="INFO">
    <appender-ref ref="jsonConsoleAppender"/>
  </root>
</configuration>

Special JSON fields in messages

When you provide a structured log as a JSON dictionary, some special fields are stripped from the jsonPayload and are written to the corresponding field in the generated LogEntry as described in the documentation for special fields.

For example, if your JSON includes a severity property, it is removed from the jsonPayload and appears instead as the log entry's severity. The message property is used as the main display text of the log entry if present. For more on special properties read the Logging Resource section below.

Correlate your container logs with a request log (services only)

In the Logs Explorer, logs correlated by the same trace are viewable in "parent-child" format: when you click on the triangle icon at the left of the request log entry, the container logs related to that request show up nested under the request log.

Container logs are not automatically correlated to request logs unless you use a Cloud Logging client library. To correlate container logs with request logs without using a client library, you can use a structured JSON log line that contains a logging.googleapis.com/trace field with the trace identifier extracted from the X-Cloud-Trace-Context header as shown in the above sample for structured logging.

Control request log resource usage (services only)

Request logs are created automatically. Although you cannot control the amount of request logs directly from Cloud Run, you can make use of the logs exclusion feature from Cloud Logging.

A note about logging agents

If you've used Cloud Logging with certain Google Cloud products, such as Compute Engine, you may have used Cloud Logging logging agents. Cloud Run does not use logging agents because it has built-in support for log collection.

Logging resource names

The logging resource names for Cloud Run are:

Logging resources

Clicking on a log entry in the Logs Explorer opens up a JSON formatted log entry so you can drill down to the details you want.

All of the fields in a log entry, such as timestamps, severity, and httpRequest are standard, and are described in the documentation for a log entry.

Cloud Run adds additional metadata, so you can identify the source of a log. This includes the (labels that you set on your Cloud Run service) and resource labels that are specific to Cloud Run.

Log entry fields for a service

The following is a list of fields that can be found in the log entry for a Cloud Run service:

Field Values and notes
LogEntry.labels.instanceId The instance that handled the request.
LogEntry.labels.mylabel,
LogEntry.labels.mysecondlabel
The labels that are set by you on the service.
LogEntry.logName Identifies the log, for example, request log, standard error, standard output, etc.
LogEntry.resource.labels.location Identifies the Google Cloud location of the service.
LogEntry.resource.labels.project_id The project the service is deployed to.
LogEntry.resource.labels.revision_name The revision that served the request.
LogEntry.resource.labels.service_name The service that served the request.
LogEntry.resource.type cloud_run_revision. The Cloud Run resource type.

Here's an example request log entry for a Cloud Run service:

{
 httpRequest: {…}
 insertId:  "5c82b3d1000ece0000000000"
 labels: {
  instanceId:  "00bf4bf00000fb59c906a00000c9e29c2c4e06dce91500000000056008d2b6460f163c0057b97b2345f2725fb2423ee5f0bafd36df887fdb1122371563cf1ff453717282afe000001"
  mylabel: "mylabelvalue"
  mysecondlabel: "mysecondlabelvalue"
 }
 logName:  "projects/my-project/logs/run.googleapis.com%2Frequests"
 receiveTimestamp:  "2019-03-08T18:26:25.981686167Z"
 resource: {
  labels: {
   configuration_name:  "myservice"
   location:  "us-central1"
   project_id:  "my-project"
   revision_name:  "myservice-00002"
   service_name:  "myservice"
  }
  type:  "cloud_run_revision"
 }
 severity:  "INFO"
 timestamp:  "2019-03-08T18:26:25.970397Z"
}

Log entry fields for jobs

The following is a list of fields that can be found in the log entry for a Cloud Run job:

Field Values and notes
LogEntry.labels.instanceId The instance.
LogEntry.labels.mylabel,

LogEntry.labels.mysecondlabel

The labels that are set by you on the job.
LogEntry.logName Identifies the log, for example, request log, standard error, standard output, etc.
LogEntry.resource.labels.location Identifies the Google Cloud location of the service.
LogEntry.resource.labels.project_id The project the service is deployed to.
LogEntry.resource.labels.job_name The name of the job.
LogEntry.labels.execution_name The name of the job execution.
LogEntry.labels.task_index The task index.
LogEntry.labels.task_attempt How many times this task has been attempted.
LogEntry.resource.type cloud_run_job. The Cloud Run resource type.