Monad Data Routing Reference

Data routing enables conditional delivery of records to different outputs based on record content. Every edge in your pipeline is a routing rule.

Core Concept

Routing Conditions Reference
  • Each edge evaluates independently

  • Records can match multiple edges (fan-out)

  • No circular routing (DAG structure)

Edge Structure

Edges connect nodes with optional conditions:

{
  "from": "transform-normalize",
  "to": "output-sentinel-analytics",
  "name": "Critical Events",
  "conditions": {
    "operator": "or",
    "conditions": [
      {"type": "equals", "key": "severity", "value": "critical"},
      {"type": "equals", "key": "severity", "value": "high"}
    ]
  }
}

Logical Operators

Operators combine multiple conditions.

Operator Function Min Conditions

always

Route ALL records (pass-through)

0

never

Block ALL records

0

and

ALL conditions must be true

1+

or

At least ONE condition true

2+

nor

NONE of the conditions true

1+

xor

EXACTLY ONE condition true

2+

Operator Examples

Pass-through (all records):

{
  "operator": "always",
  "conditions": []
}

Multi-criteria AND:

{
  "operator": "and",
  "conditions": [
    {"type": "equals", "key": "source", "value": "ise"},
    {"type": "equals", "key": "result", "value": "fail"}
  ]
}

Multi-criteria OR:

{
  "operator": "or",
  "conditions": [
    {"type": "equals", "key": "severity", "value": "critical"},
    {"type": "equals", "key": "severity", "value": "high"},
    {"type": "contains", "key": "message", "value": "intrusion"}
  ]
}

Exclusion (NOR):

{
  "operator": "nor",
  "conditions": [
    {"type": "equals", "key": "event_type", "value": "heartbeat"},
    {"type": "equals", "key": "event_type", "value": "keepalive"}
  ]
}

Condition Types

Nine condition types for flexible routing.

Field Existence

key_exists - Check if field is present

{"type": "key_exists", "key": "threat_id"}

Value Matching

equals - Exact value match

{"type": "equals", "key": "status", "value": "denied"}

equals_any - Match any value in list

{"type": "equals_any", "key": "severity", "values": ["critical", "high", "medium"]}

String Operations

contains - Substring match

{"type": "contains", "key": "message", "value": "authentication failed"}

starts_with - Prefix match

{"type": "starts_with", "key": "user", "value": "admin_"}

ends_with - Suffix match

{"type": "ends_with", "key": "filename", "value": ".exe"}

matches_regex - Regular expression match

{"type": "matches_regex", "key": "ip", "pattern": "^10\\.50\\.1\\.\\d+$"}

Numeric Comparison

greater_than - Numeric greater than

{"type": "greater_than", "key": "failed_attempts", "value": 5}

less_than - Numeric less than

{"type": "less_than", "key": "response_time_ms", "value": 100}

Sampling

sample - Percentage-based or key-based sampling

{"type": "sample", "percentage": 10}
{"type": "sample", "key": "user_id", "percentage": 5}

Routing Patterns

Pattern 1: Critical vs Bulk Split

Route security events to expensive analytics tier, bulk to cheap storage.

Edge 1: Critical → Sentinel Analytics

{
  "from": "transform",
  "to": "output-sentinel-analytics",
  "name": "Critical Security Events",
  "conditions": {
    "operator": "or",
    "conditions": [
      {"type": "equals", "key": "result", "value": "FAIL"},
      {"type": "equals", "key": "event_type", "value": "intrusion"},
      {"type": "contains", "key": "action", "value": "deny"},
      {"type": "greater_than", "key": "severity_score", "value": 7}
    ]
  }
}

Edge 2: Bulk → Sentinel Basic

{
  "from": "transform",
  "to": "output-sentinel-basic",
  "name": "Bulk Archive",
  "conditions": {
    "operator": "always",
    "conditions": []
  }
}
Both edges evaluate independently. Critical events go to BOTH outputs (analytics for alerting, basic for archive).

Pattern 2: Source-Based Routing

Route different log sources to different processing paths.

{
  "from": "input-syslog",
  "to": "transform-ise",
  "name": "ISE Logs",
  "conditions": {
    "operator": "or",
    "conditions": [
      {"type": "contains", "key": "message", "value": "CISE_"},
      {"type": "equals", "key": "facility", "value": "local6"}
    ]
  }
}

Pattern 3: Noise Exclusion

Use nor to exclude known noise patterns.

{
  "from": "transform",
  "to": "output-sentinel",
  "name": "Exclude Noise",
  "conditions": {
    "operator": "nor",
    "conditions": [
      {"type": "equals", "key": "event_type", "value": "heartbeat"},
      {"type": "equals", "key": "event_type", "value": "accounting_interim"},
      {"type": "contains", "key": "message", "value": "health check"}
    ]
  }
}

Pattern 4: Sampling for High-Volume Sources

Sample 10% of successful authentications, 100% of failures.

Edge 1: All failures

{
  "conditions": {
    "operator": "and",
    "conditions": [
      {"type": "equals", "key": "result", "value": "FAIL"}
    ]
  }
}

Edge 2: Sampled successes

{
  "conditions": {
    "operator": "and",
    "conditions": [
      {"type": "equals", "key": "result", "value": "PASS"},
      {"type": "sample", "percentage": 10}
    ]
  }
}

ISE-Specific Routing Examples

Route by ISE Message Type

ISE Prefix Meaning Route To

CISE_Failed_Attempts

Auth failures

Analytics (critical)

CISE_Passed_Authentications

Auth success

Basic (bulk)

CISE_TACACS_Accounting

Command accounting

Analytics (audit)

CISE_Posture_Assessment

Posture results

Analytics (compliance)

Condition for failures:

{"type": "contains", "key": "message", "value": "CISE_Failed_Attempts"}

Best Practices

  1. Name edges descriptively - Future you will thank past you

  2. Test with sample data - Before enabling production pipelines

  3. Document routing logic - Why this edge exists

  4. Consider fan-out - Records can match multiple edges

  5. Use nor for exclusion - Cleaner than complex and conditions