feat: DataDog monitor - base for proposal

pull/4616/head
Seluard 2 months ago
parent 9e01917a08
commit 1666659d48

@ -0,0 +1,21 @@
exports.up = function (knex) {
// Add new columns monitor.datadog*
return knex.schema
.alterTable("monitor", function (table) {
table.string("datadog_site", 255);
table.string("datadog_api_key", 255);
table.string("datadog_app_key", 255);
table.string("datadog_monitor_id", 255);
});
};
exports.down = function (knex) {
// Drop column monitor.datadog*
return knex.schema
.alterTable("monitor", function (table) {
table.dropColumn("datadog_site");
table.dropColumn("datadog_api_key");
table.dropColumn("datadog_app_key");
table.dropColumn("datadog_monitor_id");
});
};

66
package-lock.json generated

@ -9,6 +9,7 @@
"version": "2.0.0-dev",
"license": "MIT",
"dependencies": {
"@datadog/datadog-api-client": "^1.23.0",
"@grpc/grpc-js": "~1.7.3",
"@louislam/ping": "~0.4.4-mod.1",
"@louislam/sqlite3": "15.1.6",
@ -100,7 +101,7 @@
"bootstrap": "5.1.3",
"chart.js": "~4.2.1",
"chartjs-adapter-dayjs-4": "~1.0.4",
"concurrently": "^7.1.0",
"concurrently": "^7.6.0",
"core-js": "~3.26.1",
"cronstrue": "~2.24.0",
"cross-env": "~7.0.3",
@ -1917,6 +1918,26 @@
"postcss-selector-parser": "^6.0.13"
}
},
"node_modules/@datadog/datadog-api-client": {
"version": "1.23.0",
"resolved": "https://registry.npmjs.org/@datadog/datadog-api-client/-/datadog-api-client-1.23.0.tgz",
"integrity": "sha512-hwt/WIrm63Y1JWQXj5DHihgiYdaJkJ41KJTJDUtRA85B9QpoDA+P/j28xC75IIfoajcEeAe1n9BtRrRZ7Z2x3A==",
"dependencies": {
"@types/buffer-from": "^1.1.0",
"@types/node": "*",
"@types/pako": "^1.0.3",
"buffer-from": "^1.1.2",
"cross-fetch": "^3.1.5",
"es6-promise": "^4.2.8",
"form-data": "^4.0.0",
"loglevel": "^1.8.1",
"pako": "^2.0.4",
"url-parse": "^1.4.3"
},
"engines": {
"node": ">=12.0.0"
}
},
"node_modules/@es-joy/jsdoccomment": {
"version": "0.40.1",
"resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.40.1.tgz",
@ -4042,6 +4063,14 @@
"@popperjs/core": "^2.9.2"
}
},
"node_modules/@types/buffer-from": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@types/buffer-from/-/buffer-from-1.1.3.tgz",
"integrity": "sha512-2lq4YC9uLUMGHkl2IDtX4tCXSo2+hwMpOJcY1qiIk1kybc31rIlPyM1HCVJhkPFIo75a/pOVxqyvwuf5TpCG/w==",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/connect": {
"version": "3.4.38",
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
@ -4189,6 +4218,11 @@
"integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==",
"dev": true
},
"node_modules/@types/pako": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/@types/pako/-/pako-1.0.7.tgz",
"integrity": "sha512-YBtzT2ztNF6R/9+UXj2wTGFnC9NklAnASt3sC0h2m1bbH7G6FyBIkt4AN8ThZpNfxUo1b2iMVO0UawiJymEt8A=="
},
"node_modules/@types/qs": {
"version": "6.9.11",
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.11.tgz",
@ -6131,6 +6165,14 @@
"yarn": ">=1"
}
},
"node_modules/cross-fetch": {
"version": "3.1.8",
"resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.8.tgz",
"integrity": "sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==",
"dependencies": {
"node-fetch": "^2.6.12"
}
},
"node_modules/cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@ -6880,6 +6922,11 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/es6-promise": {
"version": "4.2.8",
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
"integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w=="
},
"node_modules/esbuild": {
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz",
@ -9415,6 +9462,18 @@
"integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==",
"dev": true
},
"node_modules/loglevel": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.9.1.tgz",
"integrity": "sha512-hP3I3kCrDIMuRwAwHltphhDM1r8i55H33GgqjXbrisuJhF4kRhW1dNuxsRklp4bXl8DSdLaNLuiL4A/LWRfxvg==",
"engines": {
"node": ">= 0.6.0"
},
"funding": {
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/loglevel"
}
},
"node_modules/long": {
"version": "5.2.3",
"resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz",
@ -10666,6 +10725,11 @@
"resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz",
"integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ=="
},
"node_modules/pako": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz",
"integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug=="
},
"node_modules/parent-module": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",

@ -74,6 +74,7 @@
"start-server-node14-win": "private\\node14\\node.exe server/server.js"
},
"dependencies": {
"@datadog/datadog-api-client": "^1.23.0",
"@grpc/grpc-js": "~1.7.3",
"@louislam/ping": "~0.4.4-mod.1",
"@louislam/sqlite3": "15.1.6",
@ -165,7 +166,7 @@
"bootstrap": "5.1.3",
"chart.js": "~4.2.1",
"chartjs-adapter-dayjs-4": "~1.0.4",
"concurrently": "^7.1.0",
"concurrently": "^7.6.0",
"core-js": "~3.26.1",
"cronstrue": "~2.24.0",
"cross-env": "~7.0.3",

@ -161,6 +161,9 @@ class Monitor extends BeanModel {
kafkaProducerMessage: this.kafkaProducerMessage,
screenshot,
remote_browser: this.remote_browser,
datadog_site: this.datadog_site,
datadog_monitor_id: this.datadog_monitor_id,
};
if (includeSensitiveData) {
@ -190,6 +193,8 @@ class Monitor extends BeanModel {
tlsCert: this.tlsCert,
tlsKey: this.tlsKey,
kafkaProducerSaslOptions: JSON.parse(this.kafkaProducerSaslOptions),
datadog_api_key: this.datadog_api_key,
datadog_app_key: this.datadog_app_key,
};
}

@ -0,0 +1,58 @@
const { MonitorType } = require("./monitor-type");
const { UP, log, DOWN, PENDING } = require("../../src/util");
const { client, v1 } = require("@datadog/datadog-api-client");
const { json } = require("express");
/**
* A DataDog class extends the MonitorType.
* It will query DataDog api to get datadog monitor state and sync the monitor status.
*/
class DataDog extends MonitorType {
name = "datadog";
/**
* @param {Object} monitor - The monitor object associated with the check.
* @param {Object} heartbeat - The heartbeat object to update.
* @throws Will throw an error if the API call found any.
*/
async check(monitor, heartbeat) {
try {
const configurationOpts = {
authMethods: {
apiKeyAuth: monitor.datadog_api_key,
appKeyAuth: monitor.datadog_app_key
},
};
const configuration = client.createConfiguration(configurationOpts);
configuration.setServerVariables({
site: monitor.datadog_site
});
const apiInstance = new v1.MonitorsApi(configuration)
let params = {
monitorId: monitor.datadog_monitor_id,
};
let status = await apiInstance.getMonitor(params).then((data) => {
log.debug("datadog",'DataDog API called successfully');
let state = data["overallState"]
if (state === "OK") {
log.debug("datadog","UP")
return UP;
} else if (state === "No Data") {
log.debug("datadog","PENDING")
return PENDING;
} else {
log.debug("datadog","DOWN")
return DOWN;
}
})
heartbeat.status = status
} catch (err) {
// trigger log function somewhere to display a notification or alert to the user (but how?)
throw new Error(`Error checking datadog monitor: ${err}`);
}
}
}
module.exports = {
DataDog,
};

@ -113,6 +113,7 @@ class UptimeKumaServer {
UptimeKumaServer.monitorTypeList["tailscale-ping"] = new TailscalePing();
UptimeKumaServer.monitorTypeList["dns"] = new DnsMonitorType();
UptimeKumaServer.monitorTypeList["mqtt"] = new MqttMonitorType();
UptimeKumaServer.monitorTypeList["datadog"] = new DataDog();
// Allow all CORS origins (polling) in development
let cors = undefined;
@ -516,3 +517,4 @@ const { RealBrowserMonitorType } = require("./monitor-types/real-browser-monitor
const { TailscalePing } = require("./monitor-types/tailscale-ping");
const { DnsMonitorType } = require("./monitor-types/dns");
const { MqttMonitorType } = require("./monitor-types/mqtt");
const { DataDog } = require("./monitor-types/datadog")

@ -85,6 +85,9 @@
<option v-if="!$root.info.isContainer" value="tailscale-ping">
Tailscale Ping
</option>
<option value="datadog">
DataDog
</option>
</optgroup>
</select>
</div>
@ -245,6 +248,32 @@
</div>
</template>
<!-- Datadog -->
<!-- Datadog Only-->
<template v-if="monitor.type === 'datadog'">
<div class="my-3">
<label for="datadog_site" class="form-label">DataDog Site (Site parameter)</label>
<input id="datadog_site" v-model="monitor.datadog_site" type="text" class="form-control" required>
</div>
<a href="https://docs.datadoghq.com/getting_started/site/">DataDog Sites</a>
<div class="my-3">
<label for="datadog_api_key" class="form-label">API key</label>
<input id="datadog_api_key" v-model="monitor.datadog_api_key" type="password" class="form-control" required>
</div>
<div class="my-3">
<label for="datadog_app_key" class="form-label">APP key</label>
<input id="datadog_app_key" v-model="monitor.datadog_app_key" type="password" class="form-control" required>
</div>
<div class="my-3">
<label for="datadog_monitor_id" class="form-label">Monitor Id</label>
<input id="datadog_monitor_id" v-model="monitor.datadog_monitor_id" type="text" class="form-control" required>
</div>
</template>
<!-- Hostname -->
<!-- TCP Port / Ping / DNS / Steam / MQTT / Radius / Tailscale Ping only -->
<div v-if="monitor.type === 'port' || monitor.type === 'ping' || monitor.type === 'dns' || monitor.type === 'steam' || monitor.type === 'gamedig' ||monitor.type === 'mqtt' || monitor.type === 'radius' || monitor.type === 'tailscale-ping'" class="my-3">

Loading…
Cancel
Save