From 247d0c61e857dfa91b9a4de8bf8f8a9d4a4eee6d Mon Sep 17 00:00:00 2001 From: Daniel Gempesaw Date: Mon, 19 Apr 2021 22:45:44 -0700 Subject: [PATCH] Add support for datadog as a metric source (#152) --- README.md | 1 + .../DatadogCanaryMetricSetQueryConfig.ts | 8 ++++ .../Datadog/DatadogMetricModal.tsx | 41 +++++++++++++++++++ .../client/src/metricSources/Datadog/index.ts | 24 +++++++++++ packages/client/src/metricSources/index.tsx | 4 +- 5 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 packages/client/src/metricSources/Datadog/DatadogCanaryMetricSetQueryConfig.ts create mode 100644 packages/client/src/metricSources/Datadog/DatadogMetricModal.tsx create mode 100644 packages/client/src/metricSources/Datadog/index.ts diff --git a/README.md b/README.md index f7f29bbb..b61f6c83 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,7 @@ Referee currently supports - New Relic Insights - Prometheus - SignalFx +- Datadog To add a new integration you must implement the [MetricSourceIntegration](/packages/client/src/metricSources/MetricSourceIntegration.ts) interface and then add it to the [enabled metric sources](/packages/client/src/metricSources/index.tsx). diff --git a/packages/client/src/metricSources/Datadog/DatadogCanaryMetricSetQueryConfig.ts b/packages/client/src/metricSources/Datadog/DatadogCanaryMetricSetQueryConfig.ts new file mode 100644 index 00000000..dd545651 --- /dev/null +++ b/packages/client/src/metricSources/Datadog/DatadogCanaryMetricSetQueryConfig.ts @@ -0,0 +1,8 @@ +import { CanaryMetricSetQueryConfig } from '../../domain/Kayenta'; + +/** + * {@see: https://github.com/spinnaker/kayenta/blob/master/kayenta-datadog/src/main/java/com/netflix/kayenta/canary/providers/metrics/DatadogCanaryMetricSetQueryConfig.java} + */ +export default interface DatadogCanaryMetricSetQueryConfig extends CanaryMetricSetQueryConfig { + customInlineTemplate: string +} diff --git a/packages/client/src/metricSources/Datadog/DatadogMetricModal.tsx b/packages/client/src/metricSources/Datadog/DatadogMetricModal.tsx new file mode 100644 index 00000000..cc4192f0 --- /dev/null +++ b/packages/client/src/metricSources/Datadog/DatadogMetricModal.tsx @@ -0,0 +1,41 @@ +import * as React from 'react'; +import { AbstractMetricModal } from '../../components/config/AbstractMetricModal'; +import { DATADOG_SERVICE_TYPE } from './index'; +import { InlineTextGroup } from '../../layout/InlineTextGroup'; +import { validateCanaryMetricConfig } from '../../validation/configValidators'; +import { CanaryMetricConfig } from '../../domain/Kayenta'; +import { ValidationResultsWrapper } from '../../domain/Referee'; +import DatadogCanaryMetricSetQueryConfig from './DatadogCanaryMetricSetQueryConfig'; + +export default class DatadogMetricModal extends AbstractMetricModal { + validateCanaryMetricConfig(existingMetric: CanaryMetricConfig, type: string): ValidationResultsWrapper { + return validateCanaryMetricConfig(existingMetric, type, true); + } + + getQueryInitialState(): DatadogCanaryMetricSetQueryConfig { + return { + type: DATADOG_SERVICE_TYPE, + customInlineTemplate: '', + }; + } + + getMetricSourceSpecificJsx(): JSX.Element { + return ( +
+ { + this.touch('customInlineTemplate'); + }} + touched={this.state.touched.customInlineTemplate} + error={this.state.errors['query.customInlineTemplate']} + id="customInlineTemplate" + label="Datadog Query" + value={this.state.metric.query.customInlineTemplate} + onChange={e => this.updateQueryObject('customInlineTemplate', e.target.value)} + placeHolderText="sum:requests.error{${scope}}.as_count() / sum:requests.total{${scope}}.as_count()" + subText="Custom datadog query; use ${scope} as a placeholder for your tags." + /> +
+ ); + } +} diff --git a/packages/client/src/metricSources/Datadog/index.ts b/packages/client/src/metricSources/Datadog/index.ts new file mode 100644 index 00000000..463a0773 --- /dev/null +++ b/packages/client/src/metricSources/Datadog/index.ts @@ -0,0 +1,24 @@ +import * as React from 'react'; +import { MetricSourceIntegration } from '../MetricSourceIntegration'; +import { MetricModalProps } from '../../components/config/AbstractMetricModal'; +import DatadogMetricModal from './DatadogMetricModal'; +import DatadogCanaryMetricSetQueryConfig from './DatadogCanaryMetricSetQueryConfig'; +import { string } from 'yup'; + +export const DATADOG_SERVICE_TYPE: string = 'datadog'; + +const schema = { + customInlineTemplate: string() + .trim() + .required() +}; + +const modalFactory = (props: MetricModalProps) => React.createElement(DatadogMetricModal, props); + +const Datadog: MetricSourceIntegration = { + type: DATADOG_SERVICE_TYPE, + createMetricsModal: modalFactory, + canaryMetricSetQueryConfigSchema: schema +}; + +export default Datadog; diff --git a/packages/client/src/metricSources/index.tsx b/packages/client/src/metricSources/index.tsx index 847dd2c0..83dda469 100644 --- a/packages/client/src/metricSources/index.tsx +++ b/packages/client/src/metricSources/index.tsx @@ -3,6 +3,7 @@ import { MetricSourceIntegration } from './MetricSourceIntegration'; import NewRelic from './NewRelic'; import SignalFx from './SignalFx'; import Prometheus from './Prometheus'; +import Datadog from './Datadog'; const MIN_TO_MS_CONVERSION: number = 60000; /** @@ -12,7 +13,8 @@ const MIN_TO_MS_CONVERSION: number = 60000; const enabledMetricSources: MetricSourceIntegration[] = [ NewRelic, SignalFx, - Prometheus + Prometheus, + Datadog ]; /**