Skip to content
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

Fix/missing templated fields loki prometheus + log line value format for Loki #1091

Merged
merged 3 commits into from
Jan 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ var httpOutputDefaults = map[string]map[string]any{
"APIKey": "",
"MinimumPriority": "",
"Tenant": "",
"Format": "text",
"Endpoint": "/loki/api/v1/push",
"ExtraLabels": "",
},
Expand Down
1 change: 1 addition & 0 deletions config_example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ loki:
# mutualtls: false # if true, checkcert flag will be ignored (server cert will always be checked)
# checkcert: true # check if ssl certificate of the output is valid (default: true)
# tenant: "" # Add the Tenant header
# format: "text" # Format for the log entry value: json, text (default)
# endpoint: "/loki/api/v1/push" # The endpoint URL path, default is "/loki/api/v1/push" more info : https://grafana.com/docs/loki/latest/api/#post-apiprompush
# extralabels: "" # comma separated list of fields to use as labels additionally to rule, source, priority, tags and custom_fields
# customHeaders: # Custom headers to add in POST, useful for Authentication
Expand Down
25 changes: 13 additions & 12 deletions docs/outputs/loki.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,19 @@

## Configuration

| Setting | Env var | Default value | Description |
| ---------------------- | ---------------------- | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `loki.hostport` | `LOKI_HOSTPORT` | | http://{domain or ip}:{port}, if not empty, Loki output is **enabled** |
| `loki.user` | `LOKI_USER` | | User for Grafana Logs |
| `loki.apikey` | `LOKI_APIKEY` | | API KEy for Grafana Logs |
| `loki.tenant` | `LOKI_TENANT` | | Add the tenant header if needed |
| `loki.endpoint` | `LOKI_ENDPOINT` | `/loki/api/v1/push` | The endpoint URL path, more info : https://grafana.com/docs/loki/latest/api/#post-apiprompush |
| `loki.extralabels` | `LOKI_EXTRALABELS` | | comma separated list of fields to use as labels additionally to `rule`, `source`, `priority`, `tags` and `custom_fields` |
| `loki.customheaders` | `LOKI_CUSTOMHEADERS` | | Custom headers to add in POST, useful for Authentication |
| `loki.mutualtls` | `LOKI_MUTUALTLS` | `false` | Authenticate to the output with TLS, if true, checkcert flag will be ignored (server cert will always be checked) |
| `loki.checkcert` | `LOKI_CHECKCERT` | `/api/v1/alerts` | Check if ssl certificate of the output is valid | `mattermost.minimumpriority` | `MATTERMOST_MINIMUMPRIORITY` | `""` (= `debug`) | Minimum priority of event for using this output, order is `emergency,alert,critical,error,warning,notice,informational,debug or ""`
| `loki.minimumpriority` | `LOKI_MINIMUMPRIORITY` | `""` (= `debug`) | Minimum priority of event for using this output, order is `emergency,alert,critical,error,warning,notice,informational,debug or ""` |
| Setting | Env var | Default value | Description | | | | |
| ---------------------- | ---------------------- | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | ---------------------------- | ---------------------------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `loki.hostport` | `LOKI_HOSTPORT` | | http://{domain or ip}:{port}, if not empty, Loki output is **enabled** | | | | |
| `loki.user` | `LOKI_USER` | | User for Grafana Logs | | | | |
| `loki.apikey` | `LOKI_APIKEY` | | API KEy for Grafana Logs | | | | |
| `loki.tenant` | `LOKI_TENANT` | | Add the tenant header if needed | | | | |
| `loki.format` | `LOKI_FORMAT` | `text` | Format for the log entry value: json, text | | | | |
| `loki.endpoint` | `LOKI_ENDPOINT` | `/loki/api/v1/push` | The endpoint URL path, more info : https://grafana.com/docs/loki/latest/api/#post-apiprompush | | | | |
| `loki.extralabels` | `LOKI_EXTRALABELS` | | comma separated list of fields to use as labels additionally to `rule`, `source`, `priority`, `tags` and `custom_fields` | | | | |
| `loki.customheaders` | `LOKI_CUSTOMHEADERS` | | Custom headers to add in POST, useful for Authentication | | | | |
| `loki.mutualtls` | `LOKI_MUTUALTLS` | `false` | Authenticate to the output with TLS, if true, checkcert flag will be ignored (server cert will always be checked) | | | | |
| `loki.checkcert` | `LOKI_CHECKCERT` | `/api/v1/alerts` | Check if ssl certificate of the output is valid | `mattermost.minimumpriority` | `MATTERMOST_MINIMUMPRIORITY` | `""` (= `debug`) | Minimum priority of event for using this output, order is `emergency,alert,critical,error,warning,notice,informational,debug or ""` |
| `loki.minimumpriority` | `LOKI_MINIMUMPRIORITY` | `""` (= `debug`) | Minimum priority of event for using this output, order is `emergency,alert,critical,error,warning,notice,informational,debug or ""` | | | | |


> [!NOTE]
Expand Down
5 changes: 5 additions & 0 deletions handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,11 @@ func newFalcoPayload(payload io.Reader) (types.FalcoPayload, error) {
promLabels[key] = value
}
}
for key := range config.Templatedfields {
if regPromLabels.MatchString(key) {
promLabels[key] = fmt.Sprintf("%v", falcopayload.OutputFields[key])
}
}
for _, i := range config.Prometheus.ExtraLabelsList {
promLabels[strings.ReplaceAll(i, ".", "_")] = ""
for key, value := range falcopayload.OutputFields {
Expand Down
18 changes: 15 additions & 3 deletions outputs/loki.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,17 @@ func newLokiPayload(falcopayload types.FalcoPayload, config *types.Configuration
case string:
for k := range config.Customfields {
if i == k {
s[strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(i, ".", ""), "]", ""), "[", "")] = strings.ReplaceAll(v, "\"", "")
s[strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(i, ".", "_"), "]", ""), "[", "")] = strings.ReplaceAll(v, "\"", "")
}
}
for k := range config.Templatedfields {
if i == k {
s[strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(i, ".", "_"), "]", ""), "[", "")] = strings.ReplaceAll(v, "\"", "")
}
}
for _, k := range config.Loki.ExtraLabelsList {
if i == k {
s[strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(i, ".", ""), "]", ""), "[", "")] = strings.ReplaceAll(v, "\"", "")
s[strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(i, ".", "_"), "]", ""), "[", "")] = strings.ReplaceAll(v, "\"", "")
}
}
default:
Expand All @@ -70,10 +75,17 @@ func newLokiPayload(falcopayload types.FalcoPayload, config *types.Configuration
s["tags"] = strings.Join(falcopayload.Tags, ",")
}

var v string
if config.Loki.Format == "json" {
v = falcopayload.String()
} else {
v = falcopayload.Output
}

return lokiPayload{Streams: []lokiStream{
{
Stream: s,
Values: []lokiValue{[]string{fmt.Sprintf("%v", falcopayload.Time.UnixNano()), falcopayload.Output}},
Values: []lokiValue{[]string{fmt.Sprintf("%v", falcopayload.Time.UnixNano()), v}},
},
}}
}
Expand Down
11 changes: 9 additions & 2 deletions stats_prometheus.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,21 @@ func getFalcoNewCounterVec(config *types.Configuration) *prometheus.CounterVec {
}
for i := range config.Customfields {
if !regPromLabels.MatchString(strings.ReplaceAll(i, ".", "_")) {
utils.Log(utils.ErrorLvl, "", fmt.Sprintf("Custom field '%v' is not a valid prometheus label", i))
utils.Log(utils.ErrorLvl, "Prometheus", fmt.Sprintf("Custom field '%v' is not a valid prometheus label", i))
continue
}
labelnames = append(labelnames, strings.ReplaceAll(i, ".", "_"))
}
for i := range config.Templatedfields {
if !regPromLabels.MatchString(strings.ReplaceAll(i, ".", "_")) {
utils.Log(utils.ErrorLvl, "Prometheus", fmt.Sprintf("Templated field '%v' is not a valid prometheus label", i))
continue
}
labelnames = append(labelnames, strings.ReplaceAll(i, ".", "_"))
}
for _, i := range config.Prometheus.ExtraLabelsList {
if !regPromLabels.MatchString(strings.ReplaceAll(i, ".", "_")) {
utils.Log(utils.ErrorLvl, "", fmt.Sprintf("Extra field '%v' is not a valid prometheus label", i))
utils.Log(utils.ErrorLvl, "Prometheus", fmt.Sprintf("Extra field '%v' is not a valid prometheus label", i))
continue
}
labelnames = append(labelnames, strings.ReplaceAll(i, ".", "_"))
Expand Down
1 change: 1 addition & 0 deletions types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@ type LokiOutputConfig struct {
APIKey string
MinimumPriority string
Tenant string
Format string
Endpoint string
ExtraLabels string
ExtraLabelsList []string
Expand Down
Loading