Membuat log dan melihat log di Cloud Run

Halaman ini berisi penjelasan mengenai log yang tersedia saat menggunakan Cloud Run, serta bagaimana cara melihat dan menulis log.

Cloud Run memiliki dua jenis log yang dikirim secara otomatis ke Cloud Logging:

  • Log permintaan (khusus layanan): log permintaan yang dikirim ke layanan Cloud Run. Log ini dibuat secara otomatis.
  • Log container (layanan dan tugas): log yang dikeluarkan dari instance dan biasanya berasal dari kode Anda sendiri. Log ini ditulis ke lokasi yang didukung seperti yang dijelaskan dalam Menulis log container.

Melihat log

Berikut beberapa cara untuk melihat log layanan atau tugas Anda:

Kedua metode konsol tersebut memeriksa log yang sama yang disimpan di Cloud Logging. Namun, Cloud Logging, misalnya seperti Logs Explorer, menyediakan detail yang lebih lengkap dan kemampuan pemfilteran yang lebih baik.

Melihat log di Cloud Run

Kategori log untuk layanan dan tugas dapat dilihat di halaman layanan dan tugas yang sesuai.

Melihat log khusus layanan

Cara melihat log layanan di halaman Cloud Run:

  1. Buka Cloud Run

  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 khusus tugas

Cara melihat log tugas di halaman Cloud Run:

  1. Buka Cloud Run

  2. Klik tab TUGAS.

  3. Temukan dan klik tugas yang ingin Anda lihat pada daftar tugas.

  4. Klik tab LOGS untuk mendapatkan log container untuk semua eksekusi tugas ini. Pemfilteran dapat dilakukan berdasarkan tingkat keparahan log.

  5. Klik eksekusi tugas, lalu klik tab LOGS jika Anda ingin melihat log yang sudah difilter untuk eksekusi tugas tertentu.

Melihat log layanan menggunakan Google Cloud CLI

Untuk layanan Cloud Run di command line, Anda dapat menggunakan Google Cloud CLI untuk melihat log tail atau membaca log yang ada. Secara default, log tersebut diformat dalam format baris tunggal yang dioptimalkan untuk konsol.

Untuk melakukan tail pada log, Anda harus menginstal komponen log-streaming yang ada di Google Cloud CLI. Jika komponen tersebut belum diinstal, Anda akan diminta untuk menginstalnya jika diperlukan.

Melihat log tail di command line

Untuk layanan Cloud Run, Anda dapat melakukan tail pada log secara real-time dari layanan Cloud Run di command-line:

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

Ganti

  • SERVICE dengan nama layanan Cloud Run Anda
  • PROJECT-ID dengan ID project Google Cloud Anda. ID project Anda dapat dilihat dengan menjalankan perintah berikut gcloud config get-value project.

Membaca log di command line

Untuk layanan Cloud Run, Anda dapat membaca log yang ada dengan salah satu dari dua cara berikut:

  • Dalam format yang dioptimalkan untuk konsol:
    gcloud run services logs read SERVICE --limit=10 --project PROJECT-ID
  • Langsung dari Cloud Logging:
    gcloud logging read "resource.type=cloud_run_revision AND resource.labels.service_name=SERVICE" --project PROJECT-ID --limit 10

Ganti

  • SERVICE dengan nama layanan Cloud Run Anda
  • PROJECT-ID dengan ID project Google Cloud Anda. ID project Anda dapat dilihat dengan menjalankan perintah berikut gcloud config get-value project.

Melihat log di Cloud Logging

Cara melihat log Cloud Run Anda di Cloud Logging Logs Explorer:

  1. Buka halaman Logs Explorer di konsol Google Cloud:

    Buka halaman Logs Explorer

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

  3. Dengan menggunakan menu drop-down, pilih resource Revisi Cloud Run untuk layanan, atau Tugas Cloud Run untuk tugas.

Untuk mengetahui informasi selengkapnya, lihat Menggunakan Logs Explorer.

Melihat layanan 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 menulis log dari layanan atau tugas Anda, log tersebut akan diambil secara otomatis oleh Cloud Logging. Hal ini berlaku 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 secara otomatis dikaitkan dengan layanan, revisi, dan lokasi Cloud Run, atau dengan tugas Cloud Run. Pengecualian yang terdapat dalam log ini direkam dan dilaporkan dalam Error Reporting.

Logging terintegrasi menyeimbangkan keandalan dan penggunaan resource, dan akan berfungsi untuk sebagian besar aplikasi. Menulis entri log menggunakan logging terintegrasi tidak akan menggunakan kuota untuk jumlah permintaan entries.write per menit dari Cloud Logging API.

Jika aplikasi Anda memiliki persyaratan untuk volume atau keandalan yang lebih tinggi, sebaiknya gunakan Cloud Logging API secara langsung, baik sebagai library dalam aplikasi Anda atau sebagai penampung sidecar terpisah.

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);

Sesuaikan nama kolom standar untuk mengecualikan konten yang tidak diinginkan dari kategori penyerapan di payload log. Untuk daftar nama kolom dan format data yang diharapkan, lihat Gunakan agen logging.

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

Hubungkan log container Anda dengan log permintaan (khusus layanan)

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 permintaan penggunaan resource log (khusus layanan)

Log permintaan dibuat secara otomatis. Meskipun tidak dapat mengontrol jumlah log permintaan dari Cloud Run 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. Cloud Run tidak menggunakan agen logging karena memiliki dukungan bawaan untuk pengumpulan log.

Nama resource logging

Berikut nama resource logging untuk Cloud Run:

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.

Cloud Run menambahkan metadata tambahan agar Anda dapat mengidentifikasi sumber log. Metadata ini mencakup (label yang Anda tetapkan pada layanan Cloud Run) dan label resource yang khusus untuk Cloud Run.

Kolom entri log untuk layanan

Berikut adalah daftar kolom yang dapat ditemukan dalam entri log untuk layanan Cloud Run:

Kolom Nilai dan catatan
LogEntry.labels.instanceId Instance yang menangani permintaan.
LogEntry.labels.mylabel,
LogEntry.labels.mysecondlabel
Label layanan yang ditetapkan oleh Anda.
LogEntry.logName Identifikasi log yang ada, seperti log permintaan, error standar, output standar, dan lain-lain.
LogEntry.resource.labels.location Identifikasi lokasi layanan Google Cloud.
LogEntry.resource.labels.project_id Project tempat layanan tersebut di-deploy.
LogEntry.resource.labels.revision_name Revisi yang menyajikan permintaan tersebut.
LogEntry.resource.labels.service_name Layanan yang menyajikan permintaan tersebut.
LogEntry.resource.type cloud_run_revision. Jenis resource milik Cloud Run.

Berikut adalah contoh entri log permintaan untuk layanan 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:  "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 entri log untuk tugas

Berikut adalah daftar kolom yang dapat ditemukan dalam entri log untuk tugas Cloud Run:

Kolom Nilai dan catatan
LogEntry.labels.instanceId Instance.
LogEntry.labels.mylabel,

LogEntry.labels.mysecondlabel

Label tugas yang ditetapkan oleh Anda.
LogEntry.logName Identifikasi log yang ada, seperti log permintaan, error standar, output standar, dan lain-lain.
LogEntry.resource.labels.location Identifikasi lokasi layanan Google Cloud.
LogEntry.resource.labels.project_id Project tempat layanan tersebut di-deploy.
LogEntry.resource.labels.job_name Nama tugas.
LogEntry.labels.execution_name Nama eksekusi tugas.
LogEntry.labels.task_index Indeks tugas.
LogEntry.labels.task_attempt Berapa kali tugas ini telah dicoba.
LogEntry.resource.type cloud_run_job. Jenis resource milik Cloud Run.