Escribe y visualiza registros

En esta página, se describen los registros disponibles cuando se usa Cloud Run y cómo ver y escribir registros.

Cloud Run tiene dos tipos de registros que se envían de forma automática a Cloud Logging:

  • Registros de solicitudes: Registros de solicitudes enviadas a los servicios de Cloud Run. Estos registros se crean de forma automática.
  • Registros de contenedores: Registros emitidos desde las instancias de contenedor, por lo general, desde tu propio código, escritos en ubicaciones compatibles como se describe en Escribe registros de contenedores.

Visualiza registros

Puedes visualizar los registros de tu servicio de estas dos maneras:

  • Usa la página de Cloud Run en Cloud Console.
  • Usa el visor de registros de Cloud Logging en Cloud Console.

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

Visualiza registros en Cloud Run

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

  1. Ir a Cloud Run

  2. Hacer clic en el servicio deseado 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

Visualiza registros en Cloud Logging

Para ver los registros de Cloud Run en el visor de registros de Cloud Logging, sigue estos pasos:

  1. Ve a la página Visor de registros en Cloud Console.

    Ir a la página Visor de registros

  2. Selecciona un proyecto de Google Cloud existente en la parte superior de la página o crea un proyecto nuevo.

  3. Usa los menús desplegables para seleccionar el recurso:

    • Revisión de Cloud Run para Cloud Run (completamente administrado)
    • Contenedor de Kubernetes para Cloud Run for Anthos en Google Cloud

Para obtener más información, consulta Visualiza registros en Logging de Google Cloud's operations suite.

Visualiza registros en Cloud Code

Para ver tus registros en Cloud Code, lee las guías de IntelliJ y Visual Studio Code.

Visualiza registros mediante la línea de comandos

Si deseas ver los registros de Cloud Run (completamente administrado) en un formato optimizado (“mejorado”) para verlos en la consola, usa la línea de comandos:

gcloud logging read "resource.type=cloud_run_revision AND resource.labels.service_name=SERVICE" --project PROJECT-ID --limit 10

Si necesitas el JSON real “sin mejorar”, puedes leer los registros de manera programática.

Reemplaza PROJECT-ID por el ID del proyecto de Google Cloud. Para ver el ID del proyecto, ejecuta el comando gcloud config get-value project. Reemplaza SERVICE por el nombre de tu servicio de Cloud Run.

Lee registros de manera programática

Si deseas leer los registros de manera programática, puedes usar uno de estos métodos:

Escribe registros de contenedores

Cuando escribes registros desde el servicio, Cloud Logging los selecciona de manera automática, siempre y cuando los registros 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. Las excepciones en estos registros se capturan y se informan en Error Reporting.

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:
// $project = 'The project ID of your 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.
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
# beneath request log in Log Viewer.
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"`

	// Stackdriver Log Viewer 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 Stackdriver.
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 una estructura de Entry, se llama al método String para ordenarla 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 Stackdriver.
	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, debes habilitar el codificador de JSON de Logstash en la configuración logback.xml.

// Build structured log messages as an object.
Object globalLogFields = null;
// Add log correlation to nest all log messages beneath request log in Log Viewer.
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));
}
// Create a structured log entry using key value pairs.
logger.error(
    "This is the default display field.",
    kv("component", "arbitrary-property"),
    kv("severity", "NOTICE"),
    globalLogFields);
<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>

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 de contenedores con un registro de solicitud

En el visor de registros, los registros que se correlacionan por el mismo trace se pueden ver en formato de “superior y 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

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 Google Cloud, como Compute Engine, es posible que hayas usado agentes de registro de Cloud Logging. Cloud Run no usa agentes de registro porque tiene compatibilidad integrada con la recopilación de registros.

Recurso de registro

Si haces clic en una entrada de registro en el visor 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.

Sin embargo, hay algunas etiquetas o etiquetas de recursos que son exclusivas de Cloud Run. A continuación, se enumeran algunas con contenido de muestra:

{
 httpRequest: {…}
 insertId:  "5c82b3d1000ece0000000000"
 labels: {
  instanceId:  "00bf4bf00000fb59c906a00000c9e29c2c4e06dce91500000000056008d2b6460f163c0057b97b2345f2725fb2423ee5f0bafd36df887fdb1122371563cf1ff453717282afe000001"
 }
 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"
}
Campo Valores y notas
instanceId La instancia de contenedor que controló la solicitud.
logName Identifica el registro, por ejemplo, registro de solicitud, error estándar, salida estándar, etc.
configuration_name El recurso de configuración que creó la revisión que entregó la solicitud.
location Identifica la ubicación de GCP del servicio.
project_id El proyecto en el que se implementa el servicio.
revision_name La revisión que entregó la solicitud.
service_name El servicio que entregó la solicitud.
type cloud_run_revision. El tipo de recurso de Cloud Run.