-
Notifications
You must be signed in to change notification settings - Fork 5.7k
feat(outputs.opentelemetry): Support http protocol #17997
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
base: master
Are you sure you want to change the base?
Conversation
|
Thanks so much for the pull request! |
srebhan
left a comment
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.
Thanks @minuk-dev for your contribution! I do have some initial comments below. Let's first get the code structure right and then work on the details...
| // EncodingType is the encoding type to use for sending data to the OpenTelemetry Collector. | ||
| // It is used only when Protocol is set to "http". | ||
| // Supported encoding types are "application/x-protobuf" & "application/json". Defaults to "application/x-protobuf". | ||
| EncodingType string `toml:"encoding_type"` |
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.
Does it make sense to support protobuf via HTTP? If so, please name the option format and use json or protobuf as values instead of the full HTTP encoding type to not mislead users to think they can specify an arbitrary encoding. We also usually use encoding for compression settings...
|
Download PR build artifacts for linux_amd64.tar.gz, darwin_arm64.tar.gz, and windows_amd64.zip. 📦 Click here to get additional PR build artifactsArtifact URLs |
srebhan
left a comment
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.
Thanks @minuk-dev for the update! Here is round two of my comments... ;-)
| type gRPCClient struct { | ||
| grpcClientConn *grpc.ClientConn | ||
| metricsServiceClient pmetricotlp.GRPCClient | ||
| callOptions []grpc.CallOption | ||
| } | ||
|
|
||
| type httpClient struct { | ||
| httpClient *http.Client | ||
| url string | ||
| encodingType string | ||
| compress 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.
What I meant previously is to have a client_grpc.go and a client_http.go with the respective struct etc. Sorry for being not clear!
| } | ||
|
|
||
| func (*httpClient) Close() error { | ||
| // No persistent connections to close for HTTP client |
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 think you need to CloseIdleConnections here.
| const ( | ||
| maxHTTPResponseReadBytes = 64 * 1024 // 64 KB | ||
| ) |
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.
Don't declare this const but just use the value!
| if err != nil { | ||
| t.Error(err) | ||
| } |
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.
You need to return as t.Error will not stop the processing here! Same below...
| if err != nil { | |
| t.Error(err) | |
| } | |
| if err != nil { | |
| t.Error(err) | |
| w.WriteHeader(http.StatusInternalServerError) | |
| return | |
| } |
| err = req.UnmarshalProto(body) | ||
| if err != nil { | ||
| t.Error(err) | ||
| } |
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.
Please limit the scope of the variables! Same below.
| err = req.UnmarshalProto(body) | |
| if err != nil { | |
| t.Error(err) | |
| } | |
| if err := req.UnmarshalProto(body); err != nil { | |
| t.Error(err) | |
| w.WriteHeader(http.StatusInternalServerError) | |
| return | |
| } |
| err = plugin.Connect() | ||
| require.NoError(t, err) |
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.
Please use
| err = plugin.Connect() | |
| require.NoError(t, err) | |
| require.NoError(t, plugin.Connect()) |
as it is shorter and avoids an explicit err... Same for all other instances below.
| map[string]interface{}{ | ||
| "gauge": 87.332, | ||
| }, | ||
| time.Unix(0, 1622848686000000000)) |
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.
Just a matter of taste but I like
| time.Unix(0, 1622848686000000000)) | |
| time.Unix(0, 1622848686000000000), | |
| ) |
to better see the closing bracket.
| # Send OpenTelemetry metrics over gRPC | ||
| [[outputs.opentelemetry]] | ||
| ## Override the default (grpc) protocol | ||
| ## grpc, http | ||
| # protocol = "grpc" | ||
| ## Override the default (localhost:4317) OpenTelemetry gRPC service | ||
| ## address:port | ||
| ## When the protocol is grpc, address:port | ||
| ## When the protocol is http, http(s)://address:port/path | ||
| # service_address = "localhost:4317" | ||
| ## Override the default (application/x-protobuf) encodingType when Protocol is http | ||
| ## application/x-protobuf, application/json | ||
| # encoding_type = "application/x-protobuf" | ||
|
|
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.
Please update!
| } | ||
| if o.EncodingType == "" { | ||
| o.EncodingType = "application/x-protobuf" | ||
| } |
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.
Can we please check the encoding type!? What if some uses application/pdf? I guess we are only support JSON and protobuf for now, don't we?
Use a switch statement like
switch o.EncodingType {
case "":
o.EncodingType = "application/x-protobuf"
case "application/json", "application/x-protobuf":
// Do nothing, those are valid
default:
return fmt.Errorf("invalid encoding %q", o.EncodingType)
}to be honest I would even prefer
switch o.EncodingType {
case "", "protobuf":
o.EncodingType = "application/x-protobuf"
case "json":
o.EncodingType = "application/json"
default:
return fmt.Errorf("invalid encoding %q", o.EncodingType)
}
Summary
Question
Local Test
otel.yaml
docker run --rm -it -v "$(pwd)/otel.yaml":/etc/otel/config.yaml -p 4318:4318 --name otel-collector otel/opentelemetry-collector:latest --config /etc/otel/config.yamlChecklist
Related issues