Membuat kueri multi-tahap

Didukung di:

Dokumen ini menjelaskan cara kueri multi-tahap di YARA-L memungkinkan Anda memasukkan output satu tahap kueri langsung ke input tahap berikutnya. Proses ini memberi Anda kontrol yang lebih besar atas transformasi data daripada satu kueri monolitik.

Mengintegrasikan kueri multi-tahap dengan fitur yang ada

Kueri multi-tahap berfungsi bersama dengan fitur yang ada berikut di Google Security Operations:

  • Aturan deteksi gabungan: Kueri multi-tahap melengkapi aturan deteksi gabungan dengan menjembatani kesenjangan antara deteksi otomatis dan investigasi aktif. Meskipun aturan komposit unggul dalam mengidentifikasi korelasi multi-peristiwa yang kompleks selama periode waktu yang diperpanjang, kueri multi-tahap memungkinkan analis melakukan pivot dari deteksi tersebut ke penelusuran iteratif real-time untuk langsung memvalidasi dan menentukan cakupan ancaman yang sedang terjadi.

  • Rentang waktu dan aturan multi-peristiwa: Anda dapat menggunakan kueri multi-tahap untuk mendeteksi anomali dengan membandingkan jangka waktu yang berbeda dalam data Anda. Misalnya, Anda dapat menggunakan kueri awal untuk membuat dasar pengukuran selama jangka waktu yang lebih lama, lalu menggunakan kueri berikutnya untuk mengevaluasi aktivitas terbaru terhadap dasar pengukuran tersebut. Anda juga dapat menggunakan aturan multi-peristiwa untuk membuat jenis perbandingan yang serupa.

Kueri multi-tahap di YARA-L didukung di Dasbor dan Penelusuran.

Gabungan membantu mengorelasikan data dari berbagai sumber untuk memberikan lebih banyak konteks bagi penyelidikan. Dengan menautkan peristiwa, entity, dan data lain yang terkait, Anda dapat menyelidiki skenario serangan yang kompleks. Untuk mengetahui informasi selengkapnya, lihat Menggunakan gabungan dalam Penelusuran.

Pertimbangan utama

Saat Anda mengonfigurasi kueri multi-tahap, perhatikan hal berikut:

  • Tahap batas: Kueri multi-tahap harus berisi antara satu dan empat tahap bernama, selain tahap root.
  • Sintaksis urutan: Selalu tentukan sintaksis tahap bernama sebelum menentukan sintaksis tahap root.

Sebaiknya tinjau masalah umum dan solusi yang direkomendasikan berikut saat Anda menerapkan kueri multi-tahap:

  • Semua kueri multi-tahap berperilaku seperti kueri Penelusuran statistik (outputnya terdiri dari statistik gabungan, bukan peristiwa yang tidak digabungkan atau baris tabel data).

  • Performa gabungan dengan UDM dan peristiwa entitas di satu sisi dapat mengalami performa rendah karena ukuran set data tersebut. Sebaiknya filter peristiwa UDM dan entitas di sisi gabungan sebanyak mungkin (misalnya, filter pada jenis peristiwa).

Untuk panduan umum tentang praktik yang direkomendasikan, lihat Praktik terbaik YARA-L 2.0 dan untuk informasi khusus untuk gabungan, lihat Praktik terbaik.

Terminologi utama

Dalam konteks penggabungan, tahap berwindow mengacu pada tahap dengan bagian match yang berisi window. Sebaliknya, tahap tabel tidak menghasilkan jendela.

Membuat kueri YARA-L multi-tahap

Untuk membuat kueri YARA-L multi-tahap, selesaikan langkah-langkah berikut.

Struktur dan sintaksis tahap

Buka Investigasi > Penelusuran. Ikuti struktur ini saat Anda menentukan tahap kueri:

Sintaksis: Gunakan sintaksis berikut untuk memberi nama setiap tahap dan memisahkannya dari tahap lainnya:

stage <stage name> { }

  • Kurung: Tempatkan semua sintaksis tahap di dalam kurung kurawal {}.

  • Urutan: Tentukan sintaksis untuk semua tahap bernama sebelum menentukan tahap root.

  • Mereferensikan: Setiap tahap dapat mereferensikan tahap yang ditentukan sebelumnya dalam kueri.

  • Tahap root: Kueri harus memiliki tahap root, yang diproses setelah semua tahap bernama.

Contoh tahap berikut, daily_stats, mengumpulkan statistik jaringan harian:

stage daily_stats {
  metadata.event_type = "NETWORK_CONNECTION"
  $source = principal.hostname
  $target = target.ip
  $source != ""
  $target != ""
  match:
    $source, $target by day
  outcome:
    $exchanged_bytes = sum(network.sent_bytes + network.received_bytes)
}

Output tahap akses

Output tahap bernama dapat diakses oleh tahap berikutnya menggunakan kolom tahap. Kolom tahap sesuai dengan variabel match dan outcome tahap dan dapat digunakan dengan cara yang sama seperti kolom Model Data Terpadu (UDM).

Gunakan sintaksis berikut untuk mengakses kolom tahap:

$<stage name>.<variable name>

Opsional: Stempel waktu jendela akses

Jika tahap bernama menggunakan jendela lompatan, geser, atau jatuh, akses awal jendela dan akhir jendela untuk setiap baris output menggunakan kolom khusus ini:

  • $<stage name>.window_start

  • $<stage name>.window_end

window_start dan window_end adalah kolom bilangan bulat yang dinyatakan dalam detik sejak epoch Unix. Ukuran jendela pada tahap yang berbeda dapat bervariasi.

Contoh kueri multi-tahap

Contoh dalam bagian ini membantu mengilustrasikan cara membuat kueri YARA-L multi-tahap yang lengkap.

Contoh: Menelusuri koneksi jaringan yang sangat aktif (jam)

Contoh YARA-L multi-tahap ini mengidentifikasi pasangan alamat IP dengan aktivitas jaringan yang lebih tinggi dari biasanya, menargetkan pasangan yang mempertahankan aktivitas tinggi selama lebih dari tiga jam. Kueri ini mencakup dua komponen yang diperlukan: tahap bernama, hourly_stats, dan tahap root.

Tahap hourly_stats menelusuri pasangan principal.ip dan target.ip dengan tingkat aktivitas jaringan yang tinggi.

Tahap ini menampilkan satu nilai per jam untuk kolom berikut:

  • Statistik untuk IP sumber (string): $hourly_stats.src_ip

  • Statistik untuk IP tujuan (string): $hourly_stats.dst_ip

  • Statistik untuk jumlah peristiwa (bilangan bulat): $hourly_stats.count

  • Simpangan baku byte yang diterima (float): $hourly_stats.std_recd_bytes

  • Byte yang diterima rata-rata (float): $hourly_stats.avg_recd_bytes

  • Waktu mulai bucket jam dalam detik dari epoch Unix (bilangan bulat): $hourly_stats.window_start

  • Waktu berakhir bucket jam dalam detik dari epoch Unix (bilangan bulat): $hourly_stats.window_end

Tahap root memproses output tahap hourly_stats. Fitur ini menghitung statistik untuk pasangan principal.ip dan target.ip dengan aktivitas yang melebihi nilai minimum yang ditentukan oleh $hourly_stats. Kemudian, filter pasangan dengan aktivitas tinggi lebih dari tiga jam.


stage hourly_stats {
  metadata.event_type = "NETWORK_CONNECTION"
  $src_ip = principal.ip
  $dst_ip = target.ip
  $src_ip != ""
  $dst_ip != ""

  match:
    $src_ip, $dst_ip by hour

  outcome:
    $count = count(metadata.id)
    $avg_recd_bytes = avg(network.received_bytes)
    $std_recd_bytes = stddev(network.received_bytes)

  condition:
    $avg_recd_bytes > 100 and $std_recd_bytes > 50
}

$src_ip = $hourly_stats.src_ip
$dst_ip = $hourly_stats.dst_ip
$time_bucket_count = strings.concat(timestamp.get_timestamp($hourly_stats.window_start), "|", $hourly_stats.count)

match:
 $src_ip, $dst_ip

outcome:
 $list = array_distinct($time_bucket_count)
 $count = count_distinct($hourly_stats.window_start)

condition:
 $count > 3

Jika Anda mengubah kondisi kecocokan di tahap root sebagai berikut, Anda dapat memperkenalkan agregasi berjendela menurut hari untuk kueri multi-tahap.

match:
 $src_ip, $dst_ip by day

Contoh: Menelusuri koneksi jaringan yang sangat aktif (menggunakan skor Z)

Kueri multi-tahap ini membandingkan aktivitas jaringan rata-rata harian dengan aktivitas hari ini menggunakan perhitungan skor Z (mengukur jumlah standar deviasi dari rata-rata). Kueri ini secara efektif menelusuri aktivitas jaringan yang sangat tinggi antara aset internal dan sistem eksternal.

Prasyarat: Jangka waktu kueri harus lebih besar dari atau sama dengan 2 hari dan mencakup hari ini agar skor Z yang dihitung efektif.

Kueri multi-tahap ini mencakup tahap daily_stats dan tahap root, yang bekerja sama untuk menghitung skor Z untuk aktivitas jaringan:

  • Tahap daily_stats melakukan agregasi harian awal. Fungsi ini menghitung total byte yang dipertukarkan setiap hari untuk setiap pasangan IP (source dan target) dan menampilkan kolom tahap berikut (sesuai dengan kolom dalam baris output):

    • $daily_stats.source: tunggal, string
    • $daily_stats.target: tunggal, string
    • $daily_stats.exchanged_bytes: tunggal, bilangan bulat
    • $daily_stats.window_start: tunggal, bilangan bulat
    • $daily_stats.window_end: tunggal, bilangan bulat
  • Tahap root menggabungkan output tahap daily_stats untuk setiap pasangan IP. Metrik ini menghitung rata-rata dan standar deviasi byte harian yang dipertukarkan di seluruh rentang penelusuran, beserta byte yang dipertukarkan hari ini. Fungsi ini menggunakan tiga nilai yang dihitung tersebut untuk menentukan skor Z.

  • Output mencantumkan skor Z untuk semua pasangan IP hari ini, yang diurutkan dalam urutan menurun.

// Calculate the total bytes exchanged per day by source and target

stage daily_stats {
  metadata.event_type = "NETWORK_CONNECTION"
  $source = principal.hostname
  $target = target.ip
  $source != ""
  $target != ""

  match:
    $source, $target by day

  outcome:
    $exchanged_bytes = sum(network.sent_bytes + network.received_bytes)
}

// Calculate the average per day over the time window and compare with the bytes exchanged today

$source = $daily_stats.source
$target = $daily_stats.target
$date = timestamp.get_date($daily_stats.window_start)

match:
  $source, $target

outcome:
  $today_bytes = sum(if($date = timestamp.get_date(timestamp.current_seconds()), cast.as_int($daily_stats.exchanged_bytes), 0))
  $average_bytes = window.avg($daily_stats.exchanged_bytes)
  $stddev_bytes = window.stddev($daily_stats.exchanged_bytes)
  $zscore = ($today_bytes - $average_bytes) / $stddev_bytes

order:
  $zscore desc

Mengekspor variabel yang tidak diagregasi dari tahap

Dalam kueri multi-tahap yang umum, data sering kali diteruskan antar-tahap melalui proses agregasi, yang dapat "meringkas" beberapa peristiwa menjadi satu ringkasan. Namun, ada skenario saat Anda perlu mempertahankan detail spesifik setiap peristiwa—seperti ID proses unik atau command line tertentu—tanpa kehilangan perincian tersebut. Untuk mendukung hal ini, Anda dapat mengekspor variabel secara langsung tanpa fungsi pengelompokan.

Tahapan bernama dapat menyertakan bagian outcome yang tidak diagregasi. Artinya, variabel yang ditentukan dalam bagian outcome tersebut dikeluarkan langsung dari tahap, sehingga tahap berikutnya dapat mengaksesnya sebagai kolom tahap tanpa memerlukan penggabungan yang dikelompokkan.

Detail ini bermanfaat karena melakukan hal berikut:

  • Mempertahankan keakuratan data: Anda dapat meneruskan atribut persis suatu peristiwa (misalnya, jalur file tertentu) ke tahap berikutnya tanpa harus menggunakan agregasi "placeholder" buatan seperti max() atau array_distinct().
  • Mengurangi kompleksitas kueri: Solusi ini menyederhanakan logika YARA-L Anda dengan menghilangkan kebutuhan akan bagian match atau pernyataan pengelompokan hanya untuk mentransfer nilai dari Tahap 1 ke Tahap 2.
  • Mengoptimalkan performa: Dengan melewati mesin agregasi, sistem dapat melakukan streaming data antar-tahap secara lebih efisien, sehingga menghasilkan waktu eksekusi yang lebih cepat untuk penelusuran yang kompleks dan bervolume tinggi.

Contoh: Mengekspor variabel yang tidak diagregasi

Contoh ini menunjukkan cara mengekspor variabel yang tidak diagregasi. Perhatikan logika berikut:

  • Tahap top_5_bytes_sent menelusuri lima peristiwa dengan aktivitas jaringan tertinggi.

  • Tahap top_5_bytes_sent menghasilkan kolom tahap berikut yang sesuai dengan kolom dalam baris output:

    • $top_5_bytes_sent.bytes_sent: tunggal, bilangan bulat
    • $top_5_bytes_sent.timestamp_seconds: tunggal, bilangan bulat
  • Tahap root menghitung stempel waktu terbaru dan paling awal untuk lima peristiwa dengan aktivitas jaringan tertinggi.

stage top_5_bytes_sent {
  metadata.event_type = "NETWORK_CONNECTION"
  network.sent_bytes > 0

  outcome:
    $bytes_sent = network.sent_bytes
    $timestamp_seconds = metadata.event_timestamp.seconds

  order:
    $bytes_sent desc

  limit:
    5
}

outcome:
  $latest_timestamp = timestamp.get_timestamp(max($top_5_bytes_sent.timestamp_seconds))
  $earliest_timestamp = timestamp.get_timestamp(min($top_5_bytes_sent.timestamp_seconds))

Menerapkan windowing dalam kueri multi-tahap

Dalam deteksi multi-tahap, penentuan periode memungkinkan Anda menentukan batas waktu tertentu untuk korelasi peristiwa dalam suatu tahap. Dengan mempartisi data ke dalam bucket temporal diskrit, seperti jendela geser 5 menit atau jendela bergulir 1 jam, Anda dapat mengidentifikasi pola seperti serangan brute force atau perilaku beacon yang hanya terlihat saat dianalisis sebagai urutan yang terikat waktu.

Kueri multi-tahap mendukung semua jenis windowing (hop, sliding, dan tumbling) dalam tahap bernama. Hal ini membantu Anda meneruskan data yang dikontekstualisasikan waktu antar-tahap, seperti menggunakan Tahap 1 untuk mengidentifikasi periode peristiwa frekuensi tinggi dan Tahap 2 untuk mengorelasikan periode tertentu tersebut dengan tindakan administratif berikutnya.

Jika tahap bernama menyertakan periode, awal periode dan akhir periode untuk setiap baris output dapat diakses menggunakan kolom khusus berikut:

  • $stage_window_start: Stempel waktu Unix yang menandai awal periode.
  • $stage_window_end: Stempel waktu Unix yang menandai akhir periode.

Untuk mengetahui detail selengkapnya tentang penentuan jendela, lihat Logika penentuan jendela YARA-L 2.0.

Kasus penggunaan umum

  • Deteksi berurutan: Meneruskan jangka waktu tertentu lonjakan yang terdeteksi dalam login yang gagal ke tahap kedua yang mencari login yang berhasil segera setelahnya.
  • Analisis durasi: Menghitung "waktu hingga penyusupan" dengan membandingkan $stage_window_start tahap eksploitasi awal dengan stempel waktu peristiwa pada tahap selanjutnya.
  • Penentuan dasar historis: Menggunakan periode untuk membandingkan jumlah peristiwa saat ini dengan variabel output periode sebelumnya.

Contoh: Jendela lompatan

Contoh berikut mengilustrasikan cara menggunakan jendela lompatan dalam kueri multi-tahap:

  • Tahap hourly_stats menelusuri pasangan IP yang memiliki aktivitas jaringan tinggi dalam jam yang sama.

  • hourly_stats menampilkan kolom tahap berikut yang sesuai dengan kolom dalam baris output:

    • $hourly_stats.src_ip: tunggal, string
    • $hourly_stats.dst_ip: tunggal, string
    • $hourly_stats.count: tunggal, bilangan bulat
    • $hourly_stats.std_recd_bytes: tunggal, float
    • $hourly_stats.avg_recd_bytes: tunggal, float
    • $hourly_stats.window_start: tunggal, bilangan bulat
    • $hourly_stats.window_end: tunggal, bilangan bulat
  • Tahap root memfilter pasangan IP dengan aktivitas tinggi lebih dari 3 jam. Jam dapat tumpang-tindih karena penggunaan periode hopping di tahap hourly_stats.

stage hourly_stats {
  metadata.event_type = "NETWORK_CONNECTION"
  $src_ip = principal.ip
  $dst_ip = target.ip
  $src_ip != ""
  $dst_ip != ""

  match:
    $src_ip, $dst_ip over 1h

  outcome:
    $count = count(metadata.id)
    $avg_recd_bytes = avg(network.received_bytes)
    $std_recd_bytes = stddev(network.received_bytes)

  condition:
    $avg_recd_bytes > 100 and $std_recd_bytes > 50
}

$src_ip = $hourly_stats.src_ip
$dst_ip = $hourly_stats.dst_ip
$time_bucket_count = strings.concat(timestamp.get_timestamp($hourly_stats.window_start), "|", $hourly_stats.count)

match:
 $src_ip, $dst_ip

outcome:
 $list = array_distinct($time_bucket_count)
 $count = count_distinct($hourly_stats.window_start)

condition:
 $count > 3

Inner join dalam kueri multi-tahap

Inner join memungkinkan Anda mengorelasikan data di berbagai tahap atau jenis sumber, yang menciptakan alur kerja analitis yang kompleks, seperti membandingkan peristiwa real-time dengan dasar statistik yang telah dihitung sebelumnya. Dengan menggabungkan tahap, Anda dapat memperkaya telemetri mentah dengan data stateful (seperti median atau tabel penelusuran) untuk mengidentifikasi anomali atau ancaman multi-vektor yang tidak akan terdeteksi oleh filter peristiwa satu tahap.

Inner join didukung dalam dan di antara tahap kueri multi-tahap. Fungsi inner join mendukung jenis berikut:

  • UDM dan UDM: Menghubungkan dua set peristiwa keamanan yang berbeda (misalnya, mencocokkan peristiwa login dengan akses file berikutnya).
  • UDM dan ECG: Menggabungkan data peristiwa dengan informasi Entity Context Graph untuk pengayaan identitas atau aset.
  • UDM dan tabel data: Menggabungkan acara live dengan daftar referensi statis atau yang diupload (misalnya, daftar aset bernilai tinggi atau rentang IP khusus departemen).

Contoh berikut menunjukkan cara mengonfigurasi gabungan yang tidak cocok (gabungan yang dilakukan di bagian outcome atau events, bukan bagian match) antara peristiwa UDM dan tahap tabel kalkulasi. Pola ini memungkinkan Anda melakukan deteksi anomali statistik, seperti yang ditunjukkan dalam perhitungan Mean Absolute Deviation (MAD) berikut:

  • Tahap median: Menghitung median byte yang dikirim untuk setiap pasangan IP target dan host sumber.
    • $median.host: tunggal, string
    • $median.target: tunggal, string
    • $median.median: tunggal, float
  • Tahap absolute_deviations: Menggabungkan setiap peristiwa UDM dengan baris yang sesuai dari tahap median. Dengan demikian, Anda dapat menghitung penyimpangan absolut byte yang dikirim untuk setiap peristiwa individual relatif terhadap grup pembandingnya.
    • $absolute_deviations.host: tunggal, string
    • $absolute_deviations.target: tunggal, string
    • $absolute_deviations.absolute_deviation: tunggal, float
  • Tahap root: Menghitung rata-rata penyimpangan absolut tersebut di semua peristiwa UDM untuk menetapkan nilai minimum anomali.

Contoh: Mengonfigurasi gabungan yang tidak cocok

stage median {
  metadata.event_type = "NETWORK_CONNECTION"
  $host = principal.hostname
  $target = target.ip

  match:
    $host, $target

  outcome:
    $median = window.median(network.sent_bytes, true)
}

stage absolute_deviations {
  metadata.event_type = "NETWORK_CONNECTION"
  $join_host = principal.hostname
  $join_host = $median.host
  $join_target = target.ip[0]
  $join_target = $median.target

  outcome:
    $host = $join_host
    $target = $join_target
    $absolute_deviation = math.abs(network.sent_bytes - $median.median)
}

$host = $absolute_deviations.host
$target = $absolute_deviations.target

match:
  $host, $target

outcome:
  $mean_absolute_deviation = avg($absolute_deviations.absolute_deviation)

Contoh: Penggabungan yang tidak cocok antara tahap berwindow dan tahap tabel

Contoh berikut mengilustrasikan cara mengonfigurasi gabungan yang tidak cocok antara tahap berwindow dan tahap tabel dalam kueri multi-tahap.

  • Tahap hourly_stats menghitung total byte yang dikirim untuk setiap pasangan host sumber dan target serta bucket jam.
  • Tahap hourly_stats menghasilkan kolom tahap berikut yang sesuai dengan kolom dalam baris output:
    • $hourly_stats.source_host: tunggal, string
    • $hourly_stats.dst_host: tunggal, string
    • $hourly_stats.total_bytes_sent: tunggal, float
    • $hourly_stats.window_start: tunggal, bilangan bulat
    • $hourly_stats.window_end: tunggal, bilangan bulat
  • Tahap agg_stats menghitung rata-rata dan standar deviasi byte per jam untuk setiap pasangan host sumber dan target.
  • agg_stats menampilkan kolom tahap berikut yang sesuai dengan kolom dalam baris output:

    • $agg_stats.source_host: tunggal, string
    • $agg_stats.dst_host: tunggal, string
    • $agg_stats.avg_bytes_sent: tunggal, float
    • $agg_stats.stddev_bytes_sent: tunggal, float
  • Tahap root menggabungkan setiap baris dari hourly_stats dengan baris dari agg_stats untuk pasangan host sumber dan target yang sama. Untuk setiap pasangan host sumber dan target, skor z dihitung menggunakan total byte yang dikirim untuk bucket pasangan host tersebut dan statistik gabungan.

stage hourly_stats {
 $source_host = principal.hostname
 $dst_host = target.hostname
 principal.hostname != ""
 target.hostname != ""
 match:
   $source_host, $dst_host by hour
 outcome:
   $total_bytes_sent = sum(network.sent_bytes)
}

stage agg_stats {
  $source_host = $hourly_stats.source_host
  $dst_host = $hourly_stats.dst_host
  match:
    $source_host, $dst_host
  outcome:
   $avg_bytes_sent = avg($hourly_stats.total_bytes_sent)
   $stddev_bytes_sent = stddev($hourly_stats.total_bytes_sent)
}

$source_host = $agg_stats.source_host
$source_host = $hourly_stats.source_host

$dst_host = $agg_stats.dst_host
$dst_host = $hourly_stats.dst_host

outcome:
  $hour_bucket = timestamp.get_timestamp($hourly_stats.window_start)
  $z_score = ($hourly_stats.total_bytes_sent - $agg_stats.avg_bytes_sent)/$agg_stats.stddev_bytes_sent

Cross join dalam kueri multi-tahap

Saat menggunakan Penelusuran atau Dasbor Google SecOps, gabungan silang dalam kueri multi-tahap memungkinkan Anda membandingkan data peristiwa UDM individual dengan statistik gabungan yang dihitung dalam tahap YARA-L lainnya.

Di YARA-L, kata kunci cross join berfungsi dengan tahap yang hanya menampilkan satu baris.

Jika cross join digunakan antara tahap dengan batas 1 dan set data lain (misalnya, peristiwa UDM), output satu baris dari tahap tersebut akan ditambahkan ke setiap baris set data lainnya. Hal ini memperkaya data peristiwa dengan statistik keseluruhan.

Contoh: Menemukan aktivitas login yang tidak biasa

Contoh berikut mengidentifikasi pengguna yang login lebih sering dari biasanya. Metrik ini dihitung dengan membandingkan jumlah login setiap pengguna (menggunakan tahap user_login_counts) dengan jumlah login rata-rata di semua pengguna (menggunakan tahap total_users). Pengguna yang login dalam jumlah yang tidak biasa dapat diurutkan di hasil penelusuran.

Kemudian, Anda menggunakan kata kunci cross join untuk menautkan hasil dari tahap total_users ke hasil dari tahap user_login_counts.

stage user_login_counts {
    $user = principal.user.userid
    metadata.event_type = "USER_LOGIN"
    security_result.action = "ALLOW"

    match:
        $user

    outcome:
        $login_count = count(metadata.id)
}

stage total_users {
    outcome:
        $count = count($user_login_counts.user)
    limit:
        1
}

cross join $total_users, $user_login_counts

$login_count = $user_login_counts.login_count
$user = $user_login_counts.user
$tot_users = $total_users.count

// all users who logged in the same number of times are grouped together.
match:
    $login_count
outcome:
    $num_users = count($user)
    $frequency_percent = (count($user) / max($tot_users) ) * 100

Batasan

Kueri multi-tahap memiliki batasan fungsional dan struktural berikut:

Persyaratan struktural

Anda harus mengikuti persyaratan struktural berikut saat membuat kueri:

  • Tahap root: Hanya satu tahap root yang diizinkan per kueri.
  • Tahapan bernama: Maksimum empat tahapan bernama yang didukung.
  • Referensi tahap: Tahap hanya dapat mereferensikan tahap yang ditentukan secara logis sebelumnya dalam kueri yang sama.
  • Cross join: Cross join hanya dapat mereferensikan tahap yang menampilkan satu baris. Anda harus menyertakan batas (1) di tahap yang dirujuk untuk memenuhi persyaratan ini. Hal ini bermanfaat karena memungkinkan Anda menambahkan satu statistik global (seperti maksimum atau rata-rata) ke setiap baris peristiwa individual untuk perbandingan.
  • Gabungan: Maksimum empat gabungan non-tabel data diizinkan di semua tahap.
  • Persyaratan hasil: Setiap tahap bernama (kecuali tahap root) harus menyertakan bagian match atau bagian outcome outcome yang tidak memerlukan agregasi.

Batasan jendela dan kompatibilitas

Batasan berikut berlaku untuk cara Anda menggunakan jendela dan tempat Anda menjalankan kueri:

  • Dukungan fitur: Kueri multi-tahap berfungsi di Penelusuran dan Dasbor, tetapi fitur ini tidak didukung di Aturan.
  • Jenis jendela: Hindari menggabungkan berbagai jenis jendela dalam satu kueri.
  • Dependensi jendela: Tahap yang menggunakan hop atau jendela geser tidak dapat bergantung pada tahap lain yang juga menggunakan hop atau jendela geser.
  • Ukuran jendela yang berjatuhan: Meskipun ukuran jendela yang berjatuhan di berbagai tahap dapat bervariasi, perbedaan ukuran harus kurang dari 720x.

Contoh: Perbedaan agregasi tahap (tidak valid)

Konfigurasi berikut tidak valid karena satu bulan berisi 44.640 menit (44.640 / 1 > 720):

Tahap: monthly_stats { ... match: by month }

Root: match: by minute

Contoh: Perbedaan agregasi tahap (valid)

Untuk memperbaikinya, pastikan rasio antar-tahapan lebih kecil. Misalnya, menggabungkan data per jam ke dalam laporan harian:

Tahap: daily_stats { ... match: by day }

Root: match: by hour

Karena 24 (jam dalam sehari) kurang dari 720, sistem dapat memetakan data tahap ke tahap root secara efisien.

Batasan tahap dan kueri

Setiap tahap dalam kueri multi-tahap memiliki batasan tertentu. Sebagian besar batasan yang berlaku untuk kueri satu tahap juga berlaku untuk setiap tahap:

  • Persyaratan output: Setiap tahap harus menghasilkan setidaknya satu variabel kecocokan atau hasil (kolom tahap).
  • Rentang waktu kueri:

    • Kueri standar: Maksimum 30 hari.
    • Kueri multi-tahap dengan gabungan yang tidak cocok: Maksimum dibatasi hingga 14 hari.
  • Batas ukuran jendela: Ukuran jendela maksimum (hop, geser, atau tumbling) bergantung pada apakah kueri Anda menyertakan gabungan:

    • Dengan gabungan: Ukuran periode maksimum untuk semua jenis (hop, geser, atau tumbling) adalah 2 hari. Untuk mengetahui detailnya, lihat batasan gabungan penelusuran.

    • Tanpa gabungan (satu acara):

    • Hop dan sliding window: Maksimum adalah 2 hari.

    • Periode bergulir: Maksimum meningkat menjadi 30 hari.

  • Variabel hasil maksimum:

    • 20 secara default
    • 50 untuk pelanggan yang memilih untuk menggunakan batas yang lebih besar
    • Batasan array: Maksimum 10.000 elemen diizinkan dalam variabel hasil bernilai array.
  • Batasan peristiwa per kueri:

    • Maksimum dua peristiwa UDM
    • Maksimum satu peristiwa EKG
    • Maksimum dua tabel data

Batas layanan dan performa

Kueri multi-tahap tunduk pada batasan yang sama seperti kueri statistik:

  • Kueri statistik: 120 QPH (API dan UI).
  • Penayangan penelusuran: 100 penayangan per menit.
  • Dukungan API: Sistem SecOps Google dan EventService.UDMSearch API mendukung gabungan multi-tahap, tetapi SearchService.UDMSearch API tidak mendukungnya. Sistem ini juga memungkinkan Anda menjalankan kueri multi-tahap tanpa gabungan.

Batasan acara dan global

Anda harus tetap berada dalam batas peristiwa dan seluruh platform berikut:

Acara maksimum

Kueri multi-tahap membatasi secara ketat jumlah peristiwa yang dapat diproses secara bersamaan:

  • Peristiwa UDM: Maksimum 2 peristiwa UDM diizinkan.
  • Peristiwa Entity Context Graph (ECG): Maksimum satu peristiwa ECG diizinkan.

Batasan kueri global

Batasan di seluruh platform ini mengontrol seberapa jauh rentang waktu ke belakang dan seberapa banyak data yang ditampilkan oleh kueri multi-tahap:

  • Rentang waktu kueri: Rentang waktu maksimum untuk kueri standar adalah 30 hari.
  • Total kumpulan hasil: Ukuran total kumpulan hasil maksimum adalah 10.000 hasil.

Perlu bantuan lain? Dapatkan jawaban dari anggota Komunitas dan profesional Google SecOps.