Registra y visualiza registros en Cloud Run

Cloud Run envía registros de cargas de trabajo a Cloud Logging para que puedas supervisar el estado, inspeccionar el tráfico y solucionar errores de la aplicación. Ver y escribir registros estructurados te ayuda a diagnosticar problemas de entorno de ejecución en tus recursos de Cloud Run.

Cloud Run recopila tres tipos de registros. Los registros de solicitudes registran las solicitudes entrantes de los servicios. Los registros de contenedores capturan el resultado de tu código en todos los recursos cuando se escriben en las ubicaciones compatibles que se describen en Escribe registros de contenedores. Los registros del sistema registran los eventos de la plataforma para todos los recursos de varlog/system.

Ver registros

Puedes ver los registros de tu recurso de Cloud Run de varias formas:

Ambos métodos de la consola de visualización de registros analizan los mismos registros almacenados en Cloud Logging, pero el Explorador de registros de Cloud Logging proporciona más detalles y más capacidades de filtrado.

Visualiza registros en Cloud Run

Puedes ver los registros en la página de Cloud Run para los siguientes recursos:

Servicios

  1. En la consola de Cloud de Confiance by S3NS , ve a la página Servicios de Cloud Run:

    Ir a Cloud Run

  2. Haz clic en el servicio en la lista que se muestra.

  3. Hacer clic en la pestaña Registros para obtener los registros de solicitud y contenedor de todas las revisiones de este servicio. Puedes filtrar por nivel de gravedad del registro.

Trabajos

Para ver los registros de un trabajo en la página de Cloud Run, debes hacer lo siguiente:

  1. En la consola de Cloud de Confiance by S3NS , ve a la página Trabajos de Cloud Run:

    Ir a Cloud Run

  2. Ubica el trabajo en la lista de trabajos y haz clic en él.

  3. Haz clic en la pestaña Registros para obtener los registros de contenedor de todas las ejecuciones de este trabajo. Puedes filtrar por nivel de gravedad del registro.

  4. Como alternativa, si deseas ver los registros filtrados previamente para una ejecución de trabajo específica, haz clic en la ejecución del trabajo y, luego, en la pestaña Registros.

Formato y contenido de los registros de escalamiento de instancias

Cuando se inician instancias nuevas para tu servicio de Cloud Run, Cloud Logging incluye entradas de registro con el nombre de registro varlog/system que explican por qué se creó cada instancia. La entrada de registro sigue este formato:

Starting new instance. Reason: REASON - DESCRIPTION

En la siguiente tabla, se proporciona un desglose de las descripciones de las instancias:

Motivo Descripción
MANUAL_OR_CUSTOMER_MIN_INSTANCE La instancia se inició debido a las instancias mínimas o al escalamiento manual configurados por el cliente.
AUTOSCALING La instancia se inició debido a los factores de escalamiento configurados (como el uso de CPU, la capacidad de procesamiento de solicitudes, etc.) o a que no hay suficiente capacidad existente para el tráfico actual.
DEPLOYMENT_ROLLOUT La instancia se inició debido al cambio de tráfico entre revisiones por la implementación, el ajuste de la división del tráfico o la verificación de estado de la implementación.

Escribe registros de contenedores

Cuando escribes registros desde el servicio, el trabajo o el grupo de trabajadores, Cloud Logging los selecciona de manera automática, siempre y cuando se escriban en cualquiera de estas ubicaciones:

Se espera que la mayoría de los desarrolladores escriban registros mediante transmisiones de salida estándar y error estándar.

Los registros de contenedores escritos en estas ubicaciones compatibles se asocian de manera automática con el servicio, la revisión y la ubicación de Cloud Run, el grupo de trabajadores, la revisión y la ubicación de Cloud Run, o con el trabajo de Cloud Run. Las excepciones en estos registros se capturan y se informan en Error Reporting.

El registro integrado equilibra la confiabilidad y el uso de recursos, y debería funcionar para la mayoría de las aplicaciones. Escribir entradas de registro con el registro integrado no consume la cuota de la cantidad de solicitudes entries.write por minuto de la API de Cloud Logging.

Si tu aplicación tiene requisitos para un mayor volumen o confiabilidad, te recomendamos usar la API de Cloud Logging directamente, ya sea como una biblioteca dentro de la aplicación o como un contenedor sidecar independiente.

Comparación entre el uso de texto simple y de JSON estructurado en los registros

Cuando escribes registros, puedes enviar una string de texto simple o una sola línea de JSON serializado, que también se conoce como datos estructurados. Cloud Logging lo recopila y analiza, y se coloca en jsonPayload. En cambio, el mensaje de texto simple se coloca en textPayload.

Escribe registros estructurados

En el siguiente fragmento, se muestra cómo escribir entradas de registro estructuradas. También se muestra cómo correlacionar los mensajes de registro con el registro de solicitud correspondiente.

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

Un tipo de Entry proporciona la estructura para cada entrada de registro:


// 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)
}

Cuando se registra un struct de Entry, se llama al método String para serializarla según el formato JSON que espera 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

Para habilitar el registro JSON con Logback y SLF4J, configura el adjuntador de Logback de Logging en la configuración logback.xml:

// 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];
  MDC.put(
      "logging.googleapis.com/trace",
      String.format("projects/%s/traces/%s", project, trace));
}
// -- End log correlation code --

// Create a structured log entry using MDC (Mapped Diagnostic Context) keys.
// For instantiating the "logger" variable, see
// https://cloud.google.com/run/docs/logging#run_manual_logging-java
MDC.put("component", "arbitrary-property");

logger.info("This is the default display field.");

// Clear MDC at the end of the request to avoid resource leaks
MDC.clear();

Configura el LoggingAppender para redireccionar los registros a la salida estándar (stdout) en formato JSON estructurado para que Cloud Run los capture. Para obtener más detalles, consulta Configuración de Logback.

<configuration>
  <appender name="CLOUD" class="com.google.cloud.logging.logback.LoggingAppender">
    <!-- Optional : filter logs at or above a level -->
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
      <level>INFO</level>
    </filter>
    <log>application.log</log> <!-- Optional : default java.log -->
    <resourceType>gae_app</resourceType> <!-- Optional : default: auto-detected, fallback: global -->
    <enhancer>com.example.logging.logback.enhancers.ExampleEnhancer</enhancer> <!-- Optional -->
    <flushLevel>WARN</flushLevel> <!-- Optional : default ERROR -->
    <!-- Redirect logs to stdout in JSON format for Cloud Run to capture -->
    <redirectToStdout>true</redirectToStdout>
  </appender>
  <root level="INFO">
    <appender-ref ref="CLOUD"/>
  </root>
</configuration>

Esto produce la siguiente estructura de registro de salida:

{"severity":"INFO","time":"YYYY-MM-DDTHH:MM:SS.SSSZ","logging.googleapis.com/labels":{"component":"arbitrary-property","levelName":"INFO","loggerName":"com.example.cloudrun.App","levelValue":"20000"},"logging.googleapis.com/trace_sampled":false,"message":"This is the default display field."}

Campos JSON especiales en los mensajes

Cuando proporcionas un registro estructurado como un diccionario JSON, algunos campos especiales se quitan de jsonPayload y se escriben en el campo correspondiente en la LogEntry generada, como se describe en la documentación sobre campos especiales.

Por ejemplo, si el JSON incluye una propiedad severity, se quita de jsonPayload y aparece como la severity de la entrada de registro. La propiedad message se usa como el texto de visualización principal de la entrada de registro si está presente. Para obtener más información sobre las propiedades especiales, lee la sección Recurso de registro.

Correlaciona los registros del contenedor con un registro de solicitud (solo servicios)

En el Explorador de registros, los registros que se correlacionan por el mismo trace se pueden ver en formato de “superior-secundario”. Cuando haces clic en el ícono de triángulo a la izquierda de la entrada de registro de la solicitud, los registros de contenedores relacionados con esa solicitud aparecen anidados en el registro de solicitud.

Los registros de contenedores no se correlacionan de forma automática con los registros de solicitudes, a menos que uses una biblioteca cliente de Cloud Logging. Para correlacionar registros de contenedores con registros de solicitudes sin usar una biblioteca cliente, puedes usar una línea de registro JSON estructurada que contenga un campo logging.googleapis.com/trace con el identificador de seguimiento extraído del encabezado X-Cloud-Trace-Context, como se muestra en el ejemplo anterior de un registro estructurado.

Controla el uso de recursos de registros de solicitudes (solo servicios)

Los registros de solicitudes se crean de forma automática. Aunque no puedes controlar la cantidad de registros de solicitudes directamente desde Cloud Run, puedes usar la función de exclusión de registros de Cloud Logging.

Nota sobre los agentes de registro

Si usaste Cloud Logging con ciertos productos de Cloud de Confiance by S3NS , como Compute Engine, es posible que hayas usado agentes de Logging de Cloud Logging. Cloud Run no usa agentes de Logging porque tiene compatibilidad integrada en la recopilación de registros.

Nombres de recursos de registro

Los nombres de los recursos de registro para Cloud Run son los siguientes:

Recursos de registro

Si haces clic en una entrada de registro en el Explorador de registros, se abre una entrada de registro con formato JSON para que puedas desglosar los detalles que desees.

Todos los campos de una entrada de registro, como las marcas de tiempo, la gravedad y las httpRequest, son estándar y se describen en la documentación sobre una entrada de registro.

Cloud Run agrega metadatos adicionales para que puedas identificar el origen de un registro. Esto incluye las etiquetas que estableces en el servicio de Cloud Run y las etiquetas de recursos específicas de Cloud Run.

Campos de entradas de registro de un servicio

La siguiente es una lista de campos que se pueden encontrar en la entrada de registro de un servicio de Cloud Run:

Campo Valores y notas
LogEntry.labels.instanceId Este ID se asigna a una instancia particular de este servicio a medida que aumenta o disminuye su escala.
LogEntry.labels.run.googleapis.com/base_image_versions Es la versión de la imagen base que usa el servicio. Solo aparece para los servicios implementados desde la fuente y si las actualizaciones de seguridad automáticas están habilitadas.
LogEntry.labels.run.googleapis.com/cloud_event_id Es el ID de CloudEvent. Solo aparece para los servicios que reciben eventos de Eventarc.
LogEntry.labels.run.googleapis.com/cloud_event_source Es la fuente de CloudEvent. Solo aparece para los servicios que reciben eventos de Eventarc.
LogEntry.labels.mylabel,
LogEntry.labels.mysecondlabel
Las etiquetas que configuras en el servicio.
LogEntry.logName Identifica el registro, por ejemplo, registro de solicitud, error estándar, salida estándar, etc.
LogEntry.resource.labels.location Identifica la ubicación de Cloud de Confiance by S3NS del servicio.
LogEntry.resource.labels.project_id El proyecto en el que se implementa el servicio.
LogEntry.resource.labels.revision_name La revisión que entregó la solicitud.
LogEntry.resource.labels.service_name El servicio que entregó la solicitud.
LogEntry.resource.type cloud_run_revision. El tipo de recurso de Cloud Run.

A continuación, se muestra un ejemplo de una entrada de registro de solicitud para un servicio de Cloud Run:

{
 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:  "europe-west1"
   project_id:  "my-project"
   revision_name:  "myservice-00002"
   service_name:  "myservice"
  }
  type:  "cloud_run_revision"
 }
 severity:  "INFO"
 timestamp:  "2019-03-08T18:26:25.970397Z"
}

Campos de entradas de registro para trabajos

La siguiente es una lista de campos que se pueden encontrar en la entrada de registro de un trabajo de Cloud Run:

Campo Valores y notas
LogEntry.labels.instanceId Este ID se asigna a la instancia particular que se usó para una ejecución de trabajo o de tarea específica.
LogEntry.labels.mylabel,
LogEntry.labels.mysecondlabel
Las etiquetas que configuras en el trabajo.
LogEntry.logName Identifica el registro, por ejemplo, error estándar, salida estándar, etcétera.
LogEntry.resource.labels.location Identifica la ubicación de Cloud de Confiance by S3NS del trabajo.
LogEntry.resource.labels.project_id Es el proyecto en el que se implementa el trabajo.
LogEntry.resource.labels.job_name Es el nombre del trabajo.
LogEntry.labels.execution_name Es el nombre de la ejecución del trabajo.
LogEntry.labels.task_index El índice de la tarea.
LogEntry.labels.task_attempt Cuántas veces se intentó esta tarea.
LogEntry.resource.type cloud_run_job. El tipo de recurso de Cloud Run.