Build the Phase 8 conformance corpus
The design argues the conformance suite is the specification and should be built before either implementation, since two hand-written implementations of one language diverge unless something shared pins them. This is that suite: 38 cases in /processing, a language-neutral top-level directory for the same reason /proto is one -- the Rust agent and the Go ingest tier both consume the definition and neither owns it. Nothing executes the cases, because neither implementation exists. A stdlib-only validator checks the corpus stays well-formed and runs in CI: known actions, addressable fields, compilable patterns, names matching filenames, and no case depending on record_id, which is withheld so the question of whether an ingest-side rule can see one stays open. The validator was checked against seven deliberately broken cases before being trusted, since "38/38 valid" means nothing from a validator that cannot fail. Writing the cases first has already paid for itself twice. It forced two determinism decisions the prose had left vague, both of which a conformance suite cannot avoid answering. Sampling is counter-based rather than random: random is statistically nicer and impossible to assert on. Windows are measured on record timestamps rather than wall-clock, which makes replay deterministic and, not incidentally, makes backfill behave correctly where a wall-clock window would not. And it made the missing aggregate_count answer concrete. The design does not say what that action emits, or what a query not expecting a synthetic record sees. Rather than invent one by writing cases, the validator rejects any case using it, so the design question has to be answered before the behaviour can be frozen by accident. The corpus includes the acceptance case from real measured data: the two processes that account for roughly 60% of a real workstation's journal volume, and the one kernel message worth keeping. Signed-off-by: John Coffey <[email protected]>
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"name": "actions_apply_in_order",
|
||||
"description": "The second action sees what the first produced: parse then drop one of the parsed fields.",
|
||||
"rules": [
|
||||
{
|
||||
"match": [],
|
||||
"actions": [
|
||||
{
|
||||
"action": "parse_json",
|
||||
"field": "message"
|
||||
},
|
||||
{
|
||||
"action": "drop_fields",
|
||||
"fields": [
|
||||
"attributes.secret"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "{\"keep\":\"k\",\"secret\":\"s\"}",
|
||||
"attributes": {}
|
||||
}
|
||||
],
|
||||
"expect": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "{\"keep\":\"k\",\"secret\":\"s\"}",
|
||||
"attributes": {
|
||||
"keep": "k"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"name": "derive_copies_from_another_field",
|
||||
"description": "derive with from_field copies, leaving the source in place.",
|
||||
"rules": [
|
||||
{
|
||||
"match": [],
|
||||
"actions": [
|
||||
{
|
||||
"action": "derive",
|
||||
"field": "attributes.origin_host",
|
||||
"from_field": "host"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "web-01",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "a",
|
||||
"attributes": {}
|
||||
}
|
||||
],
|
||||
"expect": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "web-01",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "a",
|
||||
"attributes": {
|
||||
"origin_host": "web-01"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"name": "derive_overwrites_an_existing_value",
|
||||
"description": "derive is a set, not an insert-if-absent.",
|
||||
"rules": [
|
||||
{
|
||||
"match": [],
|
||||
"actions": [
|
||||
{
|
||||
"action": "derive",
|
||||
"field": "attributes.env",
|
||||
"value": "dev"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "a",
|
||||
"attributes": {
|
||||
"env": "prod"
|
||||
}
|
||||
}
|
||||
],
|
||||
"expect": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "a",
|
||||
"attributes": {
|
||||
"env": "dev"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"name": "derive_sets_a_literal_value",
|
||||
"description": "derive with value writes a constant.",
|
||||
"rules": [
|
||||
{
|
||||
"match": [],
|
||||
"actions": [
|
||||
{
|
||||
"action": "derive",
|
||||
"field": "attributes.env",
|
||||
"value": "dev"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "a",
|
||||
"attributes": {}
|
||||
}
|
||||
],
|
||||
"expect": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "a",
|
||||
"attributes": {
|
||||
"env": "dev"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"name": "drop_fields_on_absent_attribute_is_not_an_error",
|
||||
"description": "Removing something that is not there succeeds and changes nothing.",
|
||||
"rules": [
|
||||
{
|
||||
"match": [],
|
||||
"actions": [
|
||||
{
|
||||
"action": "drop_fields",
|
||||
"fields": [
|
||||
"attributes.nope"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "a",
|
||||
"attributes": {
|
||||
"keep": "k"
|
||||
}
|
||||
}
|
||||
],
|
||||
"expect": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "a",
|
||||
"attributes": {
|
||||
"keep": "k"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"name": "drop_fields_removes_only_named_attributes",
|
||||
"description": "drop_fields removes the named attributes and leaves the rest alone.",
|
||||
"rules": [
|
||||
{
|
||||
"match": [],
|
||||
"actions": [
|
||||
{
|
||||
"action": "drop_fields",
|
||||
"fields": [
|
||||
"attributes.secret",
|
||||
"attributes.gone"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "a",
|
||||
"attributes": {
|
||||
"secret": "s",
|
||||
"gone": "g",
|
||||
"keep": "k"
|
||||
}
|
||||
}
|
||||
],
|
||||
"expect": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "a",
|
||||
"attributes": {
|
||||
"keep": "k"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"name": "drop_stops_later_actions_in_the_same_rule",
|
||||
"description": "Nothing after a drop runs; the record is gone, so a subsequent derive cannot resurrect it.",
|
||||
"rules": [
|
||||
{
|
||||
"match": [],
|
||||
"actions": [
|
||||
{
|
||||
"action": "drop"
|
||||
},
|
||||
{
|
||||
"action": "derive",
|
||||
"field": "attributes.late",
|
||||
"value": "x"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "a",
|
||||
"attributes": {}
|
||||
}
|
||||
],
|
||||
"expect": []
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
{
|
||||
"name": "drop_stops_later_rules",
|
||||
"description": "A drop in rule 1 means rule 2 never sees the record.",
|
||||
"rules": [
|
||||
{
|
||||
"match": [
|
||||
{
|
||||
"field": "message",
|
||||
"op": "eq",
|
||||
"value": "gone"
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"action": "drop"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"match": [],
|
||||
"actions": [
|
||||
{
|
||||
"action": "derive",
|
||||
"field": "attributes.seen",
|
||||
"value": "yes"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "gone",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 2000000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "stays",
|
||||
"attributes": {}
|
||||
}
|
||||
],
|
||||
"expect": [
|
||||
{
|
||||
"timestamp_unix_nano": 2000000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "stays",
|
||||
"attributes": {
|
||||
"seen": "yes"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
{
|
||||
"name": "empty_rule_set_is_a_pass_through",
|
||||
"description": "No rules means every record is emitted exactly as it arrived. This is the state an agent falls back to when it refuses a rule set.",
|
||||
"rules": [],
|
||||
"inputs": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "a",
|
||||
"attributes": {
|
||||
"k": "v"
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 2000000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "b",
|
||||
"attributes": {}
|
||||
}
|
||||
],
|
||||
"expect": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "a",
|
||||
"attributes": {
|
||||
"k": "v"
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 2000000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "b",
|
||||
"attributes": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"name": "keep_fields_is_an_attribute_allowlist",
|
||||
"description": "keep_fields drops every attribute not named, and never touches top-level fields.",
|
||||
"rules": [
|
||||
{
|
||||
"match": [],
|
||||
"actions": [
|
||||
{
|
||||
"action": "keep_fields",
|
||||
"fields": [
|
||||
"attributes.keep"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h9",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "message survives",
|
||||
"attributes": {
|
||||
"keep": "k",
|
||||
"a": "1",
|
||||
"b": "2"
|
||||
}
|
||||
}
|
||||
],
|
||||
"expect": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h9",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "message survives",
|
||||
"attributes": {
|
||||
"keep": "k"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "mask_leaves_non_matching_records_untouched",
|
||||
"description": "A mask whose pattern does not hit changes nothing at all.",
|
||||
"rules": [
|
||||
{
|
||||
"match": [],
|
||||
"actions": [
|
||||
{
|
||||
"action": "mask",
|
||||
"field": "message",
|
||||
"pattern": "[0-9]{16}",
|
||||
"replacement": "[REDACTED]"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "nothing sensitive here",
|
||||
"attributes": {}
|
||||
}
|
||||
],
|
||||
"expect": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "nothing sensitive here",
|
||||
"attributes": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "mask_replaces_every_occurrence",
|
||||
"description": "mask replaces all matches in the field, not just the first -- redaction that stops at the first hit is a leak.",
|
||||
"rules": [
|
||||
{
|
||||
"match": [],
|
||||
"actions": [
|
||||
{
|
||||
"action": "mask",
|
||||
"field": "message",
|
||||
"pattern": "[0-9]{16}",
|
||||
"replacement": "[REDACTED]"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "card 4111111111111111 and 5500000000000004 seen",
|
||||
"attributes": {}
|
||||
}
|
||||
],
|
||||
"expect": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "card [REDACTED] and [REDACTED] seen",
|
||||
"attributes": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"name": "match_absent_attribute_is_not_empty_string",
|
||||
"description": "A missing attribute must not compare equal to \"\" -- absence and emptiness are different.",
|
||||
"rules": [
|
||||
{
|
||||
"match": [
|
||||
{
|
||||
"field": "attributes.tier",
|
||||
"op": "eq",
|
||||
"value": ""
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"action": "drop"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "missing",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 2000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "empty",
|
||||
"attributes": {
|
||||
"tier": ""
|
||||
}
|
||||
}
|
||||
],
|
||||
"expect": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "missing",
|
||||
"attributes": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
{
|
||||
"name": "match_all_clauses_must_hold",
|
||||
"description": "Multiple clauses are AND, never OR.",
|
||||
"rules": [
|
||||
{
|
||||
"match": [
|
||||
{
|
||||
"field": "host",
|
||||
"op": "eq",
|
||||
"value": "h1"
|
||||
},
|
||||
{
|
||||
"field": "severity",
|
||||
"op": "eq",
|
||||
"value": "SEVERITY_ERROR"
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"action": "drop"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_ERROR",
|
||||
"message": "both",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 2000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "host only",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 3000,
|
||||
"host": "h2",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_ERROR",
|
||||
"message": "sev only",
|
||||
"attributes": {}
|
||||
}
|
||||
],
|
||||
"expect": [
|
||||
{
|
||||
"timestamp_unix_nano": 2000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "host only",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 3000,
|
||||
"host": "h2",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_ERROR",
|
||||
"message": "sev only",
|
||||
"attributes": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
{
|
||||
"name": "match_contains_prefix_suffix",
|
||||
"description": "The three substring operators, each matching exactly one of three records.",
|
||||
"rules": [
|
||||
{
|
||||
"match": [
|
||||
{
|
||||
"field": "message",
|
||||
"op": "prefix",
|
||||
"value": "start"
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"action": "derive",
|
||||
"field": "attributes.hit",
|
||||
"value": "prefix"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"match": [
|
||||
{
|
||||
"field": "message",
|
||||
"op": "suffix",
|
||||
"value": "end"
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"action": "derive",
|
||||
"field": "attributes.hit",
|
||||
"value": "suffix"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"match": [
|
||||
{
|
||||
"field": "message",
|
||||
"op": "contains",
|
||||
"value": "middle"
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"action": "derive",
|
||||
"field": "attributes.hit",
|
||||
"value": "contains"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "start of line",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 2000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "line to end",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 3000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "a middle b",
|
||||
"attributes": {}
|
||||
}
|
||||
],
|
||||
"expect": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "start of line",
|
||||
"attributes": {
|
||||
"hit": "prefix"
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 2000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "line to end",
|
||||
"attributes": {
|
||||
"hit": "suffix"
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 3000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "a middle b",
|
||||
"attributes": {
|
||||
"hit": "contains"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"name": "match_empty_matcher_matches_everything",
|
||||
"description": "An empty match list is 'always', not 'never'.",
|
||||
"rules": [
|
||||
{
|
||||
"match": [],
|
||||
"actions": [
|
||||
{
|
||||
"action": "drop"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "anything",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 2000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "anything else",
|
||||
"attributes": {}
|
||||
}
|
||||
],
|
||||
"expect": []
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"name": "match_eq_is_exact_not_substring",
|
||||
"description": "eq compares the whole value; a superstring does not match.",
|
||||
"rules": [
|
||||
{
|
||||
"match": [
|
||||
{
|
||||
"field": "message",
|
||||
"op": "eq",
|
||||
"value": "noise"
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"action": "drop"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "noise",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 2000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "noise and more",
|
||||
"attributes": {}
|
||||
}
|
||||
],
|
||||
"expect": [
|
||||
{
|
||||
"timestamp_unix_nano": 2000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "noise and more",
|
||||
"attributes": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"name": "match_exists_on_attribute",
|
||||
"description": "exists/not_exists test presence and take no value.",
|
||||
"rules": [
|
||||
{
|
||||
"match": [
|
||||
{
|
||||
"field": "attributes.trace_id",
|
||||
"op": "exists"
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"action": "derive",
|
||||
"field": "attributes.traced",
|
||||
"value": "yes"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "a",
|
||||
"attributes": {
|
||||
"trace_id": "abc"
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 2000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "b",
|
||||
"attributes": {}
|
||||
}
|
||||
],
|
||||
"expect": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "a",
|
||||
"attributes": {
|
||||
"trace_id": "abc",
|
||||
"traced": "yes"
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 2000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "b",
|
||||
"attributes": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"name": "match_ne_matches_when_different",
|
||||
"description": "ne is the complement of eq, including for absent fields.",
|
||||
"rules": [
|
||||
{
|
||||
"match": [
|
||||
{
|
||||
"field": "service",
|
||||
"op": "ne",
|
||||
"value": "keep-me"
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"action": "drop"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "keep-me",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "a",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 2000,
|
||||
"host": "h1",
|
||||
"service": "other",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "b",
|
||||
"attributes": {}
|
||||
}
|
||||
],
|
||||
"expect": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "keep-me",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "a",
|
||||
"attributes": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"name": "match_on_severity_by_enum_name",
|
||||
"description": "severity is matched by its enum name string, not its number.",
|
||||
"rules": [
|
||||
{
|
||||
"match": [
|
||||
{
|
||||
"field": "severity",
|
||||
"op": "eq",
|
||||
"value": "SEVERITY_DEBUG"
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"action": "drop"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_DEBUG",
|
||||
"message": "debug",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 2000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "info",
|
||||
"attributes": {}
|
||||
}
|
||||
],
|
||||
"expect": [
|
||||
{
|
||||
"timestamp_unix_nano": 2000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "info",
|
||||
"attributes": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"name": "match_regex_is_unanchored",
|
||||
"description": "regex matches anywhere in the value unless the pattern anchors itself.",
|
||||
"rules": [
|
||||
{
|
||||
"match": [
|
||||
{
|
||||
"field": "message",
|
||||
"op": "regex",
|
||||
"value": "conn(ect|ected)"
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"action": "drop"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "client connected ok",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 2000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "disconnected",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 3000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "unrelated",
|
||||
"attributes": {}
|
||||
}
|
||||
],
|
||||
"expect": [
|
||||
{
|
||||
"timestamp_unix_nano": 3000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "unrelated",
|
||||
"attributes": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"name": "non_matching_rule_leaves_the_record_untouched",
|
||||
"description": "A rule that does not match is not a rule that empties things.",
|
||||
"rules": [
|
||||
{
|
||||
"match": [
|
||||
{
|
||||
"field": "host",
|
||||
"op": "eq",
|
||||
"value": "other"
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"action": "drop_fields",
|
||||
"fields": [
|
||||
"attributes.keep"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "a",
|
||||
"attributes": {
|
||||
"keep": "k"
|
||||
}
|
||||
}
|
||||
],
|
||||
"expect": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "a",
|
||||
"attributes": {
|
||||
"keep": "k"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"name": "parse_json_lifts_top_level_keys_to_attributes",
|
||||
"description": "parse_json on message adds string attributes and leaves message intact.",
|
||||
"rules": [
|
||||
{
|
||||
"match": [],
|
||||
"actions": [
|
||||
{
|
||||
"action": "parse_json",
|
||||
"field": "message"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "{\"level\":\"warn\",\"code\":\"503\"}",
|
||||
"attributes": {}
|
||||
}
|
||||
],
|
||||
"expect": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "{\"level\":\"warn\",\"code\":\"503\"}",
|
||||
"attributes": {
|
||||
"level": "warn",
|
||||
"code": "503"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "parse_json_on_invalid_json_is_a_no_op",
|
||||
"description": "A record that is not JSON passes through unchanged rather than being dropped or erroring -- same schema-on-read fallback the agent parser already uses.",
|
||||
"rules": [
|
||||
{
|
||||
"match": [],
|
||||
"actions": [
|
||||
{
|
||||
"action": "parse_json",
|
||||
"field": "message"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "this is not json {",
|
||||
"attributes": {}
|
||||
}
|
||||
],
|
||||
"expect": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "this is not json {",
|
||||
"attributes": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"name": "parse_json_prefixes_keys_when_asked",
|
||||
"description": "prefix namespaces the lifted keys so they cannot collide with existing attributes.",
|
||||
"rules": [
|
||||
{
|
||||
"match": [],
|
||||
"actions": [
|
||||
{
|
||||
"action": "parse_json",
|
||||
"field": "message",
|
||||
"prefix": "json."
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "{\"code\":\"503\"}",
|
||||
"attributes": {
|
||||
"code": "keep-me"
|
||||
}
|
||||
}
|
||||
],
|
||||
"expect": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "{\"code\":\"503\"}",
|
||||
"attributes": {
|
||||
"code": "keep-me",
|
||||
"json.code": "503"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"name": "parse_regex_named_captures_become_attributes",
|
||||
"description": "Only named groups are lifted; unnamed groups are ignored.",
|
||||
"rules": [
|
||||
{
|
||||
"match": [],
|
||||
"actions": [
|
||||
{
|
||||
"action": "parse_regex",
|
||||
"field": "message",
|
||||
"pattern": "user=(?P<user>[a-z]+) code=(?P<code>[0-9]+)"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "user=alice code=403 extra",
|
||||
"attributes": {}
|
||||
}
|
||||
],
|
||||
"expect": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "user=alice code=403 extra",
|
||||
"attributes": {
|
||||
"user": "alice",
|
||||
"code": "403"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"name": "parse_regex_that_does_not_match_is_a_no_op",
|
||||
"description": "A non-matching pattern adds nothing and does not drop the record.",
|
||||
"rules": [
|
||||
{
|
||||
"match": [],
|
||||
"actions": [
|
||||
{
|
||||
"action": "parse_regex",
|
||||
"field": "message",
|
||||
"pattern": "user=(?P<user>[a-z]+)"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "no user here",
|
||||
"attributes": {}
|
||||
}
|
||||
],
|
||||
"expect": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "no user here",
|
||||
"attributes": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"name": "rename_from_absent_field_is_a_no_op",
|
||||
"description": "Renaming something absent does not create an empty destination.",
|
||||
"rules": [
|
||||
{
|
||||
"match": [],
|
||||
"actions": [
|
||||
{
|
||||
"action": "rename",
|
||||
"from": "attributes.old",
|
||||
"to": "attributes.new"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "a",
|
||||
"attributes": {
|
||||
"other": "v"
|
||||
}
|
||||
}
|
||||
],
|
||||
"expect": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "a",
|
||||
"attributes": {
|
||||
"other": "v"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"name": "rename_moves_an_attribute",
|
||||
"description": "rename removes the source key and creates the destination.",
|
||||
"rules": [
|
||||
{
|
||||
"match": [],
|
||||
"actions": [
|
||||
{
|
||||
"action": "rename",
|
||||
"from": "attributes.old",
|
||||
"to": "attributes.new"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "a",
|
||||
"attributes": {
|
||||
"old": "v"
|
||||
}
|
||||
}
|
||||
],
|
||||
"expect": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "a",
|
||||
"attributes": {
|
||||
"new": "v"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
{
|
||||
"name": "rules_apply_in_sequence_to_the_same_record",
|
||||
"description": "Every matching rule runs, each seeing the record as the previous rule left it.",
|
||||
"rules": [
|
||||
{
|
||||
"match": [],
|
||||
"actions": [
|
||||
{
|
||||
"action": "derive",
|
||||
"field": "attributes.a",
|
||||
"value": "1"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"match": [
|
||||
{
|
||||
"field": "attributes.a",
|
||||
"op": "eq",
|
||||
"value": "1"
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"action": "derive",
|
||||
"field": "attributes.b",
|
||||
"value": "2"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "x",
|
||||
"attributes": {}
|
||||
}
|
||||
],
|
||||
"expect": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "x",
|
||||
"attributes": {
|
||||
"a": "1",
|
||||
"b": "2"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
{
|
||||
"name": "sample_counts_only_matching_records",
|
||||
"description": "The counter advances on records the rule matched, so an unrelated record between two matches does not consume a slot.",
|
||||
"rules": [
|
||||
{
|
||||
"match": [
|
||||
{
|
||||
"field": "service",
|
||||
"op": "eq",
|
||||
"value": "noisy"
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"action": "sample",
|
||||
"keep_one_in": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000000,
|
||||
"host": "h1",
|
||||
"service": "noisy",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "n1",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 2000000,
|
||||
"host": "h1",
|
||||
"service": "quiet",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "other",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 3000000,
|
||||
"host": "h1",
|
||||
"service": "noisy",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "n2",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 4000000,
|
||||
"host": "h1",
|
||||
"service": "noisy",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "n3",
|
||||
"attributes": {}
|
||||
}
|
||||
],
|
||||
"expect": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000000,
|
||||
"host": "h1",
|
||||
"service": "noisy",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "n1",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 2000000,
|
||||
"host": "h1",
|
||||
"service": "quiet",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "other",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 4000000,
|
||||
"host": "h1",
|
||||
"service": "noisy",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "n3",
|
||||
"attributes": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
{
|
||||
"name": "sample_keeps_the_first_then_every_nth",
|
||||
"description": "sample is counter-based, not random: keep_one_in 3 keeps records 1, 4, 7. Random sampling is untestable; a counter is testable and close enough at volume.",
|
||||
"rules": [
|
||||
{
|
||||
"match": [],
|
||||
"actions": [
|
||||
{
|
||||
"action": "sample",
|
||||
"keep_one_in": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "m1",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 2000000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "m2",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 3000000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "m3",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 4000000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "m4",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 5000000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "m5",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 6000000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "m6",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 7000000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "m7",
|
||||
"attributes": {}
|
||||
}
|
||||
],
|
||||
"expect": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "m1",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 4000000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "m4",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 7000000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "m7",
|
||||
"attributes": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"name": "sample_of_one_keeps_everything",
|
||||
"description": "keep_one_in 1 is a no-op, not an off switch.",
|
||||
"rules": [
|
||||
{
|
||||
"match": [],
|
||||
"actions": [
|
||||
{
|
||||
"action": "sample",
|
||||
"keep_one_in": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "a",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 2000000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "b",
|
||||
"attributes": {}
|
||||
}
|
||||
],
|
||||
"expect": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "a",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 2000000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "b",
|
||||
"attributes": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"name": "suppress_duplicates_collapses_within_the_window",
|
||||
"description": "Identical messages inside the window collapse to the first; the window is measured on record timestamps, not wall-clock, so replay is deterministic and backfill behaves.",
|
||||
"rules": [
|
||||
{
|
||||
"match": [],
|
||||
"actions": [
|
||||
{
|
||||
"action": "suppress_duplicates",
|
||||
"window_ms": 5000
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"timestamp_unix_nano": 0,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "Discord 1.0.155",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 1000000000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "Discord 1.0.155",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 4999000000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "Discord 1.0.155",
|
||||
"attributes": {}
|
||||
}
|
||||
],
|
||||
"expect": [
|
||||
{
|
||||
"timestamp_unix_nano": 0,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "Discord 1.0.155",
|
||||
"attributes": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"name": "suppress_duplicates_emits_again_after_the_window",
|
||||
"description": "A duplicate outside the window is a new first occurrence.",
|
||||
"rules": [
|
||||
{
|
||||
"match": [],
|
||||
"actions": [
|
||||
{
|
||||
"action": "suppress_duplicates",
|
||||
"window_ms": 5000
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"timestamp_unix_nano": 0,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "same",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 5000000000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "same",
|
||||
"attributes": {}
|
||||
}
|
||||
],
|
||||
"expect": [
|
||||
{
|
||||
"timestamp_unix_nano": 0,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "same",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 5000000000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "same",
|
||||
"attributes": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
{
|
||||
"name": "suppress_duplicates_honours_key_fields",
|
||||
"description": "With key_fields, identical messages from different hosts are not duplicates of each other.",
|
||||
"rules": [
|
||||
{
|
||||
"match": [],
|
||||
"actions": [
|
||||
{
|
||||
"action": "suppress_duplicates",
|
||||
"window_ms": 5000,
|
||||
"key_fields": [
|
||||
"host",
|
||||
"message"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"timestamp_unix_nano": 0,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "same",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 1000000,
|
||||
"host": "h2",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "same",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 2000000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "same",
|
||||
"attributes": {}
|
||||
}
|
||||
],
|
||||
"expect": [
|
||||
{
|
||||
"timestamp_unix_nano": 0,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "same",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 1000000,
|
||||
"host": "h2",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "same",
|
||||
"attributes": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
{
|
||||
"name": "suppress_duplicates_keys_on_message_by_default",
|
||||
"description": "Two different messages never suppress each other.",
|
||||
"rules": [
|
||||
{
|
||||
"match": [],
|
||||
"actions": [
|
||||
{
|
||||
"action": "suppress_duplicates",
|
||||
"window_ms": 5000
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"timestamp_unix_nano": 0,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "a",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 1000000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "b",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 2000000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "a",
|
||||
"attributes": {}
|
||||
}
|
||||
],
|
||||
"expect": [
|
||||
{
|
||||
"timestamp_unix_nano": 0,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "a",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 1000000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "b",
|
||||
"attributes": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
{
|
||||
"name": "workstation_noise_reduction",
|
||||
"description": "The v1 acceptance shape, from real measured data: Discord repeating a byte-identical version string and a polling daemon repeating a fixed message, against one kernel message worth keeping. See /docs/phase-8-processing-design.md.",
|
||||
"rules": [
|
||||
{
|
||||
"match": [
|
||||
{
|
||||
"field": "message",
|
||||
"op": "eq",
|
||||
"value": "Discord 1.0.155"
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"action": "drop"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"match": [
|
||||
{
|
||||
"field": "message",
|
||||
"op": "eq",
|
||||
"value": "Checking active tasks"
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"action": "suppress_duplicates",
|
||||
"window_ms": 60000
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"timestamp_unix_nano": 0,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "Discord 1.0.155",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 1000000000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "Checking active tasks",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 2000000000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "Discord 1.0.155",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 3000000000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "Checking active tasks",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 4000000000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_WARN",
|
||||
"message": "[UFW BLOCK] IN=wlan0 SRC=172.16.16.1",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 5000000000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "Discord 1.0.155",
|
||||
"attributes": {}
|
||||
}
|
||||
],
|
||||
"expect": [
|
||||
{
|
||||
"timestamp_unix_nano": 1000000000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_INFO",
|
||||
"message": "Checking active tasks",
|
||||
"attributes": {}
|
||||
},
|
||||
{
|
||||
"timestamp_unix_nano": 4000000000,
|
||||
"host": "h1",
|
||||
"service": "s1",
|
||||
"severity": "SEVERITY_WARN",
|
||||
"message": "[UFW BLOCK] IN=wlan0 SRC=172.16.16.1",
|
||||
"attributes": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user