Registrar y ver registros en el servicio de Knative

En esta página se describen los registros disponibles al usar Knative Serving y cómo verlos y escribirlos.

Knative Serving tiene dos tipos de registros:

  • Registros de solicitudes: registros de solicitudes enviadas a los servicios de Knative Serving. Estos registros se crean automáticamente.
  • Registros de contenedores: registros emitidos desde las instancias de contenedor, normalmente desde tu propio código, escritos en ubicaciones admitidas, tal como se describe en Escribir registros de contenedores.

Habilitar registros

Los registros de Google Cloud se envían automáticamente a Cloud Logging. En Google Distributed Cloud, primero debes habilitar los registros.

Ver registros

Puedes ver los registros de tu servicio de dos formas:

  • Usar la página de servicio de Knative en la Google Cloud consola
  • Usa el Explorador de registros de Cloud Logging en la Google Cloud consola.

Ambos métodos examinan los mismos registros almacenados en Cloud Logging, pero el Explorador de registros de Cloud Logging proporciona más detalles y más funciones de filtrado.

Ver registros en el servicio de Knative

Para ver los registros en la página de servicio de Knative, sigue estos pasos:

  1. Ir a Knative serving

  2. En la lista que aparece, haz clic en el servicio que quieras.

  3. Haz clic en la pestaña REGISTROS para obtener los registros de solicitudes y de contenedores de todas las revisiones de este servicio. Puedes filtrar por nivel de gravedad del registro.

Ver registros en Cloud Logging

Para ver los registros de Knative Serving en el explorador de registros de Cloud Logging, sigue estos pasos:

  1. Ve a la página Explorador de registros de la consola deGoogle Cloud .

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

  3. En los menús desplegables, selecciona el recurso Contenedor de Kubernetes.

Para obtener más información, consulta el artículo sobre cómo usar el Explorador de registros.

Ver registros en Cloud Code

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

Leer registros mediante programación

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

Escribir registros de contenedores

Cuando escribas registros desde tu servicio, Cloud Logging los recogerá automáticamente siempre que se escriban en cualquiera de estas ubicaciones:

La mayoría de los desarrolladores deben escribir registros mediante la salida estándar y el error estándar.

Los registros de contenedores escritos en estas ubicaciones admitidas se asocian automáticamente al servicio, la revisión y la ubicación de Knative Serving.

Usar texto simple o JSON estructurado en los registros

Cuando escribes registros, puedes enviar una cadena de texto simple o una sola línea de JSON serializado, también llamada datos "estructurados". Cloud Logging la recoge y la analiza, y la coloca en jsonPayload. En cambio, el mensaje de texto simple se coloca en textPayload.

Escribir registros estructurados

El siguiente fragmento muestra cómo escribir entradas de registro estructuradas. También se muestra cómo correlacionar los mensajes de registro con el registro de solicitudes 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

La estructura de cada entrada de registro se proporciona mediante un tipo Entry:


// 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 una estructura Entry, se llama al método String para serializarla en 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, habilita Logstash JSON Encoder en tu configuración de 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.
// 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);
<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 mensajes

Cuando proporcionas un registro estructurado como un diccionario JSON, se eliminan algunos campos especiales del jsonPayload y se escriben en el campo correspondiente del LogEntry generado, tal como se describe en la documentación de los campos especiales.

Por ejemplo, si tu JSON incluye una propiedad severity, se elimina del jsonPayload y aparece en su lugar como severity de la entrada de registro. La propiedad message se usa como texto principal de la entrada de registro, si está presente. Para obtener más información sobre las propiedades especiales, consulta la sección Recurso de registro de abajo.

Correlacionar los registros de tu contenedor con un registro de solicitudes

En el Explorador de registros, los registros correlacionados por el mismo trace se pueden ver en formato "principal-secundario": cuando haces clic en el icono de triángulo situado a la izquierda de la entrada del registro de solicitudes, los registros del contenedor relacionados con esa solicitud se muestran anidados en el registro de solicitudes.

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

Controlar el uso de recursos de los registros de solicitudes

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

Nota sobre los agentes de registro

Si has usado Cloud Logging con determinados Google Cloud productos, como Compute Engine, es posible que hayas usado agentes de registro de Cloud Logging. Knative Serving no usa agentes de registro porque tiene asistencia integrada para la recopilación de registros.

Recurso de registro

Al hacer clic en una entrada de registro en el Explorador de registros, se abre una entrada de registro con formato JSON para que puedas desglosar la información que quieras.

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

Sin embargo, hay algunas etiquetas o etiquetas de recursos que son especiales para Knative Serving. A continuación, se muestran algunos ejemplos de contenido:

{
 httpRequest: {}
 insertId:  "5c82b3d1000ece0000000000"
 labels: {
  instanceId:  "00bf4bf00000fb59c906a00000c9e29c2c4e06dce91500000000056008d2b6460f163c0057b97b2345f2725fb2423ee5f0bafd36df887fdb1122371563cf1ff453717282afe000001"
 }
 logName:  "projects/my-project/logs/kubernetes-engine/enterprise/knative-serving/.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 ha gestionado la solicitud.
logName Identifica el registro (por ejemplo, registro de solicitudes, error estándar, salida estándar, etc.).
configuration_name El recurso Configuration que ha creado la revisión que ha servido la solicitud.
location Identifica la ubicación de GCP del servicio.
project_id El proyecto en el que se ha implementado el servicio.
revision_name La revisión que ha servido la solicitud.
service_name El servicio que ha atendido la solicitud.
type cloud_run_revision. El tipo de recurso de servicio de Knative.