Skip to content

Commit dcedfee

Browse files
committed
add support for propagating telemetry in configmap
1 parent fc1aedf commit dcedfee

File tree

2 files changed

+194
-0
lines changed

2 files changed

+194
-0
lines changed

cmd/thv-operator/controllers/mcpserver_runconfig.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"fmt"
99
"os"
1010
"sort"
11+
"strconv"
1112
"strings"
1213

1314
corev1 "k8s.io/api/core/v1"
@@ -289,6 +290,9 @@ func (r *MCPServerReconciler) createRunConfigFromMCPServer(m *mcpv1alpha1.MCPSer
289290
}
290291
}
291292

293+
// Add telemetry configuration if specified
294+
addTelemetryConfigOptions(&options, m.Spec.Telemetry, m.Name)
295+
292296
// Use the RunConfigBuilder for operator context with full builder pattern
293297
return runner.NewOperatorRunConfigBuilder(
294298
context.Background(),
@@ -534,3 +538,75 @@ func convertSecretsFromMCPServer(secs []mcpv1alpha1.SecretRef) []string {
534538
}
535539
return secrets
536540
}
541+
542+
// addTelemetryConfigOptions adds telemetry configuration options to the builder options
543+
func addTelemetryConfigOptions(
544+
options *[]runner.RunConfigBuilderOption,
545+
telemetryConfig *mcpv1alpha1.TelemetryConfig,
546+
mcpServerName string,
547+
) {
548+
if telemetryConfig == nil {
549+
return
550+
}
551+
552+
// Default values
553+
var otelEndpoint string
554+
var otelEnablePrometheusMetricsPath bool
555+
var otelTracingEnabled bool
556+
var otelMetricsEnabled bool
557+
var otelServiceName string
558+
var otelSamplingRate = 0.05 // Default sampling rate
559+
var otelHeaders []string
560+
var otelInsecure bool
561+
var otelEnvironmentVariables []string
562+
563+
// Process OpenTelemetry configuration
564+
if telemetryConfig.OpenTelemetry != nil && telemetryConfig.OpenTelemetry.Enabled {
565+
otel := telemetryConfig.OpenTelemetry
566+
567+
otelEndpoint = otel.Endpoint
568+
otelInsecure = otel.Insecure
569+
otelHeaders = otel.Headers
570+
571+
// Use MCPServer name as service name if not specified
572+
if otel.ServiceName != "" {
573+
otelServiceName = otel.ServiceName
574+
} else {
575+
otelServiceName = mcpServerName
576+
}
577+
578+
// Handle tracing configuration
579+
if otel.Tracing != nil {
580+
otelTracingEnabled = otel.Tracing.Enabled
581+
if otel.Tracing.SamplingRate != "" {
582+
// Parse sampling rate string to float64
583+
if rate, err := strconv.ParseFloat(otel.Tracing.SamplingRate, 64); err == nil {
584+
otelSamplingRate = rate
585+
}
586+
}
587+
}
588+
589+
// Handle metrics configuration
590+
if otel.Metrics != nil {
591+
otelMetricsEnabled = otel.Metrics.Enabled
592+
}
593+
}
594+
595+
// Process Prometheus configuration
596+
if telemetryConfig.Prometheus != nil {
597+
otelEnablePrometheusMetricsPath = telemetryConfig.Prometheus.Enabled
598+
}
599+
600+
// Add telemetry config to options
601+
*options = append(*options, runner.WithTelemetryConfig(
602+
otelEndpoint,
603+
otelEnablePrometheusMetricsPath,
604+
otelTracingEnabled,
605+
otelMetricsEnabled,
606+
otelServiceName,
607+
otelSamplingRate,
608+
otelHeaders,
609+
otelInsecure,
610+
otelEnvironmentVariables,
611+
))
612+
}

cmd/thv-operator/controllers/mcpserver_runconfig_test.go

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,124 @@ func TestCreateRunConfigFromMCPServer(t *testing.T) {
282282
assert.Len(t, config.Secrets, 0)
283283
},
284284
},
285+
{
286+
name: "with telemetry configuration",
287+
mcpServer: &mcpv1alpha1.MCPServer{
288+
ObjectMeta: metav1.ObjectMeta{
289+
Name: "telemetry-server",
290+
Namespace: "test-ns",
291+
},
292+
Spec: mcpv1alpha1.MCPServerSpec{
293+
Image: testImage,
294+
Transport: stdioTransport,
295+
Port: 8080,
296+
Telemetry: &mcpv1alpha1.TelemetryConfig{
297+
OpenTelemetry: &mcpv1alpha1.OpenTelemetryConfig{
298+
Enabled: true,
299+
Endpoint: "http://otel-collector:4317",
300+
ServiceName: "custom-service-name",
301+
Insecure: true,
302+
Headers: []string{"Authorization=Bearer token123", "X-API-Key=abc"},
303+
Tracing: &mcpv1alpha1.OpenTelemetryTracingConfig{
304+
Enabled: true,
305+
SamplingRate: "0.25",
306+
},
307+
Metrics: &mcpv1alpha1.OpenTelemetryMetricsConfig{
308+
Enabled: true,
309+
},
310+
},
311+
Prometheus: &mcpv1alpha1.PrometheusConfig{
312+
Enabled: true,
313+
},
314+
},
315+
},
316+
},
317+
//nolint:thelper // We want to see the error at the specific line
318+
expected: func(t *testing.T, config *runner.RunConfig) {
319+
assert.Equal(t, "telemetry-server", config.Name)
320+
321+
// Verify telemetry config is set
322+
assert.NotNil(t, config.TelemetryConfig)
323+
324+
// Check OpenTelemetry settings
325+
assert.Equal(t, "http://otel-collector:4317", config.TelemetryConfig.Endpoint)
326+
assert.Equal(t, "custom-service-name", config.TelemetryConfig.ServiceName)
327+
assert.True(t, config.TelemetryConfig.Insecure)
328+
assert.True(t, config.TelemetryConfig.TracingEnabled)
329+
assert.True(t, config.TelemetryConfig.MetricsEnabled)
330+
assert.Equal(t, 0.25, config.TelemetryConfig.SamplingRate)
331+
assert.Equal(t, map[string]string{"Authorization": "Bearer token123", "X-API-Key": "abc"}, config.TelemetryConfig.Headers)
332+
333+
// Check Prometheus settings
334+
assert.True(t, config.TelemetryConfig.EnablePrometheusMetricsPath)
335+
},
336+
},
337+
{
338+
name: "with minimal telemetry configuration",
339+
mcpServer: &mcpv1alpha1.MCPServer{
340+
ObjectMeta: metav1.ObjectMeta{
341+
Name: "minimal-telemetry-server",
342+
Namespace: "test-ns",
343+
},
344+
Spec: mcpv1alpha1.MCPServerSpec{
345+
Image: testImage,
346+
Transport: stdioTransport,
347+
Port: 8080,
348+
Telemetry: &mcpv1alpha1.TelemetryConfig{
349+
OpenTelemetry: &mcpv1alpha1.OpenTelemetryConfig{
350+
Enabled: true,
351+
Endpoint: "https://secure-otel:4318",
352+
// ServiceName not specified - should default to MCPServer name
353+
},
354+
},
355+
},
356+
},
357+
//nolint:thelper // We want to see the error at the specific line
358+
expected: func(t *testing.T, config *runner.RunConfig) {
359+
assert.Equal(t, "minimal-telemetry-server", config.Name)
360+
361+
// Verify telemetry config is set
362+
assert.NotNil(t, config.TelemetryConfig)
363+
364+
// Check that service name defaults to MCPServer name
365+
assert.Equal(t, "minimal-telemetry-server", config.TelemetryConfig.ServiceName)
366+
assert.Equal(t, "https://secure-otel:4318", config.TelemetryConfig.Endpoint)
367+
assert.False(t, config.TelemetryConfig.Insecure) // Default should be false
368+
assert.Equal(t, 0.05, config.TelemetryConfig.SamplingRate) // Default sampling rate
369+
},
370+
},
371+
{
372+
name: "with prometheus only telemetry",
373+
mcpServer: &mcpv1alpha1.MCPServer{
374+
ObjectMeta: metav1.ObjectMeta{
375+
Name: "prometheus-only-server",
376+
Namespace: "test-ns",
377+
},
378+
Spec: mcpv1alpha1.MCPServerSpec{
379+
Image: testImage,
380+
Transport: stdioTransport,
381+
Port: 8080,
382+
Telemetry: &mcpv1alpha1.TelemetryConfig{
383+
Prometheus: &mcpv1alpha1.PrometheusConfig{
384+
Enabled: true,
385+
},
386+
},
387+
},
388+
},
389+
//nolint:thelper // We want to see the error at the specific line
390+
expected: func(t *testing.T, config *runner.RunConfig) {
391+
assert.Equal(t, "prometheus-only-server", config.Name)
392+
393+
// Verify telemetry config is set
394+
assert.NotNil(t, config.TelemetryConfig)
395+
396+
// Only Prometheus should be enabled
397+
assert.True(t, config.TelemetryConfig.EnablePrometheusMetricsPath)
398+
assert.False(t, config.TelemetryConfig.TracingEnabled)
399+
assert.False(t, config.TelemetryConfig.MetricsEnabled)
400+
assert.Equal(t, "", config.TelemetryConfig.Endpoint)
401+
},
402+
},
285403
}
286404

287405
for _, tt := range tests {

0 commit comments

Comments
 (0)