Skip to content

feat: add option for exporting traces to a provided Honeycomb team #4816

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

Merged
merged 3 commits into from
Nov 1, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
feat: add option for exporting traces to a provided Honeycomb team
  • Loading branch information
coadler committed Oct 31, 2022
commit ca5539b514bee68b482a36353ddc54b0dc8c7a0d
15 changes: 11 additions & 4 deletions cli/deployment/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,10 +289,17 @@ func newConfig() *codersdk.DeploymentConfig {
Default: "tls12",
},
},
TraceEnable: &codersdk.DeploymentConfigField[bool]{
Name: "Trace Enable",
Usage: "Whether application tracing data is collected.",
Flag: "trace",
Trace: &codersdk.TraceConfig{
Enable: &codersdk.DeploymentConfigField[bool]{
Name: "Trace Enable",
Usage: "Whether application tracing data is collected. It exports to a backend configured by environment variables. See: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md",
Flag: "trace",
},
HoneycombAPIKey: &codersdk.DeploymentConfigField[string]{
Name: "Trace Honeycomb API Key",
Usage: "Enables trace exporting to Honeycomb.io using the provided API Key.",
Flag: "trace-honeycomb-api-key",
},
},
SecureAuthCookie: &codersdk.DeploymentConfigField[bool]{
Name: "Secure Auth Cookie",
Expand Down
11 changes: 11 additions & 0 deletions cli/deployment/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,16 @@ func TestConfig(t *testing.T) {
require.Equal(t, config.TLS.Enable.Value, true)
require.Equal(t, config.TLS.MinVersion.Value, "tls10")
},
}, {
Name: "Trace",
Env: map[string]string{
"CODER_TRACE_ENABLE": "true",
"CODER_TRACE_HONEYCOMB_API_KEY": "my-honeycomb-key",
},
Valid: func(config *codersdk.DeploymentConfig) {
require.Equal(t, config.Trace.Enable.Value, true)
require.Equal(t, config.Trace.HoneycombAPIKey.Value, "my-honeycomb-key")
},
}, {
Name: "OIDC",
Env: map[string]string{
Expand Down Expand Up @@ -192,6 +202,7 @@ func TestConfig(t *testing.T) {
}} {
tc := tc
t.Run(tc.Name, func(t *testing.T) {
t.Helper()
for key, value := range tc.Env {
t.Setenv(key, value)
}
Expand Down
4 changes: 2 additions & 2 deletions cli/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,9 @@ func Server(vip *viper.Viper, newAPI func(context.Context, *coderd.Options) (*co
shouldCoderTrace = cfg.Telemetry.Trace.Value
}

if cfg.TraceEnable.Value || shouldCoderTrace {
if cfg.Trace.Enable.Value || shouldCoderTrace {
sdkTracerProvider, closeTracing, err := tracing.TracerProvider(ctx, "coderd", tracing.TracerOpts{
Default: cfg.TraceEnable.Value,
Default: cfg.Trace.Enable.Value,
Coder: shouldCoderTrace,
})
if err != nil {
Expand Down
28 changes: 28 additions & 0 deletions coderd/tracing/exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
sdktrace "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.11.0"
"golang.org/x/xerrors"
"google.golang.org/grpc/credentials"
)

// TracerOpts specifies which telemetry exporters should be configured.
Expand All @@ -23,6 +24,8 @@ type TracerOpts struct {
// Coder exports traces to Coder's public tracing ingest service and is used
// to improve the product. It is disabled when opting out of telemetry.
Coder bool
// Exports traces to Honeycomb.io with the provided API key.
Honeycomb string
}

// TracerProvider creates a grpc otlp exporter and configures a trace provider.
Expand Down Expand Up @@ -57,6 +60,14 @@ func TracerProvider(ctx context.Context, service string, opts TracerOpts) (*sdkt
closers = append(closers, exporter.Shutdown)
tracerOpts = append(tracerOpts, sdktrace.WithBatcher(exporter))
}
if opts.Honeycomb != "" {
exporter, err := HoneycombExporter(ctx, opts.Honeycomb)
if err != nil {
return nil, nil, xerrors.Errorf("honeycomb exporter: %w", err)
}
closers = append(closers, exporter.Shutdown)
tracerOpts = append(tracerOpts, sdktrace.WithBatcher(exporter))
}

tracerProvider := sdktrace.NewTracerProvider(tracerOpts...)
otel.SetTracerProvider(tracerProvider)
Expand Down Expand Up @@ -101,3 +112,20 @@ func CoderExporter(ctx context.Context) (*otlptrace.Exporter, error) {

return exporter, nil
}

func HoneycombExporter(ctx context.Context, apiKey string) (*otlptrace.Exporter, error) {
opts := []otlptracegrpc.Option{
otlptracegrpc.WithEndpoint("api.honeycomb.io:443"),
otlptracegrpc.WithHeaders(map[string]string{
"x-honeycomb-team": apiKey,
}),
otlptracegrpc.WithTLSCredentials(credentials.NewClientTLSFromCert(nil, "")),
}

exporter, err := otlptrace.New(ctx, otlptracegrpc.NewClient(opts...))
if err != nil {
return nil, xerrors.Errorf("create otlp exporter: %w", err)
}

return exporter, nil
}
62 changes: 34 additions & 28 deletions codersdk/deploymentconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,34 +11,35 @@ import (

// DeploymentConfig is the central configuration for the coder server.
type DeploymentConfig struct {
AccessURL *DeploymentConfigField[string] `json:"access_url" typescript:",notnull"`
WildcardAccessURL *DeploymentConfigField[string] `json:"wildcard_access_url" typescript:",notnull"`
Address *DeploymentConfigField[string] `json:"address" typescript:",notnull"`
AutobuildPollInterval *DeploymentConfigField[time.Duration] `json:"autobuild_poll_interval" typescript:",notnull"`
DERP *DERP `json:"derp" typescript:",notnull"`
GitAuth *DeploymentConfigField[[]GitAuthConfig] `json:"gitauth" typescript:",notnull"`
Prometheus *PrometheusConfig `json:"prometheus" typescript:",notnull"`
Pprof *PprofConfig `json:"pprof" typescript:",notnull"`
ProxyTrustedHeaders *DeploymentConfigField[[]string] `json:"proxy_trusted_headers" typescript:",notnull"`
ProxyTrustedOrigins *DeploymentConfigField[[]string] `json:"proxy_trusted_origins" typescript:",notnull"`
CacheDirectory *DeploymentConfigField[string] `json:"cache_directory" typescript:",notnull"`
InMemoryDatabase *DeploymentConfigField[bool] `json:"in_memory_database" typescript:",notnull"`
ProvisionerDaemons *DeploymentConfigField[int] `json:"provisioner_daemons" typescript:",notnull"`
PostgresURL *DeploymentConfigField[string] `json:"pg_connection_url" typescript:",notnull"`
OAuth2 *OAuth2Config `json:"oauth2" typescript:",notnull"`
OIDC *OIDCConfig `json:"oidc" typescript:",notnull"`
Telemetry *TelemetryConfig `json:"telemetry" typescript:",notnull"`
TLS *TLSConfig `json:"tls" typescript:",notnull"`
TraceEnable *DeploymentConfigField[bool] `json:"trace_enable" typescript:",notnull"`
SecureAuthCookie *DeploymentConfigField[bool] `json:"secure_auth_cookie" typescript:",notnull"`
SSHKeygenAlgorithm *DeploymentConfigField[string] `json:"ssh_keygen_algorithm" typescript:",notnull"`
AutoImportTemplates *DeploymentConfigField[[]string] `json:"auto_import_templates" typescript:",notnull"`
MetricsCacheRefreshInterval *DeploymentConfigField[time.Duration] `json:"metrics_cache_refresh_interval" typescript:",notnull"`
AgentStatRefreshInterval *DeploymentConfigField[time.Duration] `json:"agent_stat_refresh_interval" typescript:",notnull"`
AuditLogging *DeploymentConfigField[bool] `json:"audit_logging" typescript:",notnull"`
BrowserOnly *DeploymentConfigField[bool] `json:"browser_only" typescript:",notnull"`
SCIMAPIKey *DeploymentConfigField[string] `json:"scim_api_key" typescript:",notnull"`
UserWorkspaceQuota *DeploymentConfigField[int] `json:"user_workspace_quota" typescript:",notnull"`
AccessURL *DeploymentConfigField[string] `json:"access_url" typescript:",notnull"`
WildcardAccessURL *DeploymentConfigField[string] `json:"wildcard_access_url" typescript:",notnull"`
Address *DeploymentConfigField[string] `json:"address" typescript:",notnull"`
AutobuildPollInterval *DeploymentConfigField[time.Duration] `json:"autobuild_poll_interval" typescript:",notnull"`
DERP *DERP `json:"derp" typescript:",notnull"`
GitAuth *DeploymentConfigField[[]GitAuthConfig] `json:"gitauth" typescript:",notnull"`
Prometheus *PrometheusConfig `json:"prometheus" typescript:",notnull"`
Pprof *PprofConfig `json:"pprof" typescript:",notnull"`
ProxyTrustedHeaders *DeploymentConfigField[[]string] `json:"proxy_trusted_headers" typescript:",notnull"`
ProxyTrustedOrigins *DeploymentConfigField[[]string] `json:"proxy_trusted_origins" typescript:",notnull"`
CacheDirectory *DeploymentConfigField[string] `json:"cache_directory" typescript:",notnull"`
InMemoryDatabase *DeploymentConfigField[bool] `json:"in_memory_database" typescript:",notnull"`
ProvisionerDaemons *DeploymentConfigField[int] `json:"provisioner_daemons" typescript:",notnull"`
PostgresURL *DeploymentConfigField[string] `json:"pg_connection_url" typescript:",notnull"`
OAuth2 *OAuth2Config `json:"oauth2" typescript:",notnull"`
OIDC *OIDCConfig `json:"oidc" typescript:",notnull"`
Telemetry *TelemetryConfig `json:"telemetry" typescript:",notnull"`
TLS *TLSConfig `json:"tls" typescript:",notnull"`
Trace *TraceConfig `json:"trace" typescript:",notnull"`
// TraceEnable *DeploymentConfigField[bool] `json:"trace_enable" typescript:",notnull"`
SecureAuthCookie *DeploymentConfigField[bool] `json:"secure_auth_cookie" typescript:",notnull"`
SSHKeygenAlgorithm *DeploymentConfigField[string] `json:"ssh_keygen_algorithm" typescript:",notnull"`
AutoImportTemplates *DeploymentConfigField[[]string] `json:"auto_import_templates" typescript:",notnull"`
MetricsCacheRefreshInterval *DeploymentConfigField[time.Duration] `json:"metrics_cache_refresh_interval" typescript:",notnull"`
AgentStatRefreshInterval *DeploymentConfigField[time.Duration] `json:"agent_stat_refresh_interval" typescript:",notnull"`
AuditLogging *DeploymentConfigField[bool] `json:"audit_logging" typescript:",notnull"`
BrowserOnly *DeploymentConfigField[bool] `json:"browser_only" typescript:",notnull"`
SCIMAPIKey *DeploymentConfigField[string] `json:"scim_api_key" typescript:",notnull"`
UserWorkspaceQuota *DeploymentConfigField[int] `json:"user_workspace_quota" typescript:",notnull"`
}

type DERP struct {
Expand Down Expand Up @@ -107,6 +108,11 @@ type TLSConfig struct {
MinVersion *DeploymentConfigField[string] `json:"min_version" typescript:",notnull"`
}

type TraceConfig struct {
Enable *DeploymentConfigField[bool] `json:"enable" typescript:",notnull"`
HoneycombAPIKey *DeploymentConfigField[string] `json:"honeycomb_api_key" typescript:",notnull"`
}

type GitAuthConfig struct {
ID string `json:"id"`
Type string `json:"type"`
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ require (
golang.zx2c4.com/wireguard/windows v0.5.3 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20220915135415-7fd63a7952de // indirect
google.golang.org/grpc v1.50.1 // indirect
google.golang.org/grpc v1.50.1
gopkg.in/square/go-jose.v2 v2.6.0
gopkg.in/yaml.v2 v2.4.0 // indirect
howett.net/plist v1.0.0 // indirect
Expand Down