mirror of
https://github.com/rocky-linux/peridot.git
synced 2024-10-19 07:55:07 +00:00
198 lines
5.1 KiB
Go
198 lines
5.1 KiB
Go
|
// Copyright The OpenTelemetry Authors
|
||
|
// SPDX-License-Identifier: Apache-2.0
|
||
|
|
||
|
package semconv // import "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv"
|
||
|
|
||
|
import (
|
||
|
"net/http"
|
||
|
"strings"
|
||
|
|
||
|
"go.opentelemetry.io/otel/attribute"
|
||
|
semconvNew "go.opentelemetry.io/otel/semconv/v1.24.0"
|
||
|
)
|
||
|
|
||
|
type newHTTPServer struct{}
|
||
|
|
||
|
// TraceRequest returns trace attributes for an HTTP request received by a
|
||
|
// server.
|
||
|
//
|
||
|
// The server must be the primary server name if it is known. For example this
|
||
|
// would be the ServerName directive
|
||
|
// (https://httpd.apache.org/docs/2.4/mod/core.html#servername) for an Apache
|
||
|
// server, and the server_name directive
|
||
|
// (http://nginx.org/en/docs/http/ngx_http_core_module.html#server_name) for an
|
||
|
// nginx server. More generically, the primary server name would be the host
|
||
|
// header value that matches the default virtual host of an HTTP server. It
|
||
|
// should include the host identifier and if a port is used to route to the
|
||
|
// server that port identifier should be included as an appropriate port
|
||
|
// suffix.
|
||
|
//
|
||
|
// If the primary server name is not known, server should be an empty string.
|
||
|
// The req Host will be used to determine the server instead.
|
||
|
func (n newHTTPServer) RequestTraceAttrs(server string, req *http.Request) []attribute.KeyValue {
|
||
|
count := 3 // ServerAddress, Method, Scheme
|
||
|
|
||
|
var host string
|
||
|
var p int
|
||
|
if server == "" {
|
||
|
host, p = splitHostPort(req.Host)
|
||
|
} else {
|
||
|
// Prioritize the primary server name.
|
||
|
host, p = splitHostPort(server)
|
||
|
if p < 0 {
|
||
|
_, p = splitHostPort(req.Host)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
hostPort := requiredHTTPPort(req.TLS != nil, p)
|
||
|
if hostPort > 0 {
|
||
|
count++
|
||
|
}
|
||
|
|
||
|
method, methodOriginal := n.method(req.Method)
|
||
|
if methodOriginal != (attribute.KeyValue{}) {
|
||
|
count++
|
||
|
}
|
||
|
|
||
|
scheme := n.scheme(req.TLS != nil)
|
||
|
|
||
|
if peer, peerPort := splitHostPort(req.RemoteAddr); peer != "" {
|
||
|
// The Go HTTP server sets RemoteAddr to "IP:port", this will not be a
|
||
|
// file-path that would be interpreted with a sock family.
|
||
|
count++
|
||
|
if peerPort > 0 {
|
||
|
count++
|
||
|
}
|
||
|
}
|
||
|
|
||
|
useragent := req.UserAgent()
|
||
|
if useragent != "" {
|
||
|
count++
|
||
|
}
|
||
|
|
||
|
clientIP := serverClientIP(req.Header.Get("X-Forwarded-For"))
|
||
|
if clientIP != "" {
|
||
|
count++
|
||
|
}
|
||
|
|
||
|
if req.URL != nil && req.URL.Path != "" {
|
||
|
count++
|
||
|
}
|
||
|
|
||
|
protoName, protoVersion := netProtocol(req.Proto)
|
||
|
if protoName != "" && protoName != "http" {
|
||
|
count++
|
||
|
}
|
||
|
if protoVersion != "" {
|
||
|
count++
|
||
|
}
|
||
|
|
||
|
attrs := make([]attribute.KeyValue, 0, count)
|
||
|
attrs = append(attrs,
|
||
|
semconvNew.ServerAddress(host),
|
||
|
method,
|
||
|
scheme,
|
||
|
)
|
||
|
|
||
|
if hostPort > 0 {
|
||
|
attrs = append(attrs, semconvNew.ServerPort(hostPort))
|
||
|
}
|
||
|
if methodOriginal != (attribute.KeyValue{}) {
|
||
|
attrs = append(attrs, methodOriginal)
|
||
|
}
|
||
|
|
||
|
if peer, peerPort := splitHostPort(req.RemoteAddr); peer != "" {
|
||
|
// The Go HTTP server sets RemoteAddr to "IP:port", this will not be a
|
||
|
// file-path that would be interpreted with a sock family.
|
||
|
attrs = append(attrs, semconvNew.NetworkPeerAddress(peer))
|
||
|
if peerPort > 0 {
|
||
|
attrs = append(attrs, semconvNew.NetworkPeerPort(peerPort))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if useragent := req.UserAgent(); useragent != "" {
|
||
|
attrs = append(attrs, semconvNew.UserAgentOriginal(useragent))
|
||
|
}
|
||
|
|
||
|
if clientIP != "" {
|
||
|
attrs = append(attrs, semconvNew.ClientAddress(clientIP))
|
||
|
}
|
||
|
|
||
|
if req.URL != nil && req.URL.Path != "" {
|
||
|
attrs = append(attrs, semconvNew.URLPath(req.URL.Path))
|
||
|
}
|
||
|
|
||
|
if protoName != "" && protoName != "http" {
|
||
|
attrs = append(attrs, semconvNew.NetworkProtocolName(protoName))
|
||
|
}
|
||
|
if protoVersion != "" {
|
||
|
attrs = append(attrs, semconvNew.NetworkProtocolVersion(protoVersion))
|
||
|
}
|
||
|
|
||
|
return attrs
|
||
|
}
|
||
|
|
||
|
func (n newHTTPServer) method(method string) (attribute.KeyValue, attribute.KeyValue) {
|
||
|
if method == "" {
|
||
|
return semconvNew.HTTPRequestMethodGet, attribute.KeyValue{}
|
||
|
}
|
||
|
if attr, ok := methodLookup[method]; ok {
|
||
|
return attr, attribute.KeyValue{}
|
||
|
}
|
||
|
|
||
|
orig := semconvNew.HTTPRequestMethodOriginal(method)
|
||
|
if attr, ok := methodLookup[strings.ToUpper(method)]; ok {
|
||
|
return attr, orig
|
||
|
}
|
||
|
return semconvNew.HTTPRequestMethodGet, orig
|
||
|
}
|
||
|
|
||
|
func (n newHTTPServer) scheme(https bool) attribute.KeyValue { // nolint:revive
|
||
|
if https {
|
||
|
return semconvNew.URLScheme("https")
|
||
|
}
|
||
|
return semconvNew.URLScheme("http")
|
||
|
}
|
||
|
|
||
|
// TraceResponse returns trace attributes for telemetry from an HTTP response.
|
||
|
//
|
||
|
// If any of the fields in the ResponseTelemetry are not set the attribute will be omitted.
|
||
|
func (n newHTTPServer) ResponseTraceAttrs(resp ResponseTelemetry) []attribute.KeyValue {
|
||
|
var count int
|
||
|
|
||
|
if resp.ReadBytes > 0 {
|
||
|
count++
|
||
|
}
|
||
|
if resp.WriteBytes > 0 {
|
||
|
count++
|
||
|
}
|
||
|
if resp.StatusCode > 0 {
|
||
|
count++
|
||
|
}
|
||
|
|
||
|
attributes := make([]attribute.KeyValue, 0, count)
|
||
|
|
||
|
if resp.ReadBytes > 0 {
|
||
|
attributes = append(attributes,
|
||
|
semconvNew.HTTPRequestBodySize(int(resp.ReadBytes)),
|
||
|
)
|
||
|
}
|
||
|
if resp.WriteBytes > 0 {
|
||
|
attributes = append(attributes,
|
||
|
semconvNew.HTTPResponseBodySize(int(resp.WriteBytes)),
|
||
|
)
|
||
|
}
|
||
|
if resp.StatusCode > 0 {
|
||
|
attributes = append(attributes,
|
||
|
semconvNew.HTTPResponseStatusCode(resp.StatusCode),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
return attributes
|
||
|
}
|
||
|
|
||
|
// Route returns the attribute for the route.
|
||
|
func (n newHTTPServer) Route(route string) attribute.KeyValue {
|
||
|
return semconvNew.HTTPRoute(route)
|
||
|
}
|