failed: otelcol config schema validation in cue

failed experiment 3


failed: otelcol config schema validation in cue

failed experiment 3

cue schema validation

I wanted a json schema for the opentelemetry-collector's configuration. As far as I know, the only way config is defined is as Go types within the various components (receivers, processors, exporters, connectors, extensions).

My thought went straight to cue, thinking it could automatically extract cue schemas from go types, then maybe validate directly or generate an openapi schema.

Unfortunately, it turns out that cue get go $go_package has quite a few issues: it panics on generics, and it doesn't like unsafe, I think there was a third panic that i don't quite remember. This makes it much less useful for automatic schema extraction, even if the types I want (usually the Config structs + their fields) don't use any of generics or unsafe.

main » cue get go -i
panic: unsupported type *types.TypeParam [recovered]
	panic: unsupported type *types.TypeParam
main » cue get go
invalid identifier "unsafe.Pointer"

As for validation directly via cue, I get the feeling the output isn't quite as nice.

main » cue vet config.yaml config.cue -d '#Config'
_pipelines.logs.exporters.awss3: conflicting values false and true:

Config included below for completion

package otelcolconfig

import (

#Config: {
	receivers: {
		[=~"^webhookevent(/.+)?$"]: webhookeventreceiver.#Config
	processors?: {
		[=~"^transform(/.+)?$"]: transformprocessor.#Config
	exporters: {
		[=~"^awss3(/.+)$"]: awss3exporter.#Config
	connectors?: {}
	extensions?: {}
	// can't import service def due to
	service: close({
		telemetry?: close({
			logs?: {
				level?:              "debug" | "info" | "warn" | "error"
				development?:        bool
				disable_caller?:     bool
				disable_stacktrace?: bool
				sampling?: {
					initial?:    int
					thereafter?: int
				error_output_paths?: [...string]
				initial_fields?: [string]: string
			metrics?: {
				level:   "none" | "basic" | "normal" | "detailed"
				address: =~"^.*(:\\d)?"
				metric_readers?: [...{
					args?: _
					type?: string
			traces?: {
				propagators?: [...string]
		extensions: [...string]
		pipelines: [=~"^traces(/.*)?"]:  #Pipeline
		pipelines: [=~"^metrics(/.*)?"]: #Pipeline
		pipelines: [=~"^logs(/.*)?"]:    #Pipeline

	_extensions: {
		for e in service.extensions {
			(e): true & extensions[e] != _|_
	_pipelines: {
		for pname, pipeline in service.pipelines {
			(pname): {
				for r in pipeline.receivers {
					"receivers": (r): true & receivers[r] != _|_
				for p in pipeline.processors {
					"processors": (p): true & processors[p] != _|_
				for e in pipeline.exporters {
					"exporters": (e): true & exporters[e] != _|_
#Pipeline: {
	receivers: [...string]
	processors?: [...string]
	exporters: [...string]