Logstash
Runs 10x Engine as a sidecar to Logstash for reporting, receiving, and optimizing events before they ship to their destination (Elasticsearch, OpenSearch, Splunk, S3, Kafka, โฆ). Logstash and Log10x run as peer processes and exchange events as newline-delimited JSON over TCP โ Logstash's built-in tcp input and output plugins with codec => json_lines on both legs. Works against any stock Logstash build (OSS or Elastic distribution) and the official elastic/logstash Helm chart with a values overlay.
Architecture
graph LR
A["<div style='font-size: 14px;'>๐ Sources</div><div style='font-size: 10px;'>file, beats, http</div>"] --> F["<div style='font-size: 14px;'>๐งช ingest pipeline</div><div style='font-size: 10px;'>enrichment filters</div>"]
F --> B["<div style='font-size: 14px;'>๐ค tcp output</div><div style='font-size: 10px;'>json_lines :5044</div>"]
B --> E["<div style='font-size: 14px;'>โก 10x Engine</div><div style='font-size: 10px;'>Report/Receive/Optimize</div>"]
E --> C["<div style='font-size: 14px;'>๐ฅ tcp input</div><div style='font-size: 10px;'>json_lines :5045</div>"]
C --> D["<div style='font-size: 14px;'>๐ค Destinations</div><div style='font-size: 10px;'>ES, Splunk, S3, Kafka</div>"]
classDef input fill:#2563eb,stroke:#1d4ed8,color:#ffffff,stroke-width:2px,rx:8,ry:8
classDef filter fill:#ea580c,stroke:#c2410c,color:#ffffff,stroke-width:2px,rx:8,ry:8
classDef engine fill:#7c3aed,stroke:#6d28d9,color:#ffffff,stroke-width:2px,rx:8,ry:8
classDef output fill:#16a34a,stroke:#15803d,color:#ffffff,stroke-width:2px,rx:8,ry:8
class A input
class B filter
class C filter
class D output
class E engine
class F filter
Data Flow
- ๐ Sources โ Your existing Logstash inputs (
file,beats,tcp,http, โฆ) feed into theingestpipeline. - ๐งช ingest pipeline โ Your enrichment filters (
grok,mutate,kv,geoip,date, โฆ) run here exactly once before the event is handed off to Log10x. The pipeline also stamps atagfield that survives the round trip and surfaces as the event's source inside Log10x. - ๐ค tcp output โ Log10x โ Logstash's
tcpoutput plugin (codec => json_lines) ships the enriched event to the Log10x sidecar on TCP:5044(or a Unix socket on Linux/macOS via theunixoutput plugin). - โก 10x Engine โ The Receiver app applies rate/policy-based filtering and optionally compacts events for volume reduction.
- ๐ฅ tcp input โ destinations pipeline โ Processed events come back to Logstash on
:5045and are picked up by a separatedestinationspipeline whoseoutputblock holds your real destinations. Filters defined underingestare not re-applied โ Logstash's multi-pipeline routing keeps each pipeline's filter chain isolated. - ๐ค Destinations โ The original
tagfield survives the round trip, so destinations that route on it (Splunk index, S3 prefix, Kafka topic, โฆ) behave the same as if Log10x weren't in the path.
What an event looks like on the way back
The record structure of the original Logstash event is preserved end-to-end โ every field comes back to your destinations pipeline with the same name and same position. What changes depends on the Receiver app mode:
| Mode | Difference vs the event Logstash sent in |
|---|---|
| Receive (default) | None. Same record. |
Receive + symbolMessageHashField <name> |
Adds one new field with the symbol-pattern hash (a stable identifier for the message pattern โ usable as a dedup key, metric dimension, or correlation ID). |
receiverOptimize true |
The value of the message field (message by default, or whatever logstashInputMessageField is set to) is replaced with a compact encoded form. A separate event with tag set to tenx-template is emitted with the template needed to decode it. All other fields stay verbatim. |
receiverOptimize true + symbolMessageHashField <name> |
Both of the above. |
The tag field that the ingest pipeline stamps becomes the event's source inside Log10x โ used for rate-based grouping and preserved on each event as it returns to Logstash. The message text is read from the message field by default (override with logstashInputMessageField). When the Receiver app is configured with k8sExtractorName: fluentK8s, the kubernetes.* sub-object is also lifted into pod/container metadata fields used by message-pattern and rate filtering.
Key Files
| File | Purpose |
|---|---|
stream.yaml |
Logstash JSON socket input + output stream definitions |
conf/tenx-sidecar.conf |
Reference Logstash pipeline config showing the ingest / destinations split |
Quickstart
1. Run Log10x:
2. Wire up your Logstash config โ split your work into two pipelines via pipelines.yml, with an ingest leg that ends in tcp { codec => json_lines } and a destinations leg that starts with tcp { codec => json_lines }:
- pipeline.id: ingest
path.config: "${TENX_MODULES}/pipelines/run/modules/input/forwarder/logstash/conf/tenx-sidecar.conf"
- pipeline.id: destinations
path.config: "/etc/logstash/conf.d/destinations.conf"
3. Point the destinations pipeline at your real outputs (the recipe defaults to stdout for testing):
input {
tcp {
host => "0.0.0.0"
port => 5045
codec => json_lines
}
}
output {
# ... your real destinations ...
}
For Kubernetes deployment via the official elastic/logstash Helm chart see the Helm sidecar overlay.
Config Files
To configure the Logstash module, Edit these files.
Below is the default configuration from: logstash/config.yaml.
ewogICJ0eXBlIiA6ICJvYmplY3QiLAogICJwcm9wZXJ0aWVzIiA6IHsKICAgICJpbmNsdWRlIiA6IHsKICAgICAgInR5cGUiIDogImFycmF5IiwKICAgICAgIml0ZW1zIiA6IHsKICAgICAgICAidHlwZSIgOiAic3RyaW5nIgogICAgICB9CiAgICB9LAogICAgInRlbngiIDogewogICAgICAidHlwZSIgOiAic3RyaW5nIgogICAgfSwKICAgICJsb2dzdGFzaCIgOiB7CiAgICAgICJ0eXBlIiA6ICJvYmplY3QiLAogICAgICAiYWRkaXRpb25hbFByb3BlcnRpZXMiIDogZmFsc2UsCiAgICAgICJwcm9wZXJ0aWVzIiA6IHsKICAgICAgICAiaW5wdXQiIDogewogICAgICAgICAgInR5cGUiIDogIm9iamVjdCIsCiAgICAgICAgICAiYWRkaXRpb25hbFByb3BlcnRpZXMiIDogZmFsc2UsCiAgICAgICAgICAicHJvcGVydGllcyIgOiB7CiAgICAgICAgICAgICJwb3J0IiA6IHsKICAgICAgICAgICAgICAidHlwZSIgOiBbCiAgICAgICAgICAgICAgICAic3RyaW5nIiwKICAgICAgICAgICAgICAgICJudW1iZXIiLAogICAgICAgICAgICAgICAgIm51bGwiCiAgICAgICAgICAgICAgXSwKICAgICAgICAgICAgICAibWFya2Rvd25EZXNjcmlwdGlvbiIgOiAiVENQIHBvcnQgdG8gbGlzdGVuIG9uIGZvciBldmVudHMgZnJvbSBMb2dzdGFzaCdzIHRjcCBvdXRwdXRcblxuVENQIHBvcnQgd2hlcmUgTG9nMTB4IGxpc3RlbnMgZm9yIGV2ZW50cyBzZW50IGJ5IExvZ3N0YXNoJ3MgYHRjcGAgb3V0cHV0IHdpdGggYGNvZGVjID0+IGpzb25fbGluZXNgLiBNYXRjaCB0aGlzIGFnYWluc3QgdGhlIGBwb3J0YCBpbiB5b3VyIExvZ3N0YXNoIGBvdXRwdXQgeyB0Y3AgeyAuLi4gfSB9YCBibG9jay4gKERlZmF1bHQ6IDUwNDQpIiwKICAgICAgICAgICAgICAiZGVmYXVsdCIgOiAiNTA0NCIKICAgICAgICAgICAgfSwKICAgICAgICAgICAgInBhdGgiIDogewogICAgICAgICAgICAgICJ0eXBlIiA6IFsKICAgICAgICAgICAgICAgICJzdHJpbmciLAogICAgICAgICAgICAgICAgIm51bGwiCiAgICAgICAgICAgICAgXSwKICAgICAgICAgICAgICAibWFya2Rvd25EZXNjcmlwdGlvbiIgOiAiVW5peCBkb21haW4gc29ja2V0IHBhdGggdG8gbGlzdGVuIG9uIChMaW51eC9tYWNPUylcblxuV2hlbiBzZXQsIExvZzEweCBsaXN0ZW5zIG9uIGEgVW5peCBkb21haW4gc29ja2V0IGluc3RlYWQgb2YgVENQIOKAlCB1c2VmdWwgb24gTGludXgvbWFjT1MgdG8gYXZvaWQgVENQIG92ZXJoZWFkLiBDb25maWd1cmUgTG9nc3Rhc2gncyBgdW5peGAgb3V0cHV0IHBsdWdpbiB3aXRoIGBjb2RlYyA9PiBqc29uX2xpbmVzYCBhbmQgYSBtYXRjaGluZyBgcGF0aGAuIElnbm9yZWQgb24gV2luZG93cy4iCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgICJtZXNzYWdlRmllbGQiIDogewogICAgICAgICAgICAgICJ0eXBlIiA6IFsKICAgICAgICAgICAgICAgICJzdHJpbmciLAogICAgICAgICAgICAgICAgIm51bGwiCiAgICAgICAgICAgICAgXSwKICAgICAgICAgICAgICAibWFya2Rvd25EZXNjcmlwdGlvbiIgOiAiTmFtZSBvZiB0aGUgSlNPTiBmaWVsZCBjYXJyeWluZyB0aGUgb3JpZ2luYWwgbG9nIGxpbmVcblxuTmFtZSBvZiB0aGUgZmllbGQgaW4gZWFjaCBMb2dzdGFzaCBldmVudCB0aGF0IGNvbnRhaW5zIHRoZSBhY3R1YWwgbG9nIG1lc3NhZ2UgdGV4dC4gVGhlIGRlZmF1bHQgKGBtZXNzYWdlYCkgbWF0Y2hlcyBMb2dzdGFzaCdzIGNvbnZlbnRpb24gZm9yIHRoZSBgZmlsZWAsIGBiZWF0c2AsIGB0Y3BgLCBhbmQgYGh0dHBgIGlucHV0cy4gU2V0IHRvIGUuZy4gYGxvZ2AgaWYgeW91ciBzb3VyY2VzIGVtaXQgdGhlIGxvZyBsaW5lIHVuZGVyIGEgZGlmZmVyZW50IGtleS4gKERlZmF1bHQ6IG1lc3NhZ2UpIiwKICAgICAgICAgICAgICAiZGVmYXVsdCIgOiAibWVzc2FnZSIKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0sCiAgICAgICAgIm91dHB1dCIgOiB7CiAgICAgICAgICAidHlwZSIgOiAib2JqZWN0IiwKICAgICAgICAgICJhZGRpdGlvbmFsUHJvcGVydGllcyIgOiBmYWxzZSwKICAgICAgICAgICJwcm9wZXJ0aWVzIiA6IHsKICAgICAgICAgICAgImhvc3QiIDogewogICAgICAgICAgICAgICJ0eXBlIiA6IFsKICAgICAgICAgICAgICAgICJzdHJpbmciLAogICAgICAgICAgICAgICAgIm51bGwiCiAgICAgICAgICAgICAgXSwKICAgICAgICAgICAgICAibWFya2Rvd25EZXNjcmlwdGlvbiIgOiAiVENQIGhvc3Qgb2YgdGhlIExvZ3N0YXNoIHRjcCBpbnB1dCByZWNlaXZpbmcgcHJvY2Vzc2VkIGV2ZW50c1xuXG5Ib3N0bmFtZSBvciBJUCB3aGVyZSB0aGUgTG9nc3Rhc2ggYHRjcGAgaW5wdXQgaXMgbGlzdGVuaW5nIGZvciBwcm9jZXNzZWQgZXZlbnRzIGZyb20gTG9nMTB4LiBQYWlycyB3aXRoIGBsb2dzdGFzaE91dHB1dFBvcnRgLiAoRGVmYXVsdDogMTI3LjAuMC4xKSIsCiAgICAgICAgICAgICAgImRlZmF1bHQiIDogIjEyNy4wLjAuMSIKICAgICAgICAgICAgfSwKICAgICAgICAgICAgInBvcnQiIDogewogICAgICAgICAgICAgICJ0eXBlIiA6IFsKICAgICAgICAgICAgICAgICJzdHJpbmciLAogICAgICAgICAgICAgICAgIm51bWJlciIsCiAgICAgICAgICAgICAgICAibnVsbCIKICAgICAgICAgICAgICBdLAogICAgICAgICAgICAgICJtYXJrZG93bkRlc2NyaXB0aW9uIiA6ICJUQ1AgcG9ydCBvZiB0aGUgTG9nc3Rhc2ggdGNwIGlucHV0IHJlY2VpdmluZyBwcm9jZXNzZWQgZXZlbnRzXG5cblRDUCBwb3J0IHdoZXJlIHRoZSBMb2dzdGFzaCBgdGNwYCBpbnB1dCBpcyBsaXN0ZW5pbmcgZm9yIHByb2Nlc3NlZCBldmVudHMgZnJvbSBMb2cxMHguIE1VU1QgZGlmZmVyIGZyb20gdGhlIHBvcnQgTG9nMTB4J3Mgb3duIGlucHV0IGxpc3RlbnMgb24gKGRlZmF1bHQgYDUwNDRgKSBvciB0aGUgdHdvIHdvdWxkIGNvbGxpZGUgb24gdGhlIHNhbWUgc29ja2V0LiAoRGVmYXVsdDogNTA0NSkiLAogICAgICAgICAgICAgICJkZWZhdWx0IiA6ICI1MDQ1IgogICAgICAgICAgICB9LAogICAgICAgICAgICAiZW5jb2RlVHlwZSIgOiB7CiAgICAgICAgICAgICAgInR5cGUiIDogWwogICAgICAgICAgICAgICAgInN0cmluZyIsCiAgICAgICAgICAgICAgICAibnVsbCIKICAgICAgICAgICAgICBdLAogICAgICAgICAgICAgICJtYXJrZG93bkRlc2NyaXB0aW9uIiA6ICJPdXRwdXQgZm9ybWF0IHdoZW4gb3V0cHV0RmllbGRzIGFyZSBzZXQuIFBvc3NpYmxlIHZhbHVlczogW2pzb24sIGRlbGltaXRlZF1cblxuU3BlY2lmaWVzIGhvdyB0aGUgY29tYmluZWQgb3V0cHV0IChtYWluIGV2ZW50IGZpZWxkIHBsdXMgb3V0cHV0RmllbGRzKSBpcyBlbmNvZGVkIHdoZW4gd3JpdGluZyBiYWNrIHRvIExvZ3N0YXNoLiBQb3NzaWJsZSB2YWx1ZXM6IC0gKipqc29uKio6IGZvcm1hdHMgYWxsIGZpZWxkcyBhcyBhIEpTT04gb2JqZWN0IC0gKipkZWxpbWl0ZWQqKjogZm9ybWF0cyBmaWVsZCB2YWx1ZXMgc2VwYXJhdGVkIGJ5IHRoZSBvdXRwdXQgZGVsaW1pdGVyIE9ubHkgdGFrZXMgZWZmZWN0IHdoZW4gbG9nc3Rhc2hPdXRwdXRGaWVsZHMgaXMgc2V0LiAoRGVmYXVsdDogZGVsaW1pdGVkKSIsCiAgICAgICAgICAgICAgImRlZmF1bHQiIDogImRlbGltaXRlZCIKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgfQogIH0sCiAgImFkZGl0aW9uYWxQcm9wZXJ0aWVzIiA6IHRydWUKfQ==
# ๐โ 'run' Logstash receiver configuration
#
# To learn more see https://doc.log10x.com/run/input/forwarder/logstash/
tenx: run
# =============================== Dependencies ================================
include:
- run/input/forwarder/config.yaml
- run/modules/input/forwarder/logstash
# ============================== Logstash Options =============================
logstash:
# ----------------------------- Input Options -----------------------------
input:
# 'port' specifies the TCP port to listen on for events from Logstash's
# `tcp` output with `codec => json_lines`.
port: 5044
# 'path' switches the input to a Unix domain socket instead of TCP.
# When set, takes precedence over 'port'.
# path: /tmp/tenx-logstash-in.sock
# 'messageField' is the name of the JSON field in each Logstash event
# carrying the log line text.
messageField: message
# ----------------------------- Output Options ----------------------------
output:
# 'host' specifies the TCP host of Logstash's `tcp` input receiving
# processed events from Log10x.
host: 127.0.0.1
# 'port' specifies the TCP port of Logstash's `tcp` input. MUST differ
# from input.port or the two would collide on the same listener.
port: 5045
# 'encodeType' is the on-wire format for the socket record.
# - 'delimited': each top-level field of the rendered record becomes its
# own emitted field โ preserves the original record's structure.
# - 'json': the whole record is wrapped as one stringified field.
encodeType: delimited
Options
Specify the options below to configure the Logstash:
| Name | Description | Category |
|---|---|---|
| logstashInputPort | TCP port to listen on for events from Logstash's tcp output | Input |
| logstashInputPath | Unix domain socket path to listen on (Linux/macOS) | Input |
| logstashInputMessageField | Name of the JSON field carrying the original log line | Input |
| logstashOutputHost | TCP host of the Logstash tcp input receiving processed events | Output |
| logstashOutputPort | TCP port of the Logstash tcp input receiving processed events | Output |
| logstashOutputEncodeType | Output format when outputFields are set. Possible values: [json, delimited] | Output |
Input
logstashInputPort
TCP port to listen on for events from Logstash's tcp output.
| Type | Default | Category |
|---|---|---|
| String | 5044 | Input |
TCP port where Log10x listens for events sent by Logstash's tcp output
with codec => json_lines. Match this against the port in your
Logstash output { tcp { ... } } block.
logstashInputPath
Unix domain socket path to listen on (Linux/macOS).
| Type | Default | Category |
|---|---|---|
| String | "" | Input |
When set, Log10x listens on a Unix domain socket instead of TCP โ useful
on Linux/macOS to avoid TCP overhead. Configure Logstash's unix output
plugin with codec => json_lines and a matching path. Ignored on Windows.
logstashInputMessageField
Name of the JSON field carrying the original log line.
| Type | Default | Category |
|---|---|---|
| String | message | Input |
Name of the field in each Logstash event that contains the actual log
message text. The default (message) matches Logstash's convention for
the file, beats, tcp, and http inputs. Set to e.g. log if your
sources emit the log line under a different key.
Output
logstashOutputHost
TCP host of the Logstash tcp input receiving processed events.
| Type | Default | Category |
|---|---|---|
| String | 127.0.0.1 | Output |
Hostname or IP where the Logstash tcp input is listening for
processed events from Log10x. Pairs with logstashOutputPort.
logstashOutputPort
TCP port of the Logstash tcp input receiving processed events.
| Type | Default | Category |
|---|---|---|
| String | 5045 | Output |
TCP port where the Logstash tcp input is listening for processed
events from Log10x. MUST differ from the port Log10x's own input
listens on (default 5044) or the two would collide on the same
socket.
logstashOutputEncodeType
Output format when outputFields are set. Possible values: [json, delimited].
| Type | Default | Category |
|---|---|---|
| String | delimited | Output |
Specifies how the combined output (main event field plus outputFields) is encoded when writing back to Logstash. Possible values:
- json: formats all fields as a JSON object
- delimited: formats field values separated by the output delimiter Only takes effect when logstashOutputFields is set.
This module is defined in logstash/module.yaml.