User-defined lookup enrichment
- Dominant language
- Java
- Stars
- 14.9k
- Forks
- 3.5k
- Avg merge
- 1d 4h
- Merged PRs (30d)
- 88
Description
Logstash should have more dynamic ways to lookup and enrich events, especially with external user-defined datasets. Currently, the main venue of lookup enrichment comes from the translate filter, which is primarily basic key/value lookup and only supports YAML. Here's some ideas:
#### Use cases
- Simple key/value lookup enrichment
- Lookup user name from a user ID
- Tag/classify bad actors or blacklisted IP addresses
- Multi-field lookup enrichment
- “Join” external table data with event
- Add multiple user fields (name, address, phone #, birthday, etc.) to an event
- In more traditional BI, there are dimension tables in star schemas or CMDBs tables where relevant lookup data is sourced.
- Use RDBMS, Elasticsearch, or others as doc store for lookup dataset
#### Filter plugin additions and enhancements for user-defined data lookup
- logstash-filter-translate **(Phase 1)**
- [ ] Better multi-field enrichment, currently multi-field lookups are stored as a complex object in the destination field. We should enable this feature to have these multiple fields be directly in the top level. (https://github.com/logstash-plugins/logstash-filter-translate/issues/44)
- [ ] Full array support - old PR (https://github.com/logstash-plugins/logstash-filter-translate/pull/15)
- logstash-filter-jdbc **(Phase 1)** - there's two plugins we're building for this use case:
- [x] [jdbc_static](https://github.com/elastic/logstash/issues/6502) - this enables caching a JDBC query result set locally in memory on LS for scalable event enrichment. It will support multi-field lookups on primary/composite keys and also periodic refreshes of the lookup cache. This will have the broadest set of use cases especially with CMDBs and data warehouses.
- [ ] [jdbc_streaming](https://github.com/logstash-plugins/logstash-filter-jdbc_streaming) - this allows doing a JDBC call per event, and can be helpful when the lookup data changes often. It does require a network roundtrip per event, which can result in limited performance.
- logstash-filter-elasticsearch **(Phase 1)**
- [x] Official plugin support - starting in 5.3
- [ ] Better integration with ES percolation
- [ ] Better scalability, query latency optimization
- logstash-filter-http **(Phase 2)**
- Lookups from file returned from HTTP REST endpoint
- SSL/TLS support
- Area of inspiration: https://github.com/elastic/logstash/issues/3489 and https://github.com/logstash-plugins/logstash-filter-lookup/pull/1
- Redis document (Future)
## Ignore below, retaining for precedence
#### Lookup source file formats (for file/http)
- CSV
- Multi-field lookup enrichment **(Phase 1)**
- Popular format for tabular data, enables RDBMS/Excel table exports for CSV lookup
- JSON and YAML
- Simple key/value lookups **(Phase 1)**
- Multi-field lookup enrichment (Future)
The lookup data should be cached:
- O(1) lookups
- Configurable max memory size allocated
- Periodic reloading of cache - no need to bounce the pipeline to refresh lookup cache with changes
## Multi-field lookup
**CSV Format**
- Must contain a header line
- Must contain at least two columns
- Looks up on a single or compound key. The lookup key to use should be unique and must be defined at config time.
``` csv
code,status_description,status_type,color
200,OK,Successful,Green
201,Created,Successful,Green
202,Accepted,Successful,Green
300,Multiple Choices,Redirection,Yellow
```
**Example**
``` ruby
#Config
filter {
lookup_file {
path => "~/conf/lookup.csv"
format => "csv"
cache_size => "1MB"
refresh_interval => 10000
event_fields => ["http_code", "color"] # (required) 1+ event keys to match with. event_fields.length() == lookup_fields.length()
lookup_fields => ["code", "color"] # (required for csv) 1+ lookup keys to match against
target_fields => ["status_description", "status_type"] # (optional) whitelist of 1+ looked up fields to add to event. If not defined, adds all fields (not including lookup key fields e.g. "code" and "color") to event top level.
}
}
#Event in
Event {
http_code => "202"
color => "Green"
}
#Event out
Event {
http_code => "202"
color => "Green"
status_description => "Accepted"
status_type => "Successful"
}
```
## Simple key/value lookup
**JSON Format**
``` json
{
"200": "Green",
"201": "Green",
"202": "Green",
"300": "Yellow",
"elastic": true,
"version": 5.0
}
```
**YAML Format**
``` yaml
200: ‘Green’
201: ‘Green’
202: ‘Green’
300: ‘Yellow’
elastic: true
version: 5.0
```
**Example**
``` ruby
#Config
filter {
lookup_file {
path => "~/conf/lookup.json"
format => ["json" | "yaml"]
cache_size => "1MB"
refresh_interval => 10000
event_fields => "key"
target_fields => "lookup_value" # (optional) new field name of looked up value. If not defined, new field name defaults to "lookup_value".
}
}
#Event in
Event {
key => "elastic"
product => "logstash"
}
#Event out
Event {
key => "elastic"
product => "logstash"
lookup_value => true
}
```
## HTTP example
Very similar to file counterpart, except 'url' instead of 'path'.
``` ruby
filter {
lookup_http {
url => "localhost:9200/lookup1/"
tls => false
# other fields are the same...
}
}
```
Ref: https://github.com/elastic/logstash/issues/5087, https://github.com/elastic/logstash/issues/3633, https://github.com/elastic/logstash/issues/3446, https://github.com/elastic/logstash/issues/4510
P.S. - open to suggestions on new plugin names...~~
Contributor guide
Assessment
This issue has not been assessed yet.