[receiver/faroreceiver] Add Faro receiver logic to wireframe#39588
Conversation
|
Note: I'm basically copying #38224 from @dark0dave and making updates |
|
Moving to draft while this PR is being worked on. Please mark ready to review and ping @dehaansa when done. |
9457ef0 to
7fd4f88
Compare
|
@dehaansa please review |
| var err error | ||
| receiver := receivers.GetOrAdd( | ||
| fCfg, | ||
| func() component.Component { | ||
| var rcv component.Component | ||
| rcv, err = newFaroReceiver(fCfg, &set) | ||
| return rcv | ||
| }, | ||
| ) | ||
| if err != nil { | ||
| return nil, err | ||
| } |
There was a problem hiding this comment.
This should be refactored into a function.
| } | ||
|
|
||
| func (r *faroReceiver) handleFaroRequest(resp http.ResponseWriter, req *http.Request) { | ||
| resp.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS") |
There was a problem hiding this comment.
Should these only be set in the preflight request response path?
There was a problem hiding this comment.
Harmless, but moving these to the preflight path below it 👍🏼
| if err == nil { | ||
| err = r.nextTraces.ConsumeTraces(req.Context(), traces) | ||
| if err != nil { | ||
| errors = append(errors, fmt.Sprintf("failed to push traces: %v", err)) | ||
| } | ||
| } else { | ||
| r.settings.Logger.Debug("Faro traces are nil, skipping") |
There was a problem hiding this comment.
I'm confused here - if err != nil we log that "traces are nil", but we haven't actually checked that. Additionally, while the current implementation of the translator might always return a nil err we shouldn't assume that given that err is part of the function definition, we should handle this like a normal function that can return an err.
There was a problem hiding this comment.
I think I messed up with a linter error here and removed the check for traces (and logs) - I'm putting it back now
| if err == nil { | ||
| err = r.nextLogs.ConsumeLogs(req.Context(), logs) | ||
| if err != nil { | ||
| errors = append(errors, fmt.Sprintf("failed to push logs: %v", err)) | ||
| } | ||
| } else { | ||
| r.settings.Logger.Debug("Faro logs are nil, skipping") | ||
| } |
| r.settings.Logger.Debug("Faro traces are nil, skipping") | ||
| } | ||
| } else { | ||
| r.settings.Logger.Debug("Traces consumer not registered, skipping") |
There was a problem hiding this comment.
This could be a noisy debug log, and I'm not sure it provides value.
| if err == nil { | ||
| err = r.nextTraces.ConsumeTraces(req.Context(), traces) | ||
| if err != nil { | ||
| errors = append(errors, fmt.Sprintf("failed to push traces: %v", err)) |
There was a problem hiding this comment.
nit : "push" sounds like an exporter action
| errors = append(errors, fmt.Sprintf("failed to push traces: %v", err)) | |
| errors = append(errors, fmt.Sprintf("failed to pass traces to next consumer: %v", err)) |
There was a problem hiding this comment.
Applying suggestion (sorry for not accepting this one straight away, modified this along the other changes from above)
| if err == nil { | ||
| err = r.nextLogs.ConsumeLogs(req.Context(), logs) | ||
| if err != nil { | ||
| errors = append(errors, fmt.Sprintf("failed to push logs: %v", err)) |
There was a problem hiding this comment.
nit : "push" sounds like an exporter action
| errors = append(errors, fmt.Sprintf("failed to push logs: %v", err)) | |
| errors = append(errors, fmt.Sprintf("failed to pass logs to next consumer: %v", err)) |
| } | ||
|
|
||
| if len(errors) > 0 { | ||
| r.settings.Logger.Error("Failed to process Faro payload", zap.Any("payload", payload), zap.Any("errors", errors)) |
There was a problem hiding this comment.
Given that clients may re-send, should we fail fast? IE if traces fails, do we want to try to send logs?
There was a problem hiding this comment.
I think yes - I'm making this fail fast so not to waste time when things go wrong.
| farotranslator "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/faro" | ||
| ) | ||
|
|
||
| const faroPath = "/" |
There was a problem hiding this comment.
if I understand the faro spec correctly, should this support receiving data on /collect/{appKey}?
There was a problem hiding this comment.
I think the spec needs to be updated, I was assuming anyone was free to receive data on any URL they wish to - @mar4uk ?
There was a problem hiding this comment.
agree, let's change the spec. It should be possible to use any URL
| resp.WriteHeader(http.StatusOK) | ||
| } | ||
|
|
||
| func (r *faroReceiver) errorHandler(w http.ResponseWriter, _ *http.Request, errMsg string, statusCode int) { |
There was a problem hiding this comment.
Yep! Modifying that
I'm not sure about the schema being right in the spec though - @mar4uk I think the spec mixes Faro payload Exceptions with what the receiver can return
There was a problem hiding this comment.
Oh, right, the schema is not correct. It indeed mixes Faro payload Exceptions with error that actually returned
|
Moving to draft, please fix conflicts and address review and mark ready for review again. |
c48b82a to
666bb10
Compare
adbdda5 to
f3938a2
Compare
dehaansa
left a comment
There was a problem hiding this comment.
New concern out of the refactoring.
| } | ||
|
|
||
| if err := json.NewEncoder(w).Encode(resp); err != nil { | ||
| r.settings.Logger.Error("Could not write JSON response", |
There was a problem hiding this comment.
If it fails to write should we default to a precalculated "json" string? Otherwise this seems like it's not responding at all.
There was a problem hiding this comment.
Isn't it overkill? json.NewEncoder(w).Encode() only fails (I think) if writing to a closed connection, mem corruption, system-level I/O errors...
A fallback like
fallback := fmt.Sprintf(`{"error":%q,"code":%d,"message":%q}`, http.StatusText(statusCode), statusCode, errMsg)is easy to add now, but I don't see much benefit.
There was a problem hiding this comment.
I hear that, it feels strange handling an error case and not explicitly managing that error. A comment in the code to that effect would be nice for now, in case this ends up being an unexpected issue in the future.
…lemetry#39588) <!--Ex. Fixing a bug - Describe the bug and how this fixes the issue. Ex. Adding a feature - Explain what this achieves.--> #### Description Faro receiver package enables Faro-compatible endpoints. This makes it work. <!-- Issue number (e.g. open-telemetry#1234) or full URL to issue, if applicable. --> #### Link to tracking issue Fixes open-telemetry#19180 <!--Describe what testing was performed and which tests were added.--> #### Testing Adding more unit tests.
…lemetry#39588) <!--Ex. Fixing a bug - Describe the bug and how this fixes the issue. Ex. Adding a feature - Explain what this achieves.--> #### Description Faro receiver package enables Faro-compatible endpoints. This makes it work. <!-- Issue number (e.g. #1234) or full URL to issue, if applicable. --> #### Link to tracking issue Fixes open-telemetry#19180 <!--Describe what testing was performed and which tests were added.--> #### Testing Adding more unit tests.
| receivers: | ||
| faro: | ||
| endpoint: 'localhost:8081' | ||
| cors: |
There was a problem hiding this comment.
I believe this is incorrect. his should be something like:
receivers:
faro:
protocols:
http:
endpoint: 'localhost:8081'
cors:
..There was a problem hiding this comment.
Actually I'm not even sure the cors implementation works at all. Both the config I've posted above and the example in the readme do not change the cors response headers.
Description
Faro receiver package enables Faro-compatible endpoints. This makes it work.
Link to tracking issue
Fixes #19180
Testing
Adding more unit tests.