Membuat log dan melihat log di layanan Knative

Halaman ini menjelaskan log yang tersedia saat menggunakan penayangan Knative, serta cara melihat dan menulis log.

Penayangan Knative memiliki dua jenis log:

  • Log permintaan: log permintaan yang dikirim ke layanan penayangan Knative. Log ini dibuat secara otomatis.
  • Log container: log yang dikeluarkan dari instance container, biasanya dari kode Anda sendiri, yang ditulis ke lokasi yang didukung seperti yang dijelaskan dalam Menulis log container.

Mengaktifkan log

Untuk Google Cloud, log akan otomatis dikirim ke Cloud Logging. Untuk Google Distributed Cloud, Anda harus mengaktifkan log terlebih dahulu.

Melihat log

Anda dapat melihat log untuk layanan Anda dengan beberapa cara:

  • Menggunakan halaman penayangan Knative di konsol Google Cloud
  • Gunakan Logs Explorer Cloud Logging di Konsol Google Cloud.

Kedua metode tampilan ini memeriksa log yang sama yang disimpan di Cloud Logging, tetapi Cloud Logging Logs Explorer memberikan detail yang lebih lengkap dan kemampuan pemfilteran yang lebih baik.

Melihat log di inferensi Knative

Untuk melihat log di halaman penayangan Knative:

  1. Buka Inferensi Knative

  2. Klik layanan yang diinginkan pada daftar yang ditampilkan.

  3. Klik tab LOGS untuk mendapatkan log permintaan dan log container untuk semua revisi layanan ini. Pemfilteran dapat dilakukan berdasarkan tingkat keparahan log.

Melihat log di Cloud Logging

Untuk melihat log penayangan Knative Anda di Cloud Logging Logs Explorer:

  1. Buka halaman Logs Explorer di konsol Google Cloud.

  2. Pilih project Google Cloud yang ada di bagian atas halaman atau buat project baru.

  3. Menggunakan menu drop-down, pilih resource: Container Kubernetes.

Untuk mengetahui informasi selengkapnya, lihat Menggunakan Logs Explorer.

Melihat log di Cloud Code

Untuk melihat log Anda di Cloud Code, baca panduan untuk IntelliJ dan Visual Studio Code.

Membaca log secara terprogram

Jika ingin membaca log secara terprogram, Anda dapat menggunakan salah satu metode berikut:

Menulis log container

Saat Anda menulis log dari layanan, log tersebut akan diambil secara otomatis oleh Cloud Logging selama log tersebut ditulis ke salah satu lokasi berikut:

Sebagian besar developer diharapkan untuk menggunakan output standar dan error standar saat menulis log.

Log container yang ditulis ke lokasi yang didukung ini akan otomatis dikaitkan dengan layanan, revisi, dan lokasi penayangan Knative.

Menggunakan teks sederhana vs JSON terstruktur dalam log

Saat menulis log, Anda dapat mengirim string teks sederhana atau mengirim satu baris JSON yang di-serialisasi. Teks ini juga disebut data "terstruktur". Teks string ini diambil dan diurai oleh Cloud Logging dan ditempatkan ke jsonPayload. Sebaliknya, pesan teks sederhana ditempatkan di textPayload.

Menulis log terstruktur

Cuplikan berikut menunjukkan bagaimana cara menulis entri log yang terstruktur. Cuplikan ini juga menunjukkan bagaimana cara menghubungkan pesan log dengan log permintaan yang sesuai.

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

Struktur untuk setiap entri log disediakan oleh jenis 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)
}

Saat suatu struct Entri dicatat, metode String akan digunakan untuk mengarahkannya ke format JSON yang diperkirakan oleh 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

Aktifkan logging JSON dengan Logback dan SLF4J dengan mengaktifkan Logstash JSON Encoder dalam konfigurasi logback.xml Anda.

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

Kolom JSON khusus dalam pesan

Apabila Anda menyediakan log yang terstruktur sebagai kamus JSON, beberapa kolom khusus akan dihapus dari jsonPayload dan ditulis ke kolom yang sesuai dalam LogEntry yang dibuat. Hal ini sebagaimana dijelaskan dalam dokumentasi untuk kolom khusus.

Misalnya, jika JSON Anda menyertakan properti severity, maka JSON tersebut akan dihapus dari jsonPayload dan muncul sebagai entri log milik severity. Properti message digunakan sebagai teks tampilan utama entri log jika ada. Untuk mengetahui informasi lebih lanjut tentang properti khusus, baca bagian Resource Logging di bawah ini.

Menghubungkan log penampung dengan log permintaan

Di Logs Explorer, log yang dikorelasikan dengan trace yang sama dapat dilihat dalam format "parent-child": jika Anda mengklik ikon segitiga di sebelah kiri entri log permintaan, maka log container yang berkaitan dengan permintaan tersebut akan muncul secara bertingkat.

Log container tidak secara otomatis berkorelasi dengan log permintaan, kecuali jika Anda menggunakan library klien Cloud Logging. Untuk menghubungkan log container dengan log permintaan tanpa menggunakan library klien, Anda dapat menggunakan baris log JSON terstruktur yang berisi kolom logging.googleapis.com/trace dengan ID trace yang diekstrak dari header X-Cloud-Trace-Context, seperti yang ditunjukkan pada contoh di atas untuk logging terstruktur.

Mengontrol penggunaan resource log permintaan

Log permintaan dibuat secara otomatis. Meskipun tidak dapat mengontrol jumlah log permintaan dari penayangan Knative secara langsung, Anda dapat memanfaatkan fitur pengecualian log dari Cloud Logging.

Catatan tentang agen logging

Anda mungkin telah menggunakan agen Cloud Logging dengan produk Google Cloud tertentu seperti Compute Engine. Penyertaan Knative tidak menggunakan agen logging karena memiliki dukungan bawaan untuk pengumpulan log.

Resource logging

Mengklik entri log di Logs Explorer akan membuka entri log berformat JSON sehingga Anda dapat melihat perincian detail yang diinginkan.

Semua kolom dalam entri log, seperti stempel waktu, tingkat keparahan, dan httpRequest merupakan hal standar dan dijelaskan dalam dokumentasi untuk suatu entri log.

Namun, ada beberapa label atau label resource yang khusus untuk penayangan Knative. Hal ini tercantum di sini dengan contoh konten:

{
 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"
}
Kolom Nilai dan catatan
instanceId Instance penampung yang menangani permintaan.
logName Identifikasi log yang ada, seperti log permintaan, error standar, output standar, dan lain-lain.
configuration_name Resource Konfigurasi yang membuat revisi yang menayangkan permintaan.
location Mengidentifikasi lokasi GCP layanan.
project_id Project tempat layanan tersebut di-deploy.
revision_name Revisi yang menyajikan permintaan tersebut.
service_name Layanan yang menyajikan permintaan tersebut.
type cloud_run_revision. Jenis resource penayangan Knative.