Event Ruler (disebut Ruler di dokumen lainnya agar singkatnya) adalah pustaka Java yang memungkinkan pencocokan Rules dengan Events . Peristiwa adalah daftar bidang, yang dapat diberikan sebagai pasangan nama/nilai atau sebagai objek JSON. Aturan mengaitkan nama bidang peristiwa dengan daftar nilai yang mungkin. Ada dua alasan untuk menggunakan Penggaris:
Isi:
Cara termudah untuk menjelaskannya adalah dengan memberi contoh.
Peristiwa adalah objek JSON. Berikut ini contohnya:
{
"version" : "0" ,
"id" : "ddddd4-aaaa-7777-4444-345dd43cc333" ,
"detail-type" : "EC2 Instance State-change Notification" ,
"source" : "aws.ec2" ,
"account" : "012345679012" ,
"time" : "2017-10-02T16:24:49Z" ,
"region" : "us-east-1" ,
"resources" : [
"arn:aws:ec2:us-east-1:123456789012:instance/i-000000aaaaaa00000"
] ,
"detail" : {
"c-count" : 5 ,
"d-count" : 3 ,
"x-limit" : 301.8 ,
"source-ip" : "10.0.0.33" ,
"instance-id" : "i-000000aaaaaa00000" ,
"state" : "running"
}
}
Anda juga dapat melihatnya sebagai kumpulan pasangan nama/nilai. Untuk singkatnya, kami hanya menyajikan contohnya saja. Ruler memiliki API untuk menyediakan acara baik dalam bentuk JSON dan sebagai pasangan nama/nilai:
+--------------+------------------------------------------+
| name | value |
|--------------|------------------------------------------|
| source | "aws.ec2" |
| detail-type | "EC2 Instance State-change Notification" |
| detail.state | "running" |
+--------------+------------------------------------------+
Peristiwa dalam bentuk JSON dapat disediakan dalam bentuk String JSON mentah, atau Jackson JsonNode yang diurai.
Aturan di bagian ini semuanya cocok dengan contoh kejadian di atas:
{
"detail-type" : [ "EC2 Instance State-change Notification" ] ,
"resources" : [ "arn:aws:ec2:us-east-1:123456789012:instance/i-000000aaaaaa00000" ] ,
"detail" : {
"state" : [ "initializing" , "running" ]
}
}
Ini akan mencocokkan peristiwa apa pun dengan nilai yang diberikan untuk nilai resource
, detail-type
, dan detail.state
, dengan mengabaikan bidang lain dalam peristiwa tersebut. Ini juga akan cocok jika nilai detail.state
telah "initializing"
.
Nilai dalam aturan selalu diberikan dalam bentuk array, dan cocok jika nilai dalam kejadian adalah salah satu nilai yang disediakan dalam array. Referensi ke resources
menunjukkan bahwa jika nilai dalam peristiwa juga berupa larik, aturan akan cocok jika perpotongan antara larik peristiwa dan larik aturan tidak kosong.
{
"time" : [ { "prefix" : "2017-10-02" } ]
}
Pencocokan awalan hanya berfungsi pada bidang bernilai string.
{
"source" : [ { "prefix" : { "equals-ignore-case" : "EC2" } } ]
}
Pencocokan awalan sama dengan abaikan huruf besar/kecil hanya berfungsi pada bidang bernilai string.
{
"source" : [ { "suffix" : "ec2" } ]
}
Pencocokan sufiks hanya berfungsi pada bidang bernilai string.
{
"source" : [ { "suffix" : { "equals-ignore-case" : "EC2" } } ]
}
Pencocokan sufiks sama dengan abaikan huruf besar/kecil hanya berfungsi pada bidang bernilai string.
{
"source" : [ { "equals-ignore-case" : "EC2" } ]
}
Pencocokan huruf besar-kecil yang sama hanya berfungsi pada bidang bernilai string.
{
"source" : [ { "wildcard" : "Simple*Service" } ]
}
Pencocokan karakter pengganti hanya berfungsi pada bidang bernilai string. Nilai tunggal dapat berisi nol hingga banyak karakter wildcard, namun karakter wildcard berturut-turut tidak diperbolehkan. Untuk mencocokkan karakter asterisk secara spesifik, karakter wildcard dapat di-escape dengan garis miring terbalik. Dua garis miring terbalik yang berurutan (yaitu garis miring terbalik yang diloloskan dengan garis miring terbalik) mewakili karakter garis miring terbalik yang sebenarnya. Garis miring terbalik yang keluar dari karakter apa pun selain tanda bintang atau garis miring terbalik tidak diperbolehkan.
Apa pun kecuali pencocokan akan melakukan sesuai dengan namanya: mencocokkan apa pun kecuali yang ditentukan dalam aturan.
Apa pun-kecuali berfungsi dengan string tunggal dan nilai atau daftar numerik, yang harus berisi seluruh string atau seluruh numerik. Ini juga dapat diterapkan pada awalan, akhiran, atau pencocokan huruf besar-kecil yang sama dengan sebuah string atau daftar string.
Tunggal apa pun kecuali (string, lalu numerik):
{
"detail" : {
"state" : [ { "anything-but" : "initializing" } ]
}
}
{
"detail" : {
"x-limit" : [ { "anything-but" : 123 } ]
}
}
Apa pun kecuali daftar (string):
{
"detail" : {
"state" : [ { "anything-but" : [ "stopped" , "overloaded" ] } ]
}
}
Apa pun kecuali daftar (angka):
{
"detail" : {
"x-limit" : [ { "anything-but" : [ 100 , 200 , 300 ] } ]
}
}
Apa pun kecuali awalan:
{
"detail" : {
"state" : [ { "anything-but" : { "prefix" : "init" } } ]
}
}
Apa pun kecuali daftar awalan (string):
{
"detail" : {
"state" : [ { "anything-but" : { "prefix" : [ "init" , "error" ] } } ]
}
}
Apa pun kecuali akhiran:
{
"detail" : {
"instance-id" : [ { "anything-but" : { "suffix" : "1234" } } ]
}
}
Apa pun kecuali daftar sufiks (string):
{
"detail" : {
"instance-id" : [ { "anything-but" : { "suffix" : [ "1234" , "6789" ] } } ]
}
}
Apa pun-kecuali-abaikan-kasus:
{
"detail" : {
"state" : [ { "anything-but" : { "equals-ignore-case" : "Stopped" } } ]
}
}
Daftar kasus apa pun kecuali abaikan (string):
{
"detail" : {
"state" : [ { "anything-but" : { "equals-ignore-case" : [ "Stopped" , "OverLoaded" ] } } ]
}
}
Apa pun kecuali wildcard:
{
"detail" : {
"state" : [ { "anything-but" : { "wildcard" : "*/bin/*.jar" } } ]
}
}
Apa pun kecuali daftar wildcard (string):
{
"detail" : {
"state" : [ { "anything-but" : { "wildcard" : [ "*/bin/*.jar" , "*/bin/*.class" ] } } ]
}
}
{
"detail" : {
"c-count" : [ { "numeric" : [ ">" , 0 , "<=" , 5 ] } ] ,
"d-count" : [ { "numeric" : [ "<" , 10 ] } ] ,
"x-limit" : [ { "numeric" : [ "=" , 3.018e2 ] } ]
}
}
Di atas, referensi ke c-count
, d-count
, dan x-limit
menggambarkan pencocokan numerik, dan hanya berfungsi dengan nilai berupa angka JSON. Pencocokan numerik mendukung presisi dan jangkauan yang sama dengan primitif double
Java yang mengimplementasikan standar IEEE 754 binary64
.
{
"detail" : {
"source-ip" : [ { "cidr" : "10.0.0.0/24" } ]
}
}
Ini juga berfungsi dengan alamat IPv6.
Pencocokan yang ada berfungsi pada ada atau tidaknya bidang dalam acara JSON.
Aturan di bawah ini akan cocok dengan peristiwa apa pun yang memiliki bidang detail.c-count.
{
"detail" : {
"c-count" : [ { "exists" : true } ]
}
}
Aturan di bawah ini akan cocok dengan peristiwa apa pun yang tidak memiliki kolom detail.c-count.
{
"detail" : {
"c-count" : [ { "exists" : false } ]
}
}
Catatan Kecocokan Exists
hanya berfungsi pada node daun. Ini tidak berfungsi pada node perantara.
Sebagai contoh, contoh di atas untuk exists : false
akan cocok dengan kejadian di bawah ini:
{
"detail-type" : [ "EC2 Instance State-change Notification" ] ,
"resources" : [ "arn:aws:ec2:us-east-1:123456789012:instance/i-000000aaaaaa00000" ] ,
"detail" : {
"state" : [ "initializing" , "running" ]
}
}
tetapi juga akan cocok dengan kejadian di bawah ini karena c-count
bukan simpul daun:
{
"detail-type" : [ "EC2 Instance State-change Notification" ] ,
"resources" : [ "arn:aws:ec2:us-east-1:123456789012:instance/i-000000aaaaaa00000" ] ,
"detail" : {
"state" : [ "initializing" , "running" ]
"c-count" : {
"c1" : 100
}
}
}
{
"time" : [ { "prefix" : "2017-10-02" } ] ,
"detail" : {
"state" : [ { "anything-but" : "initializing" } ] ,
"c-count" : [ { "numeric" : [ ">" , 0 , "<=" , 5 ] } ] ,
"d-count" : [ { "numeric" : [ "<" , 10 ] } ] ,
"x-limit" : [ { "anything-but" : [ 100 , 200 , 300 ] } ] ,
"source-ip" : [ { "cidr" : "10.0.0.0/8" } ]
}
}
Seperti yang ditunjukkan oleh contoh di atas, Ruler menganggap aturan cocok jika semua bidang yang disebutkan dalam aturan cocok, dan menganggap bidang cocok jika salah satu nilai bidang yang diberikan cocok, artinya Ruler telah menerapkan logika "Dan" ke semua bidang secara default tanpa primitif "Dan" diperlukan .
Ada dua cara untuk mencapai efek "Atau":
Primitif "$or" yang memungkinkan pelanggan secara langsung mendeskripsikan hubungan "Atau" antar bidang dalam aturan.
Ruler mengakui hubungan "Atau" hanya jika rule telah memenuhi seluruh kondisi di bawah ini:
/src/main/software/amazon/event/ruler/Constants.java#L38
misalnya, aturan di bawah ini tidak akan diuraikan sebagai " Atau hubungan "karena" numerik "dan" awalan "adalah kata kunci yang dilindungi undang-undang. {
"$or": [ {"numeric" : 123}, {"prefix": "abc"} ]
}
Jika tidak, Ruler hanya memperlakukan "$or" sebagai nama file biasa, sama seperti string lain dalam aturan.
Biasa "Atau":
// Effect of "source" && ("metricName" || "namespace")
{
"source" : [ "aws.cloudwatch" ] ,
"$or" : [
{ "metricName" : [ "CPUUtilization" , "ReadLatency" ] } ,
{ "namespace" : [ "AWS/EC2" , "AWS/ES" ] }
]
}
Paralel "Atau":
// Effect of ("metricName" || "namespace") && ("detail.source" || "detail.detail-type")
{
"$or" : [
{ "metricName" : [ "CPUUtilization" , "ReadLatency" ] } ,
{ "namespace" : [ "AWS/EC2" , "AWS/ES" ] }
] ,
"detail" : {
"$or" : [
{ "source" : [ "aws.cloudwatch" ] } ,
{ "detail-type" : [ "CloudWatch Alarm State Change" ] }
]
}
}
"Atau" memiliki "Dan" di dalamnya
// Effect of ("source" && ("metricName" || ("metricType && "namespace") || "scope"))
{
"source" : [ "aws.cloudwatch" ] ,
"$or" : [
{ "metricName" : [ "CPUUtilization" , "ReadLatency" ] } ,
{
"metricType" : [ "MetricType" ] ,
"namespace" : [ "AWS/EC2" , "AWS/ES" ]
} ,
{ "scope" : [ "Service" ] }
]
}
Bersarang "Atau" dan "Dan"
// Effect of ("source" && ("metricName" || ("metricType && "namespace" && ("metricId" || "spaceId")) || "scope"))
{
"source" : [ "aws.cloudwatch" ] ,
"$or" : [
{ "metricName" : [ "CPUUtilization" , "ReadLatency" ] } ,
{
"metricType" : [ "MetricType" ] ,
"namespace" : [ "AWS/EC2" , "AWS/ES" ] ,
"$or" : [
{ "metricId" : [ 1234 ] } ,
{ "spaceId" : [ 1000 ] }
]
} ,
{ "scope" : [ "Service" ] }
]
}
"$or" mungkin sudah digunakan sebagai kunci normal di beberapa aplikasi (walaupun kemungkinannya jarang). Untuk kasus ini, Ruler mencoba yang terbaik untuk menjaga kompatibilitas ke belakang. Hanya jika 3 kondisi yang disebutkan di atas terpenuhi, perilaku penggaris akan berubah karena aturan tersebut mengasumsikan bahwa aturan Anda benar-benar menginginkan OR dan salah dikonfigurasi hingga saat ini. Misalnya, aturan di bawah ini akan tetap berfungsi sebagai aturan normal dengan memperlakukan "$or" sebagai nama bidang normal dalam aturan dan kejadian:
{
"source" : [ "aws.cloudwatch" ] ,
"$or" : {
"metricType" : [ "MetricType" ] ,
"namespace" : [ "AWS/EC2" , "AWS/ES" ]
}
}
Lihat /src/test/data/normalRulesWithOrWording.json
untuk contoh lebih lanjut bahwa "$or" diurai sebagai nama bidang normal oleh Ruler.
Kata kunci "$or" sebagai primitif hubungan "Atau" tidak boleh dirancang sebagai bidang normal di Peristiwa dan Aturan. Ruler mendukung aturan lama di mana "$or" diurai sebagai nama bidang normal untuk menjaga kompatibilitas ke belakang dan memberikan waktu bagi tim untuk memigrasikan penggunaan "$or" lama mereka dari acara dan aturan mereka sebagai nama file normal. Campuran penggunaan "$or" sebagai "Or" primitif, dan "$or" sebagai nama bidang normal tidak didukung dengan sengaja oleh Ruler untuk menghindari terjadinya ambiguitas yang sangat canggung pada "$or".
Ada dua cara untuk menggunakan Penggaris. Anda dapat mengompilasi beberapa aturan ke dalam "Mesin", lalu menggunakan salah satu metode rulesForEvent()
atau metode rulesForJSONEvent()
untuk memeriksa aturan mana yang cocok dengan Peristiwa apa pun. Perbedaan antara kedua metode ini dibahas di bawah. Diskusi ini akan menggunakan rulesForEvent()
secara umum kecuali jika perbedaannya penting.
Alternatifnya, Anda dapat menggunakan metode boolean statis tunggal untuk menentukan apakah suatu peristiwa cocok dengan aturan tertentu.
Ada satu metode boolean statis Ruler.matchesRule(event, rule)
- kedua argumen disediakan sebagai string JSON.
CATATAN: Ada metode lain yang tidak digunakan lagi yang disebut Ruler.matches(event, rule)
yang tidak boleh digunakan karena hasilnya tidak sesuai dengan rulesForJSONEvent()
dan rulesForEvent()
. Lihat dokumentasi di Ruler.matches(event, rule)
untuk detailnya.
Waktu pencocokan tidak bergantung pada jumlah aturan. Ini adalah pilihan terbaik jika Anda memiliki beberapa kemungkinan aturan yang ingin Anda pilih, dan terutama jika Anda memiliki cara untuk menyimpan Mesin yang dikompilasi.
Waktu pencocokan dipengaruhi oleh tingkat non-determinisme yang disebabkan oleh aturan wildcard dan apa pun kecuali aturan wildcard. Performa menurun karena semakin banyak awalan aturan wildcard yang cocok dengan kejadian terburuk teoretis. Untuk menghindari hal ini, aturan karakter pengganti yang berkaitan dengan bidang peristiwa yang sama harus menghindari awalan umum yang mengarah ke karakter karakter pengganti pertamanya. Jika awalan umum diperlukan, gunakan jumlah minimum karakter wildcard dan batasi urutan karakter berulang yang muncul setelah karakter wildcard. MachineComplexityEvaluator dapat digunakan untuk mengevaluasi mesin dan menentukan tingkat non-determinisme, atau "kompleksitas" (yaitu berapa banyak awalan aturan wildcard yang cocok dengan kejadian terburuk teoretis). Berikut adalah beberapa poin data yang menunjukkan penurunan kinerja secara umum untuk meningkatkan skor kompleksitas.
Penting untuk membatasi kompleksitas mesin untuk melindungi aplikasi Anda. Setidaknya ada dua strategi berbeda untuk membatasi kompleksitas mesin. Mana yang lebih masuk akal mungkin bergantung pada aplikasi Anda.
Strategi #1 lebih ideal karena mengukur kompleksitas sebenarnya dari mesin yang memuat semua aturan. Jika memungkinkan, strategi ini harus digunakan. Kelemahannya adalah, katakanlah Anda memiliki bidang kendali yang memungkinkan pembuatan satu aturan dalam satu waktu, hingga jumlah yang sangat besar. Kemudian untuk setiap operasi bidang kontrol ini, Anda harus memuat semua aturan yang ada untuk melakukan validasi. Ini bisa jadi sangat mahal. Ini juga rentan terhadap kondisi balapan. Strategi #2 adalah kompromi. Ambang batas yang digunakan oleh strategi #2 akan lebih rendah dari strategi #1 karena ini merupakan ambang batas per aturan. Katakanlah Anda ingin kompleksitas mesin, dengan semua aturan ditambahkan, tidak lebih dari 300. Kemudian dengan strategi #2, misalnya, Anda dapat membatasi setiap mesin aturan tunggal hingga kompleksitas 10, dan mengizinkan 30 aturan yang berisi pola wildcard . Dalam kasus terburuk absolut di mana kompleksitas bersifat aditif sempurna (tidak mungkin terjadi), hal ini akan menghasilkan mesin dengan kompleksitas 300. Kelemahannya adalah kecil kemungkinan kompleksitas tersebut akan menjadi aditif sempurna, sehingga jumlah aturan yang berisi wildcard akan bertambah. mungkin akan dibatasi jika tidak perlu.
Untuk strategi #2, bergantung pada bagaimana aturan disimpan, atribut tambahan mungkin perlu ditambahkan ke aturan untuk menunjukkan mana yang nondeterministik (yaitu berisi pola wildcard) untuk membatasi jumlah aturan yang mengandung wildcard.
Berikut ini cuplikan kode yang mengilustrasikan cara membatasi kompleksitas pola tertentu, seperti strategi #2.
public class Validate { private void validate ( String pattern , MachineComplexityEvaluator machineComplexityEvaluator ) { // If we cannot compile, then return exception. List < Map < String , List < Patterns >>> compilationResult = Lists . newArrayList (); try { compilationResult . addAll ( JsonRuleCompiler . compile ( pattern )); } catch ( Exception e ) { InvalidPatternException internalException = EXCEPTION_FACTORY . invalidPatternException ( e . getLocalizedMessage ()); throw ExceptionMapper . mapToModeledException ( internalException ); } // Validate wildcard patterns. Look for wildcard patterns out of all patterns that have been used. Machine machine = new Machine (); int i = 0 ; for ( Map < String , List < Patterns >> rule : compilationResult ) { if ( containsWildcard ( rule )) { // Add rule to machine for complexity evaluation. machine . addPatternRule ( Integer . toString (++ i ), rule ); } } // Machine has all rules containing wildcard match types. See if the complexity is under the limit. int complexity = machine . evaluateComplexity ( machineComplexityEvaluator ); if ( complexity > MAX_MACHINE_COMPLEXITY ) { InvalidPatternException internalException = EXCEPTION_FACTORY . invalidPatternException ( "Rule is too complex" ); throw ExceptionMapper . mapToModeledException ( internalException ); } } private boolean containsWildcard ( Map < String , List < Patterns >> rule ) { for ( List < Patterns > fieldPatterns : rule . values ()) { for ( Patterns fieldPattern : fieldPatterns ) { if ( fieldPattern . type () == WILDCARD || fieldPattern . type () == ANYTHING_BUT_WILDCARD ) { return true ; } } } return false ; } }
Kelas utama tempat Anda akan berinteraksi mengimplementasikan pencocokan aturan berbasis mesin negara. Metode yang menarik adalah:
addRule()
- menambahkan aturan baru ke mesindeleteRule()
- menghapus aturan dari mesinrulesForEvent()
/ rulesForJSONEvent()
- menemukan aturan di mesin yang cocok dengan suatu peristiwa Ada dua varian: Machine
dan GenericMachine
. Mesin hanyalah GenericMachine
. API mengacu pada tipe generik sebagai "nama", yang mencerminkan sejarah: Versi String dibuat pertama kali dan string yang disimpan dan dikembalikan dianggap sebagai nama aturan.
Demi keamanan, tipe yang digunakan untuk "memberi nama" aturan harus tidak dapat diubah. Jika Anda mengubah konten objek saat sedang digunakan sebagai nama aturan, hal ini dapat merusak pengoperasian Ruler.
Konstruktor GenericMachine dan Mesin secara opsional menerima objek GenericMachineConfiguration, yang memperlihatkan opsi konfigurasi berikut.
Default: false Biasanya, Status Nama digunakan kembali untuk rangkaian dan pola kunci tertentu jika rangkaian dan pola kunci ini telah ditambahkan sebelumnya, atau jika pola telah ditambahkan untuk rangkaian kunci tertentu. Oleh karena itu, secara default, penggunaan kembali NameState bersifat oportunistik. Namun dengan menyetel tanda ini ke true, penggunaan kembali NameState akan dipaksakan untuk rangkaian kunci berikutnya. Ini berarti bahwa pola pertama yang ditambahkan untuk rangkaian kunci akan menggunakan kembali NameState jika rangkaian kunci tersebut telah ditambahkan sebelumnya. Artinya setiap rangkaian kunci memiliki satu NameState. Hal ini meningkatkan pemanfaatan memori secara eksponensial dalam beberapa kasus, namun menyebabkan lebih banyak sub-aturan yang disimpan di NameState individual, yang terkadang diulangi oleh Ruler, yang dapat menyebabkan regresi kinerja waktu proses yang sederhana. Setelan bawaannya adalah false untuk kompatibilitas mundur, namun kemungkinan besar, semua aplikasi kecuali aplikasi yang paling sensitif terhadap latensi akan mendapat manfaat jika menyetelnya ke true.
Berikut ini contoh sederhananya. Mempertimbangkan:
machine . addRule ( "0" , "{"key1": ["a", "b", "c"]}" ) ;
Pola "a" menciptakan NameState, dan kemudian, bahkan dengan tambahanNameStateReuse=false, pola kedua ("b") dan pola ketiga ("c") menggunakan kembali NameState yang sama. Namun pertimbangkan hal berikut ini:
machine . addRule ( "0" , "{"key1": ["a"]}" ) ;
machine . addRule ( "1" , "{"key1": ["b"]}" ) ;
machine . addRule ( "2" , "{"key1": ["c"]}" ) ;
Sekarang, dengan tambahanNameStateReuse=false, kita mendapatkan tiga NameStates, karena pola pertama yang ditemukan untuk rangkaian kunci pada setiap penambahan aturan akan membuat NameState baru. Jadi, "a", "b", dan "c" semuanya mendapatkan Status Namanya sendiri. Namun, dengan tambahanNameStateReuse=true, "a" akan membuat NameState baru, lalu "b" dan "c" akan menggunakan kembali NameState yang sama. Hal ini dicapai dengan menyimpan bahwa kita sudah memiliki NameState untuk kunci berikutnya "key1".
Perhatikan bahwa tidak masalah jika setiap addRule menggunakan nama aturan yang berbeda atau nama aturan yang sama.
Semua bentuk metode ini memiliki argumen pertama yang sama, sebuah String yang memberikan nama Aturan dan dikembalikan oleh rulesForEvent()
. Argumen lainnya memberikan pasangan nama/nilai. Mereka dapat disediakan dalam JSON seperti pada contoh di atas (melalui String, Reader, InputStream, atau byte[]
), atau sebagai Map
, dengan kuncinya adalah nama bidang dan nilai adalah daftar kemungkinan kecocokan; menggunakan contoh di atas, akan ada kunci bernama detail.state
yang nilainya berupa daftar yang berisi "initializing"
dan "running"
.
Catatan: Metode ini (dan juga deleteRule()
) disinkronkan, jadi hanya satu thread yang dapat memperbarui mesin kapan saja.
Anda dapat memanggil addRule()
beberapa kali dengan nama yang sama tetapi beberapa pola nama/nilai yang berbeda, sehingga mencapai hubungan "atau"; rulesForEvent()
akan mengembalikan nama tersebut jika salah satu polanya cocok.
Misalnya, Anda memanggil addRule()
dengan nama aturan "R1" dan menambahkan pola berikut:
{
"detail" : {
"c-count" : [ { "numeric" : [ ">" , 0 , "<=" , 5 ] } ]
}
}
Kemudian Anda memanggilnya lagi dengan nama yang sama tetapi polanya berbeda:
{
"detail" : {
"x-limit" : [ { "numeric" : [ "=" , 3.018e2 ] } ]
}
}
Setelah ini, rulesForEvent()
akan mengembalikan "R1" untuk nilai c-count
sebesar 2 atau nilai x-limit
sebesar 301,8.
Ini adalah bayangan cermin dari addRule()
; dalam setiap kasus, argumen pertama adalah nama aturan, yang diberikan sebagai sebuah String. Argumen berikutnya memberikan nama dan nilai, dan dapat diberikan dengan cara yang sama seperti addRule()
.
Catatan: Metode ini (dan juga addRule()
) disinkronkan, jadi hanya satu thread yang dapat memperbarui mesin kapan saja.
Pengoperasian API ini bisa jadi tidak kentara. Mesin mengkompilasi pemetaan pola nama/nilai ke nama Aturan ke dalam finite automaton, namun tidak mengingat pola apa yang dipetakan ke nama Aturan tertentu. Oleh karena itu, tidak ada persyaratan bahwa pola dalam deleteRule()
sama persis dengan pola dalam addRule()
yang bersangkutan. Penggaris akan mencari kecocokan dengan pola nama/nilai dan melihat apakah pola tersebut memberikan kecocokan pada aturan dengan nama yang diberikan, dan jika demikian, hapuslah. Ingatlah bahwa saat melakukan panggilan deleteRule()
yang tidak sama persis dengan panggilan addRule()
yang terkait tidak akan gagal dan tidak akan membuat mesin dalam keadaan tidak konsisten, hal tersebut dapat menyebabkan "sampah" menumpuk di Mesin.
Konsekuensi spesifiknya adalah jika Anda memanggil addRule()
beberapa kali dengan nama yang sama namun polanya berbeda, seperti yang diilustrasikan di atas pada bagian Aturan dan nama aturan , Anda harus memanggil deleteRule()
dengan jumlah yang sama, dengan jumlah yang sama pola terkait, untuk menghapus semua referensi ke nama aturan tersebut dari mesin.
Metode ini mengembalikan List
untuk Mesin (dan List
untuk GenericMachine) yang berisi nama aturan yang cocok dengan kejadian yang disediakan. Peristiwa tersebut dapat diberikan ke salah satu metode sebagai sebuah String
tunggal yang mewakili bentuk JSON-nya.
Acara juga dapat diberikan ke rulesForEvent()
sebagai kumpulan string yang mengganti nama dan nilai bidang, dan harus diurutkan secara leksikal berdasarkan nama bidang. Ini mungkin List
atau String[]
.
Menyediakan acara dalam JSON adalah pendekatan yang direkomendasikan dan memiliki beberapa keuntungan. Pertama-tama, mengisi daftar String atau array dengan jumlah nama/nilai bergantian, dalam urutan yang diurutkan berdasarkan nama, itu rumit, dan Ruler tidak membantu, hanya gagal berfungsi dengan benar jika daftarnya tidak terstruktur dengan benar. Menambah kesulitan, representasi nilai bidang, yang disediakan sebagai string, harus mengikuti aturan sintaksis JSON - lihat di bawah pada pencocokan teks JSON .
Terakhir, versi daftar/array suatu peristiwa membuat Ruler tidak mungkin mengenali struktur array dan menyediakan pencocokan yang konsisten dengan array, yang dijelaskan di bawah dalam dokumen ini. rulesForEvent(String eventJSON)
API tidak digunakan lagi dan digantikan dengan rulesForJSONEvent()
khususnya karena tidak mendukung pencocokan yang konsisten dengan array.
rulesForJSONEvent()
juga memiliki keuntungan karena kode yang mengubah bentuk JSON acara menjadi daftar yang diurutkan telah diprofilkan dan dioptimalkan secara ekstensif.
Performa rulesForEvent()
dan rulesForJSONEvent()
tidak bergantung pada jumlah aturan yang ditambahkan dengan addRule()
. rulesForJSONEvent()
umumnya lebih cepat karena pemrosesan peristiwa yang dioptimalkan. Jika Anda melakukan pemrosesan acara sendiri dan memanggil rulesForEvent()
dengan daftar nama dan nilai yang telah diurutkan sebelumnya, itu masih lebih cepat; namun Anda mungkin tidak dapat melakukan persiapan daftar lapangan secepat yang dilakukan rulesForJSONEvent()
.
Metode ini memperkirakan jumlah objek di dalam mesin. Nilainya hanya bervariasi seiring dengan penambahan atau penghapusan aturan. Hal ini berguna untuk mengidentifikasi mesin besar yang berpotensi memerlukan banyak memori. Karena metode ini bergantung pada jumlah objek internal, jumlah ini dapat berubah ketika internal pustaka penggaris diubah. Metode ini melakukan semua penghitungannya pada waktu proses untuk menghindari penggunaan memori dan memperburuk dampak mesin aturan besar. Perhitungannya sengaja TIDAK aman untuk menghindari pemblokiran evaluasi aturan dan perubahan mesin. Artinya jika proses paralel ditambahkan atau dihapus dari mesin, Anda mungkin mendapatkan hasil yang berbeda dibandingkan saat proses paralel tersebut selesai. Selain itu, saat pustaka melakukan pengoptimalan internal untuk beberapa pola (lihat ShortcutTransition.java
untuk detail selengkapnya), Anda mungkin juga mendapatkan hasil yang berbeda bergantung pada urutan penambahan atau penghapusan aturan.
Jika Anda menganggap peristiwa Anda sebagai pasangan nama/nilai, bukan dokumen bergaya JSON yang disarangkan, kelas Patterns
(dan subkelas Range
) mungkin berguna dalam menyusun aturan. Metode statis berikut berguna.
public static ValuePatterns exactMatch ( final String value );
public static ValuePatterns prefixMatch ( final String prefix );
public static ValuePatterns prefixEqualsIgnoreCaseMatch ( final String prefix );
public static ValuePatterns suffixMatch ( final String suffix );
public static ValuePatterns suffixEqualsIgnoreCaseMatch ( final String suffix );
public static ValuePatterns equalsIgnoreCaseMatch ( final String value );
public static ValuePatterns wildcardMatch ( final String value );
public static AnythingBut anythingButMatch ( final String anythingBut );
public static AnythingBut anythingButMatch ( final Set < String > anythingButs );
public static AnythingBut anythingButMatch ( final double anythingBut );
public static AnythingBut anythingButNumberMatch ( final Set < Double > anythingButs );
public static AnythingButValuesSet anythingButPrefix ( final String prefix );
public static AnythingButValuesSet anythingButPrefix ( final Set < String > anythingButs );
public static AnythingButValuesSet anythingButSuffix ( final String suffix );
public static AnythingButValuesSet anythingButSuffix ( final Set < String > anythingButs );
public static AnythingButValuesSet anythingButIgnoreCaseMatch ( final String anythingBut );
public static AnythingButValuesSet anythingButIgnoreCaseMatch ( final Set < String > anythingButs );
public static AnythingButValuesSet anythingButWildcard ( final String value );
public static AnythingButValuesSet anythingButWildcard ( final Set < String > anythingButs );
public static ValuePatterns numericEquals ( final double val );
public static Range lessThan ( final double val );
public static Range lessThanOrEqualTo ( final double val );
public static Range greaterThan ( final double val );
public static Range greaterThanOrEqualTo ( final double val );
public static Range between ( final double bottom , final boolean openBottom , final double top , final boolean openTop );
Setelah Anda membuat pencocokan Patterns
yang sesuai dengan metode ini, Anda dapat menggunakan metode berikut untuk menambah atau menghapus dari mesin Anda:
public void addPatternRule ( final String name , final Map < String , List < Patterns >> namevals );
public void deletePatternRule ( final String name , final Map < String , List < Patterns >> namevals );
CATATAN: Peringatan yang tercantum dalam deleteRule()
juga berlaku untuk deletePatternRule()
.
Nilai bidang dalam aturan harus disediakan dalam representasi JSON-nya. Artinya, nilai string harus diapit oleh "tanda kutip". Nilai yang tidak diberi tanda kutip diperbolehkan, seperti angka ( -3.0e5
) dan literal khusus JSON tertentu ( true
, false
, dan null
).
Ini dapat diabaikan sepenuhnya jika aturan diberikan ke addRule()
() dalam bentuk JSON, atau jika Anda bekerja dengan Pola dan bukan string literal. Namun jika Anda memberikan aturan sebagai pasangan nama/nilai, dan Anda ingin menentukan bahwa bidang "xyz" cocok dengan string "true", itu harus dinyatakan sebagai "xyz", ""true""
. Di sisi lain, "xyz", "true"
hanya akan cocok dengan literal JSON true
.
Ruler mendukung pencocokan aturan untuk peristiwa yang berisi larik, namun hanya jika peristiwa tersebut disediakan dalam bentuk JSON - jika berupa daftar bidang yang telah diurutkan sebelumnya, struktur larik dalam peristiwa tersebut akan hilang. Perilakunya juga bergantung pada apakah Anda menggunakan rulesForEvent()
atau rulesForJSONEvent
.
Perhatikan Peristiwa berikut ini.
{
"employees" : [
{ "firstName" : "John" , "lastName" : "Doe" } ,
{ "firstName" : "Anna" , "lastName" : "Smith" } ,
{ "firstName" : "Peter" , "lastName" : "Jones" }
]
}
Maka aturan ini akan cocok:
{ "employees" : { "firstName" : [ "Anna" ] } }
Artinya, struktur array "dihancurkan" dari pola aturan, dan setiap objek yang ada di dalamnya diperlakukan seolah-olah mereka adalah nilai dari bidang induk. Ini juga berfungsi untuk array multi-level:
{
"employees" : [
[
{ "firstName" : "John" , "lastName" : "Doe" } ,
{ "firstName" : "Anna" , "lastName" : "Smith" }
] ,
[
{ "firstName" : "Peter" , "lastName" : "Jones" }
]
]
}
Di Ruler versi sebelumnya, satu-satunya metode pencocokan berbasis Mesin adalah rulesForEvent()
yang sayangnya juga akan cocok dengan aturan berikut:
{ "employees" : { "firstName" : [ "Anna" ] , "lastName" : [ "Jones" ] } }
Sebagai perbaikan, Ruler memperkenalkan rulesForJSONEvent()
yang, seperti namanya, hanya cocok dengan peristiwa yang disediakan dalam bentuk JSON. rulesForJsonEvent()
tidak akan cocok dengan aturan "Anna"/"Jones" di atas.
Secara formal: rulesForJSONEvent()
akan menolak untuk mengenali kecocokan apa pun di mana dua bidang berada dalam objek JSON yang berada dalam elemen berbeda dari larik yang sama. Dalam praktiknya, ini berarti bahwa hal ini sesuai dengan apa yang Anda harapkan.
Ada kelas pendukung com.amazon.fsm.ruler.RuleCompiler
. Ini berisi metode bernama check()
yang menerima definisi aturan JSON dan mengembalikan nilai String yang, jika nol, berarti aturan tersebut valid secara sintaksis. Jika nilai yang dikembalikan bukan Null, maka berisi pesan kesalahan yang dapat dibaca manusia yang menjelaskan masalahnya.
Untuk kenyamanan, ini juga berisi metode bernama compile()
yang berfungsi seperti check()
tetapi memberi sinyal kesalahan dengan melemparkan IOException dan, jika berhasil, mengembalikan Map
dalam bentuk addRule()
Mesin addRule()
metode yang diharapkan. Karena kelas Mesin menggunakan ini secara internal, metode ini mungkin menghemat waktu.
Saat Ruler mengkompilasi kunci, ia menggunakan titik ( .
) sebagai karakter gabungan. Artinya, ia akan mengkompilasi dua aturan berikut ke representasi internal yang sama
## has no dots in keys
{ "detail" : { "state" : { "status" : [ "running" ] } } }
## has dots in keys
{ "detail" : { "state.status" : [ "running" ] } }
Ini juga berarti bahwa peraturan ini akan cocok dengan dua kejadian berikut :
## has no dots in keys
{ "detail" : { "state" : { "status" : "running" } } }
## has dots in keys
{ "detail" : { "state.status" : "running" } }
Perilaku ini mungkin berubah di versi mendatang (untuk menghindari kebingungan) dan tidak boleh diandalkan.
Kami mengukur kinerja Ruler dengan mengkompilasi beberapa aturan ke dalam Mesin dan mencocokkan peristiwa yang disediakan sebagai string JSON.
Tolok ukur yang memproses 213.068 peristiwa JSON dengan ukuran rata-rata sekitar 900 byte terhadap 5 masing-masing pencocokan tepat, pencocokan awalan, pencocokan akhiran, pencocokan huruf sama dengan abaikan, pencocokan wildcard, pencocokan numerik, dan apa pun kecuali pencocokan mengatur dan menghitung kecocokan, menghasilkan yang berikut di MacBook 2019:
Peristiwa diproses dengan kecepatan lebih dari 220K/detik kecuali untuk:
Berikut ini beberapa saran mengenai aturan pemrosesan dan peristiwa:
Dari pertimbangan performa, Ruler sensitif terhadap item di bawah ini, jadi, saat Anda mendesain skema peristiwa dan aturan, berikut beberapa sarannya:
Lihat KONTRIBUSI untuk informasi lebih lanjut.
Proyek ini dilisensikan di bawah Lisensi Apache-2.0. Lihat LISENSI untuk informasi lebih lanjut.