@prismatic-io/components-datadog 0.0.0-stage → 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1003 @@
1
+ let _prismatic_io_spectral = require("@prismatic-io/spectral");
2
+ let _prismatic_io_spectral_http = require("@prismatic-io/spectral/http");
3
+ //#region src/constants.ts
4
+ const DATADOG_SITES = [
5
+ {
6
+ label: "US1 (datadoghq.com)",
7
+ value: "https://api.datadoghq.com"
8
+ },
9
+ {
10
+ label: "US3 (us3.datadoghq.com)",
11
+ value: "https://api.us3.datadoghq.com"
12
+ },
13
+ {
14
+ label: "US5 (us5.datadoghq.com)",
15
+ value: "https://api.us5.datadoghq.com"
16
+ },
17
+ {
18
+ label: "EU (datadoghq.eu)",
19
+ value: "https://api.datadoghq.eu"
20
+ },
21
+ {
22
+ label: "AP1 (ap1.datadoghq.com)",
23
+ value: "https://api.ap1.datadoghq.com"
24
+ },
25
+ {
26
+ label: "AP2 (ap2.datadoghq.com)",
27
+ value: "https://api.ap2.datadoghq.com"
28
+ },
29
+ {
30
+ label: "US1-FED (ddog-gov.com)",
31
+ value: "https://api.ddog-gov.com"
32
+ }
33
+ ];
34
+ const DEFAULT_DATADOG_SITE = DATADOG_SITES[0].value;
35
+ const METRIC_TYPE_OPTIONS = [
36
+ {
37
+ label: "Unspecified",
38
+ value: "0"
39
+ },
40
+ {
41
+ label: "Count",
42
+ value: "1"
43
+ },
44
+ {
45
+ label: "Rate",
46
+ value: "2"
47
+ },
48
+ {
49
+ label: "Gauge",
50
+ value: "3"
51
+ }
52
+ ];
53
+ const WEBHOOK_ENCODE_AS_OPTIONS = [{
54
+ label: "JSON",
55
+ value: "json"
56
+ }, {
57
+ label: "Form",
58
+ value: "form"
59
+ }];
60
+ const DEFAULT_WEBHOOK_ENCODE_AS = "json";
61
+ const WEBHOOK_STATE_KEY_PREFIX = "datadogWebhook";
62
+ const WEBHOOKS_CONFIGURATION_PATH = "/api/v1/integration/webhooks/configuration/webhooks";
63
+ const SUBMIT_METRICS_PATH = "/api/v2/series";
64
+ const SEARCH_METRICS_PATH = "/api/v1/search";
65
+ const METRICS_QUERY_PREFIX = "metrics:";
66
+ //#endregion
67
+ //#region src/connections/apiKey.ts
68
+ const apiKeyConnection = (0, _prismatic_io_spectral.connection)({
69
+ key: "apiKey",
70
+ display: {
71
+ label: "API Key + Application Key",
72
+ description: "Authenticate using a Datadog API Key and Application Key. The API Key authenticates the organization, and the Application Key authorizes management operations."
73
+ },
74
+ inputs: {
75
+ datadogSite: {
76
+ label: "Datadog Site",
77
+ type: "string",
78
+ required: true,
79
+ shown: true,
80
+ comments: "Select the Datadog site that matches the organization. This determines the API base URL.",
81
+ default: DEFAULT_DATADOG_SITE,
82
+ model: DATADOG_SITES
83
+ },
84
+ apiKey: {
85
+ label: "API Key",
86
+ placeholder: "Enter Datadog API Key",
87
+ type: "password",
88
+ required: true,
89
+ shown: true,
90
+ comments: "The Datadog API Key. Create one at Organization Settings > API Keys in Datadog.",
91
+ example: "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
92
+ },
93
+ applicationKey: {
94
+ label: "Application Key",
95
+ placeholder: "Enter Datadog Application Key",
96
+ type: "password",
97
+ required: true,
98
+ shown: true,
99
+ comments: "The Datadog Application Key. Required for management and read endpoints. Create one at Organization Settings > Application Keys in Datadog.",
100
+ example: "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0"
101
+ }
102
+ }
103
+ });
104
+ //#endregion
105
+ //#region src/connections/oauth2.ts
106
+ const oauth2AuthorizationCode = (0, _prismatic_io_spectral.oauth2Connection)({
107
+ key: "oauth2",
108
+ display: {
109
+ label: "OAuth 2.0 Authorization Code",
110
+ description: "Authenticate using OAuth 2.0 Authorization Code flow. Primarily used for Datadog integration partners and marketplace apps."
111
+ },
112
+ oauth2Type: _prismatic_io_spectral.OAuth2Type.AuthorizationCode,
113
+ inputs: {
114
+ datadogSite: {
115
+ label: "Datadog Site",
116
+ type: "string",
117
+ required: true,
118
+ shown: true,
119
+ comments: "Select the Datadog site that matches the organization. This determines the API base URL.",
120
+ default: DEFAULT_DATADOG_SITE,
121
+ model: DATADOG_SITES
122
+ },
123
+ authorizeUrl: {
124
+ label: "Authorize URL",
125
+ placeholder: "Enter Authorize URL",
126
+ type: "string",
127
+ required: false,
128
+ shown: false,
129
+ comments: "The Datadog OAuth 2.0 authorization endpoint.",
130
+ default: "https://app.datadoghq.com/oauth2/v1/authorize"
131
+ },
132
+ tokenUrl: {
133
+ label: "Token URL",
134
+ placeholder: "Enter Token URL",
135
+ type: "string",
136
+ required: false,
137
+ shown: false,
138
+ comments: "The Datadog OAuth 2.0 token endpoint.",
139
+ default: "https://api.datadoghq.com/oauth2/v1/token"
140
+ },
141
+ revokeUrl: {
142
+ label: "Revoke URL",
143
+ placeholder: "Enter Revoke URL",
144
+ type: "string",
145
+ required: false,
146
+ shown: false,
147
+ comments: "The Datadog OAuth 2.0 token revocation endpoint.",
148
+ default: "https://api.datadoghq.com/oauth2/v1/revoke"
149
+ },
150
+ scopes: {
151
+ label: "Scopes",
152
+ placeholder: "Enter scopes",
153
+ type: "string",
154
+ required: false,
155
+ shown: false,
156
+ comments: "Space-separated OAuth 2.0 scopes. Available scopes include: metrics_read, timeseries_query, metric_tags_manage, create_webhooks.",
157
+ default: "metrics_read timeseries_query metric_tags_manage create_webhooks"
158
+ },
159
+ clientId: {
160
+ label: "Client ID",
161
+ placeholder: "Enter Client ID",
162
+ type: "string",
163
+ required: true,
164
+ shown: true,
165
+ comments: "The Client ID from the Datadog OAuth application."
166
+ },
167
+ clientSecret: {
168
+ label: "Client Secret",
169
+ placeholder: "Enter Client Secret",
170
+ type: "password",
171
+ required: true,
172
+ shown: true,
173
+ comments: "The Client Secret from the Datadog OAuth application."
174
+ }
175
+ }
176
+ });
177
+ //#endregion
178
+ //#region src/connections/index.ts
179
+ var connections_default = [apiKeyConnection, oauth2AuthorizationCode];
180
+ //#endregion
181
+ //#region src/utils/clean.ts
182
+ const toOptionalString = (value) => value ? _prismatic_io_spectral.util.types.toString(value) : void 0;
183
+ const toOptionalNumber = (value) => value ? _prismatic_io_spectral.util.types.toNumber(value) : void 0;
184
+ const toRequiredNumber = (label) => (value) => {
185
+ if (value === void 0 || value === null || typeof value === "string" && value.trim() === "") throw new Error(`${label} is required and must be a number.`);
186
+ return _prismatic_io_spectral.util.types.toNumber(value);
187
+ };
188
+ const toMetricSeries = (value) => {
189
+ const series = _prismatic_io_spectral.util.types.toObject(value);
190
+ if (!Array.isArray(series)) throw new Error("Metric Series must be a JSON array of metric series.");
191
+ return series;
192
+ };
193
+ const toOptionalMetricIntakeType = (value) => value ? _prismatic_io_spectral.util.types.toNumber(value) : void 0;
194
+ const toStringList = (value) => value;
195
+ //#endregion
196
+ //#region src/utils/connection.ts
197
+ const validateConnection = (connection) => {
198
+ if (![apiKeyConnection.key, oauth2AuthorizationCode.key].includes(connection.key)) throw new _prismatic_io_spectral.ConnectionError(connection, `Received unexpected connection type: ${connection.key}`);
199
+ };
200
+ //#endregion
201
+ //#region src/utils/webhook.ts
202
+ const webhookConfigurationPath = (webhookName) => `${WEBHOOKS_CONFIGURATION_PATH}/${encodeURIComponent(webhookName)}`;
203
+ const isNotFoundError = (error) => error?.response?.status === 404;
204
+ const findWebhook = async (client, webhookName) => {
205
+ try {
206
+ const { data } = await client.get(webhookConfigurationPath(webhookName));
207
+ return data;
208
+ } catch (error) {
209
+ if (isNotFoundError(error)) return void 0;
210
+ throw error;
211
+ }
212
+ };
213
+ const deleteOwnedWebhook = async (client, logger, webhookName, webhookUrl) => {
214
+ if (!webhookUrl) {
215
+ logger.warn(`Skipped deleting Datadog webhook "${webhookName}": the URL of this flow is unknown.`);
216
+ return;
217
+ }
218
+ const existing = await findWebhook(client, webhookName);
219
+ if (!existing) return;
220
+ if (existing.url !== webhookUrl) {
221
+ logger.warn(`Skipped deleting Datadog webhook "${webhookName}": it points to a different URL.`);
222
+ return;
223
+ }
224
+ await client.delete(webhookConfigurationPath(webhookName));
225
+ logger.info(`Deleted Datadog webhook "${webhookName}".`);
226
+ };
227
+ //#endregion
228
+ //#region src/client.ts
229
+ const getBaseUrl = (connection) => {
230
+ return _prismatic_io_spectral.util.types.toString(connection.fields.datadogSite);
231
+ };
232
+ const getAuthHeaders = (connection) => {
233
+ if (connection.key === apiKeyConnection.key) return {
234
+ "DD-API-KEY": _prismatic_io_spectral.util.types.toString(connection.fields.apiKey),
235
+ "DD-APPLICATION-KEY": _prismatic_io_spectral.util.types.toString(connection.fields.applicationKey)
236
+ };
237
+ return { Authorization: `Bearer ${_prismatic_io_spectral.util.types.toString(connection.token?.access_token)}` };
238
+ };
239
+ const createClient = (connection) => {
240
+ validateConnection(connection);
241
+ return (0, _prismatic_io_spectral_http.createClient)({
242
+ baseUrl: getBaseUrl(connection),
243
+ responseType: "json",
244
+ headers: {
245
+ ...getAuthHeaders(connection),
246
+ Accept: "application/json",
247
+ "Content-Type": "application/json"
248
+ },
249
+ debug: false
250
+ });
251
+ };
252
+ //#endregion
253
+ //#region src/examplePayloads.ts
254
+ const submitMetricsExamplePayload = { data: { errors: [] } };
255
+ const submitSingleMetricExamplePayload = submitMetricsExamplePayload;
256
+ const listMetricsExamplePayload = { data: {
257
+ metrics: [
258
+ "system.cpu.idle",
259
+ "system.cpu.user",
260
+ "system.disk.free",
261
+ "system.load.1",
262
+ "system.mem.free"
263
+ ],
264
+ from: "1636629071"
265
+ } };
266
+ const searchMetricsExamplePayload = { data: { results: { metrics: [
267
+ "system.cpu.idle",
268
+ "system.cpu.iowait",
269
+ "system.cpu.system",
270
+ "system.cpu.user"
271
+ ] } } };
272
+ const getWebhookExamplePayload = { data: {
273
+ name: "datadog-alert-webhook",
274
+ url: "https://example.com/webhook",
275
+ custom_headers: null,
276
+ encode_as: "json",
277
+ payload: null
278
+ } };
279
+ const createWebhookExamplePayload = getWebhookExamplePayload;
280
+ const updateWebhookExamplePayload = getWebhookExamplePayload;
281
+ const deleteWebhookExamplePayload = { data: null };
282
+ const selectMetricExamplePayload = { result: [
283
+ {
284
+ label: "system.cpu.idle",
285
+ key: "system.cpu.idle"
286
+ },
287
+ {
288
+ label: "system.cpu.user",
289
+ key: "system.cpu.user"
290
+ },
291
+ {
292
+ label: "system.disk.free",
293
+ key: "system.disk.free"
294
+ },
295
+ {
296
+ label: "system.load.1",
297
+ key: "system.load.1"
298
+ }
299
+ ] };
300
+ const webhookExamplePayload = { payload: {
301
+ headers: { "Content-Type": "application/json" },
302
+ queryParameters: {},
303
+ rawBody: {
304
+ data: "{\"ALERT_ID\":\"12345678\",\"ALERT_METRIC\":\"system.load.1\",\"ALERT_QUERY\":\"avg(last_5m):avg:system.load.1{host:my-host} > 5\",\"ALERT_SCOPE\":\"host:my-host\",\"ALERT_STATUS\":\"Triggered\",\"ALERT_TITLE\":\"CPU load is high on my-host\",\"ALERT_TRANSITION\":\"Triggered\",\"ALERT_TYPE\":\"metric alert\",\"DATE\":\"2024-01-15 10:30:00 UTC\",\"EVENT_MSG\":\"CPU load exceeded threshold\",\"HOSTNAME\":\"my-host\",\"ID\":\"12345678\",\"LAST_UPDATED\":\"2024-01-15 10:30:00 UTC\",\"LINK\":\"https://app.datadoghq.com/monitors/12345678\",\"ORG_ID\":\"123456\",\"ORG_NAME\":\"My Organization\",\"TAGS\":\"environment:production,region:us-east-1\"}",
305
+ contentType: "application/json"
306
+ },
307
+ body: {
308
+ data: {
309
+ ALERT_ID: "12345678",
310
+ ALERT_METRIC: "system.load.1",
311
+ ALERT_QUERY: "avg(last_5m):avg:system.load.1{host:my-host} > 5",
312
+ ALERT_SCOPE: "host:my-host",
313
+ ALERT_STATUS: "Triggered",
314
+ ALERT_TITLE: "CPU load is high on my-host",
315
+ ALERT_TRANSITION: "Triggered",
316
+ ALERT_TYPE: "metric alert",
317
+ DATE: "2024-01-15 10:30:00 UTC",
318
+ EVENT_MSG: "CPU load exceeded threshold",
319
+ HOSTNAME: "my-host",
320
+ ID: "12345678",
321
+ LAST_UPDATED: "2024-01-15 10:30:00 UTC",
322
+ LINK: "https://app.datadoghq.com/monitors/12345678",
323
+ ORG_ID: "123456",
324
+ ORG_NAME: "My Organization",
325
+ TAGS: "environment:production,region:us-east-1"
326
+ },
327
+ contentType: "application/json"
328
+ },
329
+ pathFragment: "",
330
+ webhookUrls: {},
331
+ webhookApiKeys: {},
332
+ invokeUrl: "",
333
+ executionId: "RXhhbXBsZUV4ZWN1dGlvblJlc3VsdElk",
334
+ customer: {
335
+ id: "testCustomerId",
336
+ name: "Test Customer",
337
+ externalId: "testExternalId"
338
+ },
339
+ instance: {
340
+ id: "testInstanceId",
341
+ name: "Test Instance"
342
+ },
343
+ user: {
344
+ id: "testUserId",
345
+ email: "user@example.com",
346
+ name: "Test User",
347
+ externalId: "testUserExternalId"
348
+ },
349
+ integration: {
350
+ id: "testIntegrationId",
351
+ name: "Test Integration",
352
+ versionSequenceId: "1",
353
+ externalVersion: ""
354
+ },
355
+ flow: {
356
+ id: "testFlowId",
357
+ name: "Test Flow",
358
+ stableId: "testFlowStableId"
359
+ },
360
+ startedAt: "2024-01-15T00:00:00.000Z",
361
+ globalDebug: false
362
+ } };
363
+ //#endregion
364
+ //#region src/inputs/common.ts
365
+ const connection = (0, _prismatic_io_spectral.input)({
366
+ label: "Connection",
367
+ type: "connection",
368
+ required: true,
369
+ comments: "The Datadog connection to use for authentication."
370
+ });
371
+ //#endregion
372
+ //#region src/inputs/dataSources.ts
373
+ const selectMetricInputs = { connection };
374
+ //#endregion
375
+ //#region src/inputs/metrics.ts
376
+ const metricName = (0, _prismatic_io_spectral.input)({
377
+ label: "Metric Name",
378
+ type: "string",
379
+ required: true,
380
+ placeholder: "Enter metric name",
381
+ comments: "The name of the timeseries metric (e.g., system.load.1, custom.my_metric).",
382
+ example: "system.load.1",
383
+ dataSource: "selectMetric",
384
+ clean: _prismatic_io_spectral.util.types.toString
385
+ });
386
+ const metricSeries = (0, _prismatic_io_spectral.input)({
387
+ label: "Metric Series",
388
+ type: "code",
389
+ required: true,
390
+ language: "json",
391
+ placeholder: "Enter metric series as a JSON array",
392
+ comments: "JSON array of metric series to submit. Each series must include \"metric\" (name) and \"points\" (array of {timestamp, value}). Optional fields: type, interval, unit, tags, resources.",
393
+ example: JSON.stringify([{
394
+ metric: "system.load.1",
395
+ type: 3,
396
+ points: [{
397
+ timestamp: 1636629071,
398
+ value: .7
399
+ }],
400
+ resources: [{
401
+ name: "dummyhost",
402
+ type: "host"
403
+ }],
404
+ tags: ["environment:production"]
405
+ }], null, 2),
406
+ clean: toMetricSeries
407
+ });
408
+ const metricType = (0, _prismatic_io_spectral.input)({
409
+ label: "Type",
410
+ type: "string",
411
+ required: false,
412
+ model: METRIC_TYPE_OPTIONS,
413
+ comments: "The type of metric. Gauge is the default if unspecified. Count and Rate types require an interval.",
414
+ clean: toOptionalMetricIntakeType
415
+ });
416
+ const metricValue = (0, _prismatic_io_spectral.input)({
417
+ label: "Value",
418
+ type: "string",
419
+ required: true,
420
+ placeholder: "Enter metric value",
421
+ comments: "The numeric value for the metric data point (64-bit float).",
422
+ example: "0.7",
423
+ clean: toRequiredNumber("Value")
424
+ });
425
+ const metricTimestamp = (0, _prismatic_io_spectral.input)({
426
+ label: "Timestamp",
427
+ type: "string",
428
+ required: false,
429
+ placeholder: "Enter Unix timestamp in seconds",
430
+ comments: "Unix timestamp in seconds. Defaults to the current time if not provided. Must be within 10 minutes in the future or 1 hour in the past.",
431
+ example: "1636629071",
432
+ clean: toOptionalNumber
433
+ });
434
+ const metricTags = (0, _prismatic_io_spectral.input)({
435
+ label: "Tags",
436
+ type: "string",
437
+ required: false,
438
+ collection: "valuelist",
439
+ placeholder: "Enter tag",
440
+ comments: "Tags associated with the metric. Each tag is a string in \"key:value\" format.",
441
+ example: "environment:production",
442
+ clean: toStringList
443
+ });
444
+ const metricUnit = (0, _prismatic_io_spectral.input)({
445
+ label: "Unit",
446
+ type: "string",
447
+ required: false,
448
+ placeholder: "Enter metric unit",
449
+ comments: "The unit of the metric value (e.g., byte, second, request).",
450
+ example: "byte",
451
+ clean: toOptionalString
452
+ });
453
+ const metricInterval = (0, _prismatic_io_spectral.input)({
454
+ label: "Interval",
455
+ type: "string",
456
+ required: false,
457
+ placeholder: "Enter interval in seconds",
458
+ comments: "The interval in seconds. Required if the metric type is rate or count.",
459
+ example: "60",
460
+ clean: toOptionalNumber
461
+ });
462
+ const resourceName = (0, _prismatic_io_spectral.input)({
463
+ label: "Resource Name",
464
+ type: "string",
465
+ required: false,
466
+ placeholder: "Enter resource name",
467
+ comments: "The name of the resource to associate with this metric (e.g., hostname).",
468
+ example: "my-host",
469
+ clean: toOptionalString
470
+ });
471
+ const resourceType = (0, _prismatic_io_spectral.input)({
472
+ label: "Resource Type",
473
+ type: "string",
474
+ required: false,
475
+ placeholder: "Enter resource type",
476
+ comments: "The type of resource (e.g., \"host\").",
477
+ example: "host",
478
+ clean: toOptionalString
479
+ });
480
+ const metricsFrom = (0, _prismatic_io_spectral.input)({
481
+ label: "From",
482
+ type: "string",
483
+ required: true,
484
+ placeholder: "Enter Unix timestamp in seconds",
485
+ comments: "Unix timestamp (seconds) from which to list active metrics. Metrics reported after this time are returned.",
486
+ example: "1636629071",
487
+ clean: toRequiredNumber("From")
488
+ });
489
+ const metricsHost = (0, _prismatic_io_spectral.input)({
490
+ label: "Host",
491
+ type: "string",
492
+ required: false,
493
+ placeholder: "Enter hostname to filter by",
494
+ comments: "Hostname to filter the list of active metrics. Only metrics reported by this host are returned.",
495
+ example: "my-host",
496
+ clean: toOptionalString
497
+ });
498
+ const metricsTagFilter = (0, _prismatic_io_spectral.input)({
499
+ label: "Tag Filter",
500
+ type: "string",
501
+ required: false,
502
+ placeholder: "Enter tag filter expression",
503
+ comments: "Filter metrics by tag. Supports boolean expressions (e.g., \"env:production AND role:web\").",
504
+ example: "env:production",
505
+ clean: toOptionalString
506
+ });
507
+ const metricsQuery = (0, _prismatic_io_spectral.input)({
508
+ label: "Query",
509
+ type: "string",
510
+ required: true,
511
+ placeholder: "Enter metric name search query",
512
+ comments: "Search query to find metrics by name prefix. The \"metrics:\" prefix is added automatically.",
513
+ example: "system.cpu",
514
+ clean: _prismatic_io_spectral.util.types.toString
515
+ });
516
+ const submitMetricsInputs = {
517
+ connection,
518
+ metricSeries
519
+ };
520
+ const submitSingleMetricInputs = {
521
+ connection,
522
+ metricName,
523
+ metricValue,
524
+ metricTimestamp,
525
+ metricTags,
526
+ metricFields: (0, _prismatic_io_spectral.structuredObjectInput)({
527
+ label: "Metric Fields",
528
+ comments: "Optional metric configuration and resource details.",
529
+ inputs: {
530
+ metricType,
531
+ metricUnit,
532
+ metricInterval,
533
+ resourceName,
534
+ resourceType
535
+ }
536
+ })
537
+ };
538
+ const listMetricsInputs = {
539
+ connection,
540
+ metricsFrom,
541
+ metricsHost,
542
+ metricsTagFilter
543
+ };
544
+ const searchMetricsInputs = {
545
+ connection,
546
+ metricsQuery
547
+ };
548
+ //#endregion
549
+ //#region src/inputs/misc.ts
550
+ const rawRequestInputs = {
551
+ connection,
552
+ ..._prismatic_io_spectral_http.inputs,
553
+ url: {
554
+ ..._prismatic_io_spectral_http.inputs.url,
555
+ comments: "The URL path to send the request to. The base URL is determined by the Datadog Site configured in the connection. For example, to call the Submit Metrics endpoint, enter /api/v2/series.",
556
+ example: "/api/v2/series"
557
+ }
558
+ };
559
+ //#endregion
560
+ //#region src/inputs/webhooks.ts
561
+ const webhookName = (0, _prismatic_io_spectral.input)({
562
+ label: "Webhook Name",
563
+ type: "string",
564
+ required: true,
565
+ placeholder: "Enter webhook name",
566
+ comments: "The name of the webhook. Used in Datadog monitor notifications as @webhook-NAME.",
567
+ example: "my-integration-webhook",
568
+ clean: _prismatic_io_spectral.util.types.toString
569
+ });
570
+ const webhookUrl = (0, _prismatic_io_spectral.input)({
571
+ label: "Webhook URL",
572
+ type: "string",
573
+ required: true,
574
+ placeholder: "Enter webhook URL",
575
+ comments: "The URL of the webhook endpoint that will receive the data.",
576
+ example: "https://hooks.example.com/datadog",
577
+ clean: _prismatic_io_spectral.util.types.toString
578
+ });
579
+ const webhookCustomHeaders = (0, _prismatic_io_spectral.input)({
580
+ label: "Custom Headers",
581
+ type: "code",
582
+ required: false,
583
+ language: "json",
584
+ placeholder: "Enter custom headers as JSON",
585
+ comments: "Custom headers to attach to webhook requests as a JSON string. Useful for authentication headers.",
586
+ example: "{\"Authorization\": \"Bearer my-token\"}",
587
+ clean: toOptionalString
588
+ });
589
+ const webhookEncodeAs = (0, _prismatic_io_spectral.input)({
590
+ label: "Encode As",
591
+ type: "string",
592
+ required: false,
593
+ model: WEBHOOK_ENCODE_AS_OPTIONS,
594
+ comments: "Encoding type for the webhook payload. Defaults to \"json\".",
595
+ clean: toOptionalString
596
+ });
597
+ const webhookPayload = (0, _prismatic_io_spectral.input)({
598
+ label: "Payload",
599
+ type: "code",
600
+ required: false,
601
+ language: "json",
602
+ placeholder: "Enter custom JSON payload",
603
+ comments: "Custom JSON payload for the webhook. If not provided, uses the default Datadog payload with standard variables like $ALERT_TITLE, $ALERT_STATUS, etc.",
604
+ example: "{\"title\": \"$ALERT_TITLE\", \"status\": \"$ALERT_STATUS\"}",
605
+ clean: toOptionalString
606
+ });
607
+ const createWebhookInputs = {
608
+ connection,
609
+ webhookName,
610
+ webhookUrl,
611
+ webhookCustomHeaders,
612
+ webhookEncodeAs,
613
+ webhookPayload
614
+ };
615
+ const updateWebhookInputs = {
616
+ connection,
617
+ webhookName,
618
+ webhookUrl: {
619
+ ...webhookUrl,
620
+ required: false,
621
+ clean: toOptionalString
622
+ },
623
+ webhookCustomHeaders,
624
+ webhookEncodeAs,
625
+ webhookPayload
626
+ };
627
+ const getWebhookInputs = {
628
+ connection,
629
+ webhookName
630
+ };
631
+ const deleteWebhookInputs = {
632
+ connection,
633
+ webhookName
634
+ };
635
+ //#endregion
636
+ //#region src/inputs/triggers.ts
637
+ const webhookInputs = {
638
+ connection,
639
+ webhookName,
640
+ webhookPayload,
641
+ webhookCustomHeaders
642
+ };
643
+ //#endregion
644
+ //#region src/outputSchemas/metrics.ts
645
+ const listMetricsOutputSchema = {
646
+ type: "object",
647
+ properties: {
648
+ from: { type: "string" },
649
+ metrics: {
650
+ type: "array",
651
+ items: { type: "string" }
652
+ }
653
+ }
654
+ };
655
+ const searchMetricsOutputSchema = {
656
+ type: "object",
657
+ properties: { results: {
658
+ type: "object",
659
+ properties: { metrics: {
660
+ type: "array",
661
+ items: { type: "string" }
662
+ } }
663
+ } }
664
+ };
665
+ const submitMetricsOutputSchema = {
666
+ type: "object",
667
+ properties: { errors: {
668
+ type: "array",
669
+ items: { type: "string" }
670
+ } }
671
+ };
672
+ //#endregion
673
+ //#region src/outputSchemas/webhooks.ts
674
+ const webhooksIntegrationSchema = {
675
+ type: "object",
676
+ properties: {
677
+ name: { type: "string" },
678
+ url: { type: "string" },
679
+ custom_headers: { type: ["string", "null"] },
680
+ encode_as: {
681
+ type: "string",
682
+ enum: ["json", "form"]
683
+ },
684
+ payload: { type: ["string", "null"] }
685
+ },
686
+ required: ["name", "url"]
687
+ };
688
+ const createWebhookOutputSchema = webhooksIntegrationSchema;
689
+ const getWebhookOutputSchema = webhooksIntegrationSchema;
690
+ const updateWebhookOutputSchema = webhooksIntegrationSchema;
691
+ const deleteWebhookOutputSchema = { type: "null" };
692
+ //#endregion
693
+ //#region src/actions/metrics/index.ts
694
+ var metrics_default = {
695
+ listMetrics: (0, _prismatic_io_spectral.action)({
696
+ display: {
697
+ label: "List Metrics",
698
+ description: "List active metric names that have reported data since a given timestamp, with optional host and tag filtering."
699
+ },
700
+ inputs: listMetricsInputs,
701
+ outputSchema: (0, _prismatic_io_spectral.outputSchema)({
702
+ type: "actionOutput",
703
+ schema: listMetricsOutputSchema
704
+ }),
705
+ performSafety: "notAllowed",
706
+ perform: async (context, { connection, metricsFrom, metricsHost, metricsTagFilter }) => {
707
+ const client = createClient(connection);
708
+ const params = {
709
+ from: metricsFrom,
710
+ ...metricsHost && { host: metricsHost },
711
+ ...metricsTagFilter && { tag_filter: metricsTagFilter }
712
+ };
713
+ return { data: (await client.get("/api/v1/metrics", { params })).data };
714
+ },
715
+ examplePerform: async (_context, { metricsFrom }) => ({ data: {
716
+ ...listMetricsExamplePayload.data,
717
+ from: String(metricsFrom)
718
+ } }),
719
+ examplePayload: listMetricsExamplePayload
720
+ }),
721
+ searchMetrics: (0, _prismatic_io_spectral.action)({
722
+ display: {
723
+ label: "Search Metrics",
724
+ description: "Search for Datadog metrics by name prefix. Returns matching metric names."
725
+ },
726
+ inputs: searchMetricsInputs,
727
+ outputSchema: (0, _prismatic_io_spectral.outputSchema)({
728
+ type: "actionOutput",
729
+ schema: searchMetricsOutputSchema
730
+ }),
731
+ performSafety: "notAllowed",
732
+ perform: async (_context, { connection, metricsQuery }) => {
733
+ return { data: (await createClient(connection).get(SEARCH_METRICS_PATH, { params: { q: `${METRICS_QUERY_PREFIX}${metricsQuery}` } })).data };
734
+ },
735
+ examplePerform: async () => ({ ...searchMetricsExamplePayload }),
736
+ examplePayload: searchMetricsExamplePayload
737
+ }),
738
+ submitMetrics: (0, _prismatic_io_spectral.action)({
739
+ display: {
740
+ label: "Submit Metrics",
741
+ description: "Submit time-series metric data to Datadog for graphing on dashboards. Uses the v2 API endpoint."
742
+ },
743
+ inputs: submitMetricsInputs,
744
+ outputSchema: (0, _prismatic_io_spectral.outputSchema)({
745
+ type: "actionOutput",
746
+ schema: submitMetricsOutputSchema
747
+ }),
748
+ performSafety: "notAllowed",
749
+ perform: async (_context, { connection, metricSeries }) => {
750
+ return { data: (await createClient(connection).post(SUBMIT_METRICS_PATH, { series: metricSeries })).data };
751
+ },
752
+ examplePerform: async () => ({ ...submitMetricsExamplePayload }),
753
+ examplePayload: submitMetricsExamplePayload
754
+ }),
755
+ submitSingleMetric: (0, _prismatic_io_spectral.action)({
756
+ display: {
757
+ label: "Submit Single Metric",
758
+ description: "Submit a single metric data point to Datadog. For bulk submissions, use the Submit Metrics action."
759
+ },
760
+ inputs: submitSingleMetricInputs,
761
+ outputSchema: (0, _prismatic_io_spectral.outputSchema)({
762
+ type: "actionOutput",
763
+ schema: submitMetricsOutputSchema
764
+ }),
765
+ performSafety: "notAllowed",
766
+ perform: async (context, { connection, metricName, metricValue, metricTimestamp, metricTags, metricFields }) => {
767
+ const client = createClient(connection);
768
+ const series = {
769
+ metric: metricName,
770
+ points: [{
771
+ timestamp: metricTimestamp,
772
+ value: metricValue
773
+ }],
774
+ type: metricFields.metricType,
775
+ tags: metricTags,
776
+ unit: metricFields.metricUnit,
777
+ interval: metricFields.metricInterval,
778
+ ...metricFields.resourceName || metricFields.resourceType ? { resources: [{
779
+ name: metricFields.resourceName,
780
+ type: metricFields.resourceType
781
+ }] } : {}
782
+ };
783
+ return { data: (await client.post(SUBMIT_METRICS_PATH, { series: [series] })).data };
784
+ },
785
+ examplePerform: async () => ({ ...submitSingleMetricExamplePayload }),
786
+ examplePayload: submitSingleMetricExamplePayload
787
+ })
788
+ };
789
+ //#endregion
790
+ //#region src/actions/misc/index.ts
791
+ var misc_default = { rawRequest: (0, _prismatic_io_spectral.action)({
792
+ display: {
793
+ label: "Raw Request",
794
+ description: "Send a raw HTTP request to any Datadog API endpoint."
795
+ },
796
+ inputs: rawRequestInputs,
797
+ performSafety: "notAllowed",
798
+ perform: async (_context, { connection: conn, ...httpInputs }) => {
799
+ validateConnection(conn);
800
+ const { data } = await (0, _prismatic_io_spectral_http.sendRawRequest)(getBaseUrl(conn), {
801
+ ...httpInputs,
802
+ debugRequest: false
803
+ }, getAuthHeaders(conn));
804
+ return { data };
805
+ }
806
+ }) };
807
+ //#endregion
808
+ //#region src/actions/webhooks/index.ts
809
+ var webhooks_default = {
810
+ createWebhook: (0, _prismatic_io_spectral.action)({
811
+ display: {
812
+ label: "Create Webhook",
813
+ description: "Create a new webhook integration endpoint in Datadog. The webhook can then be referenced in monitor notifications as @webhook-NAME."
814
+ },
815
+ inputs: createWebhookInputs,
816
+ outputSchema: (0, _prismatic_io_spectral.outputSchema)({
817
+ type: "actionOutput",
818
+ schema: createWebhookOutputSchema
819
+ }),
820
+ performSafety: "notAllowed",
821
+ perform: async (context, { connection, webhookName, webhookUrl, webhookCustomHeaders, webhookEncodeAs, webhookPayload }) => {
822
+ return { data: (await createClient(connection).post(WEBHOOKS_CONFIGURATION_PATH, {
823
+ name: webhookName,
824
+ url: webhookUrl,
825
+ custom_headers: webhookCustomHeaders,
826
+ encode_as: webhookEncodeAs,
827
+ payload: webhookPayload
828
+ })).data };
829
+ },
830
+ examplePerform: async (_context, { webhookName, webhookUrl, webhookCustomHeaders, webhookEncodeAs, webhookPayload }) => ({ data: {
831
+ ...createWebhookExamplePayload.data,
832
+ name: webhookName,
833
+ url: webhookUrl,
834
+ custom_headers: webhookCustomHeaders ?? null,
835
+ encode_as: webhookEncodeAs ?? "json",
836
+ payload: webhookPayload ?? null
837
+ } }),
838
+ examplePayload: createWebhookExamplePayload
839
+ }),
840
+ deleteWebhook: (0, _prismatic_io_spectral.action)({
841
+ display: {
842
+ label: "Delete Webhook",
843
+ description: "Delete a Datadog webhook integration by name. This action cannot be undone."
844
+ },
845
+ inputs: deleteWebhookInputs,
846
+ outputSchema: (0, _prismatic_io_spectral.outputSchema)({
847
+ type: "actionOutput",
848
+ schema: deleteWebhookOutputSchema
849
+ }),
850
+ performSafety: "notAllowed",
851
+ perform: async (_context, { connection, webhookName }) => {
852
+ await createClient(connection).delete(`${WEBHOOKS_CONFIGURATION_PATH}/${encodeURIComponent(webhookName)}`);
853
+ return { data: null };
854
+ },
855
+ examplePerform: async () => ({ ...deleteWebhookExamplePayload }),
856
+ examplePayload: deleteWebhookExamplePayload
857
+ }),
858
+ getWebhook: (0, _prismatic_io_spectral.action)({
859
+ display: {
860
+ label: "Get Webhook",
861
+ description: "Retrieve the configuration of a specific Datadog webhook integration by name."
862
+ },
863
+ inputs: getWebhookInputs,
864
+ outputSchema: (0, _prismatic_io_spectral.outputSchema)({
865
+ type: "actionOutput",
866
+ schema: getWebhookOutputSchema
867
+ }),
868
+ performSafety: "safe",
869
+ perform: async (_context, { connection, webhookName }) => {
870
+ return { data: (await createClient(connection).get(`${WEBHOOKS_CONFIGURATION_PATH}/${encodeURIComponent(webhookName)}`)).data };
871
+ },
872
+ examplePayload: getWebhookExamplePayload
873
+ }),
874
+ updateWebhook: (0, _prismatic_io_spectral.action)({
875
+ display: {
876
+ label: "Update Webhook",
877
+ description: "Update the configuration of an existing Datadog webhook integration."
878
+ },
879
+ inputs: updateWebhookInputs,
880
+ outputSchema: (0, _prismatic_io_spectral.outputSchema)({
881
+ type: "actionOutput",
882
+ schema: updateWebhookOutputSchema
883
+ }),
884
+ performSafety: "notAllowed",
885
+ perform: async (context, { connection, webhookName, webhookUrl, webhookCustomHeaders, webhookEncodeAs, webhookPayload }) => {
886
+ return { data: (await createClient(connection).put(`${WEBHOOKS_CONFIGURATION_PATH}/${encodeURIComponent(webhookName)}`, {
887
+ url: webhookUrl,
888
+ custom_headers: webhookCustomHeaders,
889
+ encode_as: webhookEncodeAs,
890
+ payload: webhookPayload
891
+ })).data };
892
+ },
893
+ examplePerform: async (_context, { webhookName, webhookUrl, webhookCustomHeaders, webhookEncodeAs, webhookPayload }) => ({ data: {
894
+ ...updateWebhookExamplePayload.data,
895
+ name: webhookName,
896
+ url: webhookUrl || updateWebhookExamplePayload.data.url,
897
+ custom_headers: webhookCustomHeaders ?? null,
898
+ encode_as: webhookEncodeAs ?? "json",
899
+ payload: webhookPayload ?? null
900
+ } }),
901
+ examplePayload: updateWebhookExamplePayload
902
+ })
903
+ };
904
+ //#endregion
905
+ //#region src/actions/index.ts
906
+ var actions_default = {
907
+ ...metrics_default,
908
+ ...misc_default,
909
+ ...webhooks_default
910
+ };
911
+ //#endregion
912
+ //#region src/dataSources/index.ts
913
+ var dataSources_default = { selectMetric: (0, _prismatic_io_spectral.dataSource)({
914
+ display: {
915
+ label: "Select Metric",
916
+ description: "A searchable picklist of metric names in the Datadog account."
917
+ },
918
+ inputs: selectMetricInputs,
919
+ perform: async (_context, { connection }) => {
920
+ const { data } = await createClient(connection).get(SEARCH_METRICS_PATH, { params: { q: METRICS_QUERY_PREFIX } });
921
+ return { result: (data.results?.metrics ?? []).map((metric) => ({
922
+ label: metric,
923
+ key: metric
924
+ })).sort((a, b) => (a.label ?? "") < (b.label ?? "") ? -1 : 1) };
925
+ },
926
+ examplePayload: selectMetricExamplePayload,
927
+ dataSourceType: "picklist"
928
+ }) };
929
+ //#endregion
930
+ //#region src/triggers/index.ts
931
+ var triggers_default = { webhook: (0, _prismatic_io_spectral.trigger)({
932
+ display: {
933
+ label: "Alert Notification Events",
934
+ description: "Receive Datadog monitor alert notifications via webhook. Automatically registers a webhook in Datadog on deploy and removes it on delete."
935
+ },
936
+ inputs: webhookInputs,
937
+ examplePayload: webhookExamplePayload,
938
+ perform: async (context, payload, params) => {
939
+ return Promise.resolve({ payload });
940
+ },
941
+ webhookLifecycleHandlers: {
942
+ create: async (context, { connection, webhookName, webhookPayload, webhookCustomHeaders }) => {
943
+ const client = createClient(connection);
944
+ const webhookUrl = context.webhookUrls[context.flow.name];
945
+ const stateKey = `${WEBHOOK_STATE_KEY_PREFIX}:${context.flow.stableId}`;
946
+ const previous = context.crossFlowState[stateKey];
947
+ if (previous && previous.webhookName !== webhookName) await deleteOwnedWebhook(client, context.logger, previous.webhookName, previous.webhookUrl);
948
+ const body = {
949
+ url: webhookUrl,
950
+ encode_as: DEFAULT_WEBHOOK_ENCODE_AS,
951
+ payload: webhookPayload,
952
+ custom_headers: webhookCustomHeaders
953
+ };
954
+ const existing = await findWebhook(client, webhookName);
955
+ if (existing && existing.url !== webhookUrl) throw new Error(`A Datadog webhook named "${webhookName}" already exists and points to a different URL. Choose a unique Webhook Name.`);
956
+ if (existing) await client.put(webhookConfigurationPath(webhookName), body);
957
+ else await client.post(WEBHOOKS_CONFIGURATION_PATH, {
958
+ name: webhookName,
959
+ ...body
960
+ });
961
+ context.logger.info(`Registered Datadog webhook "${webhookName}" pointing to ${webhookUrl}`);
962
+ const registered = {
963
+ webhookName,
964
+ webhookUrl
965
+ };
966
+ return { crossFlowState: {
967
+ ...context.crossFlowState,
968
+ [stateKey]: registered
969
+ } };
970
+ },
971
+ delete: async (context, { connection, webhookName }) => {
972
+ const client = createClient(connection);
973
+ const stateKey = `${WEBHOOK_STATE_KEY_PREFIX}:${context.flow.stableId}`;
974
+ const registered = context.crossFlowState[stateKey];
975
+ await deleteOwnedWebhook(client, context.logger, webhookName, registered?.webhookUrl ?? context.webhookUrls?.[context.flow.name]);
976
+ }
977
+ },
978
+ synchronousResponseSupport: "invalid",
979
+ scheduleSupport: "invalid"
980
+ }) };
981
+ //#endregion
982
+ //#region src/index.ts
983
+ var src_default = (0, _prismatic_io_spectral.component)({
984
+ key: "datadog",
985
+ public: true,
986
+ documentationUrl: "https://prismatic.io/docs/components/datadog/",
987
+ display: {
988
+ label: "Datadog",
989
+ description: "Interact with the Datadog API to submit metrics, manage webhooks, and monitor infrastructure and application performance.",
990
+ iconPath: "icon.png",
991
+ category: "Data Platforms"
992
+ },
993
+ hooks: { error: _prismatic_io_spectral_http.handleErrors },
994
+ actions: actions_default,
995
+ connections: connections_default,
996
+ dataSources: dataSources_default,
997
+ triggers: triggers_default
998
+ });
999
+ //#endregion
1000
+ //#region npm-dist/.entry.ts
1001
+ var _entry_default = (0, _prismatic_io_spectral.callableComponent)(src_default);
1002
+ //#endregion
1003
+ module.exports = _entry_default;