-
Notifications
You must be signed in to change notification settings - Fork 5
/
dddk.ts
executable file
·150 lines (123 loc) · 4 KB
/
dddk.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#! /usr/bin/env node
import { App, Client } from "./src";
import { LockFile, Syncer } from "./src/syncer";
import * as yargs from "yargs";
import * as fs from "fs";
import * as glob from "glob";
import * as path from "path";
import { register } from "ts-node";
import log from "./src/log";
register();
if (!process.env["DD_API_KEY"] || !process.env["DD_APP_KEY"]) {
console.error("DD_API_KEY and DD_APP_KEY must be set");
process.exit(1);
}
yargs
.command(
"push",
"push datadog dashboards up",
yargs => {
yargs
.option("name", {
type: "string",
description: "only push the matching app name",
})
.positional("source", {
describe: "glob to locate all apps",
default: "src/apps/*.ts",
});
},
async (argv: any) => {
log.info(`Parsing local apps...`);
console.time(" ...completed in");
const apps: App[] = [];
for (const appfile of glob.sync(argv.source)) {
const app = require(path.join(process.cwd(), appfile)).default;
if (!(app instanceof App)) {
console.error(
`${appfile} does not have a default export extending App`,
);
process.exit(1);
}
apps.push(app);
}
console.timeEnd(" ...completed in");
const client = new Client(
process.env["DD_API_KEY"],
process.env["DD_APP_KEY"],
);
const lockFile = process.cwd() + "/lock.json";
let lock: LockFile = {
monitors: {},
dashboards: {},
synthetics: {},
slos: {},
};
if (fs.existsSync(lockFile)) {
log.info(`reading lock from ${lockFile}`)
lock = JSON.parse(fs.readFileSync(lockFile).toString());
}
log.info(`Fetching data from DataDog...`);
console.time(" ...completed in");
const syncer = await Syncer.create(client, lock);
console.timeEnd(` ...completed in`);
log.info("Pushing local changes to DataDog...");
console.time(" ...completed in");
for (const app of apps) {
if (
argv.name &&
argv.name.toLowerCase() !== app.board.title.toLowerCase()
) {
continue;
}
let outageMonitorIDs: number[] = [];
for (const syn of app.synthetics) {
await syncer.syncSynthetic(syn);
const syntheticMonitor = await client.getMonitors({
name: "[Synthetics] " + syn.name,
});
if (syntheticMonitor.length == 1) {
outageMonitorIDs.push(syntheticMonitor[0].id);
}
}
for (const monitor of app.warningMonitors) {
await syncer.syncMonitor(monitor);
}
for (const monitor of app.outageMonitors) {
outageMonitorIDs.push(await syncer.syncMonitor(monitor));
}
let sloID = "";
if (outageMonitorIDs.length > 0) {
sloID = await syncer.syncSLO({
type: "monitor",
name: `${app.name} SLO`,
description:
`Track the uptime of ${app.name} ` + app.team.warningContact,
monitor_ids: outageMonitorIDs,
thresholds: [{ timeframe: "30d", target: 99.9, warning: 99.95 }],
tags: [`service:${app.name}`],
});
app.board.widgets.unshift({
definition: {
viz: "slo",
type: "slo",
slo_id: sloID,
title: `${app.name} SLO`,
time_windows: ["30d"],
show_error_budget: true,
view_type: "detail",
view_mode: "overall",
},
});
}
await syncer.syncDashboard(app.board);
}
if (!argv.name) {
await syncer.deleteUnseen();
}
fs.writeFileSync(lockFile, JSON.stringify(syncer.lock, null, 2));
console.timeEnd(" ...completed in");
log.info(`stats =`, JSON.stringify(syncer.stats, null, 2));
},
)
.demandCommand(1, "Must specify a command, did you mean dddk push?").argv;