Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 128 additions & 0 deletions apps/api/openapi/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -1117,6 +1117,7 @@
"mapping": {
"datadog": "#/components/schemas/DatadogMetricProvider",
"http": "#/components/schemas/HTTPMetricProvider",
"prometheus": "#/components/schemas/PrometheusMetricProvider",
"sleep": "#/components/schemas/SleepMetricProvider",
"terraformCloudRun": "#/components/schemas/TerraformCloudRunMetricProvider"
},
Expand All @@ -1132,6 +1133,9 @@
{
"$ref": "#/components/schemas/DatadogMetricProvider"
},
{
"$ref": "#/components/schemas/PrometheusMetricProvider"
},
{
"$ref": "#/components/schemas/TerraformCloudRunMetricProvider"
}
Expand Down Expand Up @@ -1270,6 +1274,130 @@
],
"type": "object"
},
"PrometheusMetricProvider": {
"properties": {
"address": {
"description": "Prometheus server address (supports Go templates)",
"example": "http://prometheus.example.com:9090",
"type": "string"
},
"authentication": {
"description": "Authentication configuration for Prometheus",
"properties": {
"bearerToken": {
"description": "Bearer token for authentication (supports Go templates for variable references)",
"example": "{{.variables.prometheus_token}}",
"type": "string"
},
"oauth2": {
"description": "OAuth2 client credentials flow",
"properties": {
"clientId": {
"description": "OAuth2 client ID (supports Go templates)",
"type": "string"
},
"clientSecret": {
"description": "OAuth2 client secret (supports Go templates)",
"type": "string"
},
"scopes": {
"description": "OAuth2 scopes",
"items": {
"type": "string"
},
"type": "array"
},
"tokenUrl": {
"description": "Token endpoint URL",
"type": "string"
}
},
"required": [
"tokenUrl",
"clientId",
"clientSecret"
],
"type": "object"
}
},
"type": "object"
},
"headers": {
"description": "Additional HTTP headers for the Prometheus request (values support Go templates)",
"items": {
"properties": {
"key": {
"example": "X-Scope-OrgID",
"type": "string"
},
"value": {
"example": "tenant_a",
"type": "string"
}
},
"required": [
"key",
"value"
],
"type": "object"
},
"type": "array"
},
"insecure": {
"default": false,
"description": "Skip TLS certificate verification",
"type": "boolean"
},
"query": {
"description": "PromQL query expression (supports Go templates)",
"example": "sum(irate(istio_requests_total{reporter=\"source\",destination_service=~\"{{.resource.name}}\",response_code!~\"5.*\"}[5m]))",
"type": "string"
},
"rangeQuery": {
"description": "If provided, a range query (/api/v1/query_range) is used instead of an instant query (/api/v1/query)",
"properties": {
"end": {
"description": "How far back from now for the query end, as a Prometheus duration (e.g., \"0s\" for now, \"1m\" for 1 minute ago). Defaults to \"0s\" (now) if unset.",
"example": "0s",
"type": "string"
},
"start": {
"description": "How far back from now to start the query, as a Prometheus duration (e.g., \"5m\", \"1h\"). Defaults to 10 * step if unset.",
"example": "5m",
"type": "string"
},
"step": {
"description": "Query resolution step width as a Prometheus duration (e.g., \"15s\", \"1m\", \"500ms\")",
"example": "1m",
"type": "string"
}
},
"required": [
"step"
],
"type": "object"
},
"timeout": {
"description": "Query timeout in seconds",
"example": 30,
"format": "int64",
"type": "integer"
},
"type": {
"description": "Provider type",
"enum": [
"prometheus"
],
"type": "string"
}
},
"required": [
"type",
"address",
"query"
],
"type": "object"
},
"PropertyMatcher": {
"properties": {
"fromProperty": {
Expand Down
91 changes: 91 additions & 0 deletions apps/api/openapi/schemas/verifications.jsonnet
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ local openapi = import '../lib/openapi.libsonnet';
openapi.schemaRef('HTTPMetricProvider'),
openapi.schemaRef('SleepMetricProvider'),
openapi.schemaRef('DatadogMetricProvider'),
openapi.schemaRef('PrometheusMetricProvider'),
openapi.schemaRef('TerraformCloudRunMetricProvider'),
],
discriminator: {
Expand All @@ -126,6 +127,7 @@ local openapi = import '../lib/openapi.libsonnet';
http: '#/components/schemas/HTTPMetricProvider',
sleep: '#/components/schemas/SleepMetricProvider',
datadog: '#/components/schemas/DatadogMetricProvider',
prometheus: '#/components/schemas/PrometheusMetricProvider',
terraformCloudRun: '#/components/schemas/TerraformCloudRunMetricProvider',
},
},
Expand Down Expand Up @@ -239,6 +241,95 @@ local openapi = import '../lib/openapi.libsonnet';
},
},

PrometheusMetricProvider: {
type: 'object',
required: ['type', 'address', 'query'],
properties: {
type: {
type: 'string',
enum: ['prometheus'],
description: 'Provider type',
},
address: {
type: 'string',
description: 'Prometheus server address (supports Go templates)',
example: 'http://prometheus.example.com:9090',
},
query: {
type: 'string',
description: 'PromQL query expression (supports Go templates)',
example: 'sum(irate(istio_requests_total{reporter="source",destination_service=~"{{.resource.name}}",response_code!~"5.*"}[5m]))',
},
timeout: {
type: 'integer',
format: 'int64',
description: 'Query timeout in seconds',
example: 30,
},
insecure: {
type: 'boolean',
description: 'Skip TLS certificate verification',
default: false,
},
headers: {
type: 'array',
description: 'Additional HTTP headers for the Prometheus request (values support Go templates)',
items: {
type: 'object',
required: ['key', 'value'],
properties: {
key: { type: 'string', example: 'X-Scope-OrgID' },
value: { type: 'string', example: 'tenant_a' },
},
},
},
authentication: {
type: 'object',
description: 'Authentication configuration for Prometheus',
properties: {
bearerToken: {
type: 'string',
description: 'Bearer token for authentication (supports Go templates for variable references)',
example: '{{.variables.prometheus_token}}',
},
oauth2: {
type: 'object',
description: 'OAuth2 client credentials flow',
required: ['tokenUrl', 'clientId', 'clientSecret'],
properties: {
tokenUrl: { type: 'string', description: 'Token endpoint URL' },
clientId: { type: 'string', description: 'OAuth2 client ID (supports Go templates)' },
clientSecret: { type: 'string', description: 'OAuth2 client secret (supports Go templates)' },
scopes: { type: 'array', items: { type: 'string' }, description: 'OAuth2 scopes' },
},
},
},
},
rangeQuery: {
type: 'object',
description: 'If provided, a range query (/api/v1/query_range) is used instead of an instant query (/api/v1/query)',
required: ['step'],
properties: {
start: {
type: 'string',
description: 'How far back from now to start the query, as a Prometheus duration (e.g., "5m", "1h"). Defaults to 10 * step if unset.',
example: '5m',
},
end: {
type: 'string',
description: 'How far back from now for the query end, as a Prometheus duration (e.g., "0s" for now, "1m" for 1 minute ago). Defaults to "0s" (now) if unset.',
example: '0s',
},
step: {
type: 'string',
description: 'Query resolution step width as a Prometheus duration (e.g., "15s", "1m", "500ms")',
example: '1m',
},
},
},
},
},

TerraformCloudRunMetricProvider: {
type: 'object',
required: ['type', 'address', 'token', 'runId'],
Expand Down
74 changes: 73 additions & 1 deletion apps/api/src/types/openapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1192,7 +1192,7 @@ export interface components {
};
};
LiteralValue: components["schemas"]["BooleanValue"] | components["schemas"]["NumberValue"] | components["schemas"]["IntegerValue"] | components["schemas"]["StringValue"] | components["schemas"]["ObjectValue"] | components["schemas"]["NullValue"];
MetricProvider: components["schemas"]["HTTPMetricProvider"] | components["schemas"]["SleepMetricProvider"] | components["schemas"]["DatadogMetricProvider"] | components["schemas"]["TerraformCloudRunMetricProvider"];
MetricProvider: components["schemas"]["HTTPMetricProvider"] | components["schemas"]["SleepMetricProvider"] | components["schemas"]["DatadogMetricProvider"] | components["schemas"]["PrometheusMetricProvider"] | components["schemas"]["TerraformCloudRunMetricProvider"];
/** @enum {boolean} */
NullValue: true;
NumberValue: number;
Expand Down Expand Up @@ -1234,6 +1234,78 @@ export interface components {
verification?: components["schemas"]["VerificationRule"];
versionCooldown?: components["schemas"]["VersionCooldownRule"];
};
PrometheusMetricProvider: {
/**
* @description Prometheus server address (supports Go templates)
* @example http://prometheus.example.com:9090
*/
address: string;
/** @description Authentication configuration for Prometheus */
authentication?: {
/**
* @description Bearer token for authentication (supports Go templates for variable references)
* @example {{.variables.prometheus_token}}
*/
bearerToken?: string;
/** @description OAuth2 client credentials flow */
oauth2?: {
/** @description OAuth2 client ID (supports Go templates) */
clientId: string;
/** @description OAuth2 client secret (supports Go templates) */
clientSecret: string;
/** @description OAuth2 scopes */
scopes?: string[];
/** @description Token endpoint URL */
tokenUrl: string;
};
};
/** @description Additional HTTP headers for the Prometheus request (values support Go templates) */
headers?: {
/** @example X-Scope-OrgID */
key: string;
/** @example tenant_a */
value: string;
}[];
/**
* @description Skip TLS certificate verification
* @default false
*/
insecure: boolean;
/**
* @description PromQL query expression (supports Go templates)
* @example sum(irate(istio_requests_total{reporter="source",destination_service=~"{{.resource.name}}",response_code!~"5.*"}[5m]))
*/
query: string;
/** @description If provided, a range query (/api/v1/query_range) is used instead of an instant query (/api/v1/query) */
rangeQuery?: {
/**
* @description How far back from now for the query end, as a Prometheus duration (e.g., "0s" for now, "1m" for 1 minute ago). Defaults to "0s" (now) if unset.
* @example 0s
*/
end?: string;
/**
* @description How far back from now to start the query, as a Prometheus duration (e.g., "5m", "1h"). Defaults to 10 * step if unset.
* @example 5m
*/
start?: string;
/**
* @description Query resolution step width as a Prometheus duration (e.g., "15s", "1m", "500ms")
* @example 1m
*/
step: string;
};
/**
* Format: int64
* @description Query timeout in seconds
* @example 30
*/
timeout?: number;
/**
* @description Provider type (enum property replaced by openapi-typescript)
* @enum {string}
*/
type: "prometheus";
};
PropertyMatcher: {
fromProperty: string[];
/** @enum {string} */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ import {
import { cn } from "~/lib/utils";
import { ArgoCDVerificationDisplay } from "./argocd/ArgoCD";
import { isArgoCDMeasurement } from "./argocd/argocd-metric";
import { PrometheusVerificationDisplay } from "./prometheus/Prometheus";
import { PrometheusIcon } from "./prometheus/PrometheusIcon";
import { isPrometheusProvider } from "./prometheus/prometheus-metric";
import { VerificationMetricStatus } from "./VerificationMetricStatus";

type JobVerification = WorkspaceEngine["schemas"]["JobVerification"];
Expand Down Expand Up @@ -152,6 +155,7 @@ function MetricDisplay({ metric }: { metric: VerificationMetricStatus }) {

const isArgoCD =
latestMeasurement != null && isArgoCDMeasurement(latestMeasurement.data);
const isPrometheus = isPrometheusProvider(metric.provider);

return (
<Collapsible open={open} onOpenChange={setOpen}>
Expand All @@ -163,6 +167,9 @@ function MetricDisplay({ metric }: { metric: VerificationMetricStatus }) {
open ? "rotate-90" : "",
)}
/>
{isPrometheus && (
<PrometheusIcon className="h-4 w-4 text-orange-500" />
)}
<span className="text-sm font-medium">{metric.name}</span>
<div className="grow" />
<VerificationMetricStatus metric={metric} />
Expand All @@ -171,7 +178,8 @@ function MetricDisplay({ metric }: { metric: VerificationMetricStatus }) {

<CollapsibleContent className="space-y-2 pl-6 text-xs">
{isArgoCD && <ArgoCDVerificationDisplay metric={metric} />}
{!isArgoCD && (
{isPrometheus && <PrometheusVerificationDisplay metric={metric} />}
{!isArgoCD && !isPrometheus && (
<>
<MetricSummaryDisplay metric={metric} />
{sortedMeasurements.map((measurement, idx) => (
Expand Down
Loading
Loading