-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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
LokI Exporter - Adding a feature for loki exporter to encode JSON for log entry #3874
Conversation
@gramidt please review |
This PR was marked stale due to lack of activity. It will be closed in 7 days. |
I apologize for the delay, @crearys and @bogdandrutu. I was out of the office on vacation and returned to a pile of things to catch up on. I will try to review this PR over the weekend. |
@gramidt thanks |
This PR was marked stale due to lack of activity. It will be closed in 7 days. |
exporter/lokiexporter/exporter.go
Outdated
@@ -135,7 +135,19 @@ func (l *lokiExporter) logDataToLoki(ld pdata.Logs) (pr *logproto.PushRequest, n | |||
continue | |||
} | |||
labels := mergedLabels.String() | |||
entry := convertLogToLokiEntry(log) | |||
var entry *logproto.Entry | |||
if l.config.Format == "json" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the decision on format is not made at runtime, but rather at config time, what are your thoughts on making this decision early on and mapping the appropriate method ahead of time? This would remove the additional check per record.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gramidt I have just pushed a new commit following your comments.
@crearys - Looks like there's some linting and unit test issues. Could you address those? |
Does anyone seen my comments ? Mostly about nested structures supported or not by loki with pipe search / grafana in vizualization panel. Are you sure it's ok ? At otel-collector side can we map atttributes.attr1 to a label ? EDIT: Sorry my review was never submitted ! 😅 |
exporter/lokiexporter/encode_json.go
Outdated
TraceID: lr.TraceID().HexString(), | ||
SpanID: lr.SpanID().HexString(), | ||
Severity: lr.SeverityText(), | ||
Attributes: tracetranslator.AttributeMapToMap(lr.Attributes())} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As you created a full structure, why not add "Resources" ? Maybe conditionaly ?
} | ||
|
||
func exampleJson() string { | ||
jsonExample := `{"name":"name","body":"Example log","traceid":"01020304000000000000000000000000","spanid":"0506070800000000","severity":"error","attributes":{"attr1":"1","attr2":"2"}}` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To follow some logic and to be more explicit on loki side, why not prefix your arbitrary keys (name, body, traceid...) by someting like "otel_collector_lokiexporter_" ?
It can avoid confusion with keys in logs received by another channel than otel collector for exemple.
I would prefer use "otel.collector.lokiexporter." to be more consistent with OTEL but if you apply | json
on it, loki replace all points by underscores anyway at the end...
@@ -44,6 +44,8 @@ The following settings can be optionally configured: | |||
|
|||
- `headers` (no default): Name/value pairs added to the HTTP request headers. | |||
|
|||
- `format` (default = body): Set the log entry line format. This can be set to 'json' (the entire json encoded log record) or 'body' (the log record body field as a string). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like it, finaly it's not too intrusive as potential big change !
exporter/lokiexporter/encode_json.go
Outdated
TraceID: lr.TraceID().HexString(), | ||
SpanID: lr.SpanID().HexString(), | ||
Severity: lr.SeverityText(), | ||
Attributes: tracetranslator.AttributeMapToMap(lr.Attributes())} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about nested structures on Grafana / Loki ?
In my memories I tested it and it was not working as expected. I'm not sure if loki is able to do something like {} | json | attributes.attr1 == "xxx"
and on Grafana log pannel I think nested objects are not correctly rendered.
Does anyone can confirm ?
Do you think attributes could be flatened at json root (maybe with a key prefix) ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Working on logs enriched by a resourcedetector processor, I confirm the Resources should be converted to structured logs data !
In theory some keys could be the same in attributes and resources (even if it doesn't makes sense...) so convertLogToLokiEntry
should prefix them by something in my opinion.
@gillg To respond to all your comments. In grafana you can query the nested structures using |
Ok, if I understand, loki makes a kind of native flattening on your nested JSON structure. So it "saves" the problem, but maybe it consumes more resources at query time ? @gramidt do you know if there is a notable impact ? Are we safe doing nothing at otel collector side and let's loki parse/flatten the json ? loki:
labels:
attributes:
# Allowing 'severity' attribute and not providing a mapping, since the attribute name is a valid Loki label name.
severity: ""
http.status_code: "http_status_code" # here http.status_code is not a nested object but just a key
As Loki takes keys of each nested structures and creates a flat structure with underscores we could do the same thing to help its work. It's just an idea. And about "unprefixed" keys like name, body, severity, etc, it's less a problem if we keep them as it without a consensus. |
This PR was marked stale due to lack of activity. It will be closed in 7 days. |
This PR was marked stale due to lack of activity. It will be closed in 7 days. |
This PR was marked stale due to lack of activity. It will be closed in 7 days. |
This PR was marked stale due to lack of activity. It will be closed in 7 days. |
@gramidt updated for 0.36.0 |
@slim-bean @crearys - Would either of you be interested in becoming the new owner of the Loki exporter? My priorities have shifted and I'm unable to allocate the necessary time to be a good maintainer. |
A Loki exporter maintener is really needed :/ Moreover with this PR we are probably not so far from a final good V1. |
This PR was marked stale due to lack of activity. It will be closed in 7 days. |
Description:
The PR creates a feature for the Loki Exporter that allows you to use a JSON representation of the LogRecord as described by https://developers.google.com/protocol-buffers/docs/proto3#json.
It creates a Loki LogEntry using JSON instead of the current
body
string.The
format
option allows you to choose betweenjson
or thebody
string, the default is the body string.This feature allows us to handle structured logging the Loki exporter and use structured logging in our logging pipeline.
Link to tracking Issue:
This may fix the issue: #2529
Testing:
TestConvert - Ensuring the json encoding is providing expected responses.
TestJsonLoadConfig - Ensuring the format config option is set correctly.
TestExporter_convertLogtoJsonEntry - Ensuring the Log Entry is converted to a JSON Entry.
Documentation:
Comments added to the functions and README options updated.