-
Notifications
You must be signed in to change notification settings - Fork 372
Add loki.enrich component #2882
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
30 commits
Select commit
Hold shift + click to select a range
1e9197c
Add loki.enricher
v-zhuravlev 3587566
Add missing comma
v-zhuravlev 2405517
Fix config.alloy
v-zhuravlev 7165296
Fix integration test
v-zhuravlev d2521c3
Fix tests
v-zhuravlev 3308f9d
Register in all.go
v-zhuravlev 601e0ad
Update docs
v-zhuravlev dccff19
rename to loki.enrich
v-zhuravlev 8238809
Update docs
v-zhuravlev 68aa3a0
rename to network
v-zhuravlev 3b8cf7d
Update docs
v-zhuravlev 812da2d
Remove redundant label
v-zhuravlev 04ad59b
Update test
v-zhuravlev ecf9e1a
rename int test
v-zhuravlev d721016
Rename
v-zhuravlev 2b8f416
Add hidden label
v-zhuravlev 69cb0cc
Fix tests
v-zhuravlev 69ee31b
Update changelog
v-zhuravlev bb4e734
Make target_label optional
v-zhuravlev e8d79cd
Rename to logs_match_label, target_match_label. Make logs_match_label…
v-zhuravlev 634190c
Update test
v-zhuravlev 200d27e
rename to labels_to_copy
v-zhuravlev 52a78ca
Update docs/sources/reference/components/loki/loki.enrich.md
v-zhuravlev 364be62
Apply suggestions from code review
v-zhuravlev 6696539
Update docs
v-zhuravlev c4e200c
Add limitation notice
v-zhuravlev c37d243
Update docs/sources/reference/components/loki/loki.enrich.md
v-zhuravlev 3e2e3e4
Update docs/sources/reference/components/loki/loki.enrich.md
v-zhuravlev ba566fd
Add caution in docs
v-zhuravlev ec1fd2c
Merge branch 'main' into vzhuravlev/loki_enricher
v-zhuravlev File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
--- | ||
aliases: | ||
- /docs/alloy/latest/reference/components/loki/loki.enrich/ | ||
canonical: https://grafana.com/docs/alloy/latest/reference/components/loki/loki.enrich/ | ||
title: loki.enrich | ||
labels: | ||
stage: experimental | ||
description: The loki.enrich component enriches logs with labels from service discovery. | ||
--- | ||
|
||
# `loki.enrich` | ||
|
||
{{< docs/shared lookup="stability/experimental.md" source="alloy" version="<ALLOY_VERSION>" >}} | ||
|
||
The `loki.enrich` component enriches logs with additional labels from service discovery targets. | ||
It matches a label from incoming logs against a label from discovered targets, and copies specified labels from the matched target to the log entry. | ||
|
||
## Usage | ||
|
||
```alloy | ||
loki.enrich "<LABEL>" { | ||
// List of targets from a discovery component | ||
targets = <DISCOVERY_COMPONENT>.targets | ||
|
||
// Which label from discovered targets to match against | ||
match_label = "<LABEL>" | ||
|
||
// Which label from incoming logs to match against | ||
source_label = "<LABEL>" | ||
|
||
// List of labels to copy from discovered targets to logs | ||
labels_to_copy = ["<LABEL>", ...] | ||
|
||
// Where to send enriched logs | ||
forward_to = [<RECEIVER_LIST>] | ||
} | ||
``` | ||
|
||
## Arguments | ||
|
||
The following arguments are supported: | ||
|
||
| Name | Type | Description | Default | Required | | ||
| -------------------- | --------------------- | ------------------------------------------------------------------------------------------------ | -------------------- | -------- | | ||
| `forward_to` | `[]loki.LogsReceiver` | List of receivers to send enriched logs to. | | yes | | ||
| `target_match_label` | `string` | The label from discovered targets to match against, for example, `"__inventory_consul_service"`. | | yes | | ||
| `targets` | `[]discovery.Target` | List of targets from a discovery. component. | | yes | | ||
| `labels_to_copy` | `[]string` | List of labels to copy from discovered targets to logs. If empty, all labels will be copied. | | no | | ||
| `logs_match_label` | `string` | The label from incoming logs to match against discovered targets, for example `"service_name"`. | `target_match_label` | no | | ||
|
||
## Blocks | ||
|
||
The `loki.enrich` component doesn't support any blocks. You can configure this component with arguments. | ||
|
||
## Exports | ||
|
||
The following values are exported: | ||
|
||
| Name | Type | Description | | ||
| ---------- | ------------------- | ----------------------------------------------------------- | | ||
| `receiver` | `loki.LogsReceiver` | A receiver that can be used to send logs to this component. | | ||
|
||
## Example | ||
|
||
```alloy | ||
// Configure HTTP discovery | ||
discovery.http "default" { | ||
url = "http://network-inventory.example.com/prometheus_sd" | ||
} | ||
|
||
discovery.relabel "default" { | ||
targets = discovery.http.default.targets | ||
rule { | ||
action = "replace" | ||
source_labels = ["__inventory_rack"] | ||
target_label = "rack" | ||
} | ||
rule { | ||
action = "replace" | ||
source_labels = ["__inventory_datacenter"] | ||
target_label = "datacenter" | ||
} | ||
rule { | ||
action = "replace" | ||
source_labels = ["__inventory_environment"] | ||
target_label = "environment" | ||
} | ||
rule { | ||
action = "replace" | ||
source_labels = ["__inventory_tenant"] | ||
target_label = "tenant" | ||
} | ||
rule { | ||
action = "replace" | ||
source_labels = ["__inventory_primary_ip"] | ||
target_label = "primary_ip" | ||
} | ||
} | ||
|
||
// Receive syslog messages | ||
loki.source.syslog "incoming" { | ||
listener { | ||
address = ":514" | ||
protocol = "tcp" | ||
labels = { | ||
job = "syslog" | ||
} | ||
} | ||
forward_to = [loki.enrich.default.receiver] | ||
} | ||
|
||
// Enrich logs using HTTP discovery | ||
loki.enrich "default" { | ||
// Use targets from HTTP discovery (after relabeling) | ||
targets = discovery.relabel.default.output | ||
|
||
// Match hostname from logs to DNS name | ||
target_match_label = "primary_ip" | ||
|
||
forward_to = [loki.write.default.receiver] | ||
} | ||
``` | ||
|
||
## Component Behavior | ||
|
||
The component matches logs to discovered targets and enriches them with additional labels: | ||
|
||
1. For each log entry, it looks up the value of `logs_match_label` from the log's labels or `target_match_label` if `logs_match_label` is not specified. | ||
1. It matches this value against the `target_match_label` in discovered targets. | ||
1. If a match is found, it copies the requested `labels_to_copy` from the discovered target to the log entry. If `labels_to_copy` is empty, all labels are copied. | ||
1. The log entry, enriched or unchanged, is forwarded to the configured receivers. | ||
|
||
{{< admonition type="caution" >}} | ||
By default, `loki.enrich` is ready as soon as it starts, even if no targets have been discovered. | ||
If telemetry is sent to this component before the metadata is synced, then it will be passed though as-is, without enrichment. | ||
This is most likely to impact `loki.enrich` on startup for a short time before the `discovery` components have sent a new list of targets. | ||
{{< /admonition >}} | ||
|
||
<!-- START GENERATED COMPATIBLE COMPONENTS --> | ||
|
||
## Compatible components | ||
|
||
`loki.enrich` can accept arguments from the following components: | ||
|
||
- Components that export [Targets](../../../compatibility/#targets-exporters) | ||
- Components that export [Loki `LogsReceiver`](../../../compatibility/#loki-logsreceiver-exporters) | ||
|
||
`loki.enrich` has exports that can be consumed by the following components: | ||
|
||
- Components that consume [Loki `LogsReceiver`](../../../compatibility/#loki-logsreceiver-consumers) | ||
|
||
{{< admonition type="note" >}} | ||
Connecting some components may not be sensible or components may require further configuration to make the connection work correctly. | ||
Refer to the linked documentation for more details. | ||
{{< /admonition >}} | ||
|
||
<!-- END GENERATED COMPATIBLE COMPONENTS --> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package common | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
const lokiURL = "http://localhost:3100/loki/api/v1/" | ||
|
||
// LogQuery returns a formatted Loki query with the given test_name label | ||
func LogQuery(testName string) string { | ||
return fmt.Sprintf("%squery_range?query=%%7Btest_name%%3D%%22%s%%22%%7D", lokiURL, testName) | ||
} | ||
|
||
// AssertLogsPresent checks that logs are present in Loki and match expected labels | ||
func AssertLogsPresent(t *testing.T, testName string, expectedLabels map[string]string, expectedCount int) { | ||
var logResponse LogResponse | ||
require.EventuallyWithT(t, func(c *assert.CollectT) { | ||
err := FetchDataFromURL(LogQuery(testName), &logResponse) | ||
assert.NoError(c, err) | ||
if len(logResponse.Data.Result) == 0 { | ||
return | ||
} | ||
|
||
// Verify we got all logs | ||
result := logResponse.Data.Result[0] | ||
assert.Equal(c, expectedCount, len(result.Values), "should have %d log entries", expectedCount) | ||
|
||
// Verify labels were enriched | ||
for k, v := range expectedLabels { | ||
assert.Equal(c, v, result.Stream[k], "label %s should be %s", k, v) | ||
} | ||
}, DefaultTimeout, DefaultRetryInterval) | ||
} | ||
|
||
// AssertLogsMissing checks that logs with specific labels are not present in Loki | ||
func AssertLogsMissing(t *testing.T, testName string, labels ...string) { | ||
var logResponse LogResponse | ||
require.EventuallyWithT(t, func(c *assert.CollectT) { | ||
err := FetchDataFromURL(LogQuery(testName), &logResponse) | ||
assert.NoError(c, err) | ||
if len(logResponse.Data.Result) == 0 { | ||
return | ||
} | ||
|
||
result := logResponse.Data.Result[0] | ||
for _, label := range labels { | ||
assert.NotContains(c, result.Stream, label, "label %s should not be present", label) | ||
} | ||
}, DefaultTimeout, DefaultRetryInterval) | ||
} |
58 changes: 58 additions & 0 deletions
58
internal/cmd/integration-tests/tests/loki-enrich/config.alloy
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
logging { | ||
level = "debug" | ||
} | ||
// Discover device metadata from file | ||
discovery.file "network_devices" { | ||
files = ["./devices.json"] | ||
} | ||
|
||
// Rename hidden labels so they don't get dropped | ||
discovery.relabel "network_devices" { | ||
targets = discovery.file.network_devices.targets | ||
|
||
rule { | ||
action = "replace" | ||
source_labels = ["__meta_rack"] | ||
target_label = "rack" | ||
} | ||
} | ||
|
||
// Receive logs via HTTP API | ||
loki.source.api "network_device" { | ||
http { | ||
listen_address = "0.0.0.0" | ||
listen_port = 1514 | ||
} | ||
labels = { | ||
job = "network_device_logs", | ||
} | ||
forward_to = [loki.enrich.enricher.receiver] | ||
} | ||
|
||
// Enrich logs with device metadata | ||
loki.enrich "enricher" { | ||
|
||
targets = discovery.relabel.network_devices.output | ||
// List of labels to copy from discovered targets to logs | ||
labels_to_copy = [ | ||
"environment", | ||
"datacenter", | ||
"role", | ||
"rack", | ||
] | ||
// Match on hostname/IP from logs | ||
target_match_label = "hostname" | ||
logs_match_label = "host" | ||
|
||
forward_to = [loki.write.enriched.receiver] | ||
} | ||
|
||
// Write enriched logs to Loki | ||
loki.write "enriched" { | ||
endpoint { | ||
url = "http://127.0.0.1:3100/loki/api/v1/push" | ||
} | ||
external_labels = { | ||
test_name = "network_device_enriched", | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
internal/cmd/integration-tests/tests/loki-enrich/devices.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
[ | ||
{ | ||
"targets": ["router1.example.com"], | ||
"labels": { | ||
"hostname": "router1.example.com", | ||
"environment": "production", | ||
"datacenter": "us-east", | ||
"role": "core-router", | ||
"__meta_rack": "rack1" | ||
} | ||
}, | ||
{ | ||
"targets": ["router2.example.com"], | ||
"labels": { | ||
"hostname": "router2.example.com", | ||
"environment": "production", | ||
"datacenter": "us-west", | ||
"role": "edge-router", | ||
"__meta_rack": "rack2" | ||
} | ||
} | ||
] |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.