Skip to content

Commit 64eb12e

Browse files
authored
Vmcp: Migrate telemetry config (#3207)
Summary Stacked on #3205 Supports #3125 This PR migrates the telemetry config to use the app config's telemetry config. Changes Delete the legacy telemetry config field on the spec. Preserve the existing application of defaults and normalization of config by converting back into the legacy type. This code is more involved to refactor, so I'm leaving it in place until the refactor is complete. Update docs and examples. --------- Signed-off-by: Jeremy Drouillard <jeremy@stacklok.com>
1 parent 8e8af3b commit 64eb12e

12 files changed

Lines changed: 114 additions & 227 deletions

File tree

cmd/thv-operator/api/v1alpha1/virtualmcpserver_types.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,6 @@ type VirtualMCPServerSpec struct {
6060
// +kubebuilder:validation:Type=object
6161
PodTemplateSpec *runtime.RawExtension `json:"podTemplateSpec,omitempty"`
6262

63-
// Telemetry configures OpenTelemetry-based observability for the Virtual MCP server
64-
// including distributed tracing, OTLP metrics export, and Prometheus metrics endpoint
65-
// TODO(jerm-dro): migrate to the Config field.
66-
// +optional
67-
Telemetry *TelemetryConfig `json:"telemetry,omitempty"`
68-
6963
// Audit configures audit logging for the Virtual MCP server
7064
// When enabled, audit logs include MCP protocol operations
7165
// TODO(jerm-dro): migrate to the Config field.

cmd/thv-operator/api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 0 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cmd/thv-operator/pkg/vmcpconfig/converter.go

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"github.com/stacklok/toolhive/cmd/thv-operator/pkg/oidc"
2020
"github.com/stacklok/toolhive/cmd/thv-operator/pkg/spectoconfig"
2121
thvjson "github.com/stacklok/toolhive/pkg/json"
22+
"github.com/stacklok/toolhive/pkg/telemetry"
2223
"github.com/stacklok/toolhive/pkg/vmcp/auth/converters"
2324
authtypes "github.com/stacklok/toolhive/pkg/vmcp/auth/types"
2425
vmcpconfig "github.com/stacklok/toolhive/pkg/vmcp/config"
@@ -124,7 +125,11 @@ func (c *Converter) Convert(
124125
config.Operational = c.convertOperational(ctx, vmcp)
125126
}
126127

127-
config.Telemetry = spectoconfig.ConvertTelemetryConfig(ctx, vmcp.Spec.Telemetry, vmcp.Name)
128+
config.Telemetry = spectoconfig.ConvertTelemetryConfig(
129+
ctx,
130+
telemetryConfigFromEmbedded(vmcp.Spec.Config.Telemetry),
131+
vmcp.Name,
132+
)
128133
config.Audit = spectoconfig.ConvertAuditConfig(ctx, vmcp.Spec.Audit, vmcp.Name)
129134

130135
// Apply operational defaults (fills missing values)
@@ -910,3 +915,61 @@ func (*Converter) convertOperational(
910915

911916
return operational
912917
}
918+
919+
// telemetryConfigFromEmbedded constructs a v1alpha1.TelemetryConfig from the embedded telemetry.Config.
920+
// This allows reusing ConvertTelemetryConfig which applies all the normalization and defaults.
921+
func telemetryConfigFromEmbedded(cfg *telemetry.Config) *mcpv1alpha1.TelemetryConfig {
922+
if cfg == nil {
923+
return nil
924+
}
925+
926+
// Check if telemetry is actually configured
927+
if cfg.Endpoint == "" && !cfg.EnablePrometheusMetricsPath {
928+
return nil
929+
}
930+
931+
telemetryCfg := &mcpv1alpha1.TelemetryConfig{}
932+
933+
// Build OpenTelemetry config if endpoint is configured
934+
if cfg.Endpoint != "" || cfg.TracingEnabled || cfg.MetricsEnabled {
935+
telemetryCfg.OpenTelemetry = &mcpv1alpha1.OpenTelemetryConfig{
936+
Enabled: cfg.Endpoint != "" || cfg.TracingEnabled || cfg.MetricsEnabled,
937+
Endpoint: cfg.Endpoint,
938+
ServiceName: cfg.ServiceName,
939+
Insecure: cfg.Insecure,
940+
}
941+
942+
// Build tracing config
943+
if cfg.TracingEnabled || cfg.SamplingRate != "" {
944+
telemetryCfg.OpenTelemetry.Tracing = &mcpv1alpha1.OpenTelemetryTracingConfig{
945+
Enabled: cfg.TracingEnabled,
946+
SamplingRate: cfg.SamplingRate,
947+
}
948+
}
949+
950+
// Build metrics config
951+
if cfg.MetricsEnabled {
952+
telemetryCfg.OpenTelemetry.Metrics = &mcpv1alpha1.OpenTelemetryMetricsConfig{
953+
Enabled: cfg.MetricsEnabled,
954+
}
955+
}
956+
957+
// Convert headers from map to slice
958+
if len(cfg.Headers) > 0 {
959+
headers := make([]string, 0, len(cfg.Headers))
960+
for k, v := range cfg.Headers {
961+
headers = append(headers, k+"="+v)
962+
}
963+
telemetryCfg.OpenTelemetry.Headers = headers
964+
}
965+
}
966+
967+
// Build Prometheus config
968+
if cfg.EnablePrometheusMetricsPath {
969+
telemetryCfg.Prometheus = &mcpv1alpha1.PrometheusConfig{
970+
Enabled: cfg.EnablePrometheusMetricsPath,
971+
}
972+
}
973+
974+
return telemetryCfg
975+
}

deploy/charts/operator-crds/Chart.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ apiVersion: v2
22
name: toolhive-operator-crds
33
description: A Helm chart for installing the ToolHive Operator CRDs into Kubernetes.
44
type: application
5-
version: 0.0.91
5+
version: 0.0.92
66
appVersion: "0.0.1"

deploy/charts/operator-crds/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# ToolHive Operator CRDs Helm Chart
22

3-
![Version: 0.0.91](https://img.shields.io/badge/Version-0.0.91-informational?style=flat-square)
3+
![Version: 0.0.92](https://img.shields.io/badge/Version-0.0.92-informational?style=flat-square)
44
![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square)
55

66
A Helm chart for installing the ToolHive Operator CRDs into Kubernetes.

deploy/charts/operator-crds/files/crds/toolhive.stacklok.dev_virtualmcpservers.yaml

Lines changed: 3 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1026,7 +1026,9 @@ spec:
10261026
- source
10271027
type: object
10281028
telemetry:
1029-
description: Telemetry configures telemetry settings.
1029+
description: |-
1030+
Telemetry configures OpenTelemetry-based observability for the Virtual MCP server
1031+
including distributed tracing, OTLP metrics export, and Prometheus metrics endpoint.
10301032
properties:
10311033
customAttributes:
10321034
additionalProperties:
@@ -1090,16 +1092,9 @@ spec:
10901092
When false, no tracer provider is created even if an endpoint is configured
10911093
type: boolean
10921094
required:
1093-
- enablePrometheusMetricsPath
10941095
- endpoint
1095-
- environmentVariables
1096-
- headers
1097-
- insecure
1098-
- metricsEnabled
1099-
- samplingRate
11001096
- serviceName
11011097
- serviceVersion
1102-
- tracingEnabled
11031098
type: object
11041099
required:
11051100
- groupRef
@@ -1487,73 +1482,6 @@ spec:
14871482
- NodePort
14881483
- LoadBalancer
14891484
type: string
1490-
telemetry:
1491-
description: |-
1492-
Telemetry configures OpenTelemetry-based observability for the Virtual MCP server
1493-
including distributed tracing, OTLP metrics export, and Prometheus metrics endpoint
1494-
properties:
1495-
openTelemetry:
1496-
description: OpenTelemetry defines OpenTelemetry configuration
1497-
properties:
1498-
enabled:
1499-
default: false
1500-
description: Enabled controls whether OpenTelemetry is enabled
1501-
type: boolean
1502-
endpoint:
1503-
description: Endpoint is the OTLP endpoint URL for tracing
1504-
and metrics
1505-
type: string
1506-
headers:
1507-
description: |-
1508-
Headers contains authentication headers for the OTLP endpoint
1509-
Specified as key=value pairs
1510-
items:
1511-
type: string
1512-
type: array
1513-
insecure:
1514-
default: false
1515-
description: Insecure indicates whether to use HTTP instead
1516-
of HTTPS for the OTLP endpoint
1517-
type: boolean
1518-
metrics:
1519-
description: Metrics defines OpenTelemetry metrics-specific
1520-
configuration
1521-
properties:
1522-
enabled:
1523-
default: false
1524-
description: Enabled controls whether OTLP metrics are
1525-
sent
1526-
type: boolean
1527-
type: object
1528-
serviceName:
1529-
description: |-
1530-
ServiceName is the service name for telemetry
1531-
If not specified, defaults to the MCPServer name
1532-
type: string
1533-
tracing:
1534-
description: Tracing defines OpenTelemetry tracing configuration
1535-
properties:
1536-
enabled:
1537-
default: false
1538-
description: Enabled controls whether OTLP tracing is
1539-
sent
1540-
type: boolean
1541-
samplingRate:
1542-
default: "0.05"
1543-
description: SamplingRate is the trace sampling rate (0.0-1.0)
1544-
type: string
1545-
type: object
1546-
type: object
1547-
prometheus:
1548-
description: Prometheus defines Prometheus-specific configuration
1549-
properties:
1550-
enabled:
1551-
default: false
1552-
description: Enabled controls whether Prometheus metrics endpoint
1553-
is exposed
1554-
type: boolean
1555-
type: object
1556-
type: object
15571485
required:
15581486
- incomingAuth
15591487
type: object

deploy/charts/operator-crds/templates/toolhive.stacklok.dev_virtualmcpservers.yaml

Lines changed: 3 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,7 +1029,9 @@ spec:
10291029
- source
10301030
type: object
10311031
telemetry:
1032-
description: Telemetry configures telemetry settings.
1032+
description: |-
1033+
Telemetry configures OpenTelemetry-based observability for the Virtual MCP server
1034+
including distributed tracing, OTLP metrics export, and Prometheus metrics endpoint.
10331035
properties:
10341036
customAttributes:
10351037
additionalProperties:
@@ -1093,16 +1095,9 @@ spec:
10931095
When false, no tracer provider is created even if an endpoint is configured
10941096
type: boolean
10951097
required:
1096-
- enablePrometheusMetricsPath
10971098
- endpoint
1098-
- environmentVariables
1099-
- headers
1100-
- insecure
1101-
- metricsEnabled
1102-
- samplingRate
11031099
- serviceName
11041100
- serviceVersion
1105-
- tracingEnabled
11061101
type: object
11071102
required:
11081103
- groupRef
@@ -1490,73 +1485,6 @@ spec:
14901485
- NodePort
14911486
- LoadBalancer
14921487
type: string
1493-
telemetry:
1494-
description: |-
1495-
Telemetry configures OpenTelemetry-based observability for the Virtual MCP server
1496-
including distributed tracing, OTLP metrics export, and Prometheus metrics endpoint
1497-
properties:
1498-
openTelemetry:
1499-
description: OpenTelemetry defines OpenTelemetry configuration
1500-
properties:
1501-
enabled:
1502-
default: false
1503-
description: Enabled controls whether OpenTelemetry is enabled
1504-
type: boolean
1505-
endpoint:
1506-
description: Endpoint is the OTLP endpoint URL for tracing
1507-
and metrics
1508-
type: string
1509-
headers:
1510-
description: |-
1511-
Headers contains authentication headers for the OTLP endpoint
1512-
Specified as key=value pairs
1513-
items:
1514-
type: string
1515-
type: array
1516-
insecure:
1517-
default: false
1518-
description: Insecure indicates whether to use HTTP instead
1519-
of HTTPS for the OTLP endpoint
1520-
type: boolean
1521-
metrics:
1522-
description: Metrics defines OpenTelemetry metrics-specific
1523-
configuration
1524-
properties:
1525-
enabled:
1526-
default: false
1527-
description: Enabled controls whether OTLP metrics are
1528-
sent
1529-
type: boolean
1530-
type: object
1531-
serviceName:
1532-
description: |-
1533-
ServiceName is the service name for telemetry
1534-
If not specified, defaults to the MCPServer name
1535-
type: string
1536-
tracing:
1537-
description: Tracing defines OpenTelemetry tracing configuration
1538-
properties:
1539-
enabled:
1540-
default: false
1541-
description: Enabled controls whether OTLP tracing is
1542-
sent
1543-
type: boolean
1544-
samplingRate:
1545-
default: "0.05"
1546-
description: SamplingRate is the trace sampling rate (0.0-1.0)
1547-
type: string
1548-
type: object
1549-
type: object
1550-
prometheus:
1551-
description: Prometheus defines Prometheus-specific configuration
1552-
properties:
1553-
enabled:
1554-
default: false
1555-
description: Enabled controls whether Prometheus metrics endpoint
1556-
is exposed
1557-
type: boolean
1558-
type: object
1559-
type: object
15601488
required:
15611489
- incomingAuth
15621490
type: object

docs/operator/crd-api.md

Lines changed: 0 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)