feat: add google sheets notification provider for logging monitor events
This commit is contained in:
parent
b638ae48ef
commit
60d780927d
118
server/notification-providers/google-sheets.js
Normal file
118
server/notification-providers/google-sheets.js
Normal file
@ -0,0 +1,118 @@
|
||||
const NotificationProvider = require("./notification-provider");
|
||||
const axios = require("axios");
|
||||
const { DOWN, UP } = require("../../src/util");
|
||||
|
||||
class GoogleSheets extends NotificationProvider {
|
||||
name = "GoogleSheets";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
const okMsg = "Sent Successfully.";
|
||||
|
||||
try {
|
||||
// Prepare the data to be logged
|
||||
const timestamp = new Date().toISOString();
|
||||
let status = "N/A";
|
||||
let monitorName = "N/A";
|
||||
let monitorUrl = "N/A";
|
||||
let responseTime = "N/A";
|
||||
let statusCode = "N/A";
|
||||
|
||||
if (monitorJSON) {
|
||||
monitorName = monitorJSON.name || "N/A";
|
||||
monitorUrl = this.extractAddress(monitorJSON) || "N/A";
|
||||
}
|
||||
|
||||
if (heartbeatJSON) {
|
||||
status = heartbeatJSON.status === DOWN ? "DOWN" : heartbeatJSON.status === UP ? "UP" : "UNKNOWN";
|
||||
responseTime = heartbeatJSON.ping || "N/A";
|
||||
statusCode = heartbeatJSON.status || "N/A";
|
||||
}
|
||||
|
||||
// Prepare row data based on user configuration
|
||||
let rowData = [];
|
||||
|
||||
if (notification.googleSheetsCustomFormat) {
|
||||
// Custom format - user defines their own columns
|
||||
const customColumns = notification.googleSheetsColumns || "timestamp,status,monitor,message";
|
||||
const columns = customColumns.split(",").map(col => col.trim());
|
||||
|
||||
columns.forEach(column => {
|
||||
switch (column.toLowerCase()) {
|
||||
case "timestamp":
|
||||
rowData.push(timestamp);
|
||||
break;
|
||||
case "status":
|
||||
rowData.push(status);
|
||||
break;
|
||||
case "monitor":
|
||||
case "monitorname":
|
||||
rowData.push(monitorName);
|
||||
break;
|
||||
case "url":
|
||||
case "monitorurl":
|
||||
rowData.push(monitorUrl);
|
||||
break;
|
||||
case "message":
|
||||
case "msg":
|
||||
rowData.push(msg);
|
||||
break;
|
||||
case "responsetime":
|
||||
case "ping":
|
||||
rowData.push(responseTime);
|
||||
break;
|
||||
case "statuscode":
|
||||
rowData.push(statusCode);
|
||||
break;
|
||||
default:
|
||||
rowData.push("");
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// Default format
|
||||
rowData = [
|
||||
timestamp,
|
||||
status,
|
||||
monitorName,
|
||||
monitorUrl,
|
||||
msg,
|
||||
responseTime,
|
||||
statusCode
|
||||
];
|
||||
}
|
||||
|
||||
// Prepare the request to Google Sheets API
|
||||
const spreadsheetId = notification.googleSheetsSpreadsheetId;
|
||||
const sheetName = notification.googleSheetsSheetName || "Sheet1";
|
||||
const range = `${sheetName}!A:Z`;
|
||||
|
||||
// Use Google Sheets API v4 to append data
|
||||
const apiUrl = `https://sheets.googleapis.com/v4/spreadsheets/${spreadsheetId}/values/${range}:append`;
|
||||
|
||||
const config = this.getAxiosConfigWithProxy({
|
||||
params: {
|
||||
valueInputOption: "USER_ENTERED",
|
||||
insertDataOption: "INSERT_ROWS"
|
||||
},
|
||||
headers: {
|
||||
"Authorization": `Bearer ${notification.googleSheetsAccessToken}`,
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
});
|
||||
|
||||
const data = {
|
||||
values: [rowData]
|
||||
};
|
||||
|
||||
await axios.post(apiUrl, data, config);
|
||||
|
||||
return okMsg;
|
||||
} catch (error) {
|
||||
this.throwGeneralAxiosError(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GoogleSheets;
|
||||
@ -17,6 +17,7 @@ const Feishu = require("./notification-providers/feishu");
|
||||
const Notifery = require("./notification-providers/notifery");
|
||||
const FreeMobile = require("./notification-providers/freemobile");
|
||||
const GoogleChat = require("./notification-providers/google-chat");
|
||||
const GoogleSheets = require("./notification-providers/google-sheets");
|
||||
const Gorush = require("./notification-providers/gorush");
|
||||
const Gotify = require("./notification-providers/gotify");
|
||||
const GrafanaOncall = require("./notification-providers/grafana-oncall");
|
||||
@ -117,6 +118,7 @@ class Notification {
|
||||
new Feishu(),
|
||||
new FreeMobile(),
|
||||
new GoogleChat(),
|
||||
new GoogleSheets(),
|
||||
new Gorush(),
|
||||
new Gotify(),
|
||||
new GrafanaOncall(),
|
||||
|
||||
111
src/components/notifications/GoogleSheets.vue
Normal file
111
src/components/notifications/GoogleSheets.vue
Normal file
@ -0,0 +1,111 @@
|
||||
<template>
|
||||
<div class="mb-3">
|
||||
<label for="google-sheets-spreadsheet-id" class="form-label">{{ $t("Spreadsheet ID") }}</label>
|
||||
<input
|
||||
id="google-sheets-spreadsheet-id"
|
||||
v-model="$parent.notification.googleSheetsSpreadsheetId"
|
||||
type="text"
|
||||
class="form-control"
|
||||
required
|
||||
placeholder="1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms"
|
||||
/>
|
||||
<div class="form-text">
|
||||
{{ $t("The ID from your Google Sheets URL") }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="google-sheets-sheet-name" class="form-label">{{ $t("Sheet Name") }}</label>
|
||||
<input
|
||||
id="google-sheets-sheet-name"
|
||||
v-model="$parent.notification.googleSheetsSheetName"
|
||||
type="text"
|
||||
class="form-control"
|
||||
placeholder="Sheet1"
|
||||
/>
|
||||
<div class="form-text">
|
||||
{{ $t("The name of the sheet/tab (default: Sheet1)") }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="google-sheets-access-token" class="form-label">{{ $t("Access Token") }}</label>
|
||||
<HiddenInput
|
||||
id="google-sheets-access-token"
|
||||
v-model="$parent.notification.googleSheetsAccessToken"
|
||||
:required="true"
|
||||
autocomplete="new-password"
|
||||
placeholder="ya29.a0AfH6SMBx..."
|
||||
></HiddenInput>
|
||||
<div class="form-text">
|
||||
<p>{{ $t("Google OAuth2 Access Token or Service Account Token") }}</p>
|
||||
<a href="https://developers.google.com/sheets/api/guides/authorizing" target="_blank" rel="noopener noreferrer">
|
||||
{{ $t("Learn how to get an access token") }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<div class="form-check">
|
||||
<input
|
||||
id="google-sheets-custom-format"
|
||||
v-model="$parent.notification.googleSheetsCustomFormat"
|
||||
class="form-check-input"
|
||||
type="checkbox"
|
||||
/>
|
||||
<label class="form-check-label" for="google-sheets-custom-format">
|
||||
{{ $t("Custom Column Format") }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="$parent.notification.googleSheetsCustomFormat" class="mb-3">
|
||||
<label for="google-sheets-columns" class="form-label">{{ $t("Column Names") }}</label>
|
||||
<input
|
||||
id="google-sheets-columns"
|
||||
v-model="$parent.notification.googleSheetsColumns"
|
||||
type="text"
|
||||
class="form-control"
|
||||
placeholder="timestamp,status,monitor,message,responsetime"
|
||||
/>
|
||||
<div class="form-text">
|
||||
<p>{{ $t("Comma-separated column names. Available columns:") }}</p>
|
||||
<ul>
|
||||
<li><code>timestamp</code> - {{ $t("Current date and time") }}</li>
|
||||
<li><code>status</code> - {{ $t("UP/DOWN status") }}</li>
|
||||
<li><code>monitor</code> - {{ $t("Monitor name") }}</li>
|
||||
<li><code>url</code> - {{ $t("Monitor URL") }}</li>
|
||||
<li><code>message</code> - {{ $t("Notification message") }}</li>
|
||||
<li><code>responsetime</code> - {{ $t("Response time in ms") }}</li>
|
||||
<li><code>statuscode</code> - {{ $t("HTTP status code") }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else class="mb-3">
|
||||
<div class="alert alert-info">
|
||||
{{ $t("Default columns: Timestamp, Status, Monitor Name, URL, Message, Response Time, Status Code") }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import HiddenInput from "../HiddenInput.vue";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
HiddenInput,
|
||||
},
|
||||
mounted() {
|
||||
if (typeof this.$parent.notification.googleSheetsSheetName === "undefined") {
|
||||
this.$parent.notification.googleSheetsSheetName = "Sheet1";
|
||||
}
|
||||
if (typeof this.$parent.notification.googleSheetsCustomFormat === "undefined") {
|
||||
this.$parent.notification.googleSheetsCustomFormat = false;
|
||||
}
|
||||
if (typeof this.$parent.notification.googleSheetsColumns === "undefined") {
|
||||
this.$parent.notification.googleSheetsColumns = "timestamp,status,monitor,message,responsetime";
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@ -15,6 +15,7 @@ import Elks from "./46elks.vue";
|
||||
import Feishu from "./Feishu.vue";
|
||||
import FreeMobile from "./FreeMobile.vue";
|
||||
import GoogleChat from "./GoogleChat.vue";
|
||||
import GoogleSheets from "./GoogleSheets.vue";
|
||||
import Gorush from "./Gorush.vue";
|
||||
import Gotify from "./Gotify.vue";
|
||||
import GrafanaOncall from "./GrafanaOncall.vue";
|
||||
@ -105,6 +106,7 @@ const NotificationFormList = {
|
||||
Feishu: Feishu,
|
||||
FreeMobile: FreeMobile,
|
||||
GoogleChat: GoogleChat,
|
||||
GoogleSheets: GoogleSheets,
|
||||
gorush: Gorush,
|
||||
gotify: Gotify,
|
||||
GrafanaOncall: GrafanaOncall,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user