-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
[PROTOTYPE] Combine gRPC and HTTP servers #3765
Changes from all commits
dd3aa4d
bb8482a
c4936c1
3cb6ba5
ae11f8a
6137abe
60c44c8
1b0a9e0
b6d342c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,6 +37,7 @@ import ( | |
) | ||
|
||
const ( | ||
grpcContentType = "application/grpc" | ||
pbContentType = "application/x-protobuf" | ||
jsonContentType = "application/json" | ||
) | ||
|
@@ -202,6 +203,11 @@ func (r *otlpReceiver) registerTraceConsumer(tc consumer.Traces) error { | |
return componenterror.ErrNilNextConsumer | ||
} | ||
r.traceReceiver = trace.New(r.cfg.ID(), tc) | ||
if r.cfg.ExperimentalServerEnabled { | ||
r.httpMux.HandleFunc("/opentelemetry.proto.collector.trace.v1.TraceService/Export", func(resp http.ResponseWriter, req *http.Request) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a bit fragile. If we rename a message or service in the proto this will no longer work. Can we have a test that ensures the path for this handler matches the proto definition correctly? |
||
handleTraces(resp, req, grpcContentType, r.traceReceiver, tracesPbUnmarshaler) | ||
}).Methods(http.MethodPost).Headers("Content-Type", grpcContentType) | ||
} | ||
if r.httpMux != nil { | ||
r.httpMux.HandleFunc("/v1/traces", func(resp http.ResponseWriter, req *http.Request) { | ||
handleTraces(resp, req, pbContentType, r.traceReceiver, tracesPbUnmarshaler) | ||
|
@@ -229,6 +235,11 @@ func (r *otlpReceiver) registerMetricsConsumer(mc consumer.Metrics) error { | |
return componenterror.ErrNilNextConsumer | ||
} | ||
r.metricsReceiver = metrics.New(r.cfg.ID(), mc) | ||
if r.cfg.ExperimentalServerEnabled { | ||
r.httpMux.HandleFunc("/opentelemetry.proto.collector.metrics.v1.MetricsService/Export", func(resp http.ResponseWriter, req *http.Request) { | ||
handleMetrics(resp, req, grpcContentType, r.metricsReceiver, metricsPbUnmarshaler) | ||
}).Methods(http.MethodPost).Headers("Content-Type", grpcContentType) | ||
} | ||
Comment on lines
+238
to
+242
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this be inside |
||
if r.httpMux != nil { | ||
r.httpMux.HandleFunc("/v1/metrics", func(resp http.ResponseWriter, req *http.Request) { | ||
handleMetrics(resp, req, pbContentType, r.metricsReceiver, metricsPbUnmarshaler) | ||
|
@@ -248,6 +259,11 @@ func (r *otlpReceiver) registerLogsConsumer(lc consumer.Logs) error { | |
return componenterror.ErrNilNextConsumer | ||
} | ||
r.logReceiver = logs.New(r.cfg.ID(), lc) | ||
if r.cfg.ExperimentalServerEnabled { | ||
r.httpMux.HandleFunc("/opentelemetry.proto.collector.logs.v1.LogsService/Export", func(w http.ResponseWriter, req *http.Request) { | ||
handleLogs(w, req, grpcContentType, r.logReceiver, logsPbUnmarshaler) | ||
}).Methods(http.MethodPost).Headers("Content-Type", grpcContentType) | ||
} | ||
if r.httpMux != nil { | ||
r.httpMux.HandleFunc("/v1/logs", func(w http.ResponseWriter, req *http.Request) { | ||
handleLogs(w, req, pbContentType, r.logReceiver, logsPbUnmarshaler) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package otlpreceiver | ||
|
||
import ( | ||
"encoding/binary" | ||
"errors" | ||
"io" | ||
"net/http" | ||
"strconv" | ||
|
||
"google.golang.org/grpc/codes" | ||
) | ||
|
||
const grpcStatus = "grpc-status" | ||
const grpcMessage = "grpc-message" | ||
|
||
var errTooLong = errors.New("response payload is too long to encode into gRPC") | ||
|
||
type grpcResponseWriter struct { | ||
innerRw http.ResponseWriter | ||
headerWritten bool | ||
} | ||
|
||
func (rw grpcResponseWriter) Header() http.Header { | ||
return rw.innerRw.Header() | ||
} | ||
|
||
func (rw grpcResponseWriter) Write(b []byte) (int, error) { | ||
if !rw.headerWritten { | ||
rw.WriteHeader(int(codes.OK)) | ||
} | ||
lengthPrefix := make([]byte, 5) | ||
payloadLen := uint32(len(b)) | ||
if int(payloadLen) != len(b) { | ||
return 0, errTooLong | ||
} | ||
binary.BigEndian.PutUint32(lengthPrefix[1:], payloadLen) | ||
_, err := rw.innerRw.Write(lengthPrefix) | ||
if err != nil { | ||
return 0, err | ||
} | ||
return rw.innerRw.Write(b) | ||
} | ||
|
||
func (rw *grpcResponseWriter) WriteHeader(statusCode int) { | ||
if !rw.headerWritten { | ||
rw.headerWritten = true | ||
rw.Header()["Date"] = nil | ||
rw.Header()["Trailer"] = []string{grpcStatus, grpcMessage} | ||
rw.Header().Set("Content-Type", grpcContentType) | ||
rw.innerRw.WriteHeader(200) | ||
} | ||
rw.Header().Set(grpcStatus, strconv.FormatInt(int64(statusCode), 10)) | ||
} | ||
|
||
func unwrapProtoFromGrpc(reader io.Reader) (compressed bool, errout error) { | ||
b := make([]byte, 5) | ||
_, err := io.ReadFull(reader, b) | ||
// compressed := b[0] == 1 | ||
return b[0] == 1, 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.
Add a comment to explain why we need priority scheduler and not the default one.