datadog-mcp 5.4.0 → 5.6.0
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.
- package/README.md +14 -4
- package/dist/index.js +941 -46
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -134929,7 +134929,7 @@ var require_InputSchema = __commonJS({
|
|
|
134929
134929
|
"use strict";
|
|
134930
134930
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
134931
134931
|
exports.InputSchema = void 0;
|
|
134932
|
-
var
|
|
134932
|
+
var InputSchema24 = class _InputSchema {
|
|
134933
134933
|
constructor() {
|
|
134934
134934
|
}
|
|
134935
134935
|
/**
|
|
@@ -134939,8 +134939,8 @@ var require_InputSchema = __commonJS({
|
|
|
134939
134939
|
return _InputSchema.attributeTypeMap;
|
|
134940
134940
|
}
|
|
134941
134941
|
};
|
|
134942
|
-
exports.InputSchema =
|
|
134943
|
-
|
|
134942
|
+
exports.InputSchema = InputSchema24;
|
|
134943
|
+
InputSchema24.attributeTypeMap = {
|
|
134944
134944
|
parameters: {
|
|
134945
134945
|
baseName: "parameters",
|
|
134946
134946
|
type: "Array<InputSchemaParameters>"
|
|
@@ -281731,10 +281731,10 @@ var require_object_inspect = __commonJS({
|
|
|
281731
281731
|
}
|
|
281732
281732
|
if (!isDate(obj) && !isRegExp(obj)) {
|
|
281733
281733
|
var ys = arrObjKeys(obj, inspect);
|
|
281734
|
-
var
|
|
281734
|
+
var isPlainObject4 = gPO ? gPO(obj) === Object.prototype : obj instanceof Object || obj.constructor === Object;
|
|
281735
281735
|
var protoTag = obj instanceof Object ? "" : "null prototype";
|
|
281736
|
-
var stringTag = !
|
|
281737
|
-
var constructorTag =
|
|
281736
|
+
var stringTag = !isPlainObject4 && toStringTag && Object(obj) === obj && toStringTag in obj ? $slice.call(toStr(obj), 8, -1) : protoTag ? "Object" : "";
|
|
281737
|
+
var constructorTag = isPlainObject4 || typeof obj.constructor !== "function" ? "" : obj.constructor.name ? obj.constructor.name + " " : "";
|
|
281738
281738
|
var tag = constructorTag + (stringTag || protoTag ? "[" + $join.call($concat.call([], stringTag || [], protoTag || []), ": ") + "] " : "");
|
|
281739
281739
|
if (ys.length === 0) {
|
|
281740
281740
|
return tag + "{}";
|
|
@@ -302583,7 +302583,10 @@ function createDatadogClients(config2) {
|
|
|
302583
302583
|
usage: new import_datadog_api_client.v1.UsageMeteringApi(configuration),
|
|
302584
302584
|
spans: new import_datadog_api_client.v2.SpansApi(configuration),
|
|
302585
302585
|
services: new import_datadog_api_client.v2.ServiceDefinitionApi(configuration),
|
|
302586
|
-
auth: new import_datadog_api_client.v1.AuthenticationApi(configuration)
|
|
302586
|
+
auth: new import_datadog_api_client.v1.AuthenticationApi(configuration),
|
|
302587
|
+
logsPipelines: new import_datadog_api_client.v1.LogsPipelinesApi(configuration),
|
|
302588
|
+
logsIndexes: new import_datadog_api_client.v1.LogsIndexesApi(configuration),
|
|
302589
|
+
logsArchives: new import_datadog_api_client.v2.LogsArchivesApi(configuration)
|
|
302587
302590
|
};
|
|
302588
302591
|
}
|
|
302589
302592
|
|
|
@@ -302661,7 +302664,8 @@ var WRITE_ACTIONS = /* @__PURE__ */ new Set([
|
|
|
302661
302664
|
"unmute",
|
|
302662
302665
|
"cancel",
|
|
302663
302666
|
"add",
|
|
302664
|
-
"trigger"
|
|
302667
|
+
"trigger",
|
|
302668
|
+
"reorder"
|
|
302665
302669
|
]);
|
|
302666
302670
|
function checkReadOnly(action, readOnly) {
|
|
302667
302671
|
if (readOnly && WRITE_ACTIONS.has(action)) {
|
|
@@ -302941,6 +302945,20 @@ var InputSchema = {
|
|
|
302941
302945
|
),
|
|
302942
302946
|
maxEvents: external_exports.number().min(1).max(5e3).optional().describe(
|
|
302943
302947
|
"Maximum events to fetch for grouping in top action (default: 5000, max: 5000). Higher = more accurate but slower"
|
|
302948
|
+
),
|
|
302949
|
+
// Monitor transition filter (additive — see requirement 5.2 / monitors action=history)
|
|
302950
|
+
transitionType: external_exports.array(
|
|
302951
|
+
external_exports.enum([
|
|
302952
|
+
"alert",
|
|
302953
|
+
"alert recovery",
|
|
302954
|
+
"warning",
|
|
302955
|
+
"warning recovery",
|
|
302956
|
+
"no data",
|
|
302957
|
+
"no data recovery",
|
|
302958
|
+
"renotify"
|
|
302959
|
+
])
|
|
302960
|
+
).optional().describe(
|
|
302961
|
+
'Filter events by monitor state transition type. When set, restricts results to events with @monitor.transition.transition_type matching any value. Use ["alert","alert recovery"] to count real fires/recoveries and skip renotifies. Empty array is treated as undefined (no filter). For a fires-only count by monitor ID, prefer monitors action=history.'
|
|
302944
302962
|
)
|
|
302945
302963
|
};
|
|
302946
302964
|
function extractMonitorInfo(title) {
|
|
@@ -303168,6 +303186,9 @@ async function createEventV1(api, params) {
|
|
|
303168
303186
|
}
|
|
303169
303187
|
};
|
|
303170
303188
|
}
|
|
303189
|
+
function quoteIfNeeded(value) {
|
|
303190
|
+
return /^[A-Za-z0-9_.-]+$/.test(value) ? value : `"${value}"`;
|
|
303191
|
+
}
|
|
303171
303192
|
function buildEventQuery(params) {
|
|
303172
303193
|
const parts = [];
|
|
303173
303194
|
if (params.query) {
|
|
@@ -303185,6 +303206,10 @@ function buildEventQuery(params) {
|
|
|
303185
303206
|
if (params.priority) {
|
|
303186
303207
|
parts.push(`priority:${params.priority}`);
|
|
303187
303208
|
}
|
|
303209
|
+
if (params.transitionType && params.transitionType.length > 0) {
|
|
303210
|
+
const inner = params.transitionType.map(quoteIfNeeded).join(" OR ");
|
|
303211
|
+
parts.push(`@monitor.transition.transition_type:(${inner})`);
|
|
303212
|
+
}
|
|
303188
303213
|
return parts.length > 0 ? parts.join(" ") : "*";
|
|
303189
303214
|
}
|
|
303190
303215
|
async function searchEventsV2(api, params, limits, site) {
|
|
@@ -303200,7 +303225,8 @@ async function searchEventsV2(api, params, limits, site) {
|
|
|
303200
303225
|
query: params.query,
|
|
303201
303226
|
sources: params.sources,
|
|
303202
303227
|
tags: params.tags,
|
|
303203
|
-
priority: params.priority
|
|
303228
|
+
priority: params.priority,
|
|
303229
|
+
transitionType: params.transitionType
|
|
303204
303230
|
});
|
|
303205
303231
|
const effectiveLimit = params.limit ?? limits.defaultLimit;
|
|
303206
303232
|
const body = {
|
|
@@ -303243,7 +303269,8 @@ async function aggregateEventsV2(api, params, limits, site) {
|
|
|
303243
303269
|
const fullQuery = buildEventQuery({
|
|
303244
303270
|
query: params.query,
|
|
303245
303271
|
sources: params.sources,
|
|
303246
|
-
tags: params.tags
|
|
303272
|
+
tags: params.tags,
|
|
303273
|
+
transitionType: params.transitionType
|
|
303247
303274
|
});
|
|
303248
303275
|
const groupByFields = params.groupBy ?? ["monitor_name"];
|
|
303249
303276
|
const maxEventsToAggregate = 1e4;
|
|
@@ -303325,7 +303352,8 @@ async function topEventsV2(api, params, limits, site) {
|
|
|
303325
303352
|
to: params.to,
|
|
303326
303353
|
sources: params.sources,
|
|
303327
303354
|
tags: effectiveTags,
|
|
303328
|
-
limit: params.maxEvents ?? 5e3
|
|
303355
|
+
limit: params.maxEvents ?? 5e3,
|
|
303356
|
+
transitionType: params.transitionType
|
|
303329
303357
|
},
|
|
303330
303358
|
limits,
|
|
303331
303359
|
site
|
|
@@ -303414,7 +303442,8 @@ async function timeseriesEventsV2(api, params, limits, site) {
|
|
|
303414
303442
|
const fullQuery = buildEventQuery({
|
|
303415
303443
|
query: params.query ?? "source:alert",
|
|
303416
303444
|
sources: params.sources,
|
|
303417
|
-
tags: params.tags
|
|
303445
|
+
tags: params.tags,
|
|
303446
|
+
transitionType: params.transitionType
|
|
303418
303447
|
});
|
|
303419
303448
|
const intervalMs = parseIntervalToMs(params.interval);
|
|
303420
303449
|
const groupByFields = params.groupBy ?? ["monitor_name"];
|
|
@@ -303499,7 +303528,8 @@ async function incidentsEventsV2(api, params, limits, site) {
|
|
|
303499
303528
|
const fullQuery = buildEventQuery({
|
|
303500
303529
|
query: params.query ?? "source:alert",
|
|
303501
303530
|
sources: params.sources,
|
|
303502
|
-
tags: params.tags
|
|
303531
|
+
tags: params.tags,
|
|
303532
|
+
transitionType: params.transitionType
|
|
303503
303533
|
});
|
|
303504
303534
|
const dedupeWindowNs = parseDurationToNs(params.dedupeWindow ?? "5m");
|
|
303505
303535
|
const dedupeWindowMs = dedupeWindowNs ? Math.floor(dedupeWindowNs / 1e6) : 3e5;
|
|
@@ -303687,10 +303717,17 @@ function registerEventsTool(server, apiV1, apiV2, monitorsApi, limits, readOnly
|
|
|
303687
303717
|
`Track Datadog events. Actions: list, get, create, search, aggregate, top, timeseries, incidents, discover.
|
|
303688
303718
|
For monitor alerts, use tags: ["source:alert"].
|
|
303689
303719
|
|
|
303720
|
+
IMPORTANT \u2014 re-evaluation vs transition:
|
|
303721
|
+
- source:alert events INCLUDE renotifies and re-evaluations (every Datadog re-evaluation of an alerting monitor emits an event). A "how many times did monitor X fire" question answered with source:alert alone over-counts.
|
|
303722
|
+
- To restrict to real state transitions, pass transitionType (e.g. ["alert","alert recovery"]). This appends @monitor.transition.transition_type:(...) to the query and matches the design's live investigation.
|
|
303723
|
+
- For a fires-only numeric count rooted in a single monitor ID, prefer the higher-level primitive monitors action=history \u2014 it returns {transitions, count, meta} with the same filter applied for you.
|
|
303724
|
+
|
|
303725
|
+
transitionType: Optional array of monitor transition types (alert, alert recovery, warning, warning recovery, no data, no data recovery, renotify). Empty array is treated as undefined.
|
|
303690
303726
|
top: Generic event grouping by any fields (groupBy parameter). Returns groups ranked by count with optional context breakdown.
|
|
303691
303727
|
- Example: {groupBy: ["service"], message: "...", service: "api", total_count: 50, by_context: [{context: "queue:X", count: 30}]}
|
|
303692
303728
|
- Use for deployments, configs, custom events, or monitor alerts
|
|
303693
303729
|
- Returns "message" field (event title), NOT monitor name (use monitors tool for real names)
|
|
303730
|
+
- total_count includes renotifies when source:alert is used without transitionType \u2014 see monitors action=history for fires-only counts
|
|
303694
303731
|
discover: Returns available tag prefixes from events.
|
|
303695
303732
|
aggregate: Custom groupBy, returns pipe-delimited keys.
|
|
303696
303733
|
search: Full event details.
|
|
@@ -303716,7 +303753,8 @@ incidents: Deduplicate alerts with dedupeWindow.`,
|
|
|
303716
303753
|
dedupeWindow,
|
|
303717
303754
|
enrich,
|
|
303718
303755
|
contextTags,
|
|
303719
|
-
maxEvents
|
|
303756
|
+
maxEvents,
|
|
303757
|
+
transitionType
|
|
303720
303758
|
}) => {
|
|
303721
303759
|
try {
|
|
303722
303760
|
checkReadOnly(action, readOnly);
|
|
@@ -303765,7 +303803,8 @@ incidents: Deduplicate alerts with dedupeWindow.`,
|
|
|
303765
303803
|
tags,
|
|
303766
303804
|
priority,
|
|
303767
303805
|
limit,
|
|
303768
|
-
cursor
|
|
303806
|
+
cursor,
|
|
303807
|
+
transitionType
|
|
303769
303808
|
},
|
|
303770
303809
|
limits,
|
|
303771
303810
|
site
|
|
@@ -303787,7 +303826,8 @@ incidents: Deduplicate alerts with dedupeWindow.`,
|
|
|
303787
303826
|
sources,
|
|
303788
303827
|
tags,
|
|
303789
303828
|
groupBy,
|
|
303790
|
-
limit
|
|
303829
|
+
limit,
|
|
303830
|
+
transitionType
|
|
303791
303831
|
},
|
|
303792
303832
|
limits,
|
|
303793
303833
|
site
|
|
@@ -303806,7 +303846,8 @@ incidents: Deduplicate alerts with dedupeWindow.`,
|
|
|
303806
303846
|
limit,
|
|
303807
303847
|
groupBy,
|
|
303808
303848
|
contextTags,
|
|
303809
|
-
maxEvents
|
|
303849
|
+
maxEvents,
|
|
303850
|
+
transitionType
|
|
303810
303851
|
},
|
|
303811
303852
|
limits,
|
|
303812
303853
|
site
|
|
@@ -303839,7 +303880,8 @@ incidents: Deduplicate alerts with dedupeWindow.`,
|
|
|
303839
303880
|
tags,
|
|
303840
303881
|
groupBy,
|
|
303841
303882
|
interval,
|
|
303842
|
-
limit
|
|
303883
|
+
limit,
|
|
303884
|
+
transitionType
|
|
303843
303885
|
},
|
|
303844
303886
|
limits,
|
|
303845
303887
|
site
|
|
@@ -303856,7 +303898,8 @@ incidents: Deduplicate alerts with dedupeWindow.`,
|
|
|
303856
303898
|
sources,
|
|
303857
303899
|
tags,
|
|
303858
303900
|
dedupeWindow,
|
|
303859
|
-
limit
|
|
303901
|
+
limit,
|
|
303902
|
+
transitionType
|
|
303860
303903
|
},
|
|
303861
303904
|
limits,
|
|
303862
303905
|
site
|
|
@@ -303882,7 +303925,8 @@ var ActionSchema2 = external_exports.enum([
|
|
|
303882
303925
|
"delete",
|
|
303883
303926
|
"mute",
|
|
303884
303927
|
"unmute",
|
|
303885
|
-
"top"
|
|
303928
|
+
"top",
|
|
303929
|
+
"history"
|
|
303886
303930
|
]);
|
|
303887
303931
|
var InputSchema2 = {
|
|
303888
303932
|
action: ActionSchema2.describe("Action to perform"),
|
|
@@ -303903,8 +303947,117 @@ var InputSchema2 = {
|
|
|
303903
303947
|
contextTags: external_exports.array(external_exports.string()).optional().describe(
|
|
303904
303948
|
"Tag prefixes for context breakdown in top action (default: queue, service, ingress, pod_name, kube_namespace, kube_container_name)"
|
|
303905
303949
|
),
|
|
303906
|
-
maxEvents: external_exports.number().min(1).max(5e3).optional().describe("Maximum events to fetch for top action (default: 5000, max: 5000)")
|
|
303950
|
+
maxEvents: external_exports.number().min(1).max(5e3).optional().describe("Maximum events to fetch for top action (default: 5000, max: 5000)"),
|
|
303951
|
+
// History action parameters
|
|
303952
|
+
transitionType: external_exports.array(
|
|
303953
|
+
external_exports.enum([
|
|
303954
|
+
"alert",
|
|
303955
|
+
"alert recovery",
|
|
303956
|
+
"warning",
|
|
303957
|
+
"warning recovery",
|
|
303958
|
+
"no data",
|
|
303959
|
+
"no data recovery",
|
|
303960
|
+
"renotify"
|
|
303961
|
+
])
|
|
303962
|
+
).optional().describe(
|
|
303963
|
+
'For history action: filter by monitor state transition types. Default: ["alert","alert recovery"] (real fires + recoveries, excludes renotifies). Pass ["alert"] for fires only, or include "renotify" for full chronological audit.'
|
|
303964
|
+
),
|
|
303965
|
+
group: external_exports.string().optional().describe(
|
|
303966
|
+
'For history action: filter transitions to a specific multi-alert monitor group (e.g., "pod_name:foo,kube_namespace:bar"). Optional; omit for all groups.'
|
|
303967
|
+
)
|
|
303907
303968
|
};
|
|
303969
|
+
var MonitorThresholdsSchema = external_exports.object({
|
|
303970
|
+
critical: external_exports.number().optional(),
|
|
303971
|
+
warning: external_exports.number().optional(),
|
|
303972
|
+
ok: external_exports.number().optional(),
|
|
303973
|
+
criticalRecovery: external_exports.number().optional(),
|
|
303974
|
+
warningRecovery: external_exports.number().optional(),
|
|
303975
|
+
unknown: external_exports.number().optional()
|
|
303976
|
+
}).passthrough();
|
|
303977
|
+
var MonitorThresholdWindowsSchema = external_exports.object({
|
|
303978
|
+
triggerWindow: external_exports.string().optional(),
|
|
303979
|
+
recoveryWindow: external_exports.string().optional()
|
|
303980
|
+
}).passthrough();
|
|
303981
|
+
var SchedulingOptionsSchema = external_exports.object({
|
|
303982
|
+
evaluationWindow: external_exports.record(external_exports.unknown()).optional(),
|
|
303983
|
+
customSchedule: external_exports.record(external_exports.unknown()).optional()
|
|
303984
|
+
}).passthrough();
|
|
303985
|
+
var MonitorOptionsSchema = external_exports.object({
|
|
303986
|
+
// Notification
|
|
303987
|
+
notifyNoData: external_exports.boolean().optional(),
|
|
303988
|
+
noDataTimeframe: external_exports.number().optional(),
|
|
303989
|
+
notifyAudit: external_exports.boolean().optional(),
|
|
303990
|
+
notificationPresetName: external_exports.string().optional(),
|
|
303991
|
+
// Evaluation / delay
|
|
303992
|
+
newHostDelay: external_exports.number().optional(),
|
|
303993
|
+
newGroupDelay: external_exports.number().optional(),
|
|
303994
|
+
evaluationDelay: external_exports.number().optional(),
|
|
303995
|
+
requireFullWindow: external_exports.boolean().optional(),
|
|
303996
|
+
onMissingData: external_exports.string().optional(),
|
|
303997
|
+
// Renotification
|
|
303998
|
+
renotifyInterval: external_exports.number().nullable().optional(),
|
|
303999
|
+
renotifyOccurrences: external_exports.number().optional(),
|
|
304000
|
+
renotifyStatuses: external_exports.array(external_exports.string()).optional(),
|
|
304001
|
+
escalationMessage: external_exports.string().optional(),
|
|
304002
|
+
// Lifecycle
|
|
304003
|
+
timeoutH: external_exports.number().nullable().optional(),
|
|
304004
|
+
includeTags: external_exports.boolean().optional(),
|
|
304005
|
+
locked: external_exports.boolean().optional(),
|
|
304006
|
+
silenced: external_exports.record(external_exports.number().nullable()).optional(),
|
|
304007
|
+
groupRetentionDuration: external_exports.string().optional(),
|
|
304008
|
+
// Thresholds & scheduling
|
|
304009
|
+
thresholds: MonitorThresholdsSchema.optional(),
|
|
304010
|
+
thresholdWindows: MonitorThresholdWindowsSchema.optional(),
|
|
304011
|
+
schedulingOptions: SchedulingOptionsSchema.optional()
|
|
304012
|
+
}).passthrough();
|
|
304013
|
+
var MonitorConfigSchema = external_exports.object({
|
|
304014
|
+
name: external_exports.string().optional(),
|
|
304015
|
+
type: external_exports.string().optional(),
|
|
304016
|
+
query: external_exports.string().optional(),
|
|
304017
|
+
message: external_exports.string().optional(),
|
|
304018
|
+
tags: external_exports.array(external_exports.string()).optional(),
|
|
304019
|
+
priority: external_exports.number().int().min(1).max(5).nullable().optional(),
|
|
304020
|
+
restrictedRoles: external_exports.array(external_exports.string()).nullable().optional(),
|
|
304021
|
+
multi: external_exports.boolean().optional(),
|
|
304022
|
+
options: MonitorOptionsSchema.optional()
|
|
304023
|
+
}).passthrough();
|
|
304024
|
+
var KNOWN_TOP_LEVEL_KEYS = new Set(
|
|
304025
|
+
Object.keys(MonitorConfigSchema.shape).filter((key) => key !== "options")
|
|
304026
|
+
);
|
|
304027
|
+
var KNOWN_OPTIONS_KEYS = new Set(
|
|
304028
|
+
Object.keys(MonitorOptionsSchema.shape)
|
|
304029
|
+
);
|
|
304030
|
+
function collectUnknownKeyWarnings(config2) {
|
|
304031
|
+
const warnings = [];
|
|
304032
|
+
for (const key of Object.keys(config2)) {
|
|
304033
|
+
if (!KNOWN_TOP_LEVEL_KEYS.has(key) && key !== "options") {
|
|
304034
|
+
warnings.push(`unknown top-level key '${key}' under config forwarded without validation`);
|
|
304035
|
+
}
|
|
304036
|
+
}
|
|
304037
|
+
const options = config2.options;
|
|
304038
|
+
if (isPlainObject3(options)) {
|
|
304039
|
+
for (const key of Object.keys(options)) {
|
|
304040
|
+
if (!KNOWN_OPTIONS_KEYS.has(key)) {
|
|
304041
|
+
warnings.push(
|
|
304042
|
+
`unknown option key '${key}' under config.options forwarded without validation`
|
|
304043
|
+
);
|
|
304044
|
+
}
|
|
304045
|
+
}
|
|
304046
|
+
}
|
|
304047
|
+
return warnings;
|
|
304048
|
+
}
|
|
304049
|
+
function isPlainObject3(value) {
|
|
304050
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
304051
|
+
}
|
|
304052
|
+
function summarizeZodIssue(error2) {
|
|
304053
|
+
const issue2 = error2.issues[0];
|
|
304054
|
+
if (!issue2) {
|
|
304055
|
+
return "validation failed";
|
|
304056
|
+
}
|
|
304057
|
+
const path = issue2.path.length > 0 ? issue2.path.join(".") : "<root>";
|
|
304058
|
+
const expected = issue2.code === "invalid_type" && "expected" in issue2 ? `expected ${String(issue2.expected)}` : issue2.message;
|
|
304059
|
+
return `${path}: ${expected}`;
|
|
304060
|
+
}
|
|
303908
304061
|
function formatMonitor(m, site = "datadoghq.com") {
|
|
303909
304062
|
const monitorId = m.id ?? 0;
|
|
303910
304063
|
return {
|
|
@@ -303936,6 +304089,153 @@ function formatMonitorDetail(m, site = "datadoghq.com") {
|
|
|
303936
304089
|
}
|
|
303937
304090
|
return detail;
|
|
303938
304091
|
}
|
|
304092
|
+
var DEFAULT_HISTORY_TRANSITION_TYPES = [
|
|
304093
|
+
"alert",
|
|
304094
|
+
"alert recovery"
|
|
304095
|
+
];
|
|
304096
|
+
function quoteIfNeeded2(value) {
|
|
304097
|
+
return /^[A-Za-z0-9_.-]+$/.test(value) ? value : `"${value}"`;
|
|
304098
|
+
}
|
|
304099
|
+
function buildMonitorHistoryQuery(params) {
|
|
304100
|
+
const parts = ["source:alert", `@monitor.id:${params.monitorId}`];
|
|
304101
|
+
const transitionTypes = params.transitionType && params.transitionType.length > 0 ? params.transitionType : void 0;
|
|
304102
|
+
if (transitionTypes) {
|
|
304103
|
+
const inner = transitionTypes.map(quoteIfNeeded2).join(" OR ");
|
|
304104
|
+
parts.push(`@monitor.transition.transition_type:(${inner})`);
|
|
304105
|
+
}
|
|
304106
|
+
if (params.group && params.group.length > 0) {
|
|
304107
|
+
const escaped = params.group.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
304108
|
+
parts.push(`@monitor.groups:"${escaped}"`);
|
|
304109
|
+
}
|
|
304110
|
+
return parts.join(" ");
|
|
304111
|
+
}
|
|
304112
|
+
function isMonitorState(value) {
|
|
304113
|
+
return value === "Alert" || value === "Warn" || value === "OK" || value === "No Data";
|
|
304114
|
+
}
|
|
304115
|
+
function isTransitionType(value) {
|
|
304116
|
+
return value === "alert" || value === "alert recovery" || value === "warning" || value === "warning recovery" || value === "no data" || value === "no data recovery" || value === "renotify";
|
|
304117
|
+
}
|
|
304118
|
+
function extractTimestamp(outer, inner) {
|
|
304119
|
+
const outerTs = outer.timestamp;
|
|
304120
|
+
if (outerTs instanceof Date) {
|
|
304121
|
+
return outerTs.toISOString();
|
|
304122
|
+
}
|
|
304123
|
+
if (typeof outerTs === "string" && outerTs.length > 0) {
|
|
304124
|
+
const d = new Date(outerTs);
|
|
304125
|
+
if (!Number.isNaN(d.getTime())) return d.toISOString();
|
|
304126
|
+
}
|
|
304127
|
+
const innerTs = inner.timestamp;
|
|
304128
|
+
if (typeof innerTs === "number" && Number.isFinite(innerTs)) {
|
|
304129
|
+
return new Date(innerTs).toISOString();
|
|
304130
|
+
}
|
|
304131
|
+
if (typeof innerTs === "string" && innerTs.length > 0) {
|
|
304132
|
+
const parsed = Number.parseInt(innerTs, 10);
|
|
304133
|
+
if (!Number.isNaN(parsed)) {
|
|
304134
|
+
return new Date(parsed).toISOString();
|
|
304135
|
+
}
|
|
304136
|
+
}
|
|
304137
|
+
return "";
|
|
304138
|
+
}
|
|
304139
|
+
function formatMonitorTransition(event) {
|
|
304140
|
+
const outer = event.attributes ?? {};
|
|
304141
|
+
const inner = outer.attributes ?? {};
|
|
304142
|
+
const monitor = inner.monitor;
|
|
304143
|
+
if (!monitor) {
|
|
304144
|
+
return null;
|
|
304145
|
+
}
|
|
304146
|
+
const transition = monitor.transition ?? monitor.additionalProperties?.transition;
|
|
304147
|
+
if (!transition) {
|
|
304148
|
+
return null;
|
|
304149
|
+
}
|
|
304150
|
+
const fromState = isMonitorState(transition.source_state) ? transition.source_state : null;
|
|
304151
|
+
const toState = isMonitorState(transition.destination_state) ? transition.destination_state : null;
|
|
304152
|
+
const transitionType = isTransitionType(transition.transition_type) ? transition.transition_type : null;
|
|
304153
|
+
if (!fromState || !toState || !transitionType) {
|
|
304154
|
+
return null;
|
|
304155
|
+
}
|
|
304156
|
+
const groupsRaw = monitor.groups;
|
|
304157
|
+
const group = Array.isArray(groupsRaw) && groupsRaw.length > 0 ? groupsRaw.map((g) => String(g)).join(",") : null;
|
|
304158
|
+
const monitorId = typeof monitor.id === "number" ? monitor.id : 0;
|
|
304159
|
+
const monitorName = typeof monitor.name === "string" && monitor.name.length > 0 ? monitor.name : `Monitor ${monitorId}`;
|
|
304160
|
+
return {
|
|
304161
|
+
timestamp: extractTimestamp(outer, inner),
|
|
304162
|
+
monitorId,
|
|
304163
|
+
monitorName,
|
|
304164
|
+
group,
|
|
304165
|
+
fromState,
|
|
304166
|
+
toState,
|
|
304167
|
+
transitionType,
|
|
304168
|
+
eventId: String(event.id ?? "")
|
|
304169
|
+
};
|
|
304170
|
+
}
|
|
304171
|
+
async function historyMonitor(eventsApi, monitorId, params, limits, site) {
|
|
304172
|
+
const defaultFrom = hoursAgo(limits.defaultTimeRangeHours);
|
|
304173
|
+
const defaultTo = now();
|
|
304174
|
+
const [validFrom, validTo] = ensureValidTimeRange(
|
|
304175
|
+
parseTime(params.from, defaultFrom),
|
|
304176
|
+
parseTime(params.to, defaultTo)
|
|
304177
|
+
);
|
|
304178
|
+
const fromTime = new Date(validFrom * 1e3).toISOString();
|
|
304179
|
+
const toTime = new Date(validTo * 1e3).toISOString();
|
|
304180
|
+
const effectiveTransitionTypes = params.transitionType && params.transitionType.length > 0 ? params.transitionType : [...DEFAULT_HISTORY_TRANSITION_TYPES];
|
|
304181
|
+
const query = buildMonitorHistoryQuery({
|
|
304182
|
+
monitorId,
|
|
304183
|
+
transitionType: effectiveTransitionTypes,
|
|
304184
|
+
group: params.group
|
|
304185
|
+
});
|
|
304186
|
+
const transitions = [];
|
|
304187
|
+
const maxEventsToProcess = 1e4;
|
|
304188
|
+
const maxPages = 100;
|
|
304189
|
+
let eventCount = 0;
|
|
304190
|
+
let pageCount = 0;
|
|
304191
|
+
const body = {
|
|
304192
|
+
filter: {
|
|
304193
|
+
query,
|
|
304194
|
+
from: fromTime,
|
|
304195
|
+
to: toTime
|
|
304196
|
+
},
|
|
304197
|
+
sort: "timestamp",
|
|
304198
|
+
page: { limit: 1e3 }
|
|
304199
|
+
};
|
|
304200
|
+
let cursor;
|
|
304201
|
+
while (pageCount < maxPages && eventCount < maxEventsToProcess) {
|
|
304202
|
+
const pageBody = { ...body, page: { ...body.page, cursor } };
|
|
304203
|
+
const response = await eventsApi.searchEvents({ body: pageBody });
|
|
304204
|
+
const events = response.data ?? [];
|
|
304205
|
+
if (events.length === 0) break;
|
|
304206
|
+
for (const event of events) {
|
|
304207
|
+
const transition = formatMonitorTransition(event);
|
|
304208
|
+
if (transition !== null) {
|
|
304209
|
+
transitions.push(transition);
|
|
304210
|
+
}
|
|
304211
|
+
eventCount++;
|
|
304212
|
+
if (eventCount >= maxEventsToProcess) break;
|
|
304213
|
+
}
|
|
304214
|
+
cursor = response.meta?.page?.after;
|
|
304215
|
+
if (!cursor) break;
|
|
304216
|
+
pageCount++;
|
|
304217
|
+
}
|
|
304218
|
+
const truncated = eventCount >= maxEventsToProcess;
|
|
304219
|
+
const resolvedGroup = params.group && params.group.length > 0 ? params.group : null;
|
|
304220
|
+
const count = transitions.length;
|
|
304221
|
+
const meta = {
|
|
304222
|
+
monitorId,
|
|
304223
|
+
query,
|
|
304224
|
+
from: fromTime,
|
|
304225
|
+
to: toTime,
|
|
304226
|
+
transitionTypes: effectiveTransitionTypes,
|
|
304227
|
+
group: resolvedGroup,
|
|
304228
|
+
count,
|
|
304229
|
+
totalFetched: eventCount,
|
|
304230
|
+
truncated,
|
|
304231
|
+
datadog_url: buildEventsUrl(query, validFrom, validTo, site)
|
|
304232
|
+
};
|
|
304233
|
+
return {
|
|
304234
|
+
transitions,
|
|
304235
|
+
count,
|
|
304236
|
+
meta
|
|
304237
|
+
};
|
|
304238
|
+
}
|
|
303939
304239
|
async function listMonitors(api, params, limits, site) {
|
|
303940
304240
|
const effectiveLimit = params.limit ?? limits.defaultLimit;
|
|
303941
304241
|
const response = await api.listMonitors({
|
|
@@ -304012,6 +304312,11 @@ function normalizeMonitorConfig(config2, isUpdate = false) {
|
|
|
304012
304312
|
["include_tags", "includeTags"],
|
|
304013
304313
|
["require_full_window", "requireFullWindow"],
|
|
304014
304314
|
["escalation_message", "escalationMessage"],
|
|
304315
|
+
["notification_preset_name", "notificationPresetName"],
|
|
304316
|
+
["on_missing_data", "onMissingData"],
|
|
304317
|
+
["group_retention_duration", "groupRetentionDuration"],
|
|
304318
|
+
["threshold_windows", "thresholdWindows"],
|
|
304319
|
+
["scheduling_options", "schedulingOptions"],
|
|
304015
304320
|
["locked", "locked"],
|
|
304016
304321
|
["silenced", "silenced"]
|
|
304017
304322
|
];
|
|
@@ -304043,21 +304348,49 @@ function normalizeMonitorConfig(config2, isUpdate = false) {
|
|
|
304043
304348
|
return normalized;
|
|
304044
304349
|
}
|
|
304045
304350
|
async function createMonitor(api, config2, site = "datadoghq.com") {
|
|
304046
|
-
const
|
|
304351
|
+
const normalized = normalizeMonitorConfig(config2);
|
|
304352
|
+
try {
|
|
304353
|
+
MonitorConfigSchema.parse(normalized);
|
|
304354
|
+
} catch (error2) {
|
|
304355
|
+
if (error2 instanceof external_exports.ZodError) {
|
|
304356
|
+
throw new Error(`EINVALID_MONITOR_CONFIG: ${summarizeZodIssue(error2)}`);
|
|
304357
|
+
}
|
|
304358
|
+
throw error2;
|
|
304359
|
+
}
|
|
304360
|
+
const warnings = collectUnknownKeyWarnings(normalized);
|
|
304361
|
+
const body = normalized;
|
|
304047
304362
|
const monitor = await api.createMonitor({ body });
|
|
304048
|
-
|
|
304363
|
+
const result = {
|
|
304049
304364
|
success: true,
|
|
304050
304365
|
monitor: formatMonitorDetail(monitor, site)
|
|
304051
304366
|
};
|
|
304367
|
+
if (warnings.length > 0) {
|
|
304368
|
+
result.warnings = warnings;
|
|
304369
|
+
}
|
|
304370
|
+
return result;
|
|
304052
304371
|
}
|
|
304053
304372
|
async function updateMonitor(api, id, config2, site = "datadoghq.com") {
|
|
304054
304373
|
const monitorId = Number.parseInt(id, 10);
|
|
304055
|
-
const
|
|
304374
|
+
const normalized = normalizeMonitorConfig(config2, true);
|
|
304375
|
+
try {
|
|
304376
|
+
MonitorConfigSchema.parse(normalized);
|
|
304377
|
+
} catch (error2) {
|
|
304378
|
+
if (error2 instanceof external_exports.ZodError) {
|
|
304379
|
+
throw new Error(`EINVALID_MONITOR_CONFIG: ${summarizeZodIssue(error2)}`);
|
|
304380
|
+
}
|
|
304381
|
+
throw error2;
|
|
304382
|
+
}
|
|
304383
|
+
const warnings = collectUnknownKeyWarnings(normalized);
|
|
304384
|
+
const body = normalized;
|
|
304056
304385
|
const monitor = await api.updateMonitor({ monitorId, body });
|
|
304057
|
-
|
|
304386
|
+
const result = {
|
|
304058
304387
|
success: true,
|
|
304059
304388
|
monitor: formatMonitorDetail(monitor, site)
|
|
304060
304389
|
};
|
|
304390
|
+
if (warnings.length > 0) {
|
|
304391
|
+
result.warnings = warnings;
|
|
304392
|
+
}
|
|
304393
|
+
return result;
|
|
304061
304394
|
}
|
|
304062
304395
|
async function deleteMonitor(api, id) {
|
|
304063
304396
|
const monitorId = Number.parseInt(id, 10);
|
|
@@ -304210,16 +304543,47 @@ async function topMonitors(eventsApi, monitorsApi, params, limits, site) {
|
|
|
304210
304543
|
function registerMonitorsTool(server, api, eventsApi, limits, readOnly = false, site = "datadoghq.com") {
|
|
304211
304544
|
server.tool(
|
|
304212
304545
|
"monitors",
|
|
304213
|
-
`Manage Datadog monitors. Actions: list, get, search, create, update, delete, mute, unmute, top.
|
|
304546
|
+
`Manage Datadog monitors. Actions: list, get, search, create, update, delete, mute, unmute, top, history.
|
|
304214
304547
|
Filters: name, tags, groupStates (alert/warn/ok/no data).
|
|
304215
|
-
get/create/update return the full options object
|
|
304548
|
+
get/create/update return the full options object so callers can safely read-then-patch.
|
|
304549
|
+
|
|
304550
|
+
create/update accept a config object validated against a typed schema covering the documented Datadog Monitor fields:
|
|
304551
|
+
- Top-level: name, type, query, message, tags, priority (1-5, nullable), restrictedRoles, multi, options.
|
|
304552
|
+
- options.* validated keys grouped by category:
|
|
304553
|
+
- notification: notifyNoData, noDataTimeframe, notifyAudit, notificationPresetName.
|
|
304554
|
+
- evaluation/delay: newHostDelay, newGroupDelay, evaluationDelay, requireFullWindow, onMissingData.
|
|
304555
|
+
- renotification: renotifyInterval (nullable), renotifyOccurrences, renotifyStatuses, escalationMessage.
|
|
304556
|
+
- lifecycle: timeoutH (nullable), includeTags, locked, silenced (record of timestamps/null), groupRetentionDuration.
|
|
304557
|
+
- thresholds: thresholds (critical/warning/ok/criticalRecovery/warningRecovery/unknown), thresholdWindows.
|
|
304558
|
+
- scheduling: schedulingOptions.
|
|
304559
|
+
Unknown keys (top-level or under options) are forwarded to Datadog as-is and surfaced via an optional warnings array on the response, so the schema does not lag the API.
|
|
304560
|
+
snake_case aliases are accepted on input and normalized to camelCase before validation.
|
|
304561
|
+
Validation errors short-circuit before any HTTP call and surface as 'EINVALID_MONITOR_CONFIG: <path>: <expected>'.
|
|
304562
|
+
Reference: https://docs.datadoghq.com/api/latest/monitors/
|
|
304216
304563
|
|
|
304217
304564
|
top: Ranked monitors by alert frequency with real monitor names and context breakdown.
|
|
304218
304565
|
- Returns: {rank, monitor_id, name (with {{template.vars}}), message (template), total_count, by_context}
|
|
304219
304566
|
- Perfect for weekly/daily alert reports
|
|
304220
304567
|
- Gets real monitor names from monitors API (not event titles)
|
|
304221
|
-
|
|
304222
|
-
For
|
|
304568
|
+
- WARNING: total_count is the raw alert-event count and INCLUDES renotifies/re-evaluations.
|
|
304569
|
+
For monitors stuck in Alert state, Datadog emits a renotify event every renotify_interval
|
|
304570
|
+
minutes, which inflates this count well beyond the number of real fires. When the question
|
|
304571
|
+
is "how many times did this monitor actually fire", use action=history instead.
|
|
304572
|
+
|
|
304573
|
+
history: Count and list real state transitions for one monitor over a time window.
|
|
304574
|
+
- Inputs: id (required, monitor ID), from/to (optional time range), transitionType (optional
|
|
304575
|
+
filter, defaults to ["alert","alert recovery"]), group (optional multi-alert group filter).
|
|
304576
|
+
- Returns: {transitions: [{timestamp, monitorId, monitorName, group, fromState, toState,
|
|
304577
|
+
transitionType, eventId}], count, meta}
|
|
304578
|
+
- count = transitions.length \u2014 the number of REAL state changes (fires + recoveries by
|
|
304579
|
+
default), NOT the renotify-inflated count returned by action=top or events action=search.
|
|
304580
|
+
- Backed by Datadog v2 events search with a hardcoded source:alert + @monitor.transition.
|
|
304581
|
+
transition_type filter that excludes renotifies by default. To include renotifies, pass
|
|
304582
|
+
transitionType including "renotify".
|
|
304583
|
+
|
|
304584
|
+
For generic event grouping (deployments, configs), use events tool instead. Note that the
|
|
304585
|
+
events tool's action=search with source:alert ALSO includes renotifies; use its
|
|
304586
|
+
transitionType filter (or this action=history) for fires-only counts.`,
|
|
304223
304587
|
InputSchema2,
|
|
304224
304588
|
async ({
|
|
304225
304589
|
action,
|
|
@@ -304234,7 +304598,9 @@ For generic event grouping (deployments, configs), use events tool instead.`,
|
|
|
304234
304598
|
from,
|
|
304235
304599
|
to,
|
|
304236
304600
|
contextTags,
|
|
304237
|
-
maxEvents
|
|
304601
|
+
maxEvents,
|
|
304602
|
+
transitionType,
|
|
304603
|
+
group
|
|
304238
304604
|
}) => {
|
|
304239
304605
|
try {
|
|
304240
304606
|
checkReadOnly(action, readOnly);
|
|
@@ -304289,6 +304655,22 @@ For generic event grouping (deployments, configs), use events tool instead.`,
|
|
|
304289
304655
|
site
|
|
304290
304656
|
)
|
|
304291
304657
|
);
|
|
304658
|
+
case "history": {
|
|
304659
|
+
const monitorIdString = requireParam(id, "id", "history");
|
|
304660
|
+
const monitorId = Number.parseInt(monitorIdString, 10);
|
|
304661
|
+
if (Number.isNaN(monitorId)) {
|
|
304662
|
+
throw new Error(`Invalid monitor ID: ${monitorIdString}`);
|
|
304663
|
+
}
|
|
304664
|
+
return toolResult(
|
|
304665
|
+
await historyMonitor(
|
|
304666
|
+
eventsApi,
|
|
304667
|
+
monitorId,
|
|
304668
|
+
{ from, to, transitionType, group },
|
|
304669
|
+
limits,
|
|
304670
|
+
site
|
|
304671
|
+
)
|
|
304672
|
+
);
|
|
304673
|
+
}
|
|
304292
304674
|
default:
|
|
304293
304675
|
throw new Error(`Unknown action: ${action}`);
|
|
304294
304676
|
}
|
|
@@ -305584,6 +305966,22 @@ function registerIncidentsTool(server, api, limits, readOnly = false, _site = "d
|
|
|
305584
305966
|
);
|
|
305585
305967
|
}
|
|
305586
305968
|
|
|
305969
|
+
// src/utils/normalize.ts
|
|
305970
|
+
function snakeToCamel2(str) {
|
|
305971
|
+
return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
|
|
305972
|
+
}
|
|
305973
|
+
function normalizeConfigKeys(obj) {
|
|
305974
|
+
if (obj === null || obj === void 0) return obj;
|
|
305975
|
+
if (Array.isArray(obj)) return obj.map(normalizeConfigKeys);
|
|
305976
|
+
if (typeof obj !== "object") return obj;
|
|
305977
|
+
const normalized = {};
|
|
305978
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
305979
|
+
const camelKey = snakeToCamel2(key);
|
|
305980
|
+
normalized[camelKey] = normalizeConfigKeys(value);
|
|
305981
|
+
}
|
|
305982
|
+
return normalized;
|
|
305983
|
+
}
|
|
305984
|
+
|
|
305587
305985
|
// src/tools/slos.ts
|
|
305588
305986
|
var ActionSchema8 = external_exports.enum(["list", "get", "create", "update", "delete", "history"]);
|
|
305589
305987
|
var InputSchema8 = {
|
|
@@ -305599,7 +305997,7 @@ var InputSchema8 = {
|
|
|
305599
305997
|
};
|
|
305600
305998
|
function formatSlo(s) {
|
|
305601
305999
|
const primaryThreshold = s.thresholds?.[0];
|
|
305602
|
-
|
|
306000
|
+
const summary = {
|
|
305603
306001
|
id: s.id ?? "",
|
|
305604
306002
|
name: s.name ?? "",
|
|
305605
306003
|
description: s.description ?? null,
|
|
@@ -305617,11 +306015,24 @@ function formatSlo(s) {
|
|
|
305617
306015
|
createdAt: s.createdAt ? new Date(s.createdAt * 1e3).toISOString() : "",
|
|
305618
306016
|
modifiedAt: s.modifiedAt ? new Date(s.modifiedAt * 1e3).toISOString() : ""
|
|
305619
306017
|
};
|
|
306018
|
+
if (s.query?.numerator && s.query.denominator) {
|
|
306019
|
+
summary.query = { numerator: s.query.numerator, denominator: s.query.denominator };
|
|
306020
|
+
}
|
|
306021
|
+
if (Array.isArray(s.monitorIds) && s.monitorIds.length > 0) {
|
|
306022
|
+
summary.monitorIds = s.monitorIds;
|
|
306023
|
+
}
|
|
306024
|
+
if (Array.isArray(s.monitorTags) && s.monitorTags.length > 0) {
|
|
306025
|
+
summary.monitorTags = s.monitorTags;
|
|
306026
|
+
}
|
|
306027
|
+
if (Array.isArray(s.groups) && s.groups.length > 0) {
|
|
306028
|
+
summary.groups = s.groups;
|
|
306029
|
+
}
|
|
306030
|
+
return summary;
|
|
305620
306031
|
}
|
|
305621
306032
|
function formatSearchSlo(slo) {
|
|
305622
306033
|
const attrs = slo.data?.attributes;
|
|
305623
306034
|
const primaryThreshold = attrs?.thresholds?.[0];
|
|
305624
|
-
|
|
306035
|
+
const summary = {
|
|
305625
306036
|
id: slo.data?.id ?? "",
|
|
305626
306037
|
name: attrs?.name ?? "",
|
|
305627
306038
|
description: attrs?.description ?? null,
|
|
@@ -305645,6 +306056,16 @@ function formatSearchSlo(slo) {
|
|
|
305645
306056
|
createdAt: attrs?.createdAt ? new Date(attrs.createdAt * 1e3).toISOString() : "",
|
|
305646
306057
|
modifiedAt: attrs?.modifiedAt ? new Date(attrs.modifiedAt * 1e3).toISOString() : ""
|
|
305647
306058
|
};
|
|
306059
|
+
if (attrs?.query?.numerator && attrs.query.denominator) {
|
|
306060
|
+
summary.query = { numerator: attrs.query.numerator, denominator: attrs.query.denominator };
|
|
306061
|
+
}
|
|
306062
|
+
if (Array.isArray(attrs?.monitorIds) && attrs.monitorIds.length > 0) {
|
|
306063
|
+
summary.monitorIds = attrs.monitorIds;
|
|
306064
|
+
}
|
|
306065
|
+
if (Array.isArray(attrs?.groups) && attrs.groups.length > 0) {
|
|
306066
|
+
summary.groups = attrs.groups;
|
|
306067
|
+
}
|
|
306068
|
+
return summary;
|
|
305648
306069
|
}
|
|
305649
306070
|
function buildSearchQuery(query, tags) {
|
|
305650
306071
|
const parts = [];
|
|
@@ -305680,20 +306101,6 @@ async function getSlo(api, id) {
|
|
|
305680
306101
|
slo: response.data ? formatSlo(response.data) : null
|
|
305681
306102
|
};
|
|
305682
306103
|
}
|
|
305683
|
-
function snakeToCamel2(str) {
|
|
305684
|
-
return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
|
|
305685
|
-
}
|
|
305686
|
-
function normalizeConfigKeys(obj) {
|
|
305687
|
-
if (obj === null || obj === void 0) return obj;
|
|
305688
|
-
if (Array.isArray(obj)) return obj.map(normalizeConfigKeys);
|
|
305689
|
-
if (typeof obj !== "object") return obj;
|
|
305690
|
-
const normalized = {};
|
|
305691
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
305692
|
-
const camelKey = snakeToCamel2(key);
|
|
305693
|
-
normalized[camelKey] = normalizeConfigKeys(value);
|
|
305694
|
-
}
|
|
305695
|
-
return normalized;
|
|
305696
|
-
}
|
|
305697
306104
|
function normalizeSloConfig(config2) {
|
|
305698
306105
|
const normalized = normalizeConfigKeys(config2);
|
|
305699
306106
|
if (!normalized.name) {
|
|
@@ -307944,6 +308351,488 @@ function registerSchemaTool(server) {
|
|
|
307944
308351
|
);
|
|
307945
308352
|
}
|
|
307946
308353
|
|
|
308354
|
+
// src/tools/logs_pipelines.ts
|
|
308355
|
+
var ActionSchema20 = external_exports.enum(["list", "get", "create", "update", "delete", "reorder", "get_order"]);
|
|
308356
|
+
var InputSchema21 = {
|
|
308357
|
+
action: ActionSchema20.describe("Action to perform"),
|
|
308358
|
+
id: external_exports.string().optional().describe("Pipeline ID (required for get/update/delete)"),
|
|
308359
|
+
config: external_exports.record(external_exports.unknown()).optional().describe(
|
|
308360
|
+
"Pipeline configuration (for create/update). Requires name and filter.query. Processors are forwarded unchanged."
|
|
308361
|
+
),
|
|
308362
|
+
pipeline_ids: external_exports.array(external_exports.string()).optional().describe("Ordered pipeline ID list (required for reorder)"),
|
|
308363
|
+
verbose: external_exports.boolean().optional().describe("Return full SDK payload alongside summary (default false)")
|
|
308364
|
+
};
|
|
308365
|
+
function formatPipeline(p, verbose = false) {
|
|
308366
|
+
const summary = {
|
|
308367
|
+
id: p.id ?? "",
|
|
308368
|
+
name: p.name ?? "",
|
|
308369
|
+
filterQuery: p.filter?.query ?? null,
|
|
308370
|
+
isEnabled: p.isEnabled ?? false,
|
|
308371
|
+
isReadOnly: p.isReadOnly ?? false,
|
|
308372
|
+
type: p.type ?? null,
|
|
308373
|
+
processorsCount: p.processors?.length ?? 0
|
|
308374
|
+
};
|
|
308375
|
+
if (verbose && p.processors) {
|
|
308376
|
+
summary.processors = p.processors;
|
|
308377
|
+
}
|
|
308378
|
+
return summary;
|
|
308379
|
+
}
|
|
308380
|
+
function normalizePipelineConfig(config2) {
|
|
308381
|
+
const normalized = normalizeConfigKeys(config2);
|
|
308382
|
+
if (!normalized.name) {
|
|
308383
|
+
throw new Error("Pipeline config requires 'name' field");
|
|
308384
|
+
}
|
|
308385
|
+
const filter = normalized.filter;
|
|
308386
|
+
if (!filter || typeof filter.query !== "string" || filter.query.length === 0) {
|
|
308387
|
+
throw new Error("Pipeline config requires 'filter.query' field");
|
|
308388
|
+
}
|
|
308389
|
+
return normalized;
|
|
308390
|
+
}
|
|
308391
|
+
async function listPipelines(api, verbose = false) {
|
|
308392
|
+
const response = await api.listLogsPipelines();
|
|
308393
|
+
const pipelines = (response ?? []).map((p) => formatPipeline(p, verbose));
|
|
308394
|
+
const result = { pipelines, total: pipelines.length };
|
|
308395
|
+
if (verbose) {
|
|
308396
|
+
result.raw = response;
|
|
308397
|
+
}
|
|
308398
|
+
return result;
|
|
308399
|
+
}
|
|
308400
|
+
async function getPipeline(api, id, verbose = false) {
|
|
308401
|
+
const response = await api.getLogsPipeline({ pipelineId: id });
|
|
308402
|
+
const result = { pipeline: formatPipeline(response, verbose) };
|
|
308403
|
+
if (verbose) {
|
|
308404
|
+
result.raw = response;
|
|
308405
|
+
}
|
|
308406
|
+
return result;
|
|
308407
|
+
}
|
|
308408
|
+
async function createPipeline(api, config2, verbose = false) {
|
|
308409
|
+
const body = normalizePipelineConfig(config2);
|
|
308410
|
+
const response = await api.createLogsPipeline({ body });
|
|
308411
|
+
const result = {
|
|
308412
|
+
success: true,
|
|
308413
|
+
pipeline: formatPipeline(response, verbose)
|
|
308414
|
+
};
|
|
308415
|
+
if (verbose) {
|
|
308416
|
+
result.raw = response;
|
|
308417
|
+
}
|
|
308418
|
+
return result;
|
|
308419
|
+
}
|
|
308420
|
+
async function updatePipeline(api, id, config2, verbose = false) {
|
|
308421
|
+
const body = normalizePipelineConfig(config2);
|
|
308422
|
+
const response = await api.updateLogsPipeline({ pipelineId: id, body });
|
|
308423
|
+
const result = {
|
|
308424
|
+
success: true,
|
|
308425
|
+
pipeline: formatPipeline(response, verbose)
|
|
308426
|
+
};
|
|
308427
|
+
if (verbose) {
|
|
308428
|
+
result.raw = response;
|
|
308429
|
+
}
|
|
308430
|
+
return result;
|
|
308431
|
+
}
|
|
308432
|
+
async function deletePipeline(api, id) {
|
|
308433
|
+
await api.deleteLogsPipeline({ pipelineId: id });
|
|
308434
|
+
return {
|
|
308435
|
+
success: true,
|
|
308436
|
+
message: `Pipeline ${id} deleted`
|
|
308437
|
+
};
|
|
308438
|
+
}
|
|
308439
|
+
async function reorderPipelines(api, pipelineIds) {
|
|
308440
|
+
const body = { pipelineIds };
|
|
308441
|
+
const response = await api.updateLogsPipelineOrder({ body });
|
|
308442
|
+
return {
|
|
308443
|
+
success: true,
|
|
308444
|
+
order: {
|
|
308445
|
+
pipelineIds: response.pipelineIds ?? []
|
|
308446
|
+
}
|
|
308447
|
+
};
|
|
308448
|
+
}
|
|
308449
|
+
async function getPipelineOrder(api) {
|
|
308450
|
+
const response = await api.getLogsPipelineOrder();
|
|
308451
|
+
return {
|
|
308452
|
+
order: {
|
|
308453
|
+
pipelineIds: response.pipelineIds ?? []
|
|
308454
|
+
}
|
|
308455
|
+
};
|
|
308456
|
+
}
|
|
308457
|
+
function registerLogsPipelinesTool(server, api, _limits, readOnly = false, _site = "datadoghq.com") {
|
|
308458
|
+
server.tool(
|
|
308459
|
+
"logs_pipelines",
|
|
308460
|
+
"Manage Datadog Logs pipelines (parsing & processor chains). Actions: list, get, create, update, delete, reorder, get_order. Pipelines run sequentially on incoming logs; reorder changes the structure of downstream data. Mutations are blocked when the server is in read-only mode. Unknown processor types in 'config.processors' are forwarded to Datadog unchanged.",
|
|
308461
|
+
InputSchema21,
|
|
308462
|
+
async ({ action, id, config: config2, pipeline_ids, verbose }) => {
|
|
308463
|
+
try {
|
|
308464
|
+
checkReadOnly(action, readOnly);
|
|
308465
|
+
const isVerbose = verbose ?? false;
|
|
308466
|
+
switch (action) {
|
|
308467
|
+
case "list":
|
|
308468
|
+
return toolResult(await listPipelines(api, isVerbose));
|
|
308469
|
+
case "get": {
|
|
308470
|
+
const pipelineId = requireParam(id, "id", "get");
|
|
308471
|
+
return toolResult(await getPipeline(api, pipelineId, isVerbose));
|
|
308472
|
+
}
|
|
308473
|
+
case "create": {
|
|
308474
|
+
const pipelineConfig = requireParam(config2, "config", "create");
|
|
308475
|
+
return toolResult(await createPipeline(api, pipelineConfig, isVerbose));
|
|
308476
|
+
}
|
|
308477
|
+
case "update": {
|
|
308478
|
+
const pipelineId = requireParam(id, "id", "update");
|
|
308479
|
+
const pipelineConfig = requireParam(config2, "config", "update");
|
|
308480
|
+
return toolResult(await updatePipeline(api, pipelineId, pipelineConfig, isVerbose));
|
|
308481
|
+
}
|
|
308482
|
+
case "delete": {
|
|
308483
|
+
const pipelineId = requireParam(id, "id", "delete");
|
|
308484
|
+
return toolResult(await deletePipeline(api, pipelineId));
|
|
308485
|
+
}
|
|
308486
|
+
case "reorder": {
|
|
308487
|
+
const ids = requireParam(pipeline_ids, "pipeline_ids", "reorder");
|
|
308488
|
+
return toolResult(await reorderPipelines(api, ids));
|
|
308489
|
+
}
|
|
308490
|
+
case "get_order":
|
|
308491
|
+
return toolResult(await getPipelineOrder(api));
|
|
308492
|
+
default:
|
|
308493
|
+
throw new Error(`Unknown action: ${String(action)}`);
|
|
308494
|
+
}
|
|
308495
|
+
} catch (error2) {
|
|
308496
|
+
handleDatadogError(error2);
|
|
308497
|
+
}
|
|
308498
|
+
}
|
|
308499
|
+
);
|
|
308500
|
+
}
|
|
308501
|
+
|
|
308502
|
+
// src/tools/logs_indexes.ts
|
|
308503
|
+
var ActionSchema21 = external_exports.enum(["list", "get", "update", "reorder", "get_order"]);
|
|
308504
|
+
var InputSchema22 = {
|
|
308505
|
+
action: ActionSchema21.describe("Action to perform"),
|
|
308506
|
+
name: external_exports.string().optional().describe("Index name (required for get/update). Datadog identifies indexes by name, not id."),
|
|
308507
|
+
config: external_exports.record(external_exports.unknown()).optional().describe(
|
|
308508
|
+
"Index configuration (for update). Requires filter.query and numRetentionDays. Exclusion filters are forwarded unchanged."
|
|
308509
|
+
),
|
|
308510
|
+
index_names: external_exports.array(external_exports.string()).optional().describe("Ordered index name list (required for reorder)"),
|
|
308511
|
+
verbose: external_exports.boolean().optional().describe("Return full SDK payload alongside summary (default false)")
|
|
308512
|
+
};
|
|
308513
|
+
function formatIndex(idx, verbose = false) {
|
|
308514
|
+
const summary = {
|
|
308515
|
+
name: idx.name ?? "",
|
|
308516
|
+
filterQuery: idx.filter?.query ?? null,
|
|
308517
|
+
exclusionFiltersCount: idx.exclusionFilters?.length ?? 0,
|
|
308518
|
+
numRetentionDays: idx.numRetentionDays ?? null,
|
|
308519
|
+
numFlexLogsRetentionDays: idx.numFlexLogsRetentionDays ?? null,
|
|
308520
|
+
dailyLimit: idx.dailyLimit ?? null,
|
|
308521
|
+
isRateLimited: idx.isRateLimited ?? false
|
|
308522
|
+
};
|
|
308523
|
+
if (verbose && idx.exclusionFilters) {
|
|
308524
|
+
summary.exclusionFilters = idx.exclusionFilters;
|
|
308525
|
+
}
|
|
308526
|
+
return summary;
|
|
308527
|
+
}
|
|
308528
|
+
function normalizeIndexConfig(config2) {
|
|
308529
|
+
const normalized = normalizeConfigKeys(config2);
|
|
308530
|
+
const filter = normalized.filter;
|
|
308531
|
+
if (!filter || typeof filter.query !== "string" || filter.query.length === 0) {
|
|
308532
|
+
throw new Error("Index config requires 'filter.query' field");
|
|
308533
|
+
}
|
|
308534
|
+
if (typeof normalized.numRetentionDays !== "number") {
|
|
308535
|
+
throw new Error("Index config requires 'numRetentionDays' field");
|
|
308536
|
+
}
|
|
308537
|
+
return normalized;
|
|
308538
|
+
}
|
|
308539
|
+
async function listIndexes(api, verbose = false) {
|
|
308540
|
+
const response = await api.listLogIndexes();
|
|
308541
|
+
const indexes = (response.indexes ?? []).map((idx) => formatIndex(idx, verbose));
|
|
308542
|
+
const result = { indexes, total: indexes.length };
|
|
308543
|
+
if (verbose) {
|
|
308544
|
+
result.raw = response;
|
|
308545
|
+
}
|
|
308546
|
+
return result;
|
|
308547
|
+
}
|
|
308548
|
+
async function getIndex(api, name, verbose = false) {
|
|
308549
|
+
const response = await api.getLogsIndex({ name });
|
|
308550
|
+
const result = { index: formatIndex(response, verbose) };
|
|
308551
|
+
if (verbose) {
|
|
308552
|
+
result.raw = response;
|
|
308553
|
+
}
|
|
308554
|
+
return result;
|
|
308555
|
+
}
|
|
308556
|
+
async function updateIndex(api, name, config2, verbose = false) {
|
|
308557
|
+
const body = normalizeIndexConfig(config2);
|
|
308558
|
+
const response = await api.updateLogsIndex({ name, body });
|
|
308559
|
+
const result = {
|
|
308560
|
+
success: true,
|
|
308561
|
+
index: formatIndex(response, verbose)
|
|
308562
|
+
};
|
|
308563
|
+
if (verbose) {
|
|
308564
|
+
result.raw = response;
|
|
308565
|
+
}
|
|
308566
|
+
return result;
|
|
308567
|
+
}
|
|
308568
|
+
async function reorderIndexes(api, indexNames) {
|
|
308569
|
+
const body = { indexNames };
|
|
308570
|
+
const response = await api.updateLogsIndexOrder({ body });
|
|
308571
|
+
return {
|
|
308572
|
+
success: true,
|
|
308573
|
+
order: {
|
|
308574
|
+
indexNames: response.indexNames ?? []
|
|
308575
|
+
}
|
|
308576
|
+
};
|
|
308577
|
+
}
|
|
308578
|
+
async function getIndexOrder(api) {
|
|
308579
|
+
const response = await api.getLogsIndexOrder();
|
|
308580
|
+
return {
|
|
308581
|
+
order: {
|
|
308582
|
+
indexNames: response.indexNames ?? []
|
|
308583
|
+
}
|
|
308584
|
+
};
|
|
308585
|
+
}
|
|
308586
|
+
function registerLogsIndexesTool(server, api, _limits, readOnly = false, _site = "datadoghq.com") {
|
|
308587
|
+
server.tool(
|
|
308588
|
+
"logs_indexes",
|
|
308589
|
+
"Manage Datadog Logs indexes (filters, retention, exclusion filters, daily limits). Actions: list, get, update, reorder, get_order. Datadog identifies indexes by 'name', not 'id'. Note: create/delete are UI-only per Datadog and not supported through the API. Mutations (update, reorder) are blocked when the server is in read-only mode.",
|
|
308590
|
+
InputSchema22,
|
|
308591
|
+
async ({ action, name, config: config2, index_names, verbose }) => {
|
|
308592
|
+
try {
|
|
308593
|
+
checkReadOnly(action, readOnly);
|
|
308594
|
+
const isVerbose = verbose ?? false;
|
|
308595
|
+
switch (action) {
|
|
308596
|
+
case "list":
|
|
308597
|
+
return toolResult(await listIndexes(api, isVerbose));
|
|
308598
|
+
case "get": {
|
|
308599
|
+
const indexName = requireParam(name, "name", "get");
|
|
308600
|
+
return toolResult(await getIndex(api, indexName, isVerbose));
|
|
308601
|
+
}
|
|
308602
|
+
case "update": {
|
|
308603
|
+
const indexName = requireParam(name, "name", "update");
|
|
308604
|
+
const indexConfig = requireParam(config2, "config", "update");
|
|
308605
|
+
return toolResult(await updateIndex(api, indexName, indexConfig, isVerbose));
|
|
308606
|
+
}
|
|
308607
|
+
case "reorder": {
|
|
308608
|
+
const names = requireParam(index_names, "index_names", "reorder");
|
|
308609
|
+
return toolResult(await reorderIndexes(api, names));
|
|
308610
|
+
}
|
|
308611
|
+
case "get_order":
|
|
308612
|
+
return toolResult(await getIndexOrder(api));
|
|
308613
|
+
default:
|
|
308614
|
+
throw new Error(`Unknown action: ${String(action)}`);
|
|
308615
|
+
}
|
|
308616
|
+
} catch (error2) {
|
|
308617
|
+
handleDatadogError(error2);
|
|
308618
|
+
}
|
|
308619
|
+
}
|
|
308620
|
+
);
|
|
308621
|
+
}
|
|
308622
|
+
|
|
308623
|
+
// src/tools/logs_archives.ts
|
|
308624
|
+
var ActionSchema22 = external_exports.enum(["list", "get", "create", "update", "delete", "reorder", "get_order"]);
|
|
308625
|
+
var InputSchema23 = {
|
|
308626
|
+
action: ActionSchema22.describe("Action to perform"),
|
|
308627
|
+
id: external_exports.string().optional().describe("Archive ID (required for get/update/delete)"),
|
|
308628
|
+
config: external_exports.record(external_exports.unknown()).optional().describe(
|
|
308629
|
+
"Archive configuration (for create/update). Requires name, query, and destination with type \u2208 { s3, gcs, azure_storage }. Provider credential / integration fields are forwarded unchanged."
|
|
308630
|
+
),
|
|
308631
|
+
archive_ids: external_exports.array(external_exports.string()).optional().describe("Ordered archive ID list (required for reorder)"),
|
|
308632
|
+
verbose: external_exports.boolean().optional().describe("Return full SDK payload alongside summary (default false)")
|
|
308633
|
+
};
|
|
308634
|
+
var VALID_DESTINATION_TYPES = ["s3", "gcs", "azure_storage"];
|
|
308635
|
+
function extractDestinationContainer(destination) {
|
|
308636
|
+
if (!destination || typeof destination !== "object") return null;
|
|
308637
|
+
const dest = destination;
|
|
308638
|
+
if (typeof dest.bucket === "string") return dest.bucket;
|
|
308639
|
+
if (typeof dest.container === "string") return dest.container;
|
|
308640
|
+
return null;
|
|
308641
|
+
}
|
|
308642
|
+
function formatArchive(archive, verbose = false) {
|
|
308643
|
+
const attrs = archive.attributes;
|
|
308644
|
+
const destination = attrs?.destination ?? null;
|
|
308645
|
+
const destinationType = destination && typeof destination === "object" && "type" in destination ? String(destination.type ?? "") : "";
|
|
308646
|
+
const summary = {
|
|
308647
|
+
id: archive.id ?? "",
|
|
308648
|
+
name: attrs?.name ?? "",
|
|
308649
|
+
query: attrs?.query ?? null,
|
|
308650
|
+
destinationType,
|
|
308651
|
+
destinationContainer: extractDestinationContainer(destination),
|
|
308652
|
+
includeTags: attrs?.includeTags ?? false,
|
|
308653
|
+
rehydrationTags: attrs?.rehydrationTags ?? [],
|
|
308654
|
+
state: attrs?.state ?? null
|
|
308655
|
+
};
|
|
308656
|
+
if (verbose && destination) {
|
|
308657
|
+
summary.destination = destination;
|
|
308658
|
+
}
|
|
308659
|
+
return summary;
|
|
308660
|
+
}
|
|
308661
|
+
function normalizeArchiveConfig(config2) {
|
|
308662
|
+
const normalized = normalizeConfigKeys(config2);
|
|
308663
|
+
if (typeof normalized.name !== "string" || normalized.name.length === 0) {
|
|
308664
|
+
throw new Error("Archive config requires 'name' field");
|
|
308665
|
+
}
|
|
308666
|
+
if (typeof normalized.query !== "string" || normalized.query.length === 0) {
|
|
308667
|
+
throw new Error("Archive config requires 'query' field");
|
|
308668
|
+
}
|
|
308669
|
+
const destination = normalized.destination;
|
|
308670
|
+
if (!destination || typeof destination !== "object") {
|
|
308671
|
+
throw new Error("Archive config requires 'destination' object");
|
|
308672
|
+
}
|
|
308673
|
+
const destinationType = destination.type;
|
|
308674
|
+
if (typeof destinationType !== "string" || !VALID_DESTINATION_TYPES.includes(destinationType)) {
|
|
308675
|
+
throw new Error("destination.type must be one of: s3, gcs, azure_storage");
|
|
308676
|
+
}
|
|
308677
|
+
if (destinationType === "azure_storage") {
|
|
308678
|
+
;
|
|
308679
|
+
destination.type = "azure";
|
|
308680
|
+
}
|
|
308681
|
+
return normalized;
|
|
308682
|
+
}
|
|
308683
|
+
function buildArchiveRequestBody(normalizedConfig) {
|
|
308684
|
+
const { name, query, destination, includeTags, rehydrationTags, rehydrationMaxScanSizeInGb } = normalizedConfig;
|
|
308685
|
+
const attributes = {
|
|
308686
|
+
name,
|
|
308687
|
+
query,
|
|
308688
|
+
destination
|
|
308689
|
+
};
|
|
308690
|
+
if (includeTags !== void 0) attributes.includeTags = includeTags;
|
|
308691
|
+
if (rehydrationTags !== void 0) attributes.rehydrationTags = rehydrationTags;
|
|
308692
|
+
if (rehydrationMaxScanSizeInGb !== void 0) {
|
|
308693
|
+
attributes.rehydrationMaxScanSizeInGb = rehydrationMaxScanSizeInGb;
|
|
308694
|
+
}
|
|
308695
|
+
return {
|
|
308696
|
+
data: {
|
|
308697
|
+
type: "archives",
|
|
308698
|
+
attributes
|
|
308699
|
+
}
|
|
308700
|
+
};
|
|
308701
|
+
}
|
|
308702
|
+
async function listArchives(api, verbose = false) {
|
|
308703
|
+
const response = await api.listLogsArchives();
|
|
308704
|
+
const archives = (response.data ?? []).map((archive) => formatArchive(archive, verbose));
|
|
308705
|
+
const result = { archives, total: archives.length };
|
|
308706
|
+
if (verbose) {
|
|
308707
|
+
result.raw = response;
|
|
308708
|
+
}
|
|
308709
|
+
return result;
|
|
308710
|
+
}
|
|
308711
|
+
async function getArchive(api, id, verbose = false) {
|
|
308712
|
+
const response = await api.getLogsArchive({ archiveId: id });
|
|
308713
|
+
const archive = response.data;
|
|
308714
|
+
if (!archive) {
|
|
308715
|
+
throw new Error(`Archive ${id} returned an empty payload`);
|
|
308716
|
+
}
|
|
308717
|
+
const result = { archive: formatArchive(archive, verbose) };
|
|
308718
|
+
if (verbose) {
|
|
308719
|
+
result.raw = response;
|
|
308720
|
+
}
|
|
308721
|
+
return result;
|
|
308722
|
+
}
|
|
308723
|
+
async function createArchive(api, config2, verbose = false) {
|
|
308724
|
+
const normalized = normalizeArchiveConfig(config2);
|
|
308725
|
+
const body = buildArchiveRequestBody(normalized);
|
|
308726
|
+
const response = await api.createLogsArchive({ body });
|
|
308727
|
+
const archive = response.data;
|
|
308728
|
+
if (!archive) {
|
|
308729
|
+
throw new Error("Archive creation returned an empty payload");
|
|
308730
|
+
}
|
|
308731
|
+
const result = {
|
|
308732
|
+
success: true,
|
|
308733
|
+
archive: formatArchive(archive, verbose)
|
|
308734
|
+
};
|
|
308735
|
+
if (verbose) {
|
|
308736
|
+
result.raw = response;
|
|
308737
|
+
}
|
|
308738
|
+
return result;
|
|
308739
|
+
}
|
|
308740
|
+
async function updateArchive(api, id, config2, verbose = false) {
|
|
308741
|
+
const normalized = normalizeArchiveConfig(config2);
|
|
308742
|
+
const body = buildArchiveRequestBody(normalized);
|
|
308743
|
+
const response = await api.updateLogsArchive({ archiveId: id, body });
|
|
308744
|
+
const archive = response.data;
|
|
308745
|
+
if (!archive) {
|
|
308746
|
+
throw new Error(`Archive ${id} update returned an empty payload`);
|
|
308747
|
+
}
|
|
308748
|
+
const result = {
|
|
308749
|
+
success: true,
|
|
308750
|
+
archive: formatArchive(archive, verbose)
|
|
308751
|
+
};
|
|
308752
|
+
if (verbose) {
|
|
308753
|
+
result.raw = response;
|
|
308754
|
+
}
|
|
308755
|
+
return result;
|
|
308756
|
+
}
|
|
308757
|
+
async function deleteArchive(api, id) {
|
|
308758
|
+
await api.deleteLogsArchive({ archiveId: id });
|
|
308759
|
+
return {
|
|
308760
|
+
success: true,
|
|
308761
|
+
message: `Archive ${id} deleted`
|
|
308762
|
+
};
|
|
308763
|
+
}
|
|
308764
|
+
async function reorderArchives(api, archiveIds) {
|
|
308765
|
+
const body = {
|
|
308766
|
+
data: {
|
|
308767
|
+
type: "archive_order",
|
|
308768
|
+
attributes: {
|
|
308769
|
+
archiveIds
|
|
308770
|
+
}
|
|
308771
|
+
}
|
|
308772
|
+
};
|
|
308773
|
+
const response = await api.updateLogsArchiveOrder({ body });
|
|
308774
|
+
const resultIds = response.data?.attributes?.archiveIds ?? [];
|
|
308775
|
+
return {
|
|
308776
|
+
success: true,
|
|
308777
|
+
order: {
|
|
308778
|
+
archiveIds: resultIds
|
|
308779
|
+
}
|
|
308780
|
+
};
|
|
308781
|
+
}
|
|
308782
|
+
async function getArchiveOrder(api) {
|
|
308783
|
+
const response = await api.getLogsArchiveOrder();
|
|
308784
|
+
const resultIds = response.data?.attributes?.archiveIds ?? [];
|
|
308785
|
+
return {
|
|
308786
|
+
order: {
|
|
308787
|
+
archiveIds: resultIds
|
|
308788
|
+
}
|
|
308789
|
+
};
|
|
308790
|
+
}
|
|
308791
|
+
function registerLogsArchivesTool(server, api, _limits, readOnly = false, _site = "datadoghq.com") {
|
|
308792
|
+
server.tool(
|
|
308793
|
+
"logs_archives",
|
|
308794
|
+
"Manage Datadog Logs archives (long-term log retention to S3 / GCS / Azure Blob). Actions: list, get, create, update, delete, reorder, get_order. Archives accept destinations of type 's3', 'gcs', or 'azure_storage'; per-provider credential and integration fields (S3 IAM role ARN, GCS service account, Azure tenant/secret) are forwarded unchanged. Mutations (create, update, delete, reorder) are blocked when the server is in read-only mode.",
|
|
308795
|
+
InputSchema23,
|
|
308796
|
+
async ({ action, id, config: config2, archive_ids, verbose }) => {
|
|
308797
|
+
try {
|
|
308798
|
+
checkReadOnly(action, readOnly);
|
|
308799
|
+
const isVerbose = verbose ?? false;
|
|
308800
|
+
switch (action) {
|
|
308801
|
+
case "list":
|
|
308802
|
+
return toolResult(await listArchives(api, isVerbose));
|
|
308803
|
+
case "get": {
|
|
308804
|
+
const archiveId = requireParam(id, "id", "get");
|
|
308805
|
+
return toolResult(await getArchive(api, archiveId, isVerbose));
|
|
308806
|
+
}
|
|
308807
|
+
case "create": {
|
|
308808
|
+
const archiveConfig = requireParam(config2, "config", "create");
|
|
308809
|
+
return toolResult(await createArchive(api, archiveConfig, isVerbose));
|
|
308810
|
+
}
|
|
308811
|
+
case "update": {
|
|
308812
|
+
const archiveId = requireParam(id, "id", "update");
|
|
308813
|
+
const archiveConfig = requireParam(config2, "config", "update");
|
|
308814
|
+
return toolResult(await updateArchive(api, archiveId, archiveConfig, isVerbose));
|
|
308815
|
+
}
|
|
308816
|
+
case "delete": {
|
|
308817
|
+
const archiveId = requireParam(id, "id", "delete");
|
|
308818
|
+
return toolResult(await deleteArchive(api, archiveId));
|
|
308819
|
+
}
|
|
308820
|
+
case "reorder": {
|
|
308821
|
+
const ids = requireParam(archive_ids, "archive_ids", "reorder");
|
|
308822
|
+
return toolResult(await reorderArchives(api, ids));
|
|
308823
|
+
}
|
|
308824
|
+
case "get_order":
|
|
308825
|
+
return toolResult(await getArchiveOrder(api));
|
|
308826
|
+
default:
|
|
308827
|
+
throw new Error(`Unknown action: ${String(action)}`);
|
|
308828
|
+
}
|
|
308829
|
+
} catch (error2) {
|
|
308830
|
+
handleDatadogError(error2);
|
|
308831
|
+
}
|
|
308832
|
+
}
|
|
308833
|
+
);
|
|
308834
|
+
}
|
|
308835
|
+
|
|
307947
308836
|
// src/tools/index.ts
|
|
307948
308837
|
function registerAllTools(server, clients, limits, features, site = "datadoghq.com", datadogConfig) {
|
|
307949
308838
|
const { readOnly, disabledTools } = features;
|
|
@@ -307958,6 +308847,12 @@ function registerAllTools(server, clients, limits, features, site = "datadoghq.c
|
|
|
307958
308847
|
if (enabled("dashboards"))
|
|
307959
308848
|
registerDashboardsTool(server, clients.dashboards, limits, readOnly, credentials);
|
|
307960
308849
|
if (enabled("logs")) registerLogsTool(server, clients.logs, limits, site);
|
|
308850
|
+
if (enabled("logs_pipelines"))
|
|
308851
|
+
registerLogsPipelinesTool(server, clients.logsPipelines, limits, readOnly, site);
|
|
308852
|
+
if (enabled("logs_indexes"))
|
|
308853
|
+
registerLogsIndexesTool(server, clients.logsIndexes, limits, readOnly, site);
|
|
308854
|
+
if (enabled("logs_archives"))
|
|
308855
|
+
registerLogsArchivesTool(server, clients.logsArchives, limits, readOnly, site);
|
|
307961
308856
|
if (enabled("metrics"))
|
|
307962
308857
|
registerMetricsTool(server, clients.metricsV1, clients.metricsV2, limits, site);
|
|
307963
308858
|
if (enabled("traces")) registerTracesTool(server, clients.spans, clients.services, limits, site);
|