diff --git a/.github/workflows/build-check.yaml b/.github/workflows/build-check.yaml index 50b44a41..58d19036 100644 --- a/.github/workflows/build-check.yaml +++ b/.github/workflows/build-check.yaml @@ -25,8 +25,8 @@ jobs: - name: validate example run: make validate-examples - - name: meta schema - run: make all-meta-schema + - name: make all + run: make all - name: check for diff run: | @@ -38,7 +38,7 @@ jobs: then echo "No diff detected." else - echo "Diff detected - did you run 'make all-meta-schema'?" + echo "Diff detected - did you run 'make all'?" echo $(git diff --cached --name-only) echo $(git diff --cached) exit 1 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 65d2aa23..2c968c61 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -429,6 +429,48 @@ When this target adds new entries to `meta_schema_language_{langauage}.yaml`, th It's important to run `fix-language-implementations` before committing changes to the schema as uncommitted changes will cause the build to fail. The default `make` target will run `fix-language-implementations` automatically. +### Snippets + +[snippets](snippets) contains small targeted configuration files illustrating different scenarios. These are used to supplement documentation and as a library of valid configuration files which implementations can use in testing. + +Each snippet file name follows the pattern: `_.yaml`: + +* ``: Refers to the name of a JSON schema type as referenced in [types](https://github.com/open-telemetry/opentelemetry-configuration/blob/main/schema-docs.md#types-). +* ``: A short description of what the snippet demonstrates, in lower snake case. +* File content must validate against the top level `OpenTelemetryConfiguration` type. +* File content must contain `# SNIPPET_START`, which marks the start of the relevant portion of the snippet. The content which follows is validated against the `` type in the file name. NOTE: The same number of whitespace characters proceeding `# SNIPPET_START` are stripped from later lines before validation. + +For example, the content for snippet file `OtlpHttpMetricExporter_use_base2_exponential_histogram` looks like: + +```shell +file_format: "1.0-rc.2" + +meter_provider: + readers: + - periodic: + exporter: + otlp_http: + # SNIPPET_START + endpoint: http://localhost:4317 + default_histogram_aggregation: base2_exponential_bucket_histogram +``` + +Notes: + +* The snippet has `` of `OtlpHttpMetricExporter` and `` of `use_base2_exponential_histogram`, or "use base2 exponential histogram" in plain english. +* The portion after `# SNIPPET_START` is validated against the `OtlpHttpMetricExporter` type: + +```yaml +endpoint: http://localhost:4317 +default_histogram_aggregation: base2_exponential_bucket_histogram +``` + +To validate all snippets: + +```shell +make validate-snippets +``` + ### Documentation generation [schema-docs.md](schema-docs.md) contains generated markdown summarizing a variety of useful information about the JSON schema and [language implementation status](#language-implementation-status-tracking) in an easy to consume format. diff --git a/Makefile b/Makefile index 40067190..6cdfff4f 100644 --- a/Makefile +++ b/Makefile @@ -2,10 +2,11 @@ # SPDX-License-Identifier: Apache-2.0 EXAMPLE_FILES := $(shell find . -path './examples/*.yaml' -exec basename {} \; | sort) +SNIPPET_FILES := $(shell find . -path './snippets/*.yaml' -exec basename {} \; | sort) $(shell mkdir -p out) .PHONY: all -all: install-tools compile-schema validate-examples all-meta-schema +all: install-tools validate-examples fix-language-implementations generate-markdown include validator/Makefile @@ -17,7 +18,7 @@ compile-schema: npx --no ajv-cli compile --spec=draft2020 --allow-matching-properties -s ./opentelemetry_configuration.json; .PHONY: validate-examples -validate-examples: +validate-examples: compile-schema @if ! npm ls ajv-cli; then npm install; fi @for f in $(EXAMPLE_FILES); do \ npx envsub ./examples/$$f ./out/$$f || exit 1; \ @@ -25,24 +26,28 @@ validate-examples: || exit 1; \ done +.PHONY: validate-snippets +validate-snippets: compile-schema + npm run-script validate-snippets || exit 1; \ + .PHONY: update-file-format update-file-format: - @echo "Updating \"file_format:\" in ./examples/* to: $(FILE_FORMAT)" + @echo "Updating \"file_format:\" in ./examples/* and ./snippets/* to: $(FILE_FORMAT)" @for f in $(EXAMPLE_FILES); do \ sed -e 's/file_format:.*/file_format: \"$(FILE_FORMAT)\"/g' -i '' ./examples/$$f; \ done + @for f in $(SNIPPET_FILES); do \ + sed -e 's/file_format:.*/file_format: \"$(FILE_FORMAT)\"/g' -i '' ./snippets/$$f; \ + done .PHONY: fix-language-implementations fix-language-implementations: compile-schema npm run-script fix-language-implementations || exit 1; \ .PHONY: generate-markdown -generate-markdown: +generate-markdown: validate-snippets npm run-script generate-markdown || exit 1; \ -.PHONY: all-meta-schema -all-meta-schema: fix-language-implementations generate-markdown - .PHONY: install-tools install-tools: npm install diff --git a/README.md b/README.md index 294fbe15..75a8cba6 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ JSON schema was chosen in part because of the large [ecosystem of tools](https:/ * [schema-docs.md](schema-docs.md): generated documentation for the schema and language implementation status, optimized for human consumption * [/schema](schema): the source schema and language implementation status tracking files (see [CONTRIBUTING.md](CONTRIBUTING.md#json-schema-source-and-output) for more details) * [/examples](examples): sample configuration files (see [starter templates](#starter-templates) for more details) +* [/snippets](snippets): small targeted configuration files illustrating specific scenarios (see [snippets](CONTRIBUTING.md#snippets) for more details) * [/validator](validator): a tool which performs env var substitution on YAML, validates YAML against the schema, and outputs to JSON or YAML ## Starter templates diff --git a/RELEASING.md b/RELEASING.md index deaf56a6..b4cebe7c 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -28,7 +28,7 @@ unchanged and increment the `patch`. ## Update `file_format` {#update-file-format} -Update the `file_format: ".` of [./examples](./examples) as follows: +Update the `file_format: ".` of [./examples](./examples) and [./snippets](./snippets) as follows: ```shell # Set FILE_FORMAT env var to target version of the release diff --git a/package.json b/package.json index a6e56e8c..e6736bc0 100644 --- a/package.json +++ b/package.json @@ -3,12 +3,14 @@ "scripts": { "compile-schema": "node scripts/compile-schema.js", "generate-markdown": "node scripts/generate-markdown.js", + "validate-snippets": "node scripts/validate-snippets.js", "fix-language-implementations": "node scripts/fix-language-implementations.js" }, "devDependencies": { "ajv-cli": "5.0.0" }, "dependencies": { + "ajv": "^8.17.1", "envsub": "^4.1.0", "yaml": "^2.4.5" } diff --git a/schema-docs.md b/schema-docs.md index 2e16802a..dba3d081 100644 --- a/schema-docs.md +++ b/schema-docs.md @@ -46,6 +46,8 @@ Usages: * [`ViewStream.aggregation`](#viewstream) +No snippets. +
JSON Schema @@ -90,6 +92,8 @@ Usages: * [`Sampler.always_off`](#sampler) +No snippets. +
JSON Schema @@ -115,6 +119,8 @@ Usages: * [`Sampler.always_on`](#sampler) +No snippets. +
JSON Schema @@ -152,6 +158,8 @@ Usages: * [`OpenTelemetryConfiguration.attribute_limits`](#opentelemetryconfiguration) +No snippets. +
JSON Schema @@ -205,6 +213,8 @@ Usages: * [`Resource.attributes`](#resource) +No snippets. +
JSON Schema @@ -300,6 +310,8 @@ Usages: * [`AttributeNameValue.type`](#attributenamevalue) +No snippets. +
JSON Schema @@ -334,6 +346,8 @@ Usages: * [`TextMapPropagator.b3multi`](#textmappropagator) +No snippets. +
JSON Schema @@ -359,6 +373,8 @@ Usages: * [`TextMapPropagator.b3`](#textmappropagator) +No snippets. +
JSON Schema @@ -384,6 +400,8 @@ Usages: * [`TextMapPropagator.baggage`](#textmappropagator) +No snippets. +
JSON Schema @@ -423,6 +441,8 @@ Usages: * [`Aggregation.base2_exponential_bucket_histogram`](#aggregation) +No snippets. +
JSON Schema @@ -490,6 +510,8 @@ Usages: * [`LogRecordProcessor.batch`](#logrecordprocessor) +No snippets. +
JSON Schema @@ -567,6 +589,8 @@ Usages: * [`SpanProcessor.batch`](#spanprocessor) +No snippets. +
JSON Schema @@ -650,6 +674,8 @@ Usages: * [`PeriodicMetricReader.cardinality_limits`](#periodicmetricreader) * [`PullMetricReader.cardinality_limits`](#pullmetricreader) +No snippets. +
JSON Schema @@ -731,6 +757,8 @@ Usages: * [`LogRecordExporter.console`](#logrecordexporter) * [`SpanExporter.console`](#spanexporter) +No snippets. +
JSON Schema @@ -768,6 +796,8 @@ Usages: * [`PushMetricExporter.console`](#pushmetricexporter) +No snippets. +
JSON Schema @@ -801,6 +831,8 @@ Usages: * [`Aggregation.default`](#aggregation) +No snippets. +
JSON Schema @@ -827,6 +859,8 @@ Usages: * [`OpenTelemetryConfiguration.distribution`](#opentelemetryconfiguration) +No snippets. +
JSON Schema @@ -852,6 +886,8 @@ Usages: * [`Aggregation.drop`](#aggregation) +No snippets. +
JSON Schema @@ -891,6 +927,8 @@ Usages: * [`MeterProvider.exemplar_filter`](#meterprovider) +No snippets. +
JSON Schema @@ -932,6 +970,8 @@ Usages: * [`Aggregation.explicit_bucket_histogram`](#aggregation) +No snippets. +
JSON Schema @@ -987,6 +1027,8 @@ Usages: * [`ExperimentalOtlpFileMetricExporter.default_histogram_aggregation`](#experimentalotlpfilemetricexporter) * [`ConsoleMetricExporter.default_histogram_aggregation`](#consolemetricexporter) +No snippets. +
JSON Schema @@ -1032,6 +1074,8 @@ Usages: * [`ExperimentalOtlpFileMetricExporter.temporality_preference`](#experimentalotlpfilemetricexporter) * [`ConsoleMetricExporter.temporality_preference`](#consolemetricexporter) +No snippets. +
JSON Schema @@ -1078,6 +1122,8 @@ Usages: * [`OtlpGrpcExporter.tls`](#otlpgrpcexporter) * [`OtlpGrpcMetricExporter.tls`](#otlpgrpcmetricexporter) +No snippets. +
JSON Schema @@ -1144,6 +1190,8 @@ Usages: * [`OtlpHttpExporter.tls`](#otlphttpexporter) * [`OtlpHttpMetricExporter.tls`](#otlphttpmetricexporter) +No snippets. +
JSON Schema @@ -1203,6 +1251,8 @@ Usages: * [`ViewStream.attribute_keys`](#viewstream) * [`ExperimentalResourceDetection.attributes`](#experimentalresourcedetection) +No snippets. +
JSON Schema @@ -1263,6 +1313,8 @@ Usages: * [`ViewSelector.instrument_type`](#viewselector) +No snippets. +
JSON Schema @@ -1296,6 +1348,8 @@ Usages: * [`TextMapPropagator.jaeger`](#textmappropagator) +No snippets. +
JSON Schema @@ -1321,6 +1375,8 @@ Usages: * [`Aggregation.last_value`](#aggregation) +No snippets. +
JSON Schema @@ -1361,6 +1417,8 @@ Usages: * [`OpenTelemetryConfiguration.logger_provider`](#opentelemetryconfiguration) +No snippets. +
JSON Schema @@ -1422,6 +1480,8 @@ Usages: * [`SimpleLogRecordProcessor.exporter`](#simplelogrecordprocessor) * [`BatchLogRecordProcessor.exporter`](#batchlogrecordprocessor) +No snippets. +
JSON Schema @@ -1477,6 +1537,8 @@ Usages: * [`LoggerProvider.limits`](#loggerprovider) +No snippets. +
JSON Schema @@ -1531,6 +1593,8 @@ Usages: * [`LoggerProvider.processors`](#loggerprovider) +No snippets. +
JSON Schema @@ -1585,6 +1649,8 @@ Usages: * [`OpenTelemetryConfiguration.meter_provider`](#opentelemetryconfiguration) +No snippets. +
JSON Schema @@ -1647,6 +1713,8 @@ Usages: * [`PeriodicMetricReader.producers`](#periodicmetricreader) * [`PullMetricReader.producers`](#pullmetricreader) +No snippets. +
JSON Schema @@ -1695,6 +1763,8 @@ Usages: * [`MeterProvider.readers`](#meterprovider) +No snippets. +
JSON Schema @@ -1743,6 +1813,8 @@ Usages: * [`OtlpHttpMetricExporter.headers`](#otlphttpmetricexporter) * [`OtlpGrpcMetricExporter.headers`](#otlpgrpcmetricexporter) +No snippets. +
JSON Schema @@ -1780,6 +1852,8 @@ Usages: * [`MetricProducer.opencensus`](#metricproducer) +No snippets. +
JSON Schema @@ -1834,6 +1908,8 @@ Constraints: No usages. +No snippets. +
JSON Schema @@ -1900,6 +1976,8 @@ Usages: * [`TextMapPropagator.ottrace`](#textmappropagator) +No snippets. +
JSON Schema @@ -1946,6 +2024,8 @@ Usages: * [`LogRecordExporter.otlp_grpc`](#logrecordexporter) * [`SpanExporter.otlp_grpc`](#spanexporter) +No snippets. +
JSON Schema @@ -2032,6 +2112,8 @@ Usages: * [`PushMetricExporter.otlp_grpc`](#pushmetricexporter) +No snippets. +
JSON Schema @@ -2113,6 +2195,8 @@ Usages: * [`OtlpHttpExporter.encoding`](#otlphttpexporter) * [`OtlpHttpMetricExporter.encoding`](#otlphttpmetricexporter) +No snippets. +
JSON Schema @@ -2164,6 +2248,8 @@ Usages: * [`LogRecordExporter.otlp_http`](#logrecordexporter) * [`SpanExporter.otlp_http`](#spanexporter) +No snippets. +
JSON Schema @@ -2255,6 +2341,18 @@ Usages: * [`PushMetricExporter.otlp_http`](#pushmetricexporter) +Snippets: + +
+Use Base2 Exponential Histogram + +[Snippet Source File](./snippets/OtlpHttpMetricExporter_use_base2_exponential_histogram.yaml) +```yaml +endpoint: http://localhost:4317 +default_histogram_aggregation: base2_exponential_bucket_histogram +``` +
+
JSON Schema @@ -2344,6 +2442,8 @@ Usages: * [`Sampler.parent_based`](#sampler) +No snippets. +
JSON Schema @@ -2405,6 +2505,8 @@ Usages: * [`MetricReader.periodic`](#metricreader) +No snippets. +
JSON Schema @@ -2471,6 +2573,8 @@ Usages: * [`OpenTelemetryConfiguration.propagator`](#opentelemetryconfiguration) +No snippets. +
JSON Schema @@ -2522,6 +2626,8 @@ Usages: * [`PullMetricReader.exporter`](#pullmetricreader) +No snippets. +
JSON Schema @@ -2571,6 +2677,8 @@ Usages: * [`MetricReader.pull`](#metricreader) +No snippets. +
JSON Schema @@ -2631,6 +2739,8 @@ Usages: * [`PeriodicMetricReader.exporter`](#periodicmetricreader) +No snippets. +
JSON Schema @@ -2690,6 +2800,8 @@ Usages: * [`OpenTelemetryConfiguration.resource`](#opentelemetryconfiguration) +No snippets. +
JSON Schema @@ -2768,6 +2880,29 @@ Usages: * [`ParentBasedSampler.local_parent_sampled`](#parentbasedsampler) * [`ParentBasedSampler.local_parent_not_sampled`](#parentbasedsampler) +Snippets: + +
+Parent Based Typical + +[Snippet Source File](./snippets/Sampler_parent_based_typical.yaml) +```yaml +# configure the parent based sampler to sample 1% of root spans, and follow the sampling decision of parent spans +parent_based: + root: + trace_id_ratio_based: + ratio: 0.01 + remote_parent_sampled: + always_on: + remote_parent_not_sampled: + always_off: + local_parent_sampled: + always_on: + local_parent_not_sampled: + always_off: +``` +
+
JSON Schema @@ -2877,6 +3012,8 @@ Usages: * [`ExperimentalLoggerConfig.minimum_severity`](#experimentalloggerconfig) * [`OpenTelemetryConfiguration.log_level`](#opentelemetryconfiguration) +No snippets. +
JSON Schema @@ -2938,6 +3075,8 @@ Usages: * [`LogRecordProcessor.simple`](#logrecordprocessor) +No snippets. +
JSON Schema @@ -2979,6 +3118,8 @@ Usages: * [`SpanProcessor.simple`](#spanprocessor) +No snippets. +
JSON Schema @@ -3030,6 +3171,8 @@ Usages: * [`BatchSpanProcessor.exporter`](#batchspanprocessor) * [`SimpleSpanProcessor.exporter`](#simplespanprocessor) +No snippets. +
JSON Schema @@ -3091,6 +3234,8 @@ Usages: * [`ExperimentalComposableRuleBasedSamplerRule.span_kinds`](#experimentalcomposablerulebasedsamplerrule) +No snippets. +
JSON Schema @@ -3142,6 +3287,8 @@ Usages: * [`TracerProvider.limits`](#tracerprovider) +No snippets. +
JSON Schema @@ -3224,6 +3371,8 @@ Usages: * [`TracerProvider.processors`](#tracerprovider) +No snippets. +
JSON Schema @@ -3261,6 +3410,8 @@ Usages: * [`Aggregation.sum`](#aggregation) +No snippets. +
JSON Schema @@ -3310,6 +3461,8 @@ Usages: * [`Propagator.composite`](#propagator) +No snippets. +
JSON Schema @@ -3359,6 +3512,8 @@ Usages: * [`TextMapPropagator.tracecontext`](#textmappropagator) +No snippets. +
JSON Schema @@ -3394,6 +3549,8 @@ Usages: * [`Sampler.trace_id_ratio_based`](#sampler) +No snippets. +
JSON Schema @@ -3446,6 +3603,8 @@ Usages: * [`OpenTelemetryConfiguration.tracer_provider`](#opentelemetryconfiguration) +No snippets. +
JSON Schema @@ -3502,6 +3661,23 @@ Usages: * [`MeterProvider.views`](#meterprovider) +Snippets: + +
+Override Default Histogram Buckets + +[Snippet Source File](./snippets/View_override_default_histogram_buckets.yaml) +```yaml +selector: + instrument_name: my.instrument.name + instrument_type: histogram +stream: + aggregation: + explicit_bucket_histogram: + boundaries: [0, 5, 10] +``` +
+
JSON Schema @@ -3556,6 +3732,8 @@ Usages: * [`View.selector`](#view) +No snippets. +
JSON Schema @@ -3631,6 +3809,8 @@ Usages: * [`View.stream`](#view) +No snippets. +
JSON Schema @@ -3685,6 +3865,8 @@ Usages: * [`ExperimentalComposableSampler.always_off`](#experimentalcomposablesampler) +No snippets. +
JSON Schema @@ -3713,6 +3895,8 @@ Usages: * [`ExperimentalComposableSampler.always_on`](#experimentalcomposablesampler) +No snippets. +
JSON Schema @@ -3752,6 +3936,8 @@ Usages: * [`ExperimentalComposableSampler.parent_threshold`](#experimentalcomposablesampler) +No snippets. +
JSON Schema @@ -3797,6 +3983,8 @@ Usages: * [`ExperimentalComposableSampler.probability`](#experimentalcomposablesampler) +No snippets. +
JSON Schema @@ -3845,6 +4033,8 @@ Usages: * [`ExperimentalComposableSampler.rule_based`](#experimentalcomposablesampler) +No snippets. +
JSON Schema @@ -3901,6 +4091,8 @@ Constraints: No usages. +No snippets. +
JSON Schema @@ -3970,6 +4162,8 @@ Usages: * [`ExperimentalComposableRuleBasedSamplerRule.attribute_patterns`](#experimentalcomposablerulebasedsamplerrule) +No snippets. +
JSON Schema @@ -4030,6 +4224,8 @@ Usages: * [`ExperimentalComposableRuleBasedSamplerRule.attribute_values`](#experimentalcomposablerulebasedsamplerrule) +No snippets. +
JSON Schema @@ -4093,6 +4289,8 @@ Usages: * [`ExperimentalComposableParentThresholdSampler.root`](#experimentalcomposableparentthresholdsampler) * [`ExperimentalComposableRuleBasedSamplerRule.sampler`](#experimentalcomposablerulebasedsamplerrule) +No snippets. +
JSON Schema @@ -4142,6 +4340,8 @@ Usages: * [`ExperimentalResourceDetector.container`](#experimentalresourcedetector) +No snippets. +
JSON Schema @@ -4182,6 +4382,8 @@ Usages: * [`ExperimentalInstrumentation.general`](#experimentalinstrumentation) +No snippets. +
JSON Schema @@ -4215,6 +4417,8 @@ Usages: * [`ExperimentalResourceDetector.host`](#experimentalresourcedetector) +No snippets. +
JSON Schema @@ -4255,6 +4459,8 @@ Usages: * [`ExperimentalHttpInstrumentation.client`](#experimentalhttpinstrumentation) +No snippets. +
JSON Schema @@ -4308,6 +4514,8 @@ Usages: * [`ExperimentalGeneralInstrumentation.http`](#experimentalgeneralinstrumentation) +No snippets. +
JSON Schema @@ -4353,6 +4561,8 @@ Usages: * [`ExperimentalHttpInstrumentation.server`](#experimentalhttpinstrumentation) +No snippets. +
JSON Schema @@ -4426,6 +4636,8 @@ Usages: * [`OpenTelemetryConfiguration.instrumentation/development`](#opentelemetryconfiguration) +No snippets. +
JSON Schema @@ -4504,6 +4716,8 @@ Usages: * [`Sampler.jaeger_remote/development`](#sampler) +No snippets. +
JSON Schema @@ -4563,6 +4777,8 @@ Usages: * [`ExperimentalInstrumentation.rust`](#experimentalinstrumentation) * [`ExperimentalInstrumentation.swift`](#experimentalinstrumentation) +No snippets. +
JSON Schema @@ -4605,6 +4821,8 @@ Usages: * [`ExperimentalLoggerConfigurator.default_config`](#experimentalloggerconfigurator) * [`ExperimentalLoggerMatcherAndConfig.config`](#experimentalloggermatcherandconfig) +No snippets. +
JSON Schema @@ -4661,6 +4879,8 @@ Usages: * [`LoggerProvider.logger_configurator/development`](#loggerprovider) +No snippets. +
JSON Schema @@ -4713,6 +4933,8 @@ Usages: * [`ExperimentalLoggerConfigurator.loggers`](#experimentalloggerconfigurator) +No snippets. +
JSON Schema @@ -4765,6 +4987,8 @@ Usages: * [`ExperimentalMeterConfigurator.default_config`](#experimentalmeterconfigurator) * [`ExperimentalMeterMatcherAndConfig.config`](#experimentalmetermatcherandconfig) +No snippets. +
JSON Schema @@ -4811,6 +5035,8 @@ Usages: * [`MeterProvider.meter_configurator/development`](#meterprovider) +No snippets. +
JSON Schema @@ -4863,6 +5089,8 @@ Usages: * [`ExperimentalMeterConfigurator.meters`](#experimentalmeterconfigurator) +No snippets. +
JSON Schema @@ -4915,6 +5143,8 @@ Usages: * [`LogRecordExporter.otlp_file/development`](#logrecordexporter) * [`SpanExporter.otlp_file/development`](#spanexporter) +No snippets. +
JSON Schema @@ -4965,6 +5195,8 @@ Usages: * [`PushMetricExporter.otlp_file/development`](#pushmetricexporter) +No snippets. +
JSON Schema @@ -5017,6 +5249,8 @@ Usages: * [`ExperimentalGeneralInstrumentation.peer`](#experimentalgeneralinstrumentation) +No snippets. +
JSON Schema @@ -5064,6 +5298,8 @@ Usages: * [`ExperimentalPeerInstrumentation.service_mapping`](#experimentalpeerinstrumentation) +No snippets. +
JSON Schema @@ -5111,6 +5347,8 @@ Usages: * [`Sampler.probability/development`](#sampler) +No snippets. +
JSON Schema @@ -5149,6 +5387,8 @@ Usages: * [`ExperimentalResourceDetector.process`](#experimentalresourcedetector) +No snippets. +
JSON Schema @@ -5197,6 +5437,8 @@ Usages: * [`PullMetricExporter.prometheus/development`](#pullmetricexporter) +No snippets. +
JSON Schema @@ -5273,6 +5515,8 @@ Usages: * [`ExperimentalPrometheusMetricExporter.translation_strategy`](#experimentalprometheusmetricexporter) +No snippets. +
JSON Schema @@ -5318,6 +5562,8 @@ Usages: * [`Resource.detection/development`](#resource) +No snippets. +
JSON Schema @@ -5375,6 +5621,8 @@ Usages: * [`ExperimentalResourceDetection.detectors`](#experimentalresourcedetection) +No snippets. +
JSON Schema @@ -5421,6 +5669,8 @@ Usages: * [`ExperimentalResourceDetector.service`](#experimentalresourcedetector) +No snippets. +
JSON Schema @@ -5463,6 +5713,8 @@ Usages: * [`ExperimentalComposableRuleBasedSamplerRule.parent`](#experimentalcomposablerulebasedsamplerrule) +No snippets. +
JSON Schema @@ -5506,6 +5758,8 @@ Usages: * [`ExperimentalTracerConfigurator.default_config`](#experimentaltracerconfigurator) * [`ExperimentalTracerMatcherAndConfig.config`](#experimentaltracermatcherandconfig) +No snippets. +
JSON Schema @@ -5552,6 +5806,8 @@ Usages: * [`TracerProvider.tracer_configurator/development`](#tracerprovider) +No snippets. +
JSON Schema @@ -5604,6 +5860,8 @@ Usages: * [`ExperimentalTracerConfigurator.tracers`](#experimentaltracerconfigurator) +No snippets. +
JSON Schema diff --git a/scripts/generate-markdown.js b/scripts/generate-markdown.js index 3369225a..053e1c19 100644 --- a/scripts/generate-markdown.js +++ b/scripts/generate-markdown.js @@ -8,6 +8,7 @@ import { schemaPath } from "./util.js"; import {readSourceTypesByType} from "./source-schema.js"; +import {readSnippets} from "./snippets.js"; const sourceTypesByType = readSourceTypesByType(); const sourceTypes = Object.values(sourceTypesByType); @@ -19,6 +20,14 @@ if (messages.length > 0) { const outputSchema = JSON.parse(fs.readFileSync(schemaPath, "utf-8")); +const snippetsByType = {}; +readSnippets().forEach(snippet => { + if (!(snippet.jsonSchemaType in snippetsByType)) { + snippetsByType[snippet.jsonSchemaType] = []; + } + snippetsByType[snippet.jsonSchemaType].push(snippet); +}); + const output = []; addHeader('Overview', 'overview', 1); @@ -187,6 +196,26 @@ function writeType(sourceSchemaType) { output.push('No usages.\n\n'); } + // Snippets + const snippetsForType = snippetsByType[type]; + if (!snippetsForType) { + output.push("No snippets.\n\n"); + } else { + output.push("Snippets:\n\n"); + snippetsForType.forEach(snippet => { + output.push(`
\n`); + output.push(`${snippet.description}\n\n`); + output.push(`[Snippet Source File](./snippets/${snippet.file})\n`) + output.push(`\`\`\`yaml\n`); + output.push(snippet.rawSnippetContent); + if (!snippet.rawSnippetContent.endsWith('\n')) { + output.push('\n'); + } + output.push(`\`\`\`\n`); + output.push('
\n\n'); + }); + } + // JSON schema collapsible section output.push(`
\n`); output.push(`JSON Schema\n\n`); diff --git a/scripts/snippets.js b/scripts/snippets.js new file mode 100644 index 00000000..9ef636ee --- /dev/null +++ b/scripts/snippets.js @@ -0,0 +1,66 @@ +import fs from "fs"; +import {snippetsDirPath} from "./util.js"; +import yaml from "yaml"; + +const snippetFileNameFormat = "_.yaml"; +const yamlFileExtension = ".yaml"; + +const snippetStart = "# SNIPPET_START"; + +export function readSnippets() { + return fs.readdirSync(snippetsDirPath) + .filter(file => file.endsWith(yamlFileExtension)) + .map(file => { + const fileParts = file.split('_'); + if (fileParts.length < 2) { + throw new Error(`Invalid snippet file name: ${file}. File names follow the form ${snippetFileNameFormat}`); + } + const jsonSchemaType = fileParts[0]; + // Strip file extension from the last entry + fileParts[fileParts.length - 1] = fileParts[fileParts.length - 1].substring(0, fileParts[fileParts.length - 1].indexOf(yamlFileExtension)); + // Build description by converting the snake_case to title case + const description = fileParts.slice(1) + .map(word => (word.charAt(0).toUpperCase() + word.slice(1))) + .join(" "); + + // Read the full snippet file, and extract the bit of interest after "# SNIPPET_START" + // 1. Find the line containing the snippet start marker + // 2. For lines that follow, remove whitespace up to the indentation of the snippet start marker + // 3. Join the lines + const rawFullContent = fs.readFileSync(snippetsDirPath + file, "utf-8"); + const lines = rawFullContent.split("\n"); + const snippetStartLineIndex = lines.findIndex(line => line.indexOf(snippetStart) !== -1); + if (snippetStartLineIndex === -1) { + throw new Error(`Snippet file ${file} does not contain ${snippetStart}`); + } + const snippetStartLine = lines[snippetStartLineIndex ]; + const snippetStartIndentation = snippetStartLine.indexOf(snippetStart); + const rawSnippetContent = lines.splice(snippetStartLineIndex + 1).map(line => line.substring(snippetStartIndentation)).join("\n"); + + const parsedFullContent = yaml.parse(rawFullContent); + const parsedSnippetContent = yaml.parse(rawSnippetContent); + return new Snippet(file, description, jsonSchemaType, rawFullContent, parsedFullContent, rawSnippetContent, parsedSnippetContent); + }); +} + +// Types + +export class Snippet { + file; + description; + jsonSchemaType; + rawFullContent; + parsedFullContent; + rawSnippetContent; + parsedSnippetContent; + + constructor(file, description, jsonSchemaType, rawContent, parsedContent, rawSnippetContent, parsedSnippetContent) { + this.file = file; + this.description = description; + this.jsonSchemaType = jsonSchemaType; + this.rawFullContent = rawContent; + this.parsedFullContent = parsedContent; + this.rawSnippetContent = rawSnippetContent; + this.parsedSnippetContent = parsedSnippetContent; + } +} diff --git a/scripts/util.js b/scripts/util.js index 6987328e..f9877c8a 100644 --- a/scripts/util.js +++ b/scripts/util.js @@ -16,4 +16,5 @@ export const metaSchemaLanguageStatusPath = (language) => schemaSourceDirPath + export const isExperimentalProperty = (property) => property.endsWith('/development'); export const isExperimentalType = (type) => type.startsWith('Experimental'); -export const rootTypeName = 'OpenTelemetryConfiguration'; \ No newline at end of file +export const snippetsDirPath = __dirname + "/../snippets/"; +export const rootTypeName = 'OpenTelemetryConfiguration'; diff --git a/scripts/validate-snippets.js b/scripts/validate-snippets.js new file mode 100644 index 00000000..75f6a5e9 --- /dev/null +++ b/scripts/validate-snippets.js @@ -0,0 +1,84 @@ +import fs from "fs"; +import {rootTypeName, schemaPath} from "./util.js"; +import Ajv from "ajv/dist/2020.js"; +import {readSnippets} from "./snippets.js"; +import {readSourceTypesByType} from "./source-schema.js"; + +// Initialize ajv +const ajv = new Ajv({ allErrors: true }); +const outputSchema = JSON.parse(fs.readFileSync(schemaPath, "utf-8")); +ajv.addSchema(outputSchema); + +const sourceTypesByType = readSourceTypesByType(); + +const rootJsonSchemaType = sourceTypesByType[rootTypeName]; +const rootJsonSchemaTypeRef = computeJsonSchemaTypeRef(rootJsonSchemaType); + +const messages = []; + +readSnippets() + .forEach(snippet => { + const rootValidator = ajv.getSchema(rootJsonSchemaTypeRef); + if (!rootValidator) { + throw new Error(`Unable to resolve root schema for JSON schema type ref: ${rootJsonSchemaTypeRef}`); + } + + const snippetJsonSchemaType = sourceTypesByType[snippet.jsonSchemaType]; + if (!snippetJsonSchemaType) { + messages.push(`Error validating snippet ${snippet.file}. Resolved JSON schema type not found: ${snippet.jsonSchemaType}`); + return; + } + const snippetTypeRef = computeJsonSchemaTypeRef(snippetJsonSchemaType); + const snippetValidator = ajv.getSchema(snippetTypeRef); + if (!snippetValidator) { + messages.push(`Error validating snippet ${snippet.file}. Unable to resolve schema for JSON schema type ref: ${snippetTypeRef}`); + return; + } + + // Validate the snippet against the specific schema + // Return if schema is invalid, so we don't validate the entire snippet against the root schema and duplicate errors + if (!validate(snippet.file, snippetValidator, snippetTypeRef, snippet.parsedSnippetContent)) { + return; + } + + // Validate entire snippet against root schema + validate(snippet.file, rootValidator, rootJsonSchemaTypeRef, snippet.parsedFullContent); + }); + +if (messages.length > 0) { + messages.forEach(message => console.log(message)); + process.exit(1); +} else { + console.log("All snippets are valid."); + process.exit(0); +} + +// Helper functions + +function validate(snippetFile, ajvValidator, ajvRef, data) { + try { + const valid = ajvValidator(data); + if (!valid) { + messages.push(`Snippet ${snippetFile} failed validation against ref ${ajvRef} with errors:`); + ajvValidator.errors.forEach(error => messages.push(` ${formatError(error)}`)); + return false; + } + return true; + } catch (error) { + messages.push(`Error validating snippet ${snippetFile} against ref ${ajvRef}: ${error.message}`); + return false; + } +} + +function computeJsonSchemaTypeRef(jsonSchemaType) { + const rootId = outputSchema['$id']; + if (jsonSchemaType.type === rootTypeName) { + return rootId; + } + return `${rootId}#/$defs/${jsonSchemaType.type}`; +} + +function formatError(error) { + const path = error.instancePath.replaceAll('\/', '.'); + return `${path} ${error.message}`; +} diff --git a/snippets/OtlpHttpMetricExporter_use_base2_exponential_histogram.yaml b/snippets/OtlpHttpMetricExporter_use_base2_exponential_histogram.yaml new file mode 100644 index 00000000..a96b12af --- /dev/null +++ b/snippets/OtlpHttpMetricExporter_use_base2_exponential_histogram.yaml @@ -0,0 +1,10 @@ +file_format: "1.0-rc.2" + +meter_provider: + readers: + - periodic: + exporter: + otlp_http: + # SNIPPET_START + endpoint: http://localhost:4317 + default_histogram_aggregation: base2_exponential_bucket_histogram \ No newline at end of file diff --git a/snippets/Sampler_parent_based_typical.yaml b/snippets/Sampler_parent_based_typical.yaml new file mode 100644 index 00000000..5bb7386a --- /dev/null +++ b/snippets/Sampler_parent_based_typical.yaml @@ -0,0 +1,22 @@ +file_format: "1.0-rc.2" + +tracer_provider: + processors: + - simple: + exporter: + console: + sampler: + # SNIPPET_START + # configure the parent based sampler to sample 1% of root spans, and follow the sampling decision of parent spans + parent_based: + root: + trace_id_ratio_based: + ratio: 0.01 + remote_parent_sampled: + always_on: + remote_parent_not_sampled: + always_off: + local_parent_sampled: + always_on: + local_parent_not_sampled: + always_off: \ No newline at end of file diff --git a/snippets/View_override_default_histogram_buckets.yaml b/snippets/View_override_default_histogram_buckets.yaml new file mode 100644 index 00000000..1fa061da --- /dev/null +++ b/snippets/View_override_default_histogram_buckets.yaml @@ -0,0 +1,18 @@ +# select a specific histogram instrument and override the default buckets +file_format: "1.0-rc.2" + +meter_provider: + readers: + - periodic: + exporter: + console: + views: + - + # SNIPPET_START + selector: + instrument_name: my.instrument.name + instrument_type: histogram + stream: + aggregation: + explicit_bucket_histogram: + boundaries: [0, 5, 10] \ No newline at end of file