From acc6b0c498236a19e2a7cb61b28c4d245893a067 Mon Sep 17 00:00:00 2001 From: Tim Beyer Date: Wed, 12 Jul 2023 11:47:45 +0200 Subject: [PATCH] refactor: move validators into exporter modules and use those for the config types --- core/src/config/zod.ts | 3 +- .../src/plugins/otel-collector/config/base.ts | 9 ++++ .../plugins/otel-collector/config/datadog.ts | 20 +++++--- .../otel-collector/config/honeycomb.ts | 22 +++++--- .../plugins/otel-collector/config/logging.ts | 19 +++++-- .../plugins/otel-collector/config/newrelic.ts | 20 +++++--- .../plugins/otel-collector/config/otlphttp.ts | 21 +++++--- .../plugins/otel-collector/otel-collector.ts | 51 ++----------------- 8 files changed, 88 insertions(+), 77 deletions(-) diff --git a/core/src/config/zod.ts b/core/src/config/zod.ts index b70baecab5..8177b969ca 100644 --- a/core/src/config/zod.ts +++ b/core/src/config/zod.ts @@ -6,7 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { Schema, z } from "zod" +import { Schema, z, infer as inferZodType, ZodType } from "zod" import { envVarRegex, identifierRegex, joiIdentifierDescription, userIdentifierRegex } from "./constants" // Add metadata support to schemas. See https://github.com/colinhacks/zod/issues/273#issuecomment-1434077058 @@ -76,6 +76,7 @@ type GardenSchema = typeof z & { // This should be imported instead of z because we augment zod with custom methods export const s = z as GardenSchema +export type inferType> = inferZodType s.envVars = () => s.record(s.string().regex(envVarRegex).min(1), z.string()) diff --git a/core/src/plugins/otel-collector/config/base.ts b/core/src/plugins/otel-collector/config/base.ts index 9cd9a43166..7212b0f852 100644 --- a/core/src/plugins/otel-collector/config/base.ts +++ b/core/src/plugins/otel-collector/config/base.ts @@ -6,6 +6,15 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +import { sdk } from "../../../plugin/sdk" + +const s = sdk.schema + +export const baseValidator = s.object({ + name: s.string(), + enabled: s.boolean(), +}) + export type OtelCollectorBaseConfig = { processors: { batch: null | { diff --git a/core/src/plugins/otel-collector/config/datadog.ts b/core/src/plugins/otel-collector/config/datadog.ts index 7e2c93401f..32a30eb0f3 100644 --- a/core/src/plugins/otel-collector/config/datadog.ts +++ b/core/src/plugins/otel-collector/config/datadog.ts @@ -7,6 +7,19 @@ */ import { hostname } from "os" +import { sdk } from "../../../plugin/sdk" +import { baseValidator } from "./base" +import { inferType } from "../../../config/zod" + +const s = sdk.schema + +export const dataDogValidator = baseValidator.merge( + s.object({ + name: s.literal("datadog"), + site: s.string().min(1).default("datadoghq.com"), + apiKey: s.string().min(1), + }) +) export type DatadogExporterConfigPartial = { exporters: { @@ -28,12 +41,7 @@ export type DatadogExporterConfigPartial = { } } -export type OtelCollectorDatadogConfiguration = { - name: "datadog" - enabled: boolean - site: string - apiKey: string -} +export type OtelCollectorDatadogConfiguration = inferType export function makeDatadogPartialConfig(config: OtelCollectorDatadogConfiguration): DatadogExporterConfigPartial { return { diff --git a/core/src/plugins/otel-collector/config/honeycomb.ts b/core/src/plugins/otel-collector/config/honeycomb.ts index ca0172ece3..be872b8e66 100644 --- a/core/src/plugins/otel-collector/config/honeycomb.ts +++ b/core/src/plugins/otel-collector/config/honeycomb.ts @@ -7,14 +7,22 @@ */ import { OtlpHttpExporterConfigPartial, makeOtlpHttpPartialConfig } from "./otlphttp" +import { sdk } from "../../../plugin/sdk" +import { baseValidator } from "./base" +import { inferType } from "../../../config/zod" -export type OtelCollectorHoneycombConfiguration = { - name: "honeycomb" - enabled: boolean - endpoint: string - apiKey: string - dataset?: string -} +const s = sdk.schema + +export const honeycombValidator = baseValidator.merge( + s.object({ + name: s.literal("honeycomb"), + endpoint: s.string().url().default("https://api.honeycomb.io"), + apiKey: s.string().min(1), + dataset: s.string().optional(), + }) +) + +export type OtelCollectorHoneycombConfiguration = inferType export function makeHoneycombPartialConfig(config: OtelCollectorHoneycombConfiguration): OtlpHttpExporterConfigPartial { return makeOtlpHttpPartialConfig({ diff --git a/core/src/plugins/otel-collector/config/logging.ts b/core/src/plugins/otel-collector/config/logging.ts index da8287b966..c864e19b49 100644 --- a/core/src/plugins/otel-collector/config/logging.ts +++ b/core/src/plugins/otel-collector/config/logging.ts @@ -6,6 +6,10 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +import { inferType } from "../../../config/zod" +import { sdk } from "../../../plugin/sdk" +import { baseValidator } from "./base" + export type LoggingExporterVerbosityLevel = "detailed" | "normal" | "basic" export const LoggingExporterVerbosityLevelEnum = [ "detailed", @@ -13,6 +17,15 @@ export const LoggingExporterVerbosityLevelEnum = [ "basic", ] as const satisfies readonly LoggingExporterVerbosityLevel[] +const s = sdk.schema + +export const loggingValidator = baseValidator.merge( + s.object({ + name: s.literal("logging"), + verbosity: s.enum(LoggingExporterVerbosityLevelEnum).default("normal"), + }) +) + export type LoggingExporterConfigPartial = { exporters: { logging?: { @@ -28,11 +41,7 @@ export type LoggingExporterConfigPartial = { } } -export type OtelCollectorLoggingConfiguration = { - name: "logging" - enabled: boolean - verbosity: LoggingExporterVerbosityLevel -} +export type OtelCollectorLoggingConfiguration = inferType export function makeLoggingPartialConfig(config: OtelCollectorLoggingConfiguration): LoggingExporterConfigPartial { return { diff --git a/core/src/plugins/otel-collector/config/newrelic.ts b/core/src/plugins/otel-collector/config/newrelic.ts index 627e55c070..f33b306163 100644 --- a/core/src/plugins/otel-collector/config/newrelic.ts +++ b/core/src/plugins/otel-collector/config/newrelic.ts @@ -7,13 +7,21 @@ */ import { OtlpHttpExporterConfigPartial, makeOtlpHttpPartialConfig } from "./otlphttp" +import { sdk } from "../../../plugin/sdk" +import { baseValidator } from "./base" +import { inferType } from "../../../config/zod" -export type OtelCollectorNewRelicConfiguration = { - name: "newrelic" - enabled: boolean - endpoint: string - apiKey: string -} +const s = sdk.schema + +export const newRelicValidator = baseValidator.merge( + s.object({ + name: s.literal("newrelic"), + endpoint: s.string().url().default("https://otlp.nr-data.net:4318"), + apiKey: s.string().min(1), + }) +) + +export type OtelCollectorNewRelicConfiguration = inferType export function makeNewRelicPartialConfig(config: OtelCollectorNewRelicConfiguration): OtlpHttpExporterConfigPartial { return makeOtlpHttpPartialConfig({ diff --git a/core/src/plugins/otel-collector/config/otlphttp.ts b/core/src/plugins/otel-collector/config/otlphttp.ts index da1a2f1aad..4733c8993e 100644 --- a/core/src/plugins/otel-collector/config/otlphttp.ts +++ b/core/src/plugins/otel-collector/config/otlphttp.ts @@ -6,6 +6,20 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +import { inferType } from "../../../config/zod" +import { sdk } from "../../../plugin/sdk" +import { baseValidator } from "./base" + +const s = sdk.schema + +export const otlpHttpValidator = baseValidator.merge( + s.object({ + name: s.literal("otlphttp"), + endpoint: s.string().url(), + headers: s.record(s.string().min(1), s.union([s.number(), s.string().min(1), s.undefined()])).optional(), + }) +) + export type OtlpHttpExporterName = `otlphttp/${string | number}` export type OtlpHttpExporterConfigPartial = { @@ -26,12 +40,7 @@ export type OtlpHttpExporterConfigPartial = { } } -export type OtelCollectorOtlpHttpConfiguration = { - name: "otlphttp" - enabled: boolean - endpoint: string - headers?: Record -} +export type OtelCollectorOtlpHttpConfiguration = inferType export const makeOtlpHttpPartialConfig = (() => { // We use the counter to make sure every http based config has a unique key diff --git a/core/src/plugins/otel-collector/otel-collector.ts b/core/src/plugins/otel-collector/otel-collector.ts index 168ef82c61..26fada641f 100644 --- a/core/src/plugins/otel-collector/otel-collector.ts +++ b/core/src/plugins/otel-collector/otel-collector.ts @@ -19,7 +19,11 @@ import { writeFile } from "fs-extra" import { streamLogs, waitForLogLine, waitForProcessExit } from "../../util/process" import getPort from "get-port" import { wrapActiveSpan } from "../../util/tracing/spans" -import { LoggingExporterVerbosityLevelEnum } from "./config/logging" +import { dataDogValidator } from "./config/datadog" +import { honeycombValidator } from "./config/honeycomb" +import { loggingValidator } from "./config/logging" +import { newRelicValidator } from "./config/newrelic" +import { otlpHttpValidator } from "./config/otlphttp" const OTEL_CONFIG_NAME = "otel-config.yaml" @@ -86,51 +90,6 @@ gardenPlugin.addTool({ ], }) -const baseValidator = s.object({ - name: s.string(), - enabled: s.boolean(), -}) - -const loggingValidator = baseValidator.merge( - s.object({ - name: s.literal("logging"), - verbosity: s.enum(LoggingExporterVerbosityLevelEnum).default("normal"), - }) -) - -const otlpHttpValidator = baseValidator.merge( - s.object({ - name: s.literal("otlphttp"), - endpoint: s.string().url(), - headers: s.record(s.string().min(1), s.number()).optional(), - }) -) - -const newRelicValidator = baseValidator.merge( - s.object({ - name: s.literal("newrelic"), - endpoint: s.string().url().default("https://otlp.nr-data.net:4318"), - apiKey: s.string().min(1), - }) -) - -const honeycombValidator = baseValidator.merge( - s.object({ - name: s.literal("honeycomb"), - endpoint: s.string().url().default("https://api.honeycomb.io"), - apiKey: s.string().min(1), - dataset: s.string().optional(), - }) -) - -const dataDogValidator = baseValidator.merge( - s.object({ - name: s.literal("datadog"), - site: s.string().min(1).default("datadoghq.com"), - apiKey: s.string().min(1), - }) -) - const providerConfigSchema = s.object({ exporters: s.array( s.union([loggingValidator, otlpHttpValidator, newRelicValidator, dataDogValidator, honeycombValidator])