diff --git a/config/options.go b/config/options.go index 4b041ade1..dc909f1ae 100644 --- a/config/options.go +++ b/config/options.go @@ -196,6 +196,9 @@ type Options struct { TracingProvider string `mapstructure:"tracing_provider" yaml:"tracing_provider,omitempty"` TracingSampleRate float64 `mapstructure:"tracing_sample_rate" yaml:"tracing_sample_rate,omitempty"` + // Datadog tracing address + TracingDatadogAddress string `mapstructure:"tracing_datadog_address" yaml:"tracing_datadog_address,omitempty"` + // Jaeger // // CollectorEndpoint is the full url to the Jaeger HTTP Thrift collector. diff --git a/config/trace.go b/config/trace.go index 6028737f1..2d3bd8447 100644 --- a/config/trace.go +++ b/config/trace.go @@ -26,6 +26,8 @@ func NewTracingOptions(o *Options) (*TracingOptions, error) { } switch o.TracingProvider { + case trace.DatadogTracingProviderName: + tracingOpts.DatadogAddress = o.TracingDatadogAddress case trace.JaegerTracingProviderName: if o.TracingJaegerCollectorEndpoint != "" { jaegerCollectorEndpoint, err := urlutil.ParseAndValidateURL(o.TracingJaegerCollectorEndpoint) diff --git a/config/trace_test.go b/config/trace_test.go index 6f91ff628..d2bf46736 100644 --- a/config/trace_test.go +++ b/config/trace_test.go @@ -22,6 +22,12 @@ func Test_NewTracingOptions(t *testing.T) { want *TracingOptions wantErr bool }{ + { + "datadog_good", + &Options{TracingProvider: "datadog"}, + &TracingOptions{Provider: "datadog", Service: "pomerium"}, + false, + }, { "jaeger_good", &Options{TracingProvider: "jaeger", TracingJaegerAgentEndpoint: "foo", TracingJaegerCollectorEndpoint: "http://foo", Services: ServiceAll}, diff --git a/docs/reference/readme.md b/docs/reference/readme.md index 4dd9dfd33..0f19d4bd6 100644 --- a/docs/reference/readme.md +++ b/docs/reference/readme.md @@ -244,7 +244,7 @@ For example, if `true` ``` 10:37AM INF cmd/pomerium version=v0.0.1-dirty+ede4124 -10:37AM INF proxy: new route from=verify.localhost.pomerium.io to=https://verify.org +10:37AM INF proxy: new route from=verify.localhost.pomerium.io to=https://verify.pomerium.com 10:37AM INF proxy: new route from=ssl.localhost.pomerium.io to=http://neverssl.com 10:37AM INF proxy/authenticator: grpc connection OverrideCertificateName= addr=auth.localhost.pomerium.io:443 ``` @@ -253,7 +253,7 @@ If `false` ``` {"level":"info","version":"v0.0.1-dirty+ede4124","time":"2019-02-18T10:41:03-08:00","message":"cmd/pomerium"} -{"level":"info","from":"verify.localhost.pomerium.io","to":"https://verify.org","time":"2019-02-18T10:41:03-08:00","message":"proxy: new route"} +{"level":"info","from":"verify.localhost.pomerium.io","to":"https://verify.pomerium.com","time":"2019-02-18T10:41:03-08:00","message":"proxy: new route"} {"level":"info","from":"ssl.localhost.pomerium.io","to":"http://neverssl.com","time":"2019-02-18T10:41:03-08:00","message":"proxy: new route"} {"level":"info","OverrideCertificateName":"","addr":"auth.localhost.pomerium.io:443","time":"2019-02-18T10:41:03-08:00","message":"proxy/authenticator: grpc connection"} ``` @@ -331,7 +331,7 @@ services: - /var/run/docker.sock:/var/run/docker.sock verify: # A container that exposes an API to show its IP address - image: pomerium/verify + image: pomerium/verify:latest labels: - "traefik.http.routers.verify.rule=Host(`verify.corp.example.com`)" # Create a middleware named `foo-add-prefix` @@ -480,33 +480,33 @@ Expose a prometheus endpoint on the specified port. #### Pomerium Metrics Tracked -| Name | Type | Description | -| --------------------------------------------- | --------- | ----------------------------------------------------------------------- | -| grpc_client_request_duration_ms | Histogram | GRPC client request duration by service | -| grpc_client_request_size_bytes | Histogram | GRPC client request size by service | -| grpc_client_requests_total | Counter | Total GRPC client requests made by service | -| grpc_client_response_size_bytes | Histogram | GRPC client response size by service | -| grpc_server_request_duration_ms | Histogram | GRPC server request duration by service | -| grpc_server_request_size_bytes | Histogram | GRPC server request size by service | -| grpc_server_requests_total | Counter | Total GRPC server requests made by service | -| grpc_server_response_size_bytes | Histogram | GRPC server response size by service | -| http_client_request_duration_ms | Histogram | HTTP client request duration by service | -| http_client_request_size_bytes | Histogram | HTTP client request size by service | -| http_client_requests_total | Counter | Total HTTP client requests made by service | -| http_client_response_size_bytes | Histogram | HTTP client response size by service | -| http_server_request_duration_ms | Histogram | HTTP server request duration by service | -| http_server_request_size_bytes | Histogram | HTTP server request size by service | -| http_server_requests_total | Counter | Total HTTP server requests handled by service | -| http_server_response_size_bytes | Histogram | HTTP server response size by service | -| pomerium_build_info | Gauge | Pomerium build metadata by git revision, service, version and goversion | -| pomerium_config_checksum_int64 | Gauge | Currently loaded configuration checksum by service | -| pomerium_config_last_reload_success | Gauge | Whether the last configuration reload succeeded by service | -| pomerium_config_last_reload_success_timestamp | Gauge | The timestamp of the last successful configuration reload by service | -| redis_conns | Gauge | Number of total connections in the pool | -| redis_idle_conns | Gauge | Total number of times free connection was found in the pool | -| redis_wait_count_total | Counter | Total number of connections waited for | -| redis_wait_duration_ms_total | Counter | Total time spent waiting for connections | -| storage_operation_duration_ms | Histogram | Storage operation duration by operation, result, backend and service | +Name | Type | Description +--------------------------------------------- | --------- | ----------------------------------------------------------------------- +grpc_client_request_duration_ms | Histogram | GRPC client request duration by service +grpc_client_request_size_bytes | Histogram | GRPC client request size by service +grpc_client_requests_total | Counter | Total GRPC client requests made by service +grpc_client_response_size_bytes | Histogram | GRPC client response size by service +grpc_server_request_duration_ms | Histogram | GRPC server request duration by service +grpc_server_request_size_bytes | Histogram | GRPC server request size by service +grpc_server_requests_total | Counter | Total GRPC server requests made by service +grpc_server_response_size_bytes | Histogram | GRPC server response size by service +http_client_request_duration_ms | Histogram | HTTP client request duration by service +http_client_request_size_bytes | Histogram | HTTP client request size by service +http_client_requests_total | Counter | Total HTTP client requests made by service +http_client_response_size_bytes | Histogram | HTTP client response size by service +http_server_request_duration_ms | Histogram | HTTP server request duration by service +http_server_request_size_bytes | Histogram | HTTP server request size by service +http_server_requests_total | Counter | Total HTTP server requests handled by service +http_server_response_size_bytes | Histogram | HTTP server response size by service +pomerium_build_info | Gauge | Pomerium build metadata by git revision, service, version and goversion +pomerium_config_checksum_int64 | Gauge | Currently loaded configuration checksum by service +pomerium_config_last_reload_success | Gauge | Whether the last configuration reload succeeded by service +pomerium_config_last_reload_success_timestamp | Gauge | The timestamp of the last successful configuration reload by service +redis_conns | Gauge | Number of total connections in the pool +redis_idle_conns | Gauge | Total number of times free connection was found in the pool +redis_wait_count_total | Counter | Total number of connections waited for +redis_wait_duration_ms_total | Counter | Total time spent waiting for connections +storage_operation_duration_ms | Histogram | Storage operation duration by operation, result, backend and service #### Envoy Proxy Metrics @@ -555,10 +555,18 @@ Each unit work is called a Span in a trace. Spans include metadata about the wor #### Shared Tracing Settings -| Config Key | Description | Required | -| :------------------ | :----------------------------------------------------------------------------------- | -------- | -| tracing_provider | The name of the tracing provider. (e.g. jaeger, zipkin) | ✅ | -| tracing_sample_rate | Percentage of requests to sample in decimal notation. Default is `0.0001`, or `.01%` | ❌ | +Config Key | Description | Required +:------------------ | :----------------------------------------------------------------------------------- | -------- +tracing_provider | The name of the tracing provider. (e.g. jaeger, zipkin) | ✅ +tracing_sample_rate | Percentage of requests to sample in decimal notation. Default is `0.0001`, or `.01%` | ❌ + +#### Datadog + +Datadog is a real-time monitoring system that supports distributed tracing and monitoring. + +Config Key | Description | Required +:---------------------- | :--------------------------------------------------------------------------- | -------- +tracing_datadog_address | `host:port` address of the Datadog Trace Agent. Defaults to `localhost:8126` | ❌ #### Jaeger (partial) @@ -572,10 +580,10 @@ Each unit work is called a Span in a trace. Spans include metadata about the wor - Service dependency analysis - Performance / latency optimization -| Config Key | Description | Required | -| :-------------------------------- | :------------------------------------------ | -------- | -| tracing_jaeger_collector_endpoint | Url to the Jaeger HTTP Thrift collector. | ✅ | -| tracing_jaeger_agent_endpoint | Send spans to jaeger-agent at this address. | ✅ | +Config Key | Description | Required +:-------------------------------- | :------------------------------------------ | -------- +tracing_jaeger_collector_endpoint | Url to the Jaeger HTTP Thrift collector. | ✅ +tracing_jaeger_agent_endpoint | Send spans to jaeger-agent at this address. | ✅ #### Zipkin @@ -583,9 +591,9 @@ Zipkin is an open source distributed tracing system and protocol. Many tracing backends support zipkin either directly or through intermediary agents, including Jaeger. For full tracing support, we recommend using the Zipkin tracing protocol. -| Config Key | Description | Required | -| :---------------------- | :------------------------------- | -------- | -| tracing_zipkin_endpoint | Url to the Zipkin HTTP endpoint. | ✅ | +Config Key | Description | Required +:---------------------- | :------------------------------- | -------- +tracing_zipkin_endpoint | Url to the Zipkin HTTP endpoint. | ✅ #### Example @@ -1237,7 +1245,7 @@ Remove Request Headers allows you to remove given request headers. This can be u - Type: `URL` (must contain a scheme and hostname) - Schemes: `http`, `https`, `tcp` - Required -- Example: `http://verify` , `https://192.1.20.12:8080`, `http://neverssl.com`, `https://verify.org/anything/` +- Example: `http://verify` , `https://192.1.20.12:8080`, `http://neverssl.com`, `https://verify.pomerium.com/anything/` `To` is the destination of a proxied request. It can be an internal resource, or an external resource. @@ -1254,7 +1262,7 @@ With rule: to: https://verify.pomerium.com/anything ``` -Requests to `https://verify.corp.example.com` will be forwarded to `https://verify.org/anything`, while requests to `https://verify.corp.example.com/foo` will be forwarded to `https://verify.org/anythingfoo`.To make the request forwarded to `https://httbin.org/anything/foo`, you can use double slashes in your request `https://httbin.corp.example.com//foo`. +Requests to `https://verify.corp.example.com` will be forwarded to `https://verify.pomerium.com/anything`, while requests to `https://verify.corp.example.com/foo` will be forwarded to `https://verify.pomerium.com/anythingfoo`.To make the request forwarded to `https://httbin.org/anything/foo`, you can use double slashes in your request `https://httbin.corp.example.com//foo`. While the rule: @@ -1263,7 +1271,7 @@ While the rule: to: https://verify.pomerium.com/anything/ ``` -All requests to `https://verify.corp.example.com/*` will be forwarded to `https://verify.org/anything/*`. That means accessing to `https://verify.corp.example.com` will be forwarded to `https://verify.org/anything/`. That said, if your application does not handle trailing slash, the request will end up with 404 not found. +All requests to `https://verify.corp.example.com/*` will be forwarded to `https://verify.pomerium.com/anything/*`. That means accessing to `https://verify.corp.example.com` will be forwarded to `https://verify.pomerium.com/anything/`. That said, if your application does not handle trailing slash, the request will end up with 404 not found. ::: diff --git a/docs/reference/settings.yaml b/docs/reference/settings.yaml index a36df6c8f..aa907ffd4 100644 --- a/docs/reference/settings.yaml +++ b/docs/reference/settings.yaml @@ -627,6 +627,7 @@ settings: [ "tracing_provider", "tracing_sample_rate", + "tracing_datadog_address", "tracing_jaeger_collector_endpoint", "tracing_jaeger_agent_endpoint", "tracing_zipkin_endpoint", @@ -643,6 +644,14 @@ settings: tracing_provider | The name of the tracing provider. (e.g. jaeger, zipkin) | ✅ tracing_sample_rate | Percentage of requests to sample in decimal notation. Default is `0.0001`, or `.01%` | ❌ + #### Datadog + + Datadog is a real-time monitoring system that supports distributed tracing and monitoring. + + Config Key | Description | Required + :---------------------- | :--------------------------------------------------------------------------- | -------- + tracing_datadog_address | `host:port` address of the Datadog Trace Agent. Defaults to `localhost:8126` | ❌ + #### Jaeger (partial) **Warning** At this time, Jaeger protocol does not capture spans inside the proxy service. Please use Zipkin protocol with Jaeger for full support. diff --git a/go.mod b/go.mod index a4f695e79..4791d7962 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( contrib.go.opencensus.io/exporter/jaeger v0.2.1 contrib.go.opencensus.io/exporter/prometheus v0.2.0 contrib.go.opencensus.io/exporter/zipkin v0.1.2 + github.com/DataDog/opencensus-go-exporter-datadog v0.0.0-20200406135749-5c268882acf0 github.com/aybabtme/iocontrol v0.0.0-20150809002002-ad15bcfc95a0 // indirect github.com/benbjohnson/clock v1.0.3 // indirect github.com/btcsuite/btcutil v1.0.2 diff --git a/go.sum b/go.sum index 8e08bfe15..884a1aedb 100644 --- a/go.sum +++ b/go.sum @@ -46,6 +46,10 @@ github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/DataDog/datadog-go v3.5.0+incompatible h1:AShr9cqkF+taHjyQgcBcQUt/ZNK+iPq4ROaZwSX5c/U= +github.com/DataDog/datadog-go v3.5.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/DataDog/opencensus-go-exporter-datadog v0.0.0-20200406135749-5c268882acf0 h1:Y6HFfo8UuntPOpfmUmLb0o3MNYKfUuH2aNmvypsDbY4= +github.com/DataDog/opencensus-go-exporter-datadog v0.0.0-20200406135749-5c268882acf0/go.mod h1:/VV3EFO/hTNQZHAqaj+CPGy2+ioFrP4EX3iRwozubhQ= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= @@ -477,6 +481,8 @@ github.com/pelletier/go-toml v1.6.0 h1:aetoXYr0Tv7xRU/V4B4IZJ2QcbtMUFoNb3ORp7TzI github.com/pelletier/go-toml v1.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/peterh/liner v0.0.0-20170211195444-bf27d3ba8e1d/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc= +github.com/philhofer/fwd v1.0.0 h1:UbZqGr5Y38ApvM/V/jEljVxwocdweyH+vmYvRPBnbqQ= +github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -592,6 +598,7 @@ github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3 github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -601,6 +608,8 @@ github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/tinylib/msgp v1.1.2 h1:gWmO7n0Ys2RBEb7GPYB9Ujq8Mk5p2U08lRnmMcGy6BQ= +github.com/tinylib/msgp v1.1.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 h1:nrZ3ySNYwJbSpD6ce9duiP+QkD3JuLCcWkdaehUS/3Y= @@ -966,6 +975,8 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +gopkg.in/DataDog/dd-trace-go.v1 v1.22.0 h1:gpWsqqkwUldNZXGJqT69NU9MdEDhLboK1C4nMgR0MWw= +gopkg.in/DataDog/dd-trace-go.v1 v1.22.0/go.mod h1:DVp8HmDh8PuTu2Z0fVVlBsyWaC++fzwVCaGWylTe3tg= gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/auth0.v4 v4.6.0 h1:Wuc8tgAW2l+vcQ1JnwFlK5KwbJtoABA8osug8eNS3xU= diff --git a/internal/envoy/envoy.go b/internal/envoy/envoy.go index 85965b249..e48964aa9 100644 --- a/internal/envoy/envoy.go +++ b/internal/envoy/envoy.go @@ -7,6 +7,7 @@ import ( "errors" "fmt" "io" + "net" "os" "os/exec" "path/filepath" @@ -26,10 +27,10 @@ import ( "github.com/google/go-cmp/cmp" "github.com/golang/protobuf/proto" - "github.com/golang/protobuf/ptypes" "github.com/natefinch/atomic" "github.com/rs/zerolog" "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/types/known/anypb" "google.golang.org/protobuf/types/known/durationpb" "github.com/pomerium/pomerium/config" @@ -301,6 +302,57 @@ func (srv *Server) buildBootstrapConfig() ([]byte, error) { }, } + if srv.options.tracingOptions.Provider == trace.DatadogTracingProviderName { + addr := &envoy_config_core_v3.SocketAddress{ + Address: "127.0.0.1", + PortSpecifier: &envoy_config_core_v3.SocketAddress_PortValue{ + PortValue: 8126, + }, + } + if srv.options.tracingOptions.DatadogAddress != "" { + a, p, err := net.SplitHostPort(srv.options.tracingOptions.DatadogAddress) + if err == nil { + addr.Address = a + if pv, err := strconv.ParseUint(p, 10, 32); err == nil { + addr.PortSpecifier = &envoy_config_core_v3.SocketAddress_PortValue{ + PortValue: uint32(pv), + } + } + } + } + + staticCfg.Clusters = append(staticCfg.Clusters, &envoy_config_cluster_v3.Cluster{ + Name: "datadog-apm", + ConnectTimeout: &durationpb.Duration{ + Seconds: 5, + }, + ClusterDiscoveryType: &envoy_config_cluster_v3.Cluster_Type{ + Type: envoy_config_cluster_v3.Cluster_STATIC, + }, + LbPolicy: envoy_config_cluster_v3.Cluster_ROUND_ROBIN, + LoadAssignment: &envoy_config_endpoint_v3.ClusterLoadAssignment{ + ClusterName: "datadog-apm", + Endpoints: []*envoy_config_endpoint_v3.LocalityLbEndpoints{ + { + LbEndpoints: []*envoy_config_endpoint_v3.LbEndpoint{ + { + HostIdentifier: &envoy_config_endpoint_v3.LbEndpoint_Endpoint{ + Endpoint: &envoy_config_endpoint_v3.Endpoint{ + Address: &envoy_config_core_v3.Address{ + Address: &envoy_config_core_v3.Address_SocketAddress{ + SocketAddress: addr, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }) + } + cfg := &envoy_config_bootstrap_v3.Bootstrap{ Node: nodeCfg, Admin: adminCfg, @@ -339,44 +391,54 @@ func (srv *Server) addTraceConfig(bootCfg *envoy_config_bootstrap_v3.Bootstrap) return nil } - // We only support zipkin in envoy currently - if srv.options.tracingOptions.Provider != trace.ZipkinTracingProviderName { + switch srv.options.tracingOptions.Provider { + default: return nil - } - - if srv.options.tracingOptions.ZipkinEndpoint.String() == "" { - return fmt.Errorf("missing zipkin url") - } - - // TODO the outbound header list should be configurable when this moves to - // HTTPConnectionManager filters - tracingTC, _ := ptypes.MarshalAny( - &envoy_config_trace_v3.OpenCensusConfig{ - ZipkinExporterEnabled: true, - ZipkinUrl: srv.options.tracingOptions.ZipkinEndpoint.String(), - IncomingTraceContext: []envoy_config_trace_v3.OpenCensusConfig_TraceContext{ - envoy_config_trace_v3.OpenCensusConfig_B3, - envoy_config_trace_v3.OpenCensusConfig_TRACE_CONTEXT, - envoy_config_trace_v3.OpenCensusConfig_CLOUD_TRACE_CONTEXT, - envoy_config_trace_v3.OpenCensusConfig_GRPC_TRACE_BIN, + case trace.DatadogTracingProviderName: + tracingTC, _ := anypb.New(&envoy_config_trace_v3.DatadogConfig{ + CollectorCluster: "datadog-apm", + ServiceName: srv.options.tracingOptions.Service, + }) + bootCfg.Tracing = &envoy_config_trace_v3.Tracing{ + Http: &envoy_config_trace_v3.Tracing_Http{ + Name: "envoy.tracers.datadog", + ConfigType: &envoy_config_trace_v3.Tracing_Http_TypedConfig{ + TypedConfig: tracingTC, + }, }, - OutgoingTraceContext: []envoy_config_trace_v3.OpenCensusConfig_TraceContext{ - envoy_config_trace_v3.OpenCensusConfig_B3, - envoy_config_trace_v3.OpenCensusConfig_TRACE_CONTEXT, - envoy_config_trace_v3.OpenCensusConfig_GRPC_TRACE_BIN, + } + case trace.ZipkinTracingProviderName: + if srv.options.tracingOptions.ZipkinEndpoint.String() == "" { + return fmt.Errorf("missing zipkin url") + } + // TODO the outbound header list should be configurable when this moves to + // HTTPConnectionManager filters + tracingTC, _ := anypb.New( + &envoy_config_trace_v3.OpenCensusConfig{ + ZipkinExporterEnabled: true, + ZipkinUrl: srv.options.tracingOptions.ZipkinEndpoint.String(), + IncomingTraceContext: []envoy_config_trace_v3.OpenCensusConfig_TraceContext{ + envoy_config_trace_v3.OpenCensusConfig_B3, + envoy_config_trace_v3.OpenCensusConfig_TRACE_CONTEXT, + envoy_config_trace_v3.OpenCensusConfig_CLOUD_TRACE_CONTEXT, + envoy_config_trace_v3.OpenCensusConfig_GRPC_TRACE_BIN, + }, + OutgoingTraceContext: []envoy_config_trace_v3.OpenCensusConfig_TraceContext{ + envoy_config_trace_v3.OpenCensusConfig_B3, + envoy_config_trace_v3.OpenCensusConfig_TRACE_CONTEXT, + envoy_config_trace_v3.OpenCensusConfig_GRPC_TRACE_BIN, + }, }, - }, - ) - - tracingCfg := &envoy_config_trace_v3.Tracing{ - Http: &envoy_config_trace_v3.Tracing_Http{ - Name: "envoy.tracers.opencensus", - ConfigType: &envoy_config_trace_v3.Tracing_Http_TypedConfig{ - TypedConfig: tracingTC, + ) + bootCfg.Tracing = &envoy_config_trace_v3.Tracing{ + Http: &envoy_config_trace_v3.Tracing_Http{ + Name: "envoy.tracers.opencensus", + ConfigType: &envoy_config_trace_v3.Tracing_Http_TypedConfig{ + TypedConfig: tracingTC, + }, }, - }, + } } - bootCfg.Tracing = tracingCfg return nil } diff --git a/internal/telemetry/trace/trace.go b/internal/telemetry/trace/trace.go index 1104267c9..5d3944ef7 100644 --- a/internal/telemetry/trace/trace.go +++ b/internal/telemetry/trace/trace.go @@ -7,6 +7,7 @@ import ( "contrib.go.opencensus.io/exporter/jaeger" ocZipkin "contrib.go.opencensus.io/exporter/zipkin" + datadog "github.com/DataDog/opencensus-go-exporter-datadog" "github.com/openzipkin/zipkin-go" zipkinHTTP "github.com/openzipkin/zipkin-go/reporter/http" "go.opencensus.io/trace" @@ -15,6 +16,8 @@ import ( ) const ( + // DatadogTracingProviderName is the name of the tracing provider Datadog. + DatadogTracingProviderName = "datadog" // JaegerTracingProviderName is the name of the tracing provider Jaeger. JaegerTracingProviderName = "jaeger" // ZipkinTracingProviderName is the name of the tracing provider Zipkin. @@ -28,6 +31,9 @@ type TracingOptions struct { Service string Debug bool + // Datadog + DatadogAddress string + // Jaeger // CollectorEndpoint is the full url to the Jaeger HTTP Thrift collector. @@ -57,6 +63,8 @@ func RegisterTracing(opts *TracingOptions) (trace.Exporter, error) { var exporter trace.Exporter var err error switch opts.Provider { + case DatadogTracingProviderName: + exporter, err = registerDatadog(opts) case JaegerTracingProviderName: exporter, err = registerJaeger(opts) case ZipkinTracingProviderName: @@ -78,6 +86,19 @@ func UnregisterTracing(exporter trace.Exporter) { trace.UnregisterExporter(exporter) } +func registerDatadog(opts *TracingOptions) (trace.Exporter, error) { + dOpts := datadog.Options{ + Service: opts.Service, + TraceAddr: opts.DatadogAddress, + } + dex, err := datadog.NewExporter(dOpts) + if err != nil { + return nil, err + } + trace.RegisterExporter(dex) + return dex, nil +} + func registerJaeger(opts *TracingOptions) (trace.Exporter, error) { jOpts := jaeger.Options{ ServiceName: opts.Service,