← Semua pembelajaran / AWS untuk AI Engineer
Fase 7 · Observability, Biaya & Evaluasi

CloudWatch Logs Insights

Logs Insights memberi bahasa kueri untuk log CloudWatch. Digabung dengan log terstruktur, ia mengubah investigasi dari menit jadi detik.

Intisari

  • Kueri disusun dari perintah yang dirangkai dengan |: fields, filter, stats, sort, limit.
  • Log berformat JSON di-parse otomatis — field-nya langsung bisa dikueri.
  • Ini alasan konkret memakai log terstruktur, bukan print().
  • Bisa mengueri banyak log group sekaligus — berguna untuk menelusuri satu permintaan lintas Lambda.
  • Ditagih berdasarkan jumlah data yang dipindai; persempit rentang waktu sebelum menjalankan.

Log terstruktur dulu

import json
import logging

log = logging.getLogger()
log.setLevel("INFO")


def catat(peristiwa: str, **field):
    log.info(json.dumps({"peristiwa": peristiwa, **field}, ensure_ascii=False))


catat("bedrock_selesai",
      request_id=context.aws_request_id,
      model=MODEL_ID,
      token_masuk=resp["usage"]["inputTokens"],
      token_keluar=resp["usage"]["outputTokens"],
      latensi_ms=resp["metrics"]["latencyMs"],
      potongan=len(potongan),
      guardrail=diblokir)

Inilah imbalan konkret dari log terstruktur. Baris log berbentuk JSON di-parse otomatis, sehingga token_keluar langsung jadi field yang bisa difilter dan diagregasi. Log berupa kalimat bebas seperti print(f"selesai, {n} token") tidak bisa dikueri tanpa regex yang rapuh.

Kueri yang langsung terpakai

-- Biaya token per model, satu jam terakhir
fields @timestamp, model, token_masuk, token_keluar
| filter peristiwa = "bedrock_selesai"
| stats sum(token_masuk) as masuk,
        sum(token_keluar) as keluar,
        count(*) as permintaan
  by model
-- Permintaan paling lambat
fields @timestamp, request_id, latensi_ms, token_keluar
| filter peristiwa = "bedrock_selesai"
| sort latensi_ms desc
| limit 20
-- Persentil latensi per 5 menit
filter peristiwa = "bedrock_selesai"
| stats pct(latensi_ms, 50) as p50,
        pct(latensi_ms, 99) as p99
  by bin(5m)
-- Menelusuri satu permintaan lintas seluruh komponen
fields @timestamp, @log, @message
| filter request_id = "abc-123-def"
| sort @timestamp asc

Perintah yang perlu dihafal

PerintahGunanya
fieldsMemilih dan menghitung field
filterMenyaring baris
stats … by …Agregasi: sum, avg, count, pct
bin(5m)Mengelompokkan per rentang waktu
parseMengambil bagian dari teks yang tidak terstruktur
sort, limitMengurutkan dan memotong
@logLog group asal — penting saat mengueri banyak group

Biaya

Logs Insights ditagih berdasarkan jumlah data yang dipindai. Kueri tanpa filter atas rentang tujuh hari bisa mahal. Tiga kebiasaan yang menekan biayanya:

Dari kueri jadi metrik

Kalau sebuah kueri kamu jalankan berulang-ulang, ubah jadi metric filter. Ia mengubah pola di log jadi metrik CloudWatch yang bisa dipasangi alarm — sehingga kamu berhenti memeriksa manual.

log_group.add_metric_filter(
    "GuardrailIntervensi",
    filter_pattern=logs.FilterPattern.string_value("$.guardrail", "=", "true"),
    metric_namespace="AsistenHR",
    metric_name="GuardrailIntervensi",
)

Latihan: ubah seluruh print() di aplikasimu jadi log JSON terstruktur, lalu tulis tiga kueri: biaya token per model, p99 latensi per 5 menit, dan jumlah intervensi guardrail per jam. Simpan ketiganya, dan ubah yang ketiga jadi metric filter beserta alarmnya.

Rangkuman ini sengaja dipangkas ke bagian yang dipakai di roadmap. Buka sumber aslinya saat kamu butuh detail lengkap atau referensi parameter.