https://github.com/SchwarzIT/hypermatch
hypermatch is a high-performance ⚡ Go library designed for rapid matching of a large number of rules to events. It processes thousands of events per second 🚀 against extensive rule sets in-memory with minimal latency ⏱️.
https://github.com/SchwarzIT/hypermatch
event-driven events go golang json matching matching-engine performance rule-engine
Last synced: 5 months ago
JSON representation
hypermatch is a high-performance ⚡ Go library designed for rapid matching of a large number of rules to events. It processes thousands of events per second 🚀 against extensive rule sets in-memory with minimal latency ⏱️.
- Host: GitHub
- URL: https://github.com/SchwarzIT/hypermatch
- Owner: SchwarzIT
- License: apache-2.0
- Created: 2024-08-26T06:35:35.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2025-02-10T01:58:25.000Z (10 months ago)
- Last Synced: 2025-04-06T14:39:21.955Z (8 months ago)
- Topics: event-driven, events, go, golang, json, matching, matching-engine, performance, rule-engine
- Language: Go
- Homepage:
- Size: 312 KB
- Stars: 26
- Watchers: 6
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
- Codeowners: CODEOWNERS
Awesome Lists containing this project
- awesome-go-cn - hypermatch
- awesome-go-plus - hypermatch - A very fast and efficient Go library for matching events to a large set of rules  (Messaging / Search and Analytic Databases)
- fucking-awesome-go - hypermatch - A very fast and efficient Go library for matching events to a large set of rules (Messaging / Search and Analytic Databases)
- awesome-go - hypermatch - A very fast and efficient Go library for matching events to a large set of rules (Messaging / Search and Analytic Databases)
- awesome-go-with-stars - hypermatch - A very fast and efficient Go library for matching events to a large set of rules (Messaging / Search and Analytic Databases)
- awesome-go - SchwarzIT/hypermatch - performance Go library designed for rapid matching of a large number of rules to events. It processes thousands of events per second against extensive rule sets in-memory with minimal latency . ☆`32` (Messaging / Search and Analytic Databases)
- awesome-go - hypermatch - A very fast and efficient Go library for matching events to a large set of rules (Messaging / Search and Analytic Databases)
README
[](https://jobs.schwarz)
[](https://github.com/SchwarzIT/hypermatch/actions/workflows/go-test.yml)
[](https://coveralls.io/github/SchwarzIT/hypermatch?branch=main)
[](https://goreportcard.com/report/github.com/SchwarzIT/hypermatch)
[](https://pkg.go.dev/github.com/schwarzit/hypermatch)


[](https://github.com/avelino/awesome-go)

# Introduction
Hypermatch is a high-performance Go library that enables rapid matching of a large number of rules against events. Designed for speed and efficiency, hypermatch handles thousands of events per second with low latency, making it ideal for real-time systems.
- **Fast Matching**: Matches events to a large set of rules in-memory with minimal delay ... [it's really fast! (Benchmark)](_benchmark/benchmark.md)
- **Readable Rule Format**: Serialize rules into human-readable JSON objects.
- **Flexible Rule Syntax**: Supports various matching conditions, including equals, prefix, suffix, wildcard, anything-but, all-of, and any-of.
An event consists of a list of fields, provided as name/value pairs. A rule links these event fields to patterns that determine whether the event matches.

# Quick Start
```go
import (
hypermatch "github.com/SchwarzIT/hypermatch"
)
func main() {
//Initialize hypermatch
hm := hypermatch.NewHyperMatch()
//Add a rule
if err := hm.AddRule("markus_rule", hypermatch.ConditionSet{
hypermatch.Condition{Path: "firstname", Pattern: hypermatch.Pattern{Type: hypermatch.PatternEquals, Value: "markus"}},
hypermatch.Condition{Path: "lastname", Pattern: hypermatch.Pattern{Type: hypermatch.PatternEquals, Value: "troßbach"}},
}); err != nil {
panic(err)
}
//Test with match
matchedRules := hm.Match([]hypermatch.Property{
{Path: "firstname", Values: []string{"markus"}},
{Path: "lastname", Values: []string{"troßbach"}},
})
log.Printf("Following rules matches: %v", matchedRules)
//Test without match
matchedRules = hm.Match([]hypermatch.Property{
{Path: "firstname", Values: []string{"john"}},
{Path: "lastname", Values: []string{"doe"}},
})
log.Printf("Following rules matches: %v", matchedRules)
}
```
# Documentation
## Example Event
An event is represented as a JSON object with various fields. Here’s a sample event:
```javascript
{
"name": "Too many parallel requests on system xy",
"severity": "critical",
"status": "firing",
"message": "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
"team": "awesome-team",
"application": "webshop",
"component": "backend-service",
"tags": [
"shop",
"backend"
]
}
```
**This example will be referenced throughout the documentation.**
## Matching Basics
Rules in Hypermatch are composed of conditions defined by the `ConditionSet` type.
- **Case-Insensitive Matching**: All value comparisons are case-insensitive.
- **Supported Types**: Currently, only strings and string arrays are supported.
Each condition includes:
- **Path**: The field in the event to match against.
- **Pattern**: The pattern used to match the value at the specified path.
Here’s an example rule that matches the event above:
```go
ConditionSet{
{
Path: "status",
Pattern: Pattern{Type: PatternEquals, Value: "firing"},
},
{
Path: "name",
Pattern: Pattern{Type: PatternAnythingBut, Sub: []Pattern{
{Type: PatternWildcard, Value: "TEST*"},
},
},
},
{
Path: "severity",
Pattern: Pattern{ Type: PatternAnyOf,
Sub: []Pattern{
{Type: PatternEquals, Value: "critical"},
{Type: PatternEquals, Value: "warning"},
},
},
},
{
Path: "tags",
Pattern: Pattern{ Type: PatternAllOf,
Sub: []Pattern{
{Type: PatternEquals, Value: "shop"},
{Type: PatternEquals, Value: "backend"},
},
},
},
}
```
The rules and conditions are also expressible as JSON objects. The following JSON is the equivalent of the above Go notation for a `ConditionSet`:
```javascript
{
"status": {
"equals": "firing"
},
"name": {
"anythingBut": [
{"wildcard": "TEST*"}
]
},
"severity": {
"anyOf": [
{"equals": "critical"},
{"equals": "warning"}
]
},
"tags": {
"allOf": [
{"equals": "shop"},
{"equals": "backend"}
]
}
}
```
**Note**: For simplicity, all examples in this documentation will be presented in JSON format.
## Matching syntax
### "equals" matching
The `equals` condition checks if an attribute of the event matches a specified value, case-insensitively.
```javascript
{
"status": {
"equals": "firing"
}
}
```
If the attribute value is type of:
- **String**: Checks if the value is equal to "firing"
- **String array**: Checks if the array contains an element equal to "firing"
### "prefix" matching
The `prefix` condition checks if an attribute starts with a specified prefix, case-insensitively.
```javascript
{
"status": {
"prefix": "fir"
}
}
```
If the attribute value is type of:
- **String**: Checks if the value begins with "fir"
- **String array**: Checks if the array contains an element that begins with "fir"
### "suffix" matching
The `suffix` condition checks if an attribute ends with a specified suffix, case-insensitively.
```javascript
{
"status": {
"suffix": "ing"
}
}
```
If the attribute value is type of:
- **String**: Checks if the value ends with "ing"
- **String array**: Checks if the array contains an element that ends with "ing"
### "wildcard" matching
The `wildcard` condition uses wildcards to match the value of an attribute, ignoring case.
- Use * as a wildcard to match any number of characters (including none).
- You cannot place wildcards directly next to each other.
```javascript
{
"name": {
"wildcard": "*parallel requests*"
}
}
```
If the attribute value is type of:
- **String**: Checks if the value matches the pattern \*parallel requests\*
- **String array**: Checks if any value in the array matches the pattern
### "anythingBut" matching
The `anythingBut` condition negates the match, triggering only if the specified condition is not met.
```javascript
{
"status": {
"anythingBut": [
{"equals": "firing"}
]
}
}
```
If the attribute value is type of:
- **String**: Checks if the value is anything other than "firing"
- **String array**: Checks if the array does *not* contain an element equal to "firing"
### "anyOf" matching
`anyOf` does correspond to a boolean "inclusive-or". It checks multiple conditions and matches if **any** of the conditions are true.
```javascript
{
"status": {
"anyOf": [
{"equals": "firing"},
{"equals": "resolved"}
]
}
}
```
If the attribute value is type of:
- **String**: Checks if the value is either "firing" or "resolved"
- **String array**: Checks if the array contains an element equal to "firing" or "resolved" or both.
### "allOf" matching
`allOf` does correspond to a boolean "and". It checks multiple conditions and matches if **all** the conditions are true.
```javascript
{
"tags": {
"allOf": [
{"equals": "shop"},
{"equals": "backend"}
]
}
}
```
If the attribute value is type of:
- **String**: This condition makes no sense, as it checks if the value is equal to "shop" and "backend"
- **String array**: Checks if the array contains both "shop" and "backend"
# Performance
**hypermatch** is designed to be blazing fast with very large numbers of rules.
Nevertheless, there are a few things to consider to get maximum performance:
- Shorten the number of fields inside the rules, the fewer conditions, the shorter is the path to find them out.
- Try to make the **paths** as diverse as possible in events and rules. The more heterogeneous fields, the higher the performance.
- Reduce the number of **anyOf** conditions wherever possible