Skip to content

Commit

Permalink
adding otel functionality
Browse files Browse the repository at this point in the history
Signed-off-by: Andrew Steurer <andrew.steurer@fermyon.com>
  • Loading branch information
asteurer committed Aug 16, 2024
1 parent 8627742 commit 530acc5
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 4 deletions.
15 changes: 15 additions & 0 deletions api/v1alpha1/spinappexecutor_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ type ExecutorDeploymentConfig struct {
// will be created containing the certificates. If no secret name is
// defined in `CACertSecret` the secret name will be `spin-ca`.
InstallDefaultCACerts bool `json:"installDefaultCACerts,omitempty"`

// Otel provides Kubernetes Bindings to Otel Variables.
Otel *OtelConfig `json:"otel,omitempty"`
}

// SpinAppExecutorStatus defines the observed state of SpinAppExecutor
Expand All @@ -56,6 +59,18 @@ type SpinAppExecutorStatus struct {
// Important: Run "make" to regenerate code after modifying this file
}

// OtelConfig is the supported environment variables for OpenTelemetry
type OtelConfig struct {
// ExporterOtlpEndpoint configures the default combined otlp endpoint for sending telemetry
ExporterOtlpEndpoint string `json:"exporter_otlp_endpoint,omitempty"`
// ExporterOtlpTracesEndpoint configures the trace-specific otlp endpoint
ExporterOtlpTracesEndpoint string `json:"exporter_otlp_traces_endpoint,omitempty"`
// ExporterOtlpMetricsEndpoint configures the metrics-specific otlp endpoint
ExporterOtlpMetricsEndpoint string `json:"exporter_otlp_metrics_endpoint,omitempty"`
// ExporterOtlpLogsEndpoint configures the logs-specific otlp endpoint
ExporterOtlpLogsEndpoint string `json:"exporter_otlp_logs_endpoint,omitempty"`
}

//+kubebuilder:object:root=true
//+kubebuilder:subresource:status

Expand Down
22 changes: 21 additions & 1 deletion api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions config/crd/bases/core.spinoperator.dev_spinappexecutors.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,26 @@ spec:
will be created containing the certificates. If no secret name is
defined in `CACertSecret` the secret name will be `spin-ca`.
type: boolean
otel:
description: Otel provides Kubernetes Bindings to Otel Variables.
properties:
exporter_otlp_endpoint:
description: ExporterOtlpEndpoint configures the default combined
otlp endpoint for sending telemetry
type: string
exporter_otlp_logs_endpoint:
description: ExporterOtlpLogsEndpoint configures the logs-specific
otlp endpoint
type: string
exporter_otlp_metrics_endpoint:
description: ExporterOtlpMetricsEndpoint configures the metrics-specific
otlp endpoint
type: string
exporter_otlp_traces_endpoint:
description: ExporterOtlpTracesEndpoint configures the trace-specific
otlp endpoint
type: string
type: object
runtimeClassName:
description: |-
RuntimeClassName is the runtime class name that should be used by pods created
Expand Down
20 changes: 20 additions & 0 deletions config/samples/otel.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
apiVersion: core.spinoperator.dev/v1alpha1
kind: SpinApp
metadata:
name: otel-spinapp
spec:
image: ghcr.io/spinkube/spin-operator/cpu-load-gen:20240311-163328-g1121986
executor: otel-shim-executor
replicas: 1
---
apiVersion: core.spinoperator.dev/v1alpha1
kind: SpinAppExecutor
metadata:
name: otel-shim-executor
spec:
createDeployment: true
deploymentConfig:
runtimeClassName: wasmtime-spin-v2
installDefaultCACerts: true
otel:
exporter_otlp_endpoint: http://otel-collector.default.svc.cluster.local:4318
21 changes: 20 additions & 1 deletion internal/controller/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,9 @@ func ConstructVolumeMountsForApp(ctx context.Context, app *spinv1alpha1.SpinApp,

// ConstructEnvForApp constructs the env for a spin app that runs as a k8s pod.
// Variables are not guaranteed to stay backed by ENV.
func ConstructEnvForApp(ctx context.Context, app *spinv1alpha1.SpinApp, listenPort int) []corev1.EnvVar {
func ConstructEnvForApp(ctx context.Context, app *spinv1alpha1.SpinApp, listenPort int, otel *spinv1alpha1.OtelConfig) []corev1.EnvVar {
envs := make([]corev1.EnvVar, len(app.Spec.Variables))
// Adding the Spin Variables
for idx, variable := range app.Spec.Variables {
env := corev1.EnvVar{
// Spin Variables only allow lowercase ascii characters, `_`, and numbers.
Expand All @@ -121,6 +122,24 @@ func ConstructEnvForApp(ctx context.Context, app *spinv1alpha1.SpinApp, listenPo
Name: "SPIN_HTTP_LISTEN_ADDR",
Value: fmt.Sprintf("0.0.0.0:%d", listenPort),
})
// Adding the OpenTelemetry params
if otel != nil {
if otel.ExporterOtlpEndpoint != "" {
envs = append(envs, corev1.EnvVar{Name: "OTEL_EXPORTER_OTLP_ENDPOINT", Value: otel.ExporterOtlpEndpoint})
}

if otel.ExporterOtlpTracesEndpoint != "" {
envs = append(envs, corev1.EnvVar{Name: "OTEL_EXPORTER_OTLP_TRACES_ENDPOINT", Value: otel.ExporterOtlpTracesEndpoint})
}

if otel.ExporterOtlpMetricsEndpoint != "" {
envs = append(envs, corev1.EnvVar{Name: "OTEL_EXPORTER_OTLP_METRICS_ENDPOINT", Value: otel.ExporterOtlpMetricsEndpoint})
}

if otel.ExporterOtlpLogsEndpoint != "" {
envs = append(envs, corev1.EnvVar{Name: "OTEL_EXPORTER_OTLP_LOGS_ENDPOINT", Value: otel.ExporterOtlpLogsEndpoint})
}
}

return envs
}
Expand Down
37 changes: 36 additions & 1 deletion internal/controller/deployment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ func TestConstructEnvForApp(t *testing.T) {

value string
valueFrom *corev1.EnvVarSource

expectedOtelVars map[string]string
otelVars spinv1alpha1.OtelConfig
}{
{
name: "simple_secret_with_static_value",
Expand Down Expand Up @@ -129,6 +132,21 @@ func TestConstructEnvForApp(t *testing.T) {
},
},
},
{
name: "otel_vars_are_properly_set",
otelVars: spinv1alpha1.OtelConfig{
ExporterOtlpEndpoint: "http://otlp",
ExporterOtlpTracesEndpoint: "http://traces",
ExporterOtlpMetricsEndpoint: "http://metrics",
ExporterOtlpLogsEndpoint: "http://logs",
},
expectedOtelVars: map[string]string{
"OTEL_EXPORTER_OTLP_ENDPOINT": "http://otlp",
"OTEL_EXPORTER_OTLP_TRACES_ENDPOINT": "http://traces",
"OTEL_EXPORTER_OTLP_METRICS_ENDPOINT": "http://metrics",
"OTEL_EXPORTER_OTLP_LOGS_ENDPOINT": "http://logs",
},
},
}

for _, test := range tests {
Expand All @@ -142,11 +160,28 @@ func TestConstructEnvForApp(t *testing.T) {
},
}

envs := ConstructEnvForApp(context.Background(), app, 0)
envs := ConstructEnvForApp(context.Background(), app, 0, &test.otelVars)

require.Equal(t, test.expectedEnvName, envs[0].Name)
require.Equal(t, test.value, envs[0].Value)
require.Equal(t, test.valueFrom, envs[0].ValueFrom)

for key, value := range test.expectedOtelVars {
varNotFound := true
for _, envVar := range envs {
if envVar.Name == key {
varNotFound = false
if envVar.Value != value {
require.Equal(t, test.value, envVar.Value)
break
}
}
}

if varNotFound {
require.NotContains(t, test.expectedOtelVars, key)
}
}
})
}
}
Expand Down
2 changes: 1 addition & 1 deletion internal/controller/spinapp_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ func constructDeployment(ctx context.Context, app *spinv1alpha1.SpinApp, config
Requests: app.Spec.Resources.Requests,
}

env := ConstructEnvForApp(ctx, app, spinapp.DefaultHTTPPort)
env := ConstructEnvForApp(ctx, app, spinapp.DefaultHTTPPort, config.Otel)

readinessProbe, livenessProbe, err := ConstructPodHealthChecks(app)
if err != nil {
Expand Down

0 comments on commit 530acc5

Please sign in to comment.