@oneuptime/common 10.0.43 → 10.0.45
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/Models/DatabaseModels/Workflow.ts +29 -0
- package/Server/API/StatusPageAPI.ts +48 -0
- package/Server/EnvironmentConfig.ts +5 -8
- package/Server/Infrastructure/Postgres/SchemaMigrations/1774559064920-MigrationName.ts +22 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +2 -0
- package/Server/Services/AlertService.ts +45 -0
- package/Server/Services/IncidentService.ts +81 -13
- package/Server/Services/LogAggregationService.ts +1 -0
- package/Server/Services/WorkflowService.ts +28 -1
- package/Server/Types/Workflow/Components/Webhook.ts +28 -5
- package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +29 -13
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +163 -26
- package/Server/Utils/Monitor/MonitorMetricUtil.ts +92 -0
- package/Server/Utils/Profiling.ts +101 -0
- package/Server/Utils/VM/VMRunner.ts +88 -0
- package/Types/Dashboard/DashboardTemplates.ts +1149 -0
- package/Types/Exception/ExceptionMetricType.ts +15 -0
- package/Types/IsolatedVM/ReturnResult.ts +3 -0
- package/Types/Metrics/MetricDashboardMetricType.ts +28 -0
- package/Types/Metrics/MetricsQuery.ts +2 -1
- package/Types/Monitor/CustomCodeMonitor/CapturedMetric.ts +7 -0
- package/Types/Monitor/CustomCodeMonitor/CustomCodeMonitorResponse.ts +2 -0
- package/Types/Monitor/UptimeBarTooltipIncident.ts +21 -0
- package/Types/Profile/ProfileMetricType.ts +16 -0
- package/Types/Span/SpanMetricType.ts +17 -0
- package/UI/Components/Charts/Area/AreaChart.tsx +40 -33
- package/UI/Components/Charts/Bar/BarChart.tsx +37 -30
- package/UI/Components/Charts/ChartGroup/ChartGroup.tsx +196 -51
- package/UI/Components/Charts/ChartGroup/NoDataMessage.tsx +13 -0
- package/UI/Components/Charts/Line/LineChart.tsx +39 -32
- package/UI/Components/Forms/BasicForm.tsx +1 -1
- package/UI/Components/Graphs/DayUptimeGraph.tsx +88 -35
- package/UI/Components/Graphs/UptimeBarTooltip.tsx +547 -0
- package/UI/Components/MonitorGraphs/Uptime.tsx +7 -0
- package/UI/Components/MonitorGraphs/UptimeBarDayModal.tsx +225 -0
- package/UI/Components/RadioButtons/GroupRadioButtons.tsx +1 -0
- package/UI/Components/Tooltip/Tooltip.tsx +29 -4
- package/UI/Components/Workflow/ComponentSettingsModal.tsx +2 -0
- package/UI/Components/Workflow/DocumentationViewer.tsx +5 -0
- package/UI/Components/Workflow/Workflow.tsx +2 -0
- package/Utils/Alerts/AlertMetricType.ts +98 -0
- package/Utils/Incident/IncidentMetricType.ts +130 -0
- package/build/dist/Models/DatabaseModels/Workflow.js +30 -0
- package/build/dist/Models/DatabaseModels/Workflow.js.map +1 -1
- package/build/dist/Server/API/StatusPageAPI.js +42 -0
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +2 -2
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1774559064920-MigrationName.js +14 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1774559064920-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +2 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/AlertService.js +34 -0
- package/build/dist/Server/Services/AlertService.js.map +1 -1
- package/build/dist/Server/Services/IncidentService.js +52 -9
- package/build/dist/Server/Services/IncidentService.js.map +1 -1
- package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
- package/build/dist/Server/Services/WorkflowService.js +25 -0
- package/build/dist/Server/Services/WorkflowService.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/Webhook.js +23 -5
- package/build/dist/Server/Types/Workflow/Components/Webhook.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +21 -7
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +120 -21
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js +68 -1
- package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js.map +1 -1
- package/build/dist/Server/Utils/Profiling.js +80 -0
- package/build/dist/Server/Utils/Profiling.js.map +1 -0
- package/build/dist/Server/Utils/VM/VMRunner.js +68 -0
- package/build/dist/Server/Utils/VM/VMRunner.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardTemplates.js +1095 -0
- package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
- package/build/dist/Types/Exception/ExceptionMetricType.js +16 -0
- package/build/dist/Types/Exception/ExceptionMetricType.js.map +1 -0
- package/build/dist/Types/Metrics/MetricDashboardMetricType.js +26 -0
- package/build/dist/Types/Metrics/MetricDashboardMetricType.js.map +1 -0
- package/build/dist/Types/Monitor/CustomCodeMonitor/CapturedMetric.js +2 -0
- package/build/dist/Types/Monitor/CustomCodeMonitor/CapturedMetric.js.map +1 -0
- package/build/dist/Types/Monitor/UptimeBarTooltipIncident.js +2 -0
- package/build/dist/Types/Monitor/UptimeBarTooltipIncident.js.map +1 -0
- package/build/dist/Types/Profile/ProfileMetricType.js +17 -0
- package/build/dist/Types/Profile/ProfileMetricType.js.map +1 -0
- package/build/dist/Types/Span/SpanMetricType.js +18 -0
- package/build/dist/Types/Span/SpanMetricType.js.map +1 -0
- package/build/dist/UI/Components/Charts/Area/AreaChart.js +21 -16
- package/build/dist/UI/Components/Charts/Area/AreaChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/Bar/BarChart.js +20 -15
- package/build/dist/UI/Components/Charts/Bar/BarChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js +73 -15
- package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartGroup/NoDataMessage.js +7 -0
- package/build/dist/UI/Components/Charts/ChartGroup/NoDataMessage.js.map +1 -0
- package/build/dist/UI/Components/Charts/Line/LineChart.js +20 -15
- package/build/dist/UI/Components/Charts/Line/LineChart.js.map +1 -1
- package/build/dist/UI/Components/Forms/BasicForm.js +1 -1
- package/build/dist/UI/Components/Forms/BasicForm.js.map +1 -1
- package/build/dist/UI/Components/Graphs/DayUptimeGraph.js +46 -20
- package/build/dist/UI/Components/Graphs/DayUptimeGraph.js.map +1 -1
- package/build/dist/UI/Components/Graphs/UptimeBarTooltip.js +303 -0
- package/build/dist/UI/Components/Graphs/UptimeBarTooltip.js.map +1 -0
- package/build/dist/UI/Components/MonitorGraphs/Uptime.js +1 -1
- package/build/dist/UI/Components/MonitorGraphs/Uptime.js.map +1 -1
- package/build/dist/UI/Components/MonitorGraphs/UptimeBarDayModal.js +118 -0
- package/build/dist/UI/Components/MonitorGraphs/UptimeBarDayModal.js.map +1 -0
- package/build/dist/UI/Components/RadioButtons/GroupRadioButtons.js +1 -1
- package/build/dist/UI/Components/RadioButtons/GroupRadioButtons.js.map +1 -1
- package/build/dist/UI/Components/Tooltip/Tooltip.js +13 -3
- package/build/dist/UI/Components/Tooltip/Tooltip.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ComponentSettingsModal.js +1 -1
- package/build/dist/UI/Components/Workflow/ComponentSettingsModal.js.map +1 -1
- package/build/dist/UI/Components/Workflow/DocumentationViewer.js +1 -0
- package/build/dist/UI/Components/Workflow/DocumentationViewer.js.map +1 -1
- package/build/dist/UI/Components/Workflow/Workflow.js +1 -1
- package/build/dist/UI/Components/Workflow/Workflow.js.map +1 -1
- package/build/dist/Utils/Alerts/AlertMetricType.js +84 -0
- package/build/dist/Utils/Alerts/AlertMetricType.js.map +1 -0
- package/build/dist/Utils/Incident/IncidentMetricType.js +114 -0
- package/build/dist/Utils/Incident/IncidentMetricType.js.map +1 -0
- package/package.json +3 -2
|
@@ -527,6 +527,35 @@ export default class Workflow extends BaseModel {
|
|
|
527
527
|
})
|
|
528
528
|
public triggerArguments?: JSONObject = undefined;
|
|
529
529
|
|
|
530
|
+
@ColumnAccessControl({
|
|
531
|
+
create: [],
|
|
532
|
+
read: [
|
|
533
|
+
Permission.ProjectOwner,
|
|
534
|
+
Permission.ProjectAdmin,
|
|
535
|
+
Permission.ProjectMember,
|
|
536
|
+
Permission.ReadWorkflow,
|
|
537
|
+
Permission.ReadAllProjectResources,
|
|
538
|
+
],
|
|
539
|
+
update: [
|
|
540
|
+
Permission.ProjectOwner,
|
|
541
|
+
Permission.ProjectAdmin,
|
|
542
|
+
Permission.EditWorkflow,
|
|
543
|
+
],
|
|
544
|
+
})
|
|
545
|
+
@TableColumn({
|
|
546
|
+
isDefaultValueColumn: false,
|
|
547
|
+
required: false,
|
|
548
|
+
type: TableColumnType.LongText,
|
|
549
|
+
title: "Webhook Secret Key",
|
|
550
|
+
description:
|
|
551
|
+
"Secret key used to trigger this workflow via webhook. Use this instead of the workflow ID for security.",
|
|
552
|
+
})
|
|
553
|
+
@Column({
|
|
554
|
+
type: ColumnType.LongText,
|
|
555
|
+
nullable: true,
|
|
556
|
+
})
|
|
557
|
+
public webhookSecretKey?: string = undefined;
|
|
558
|
+
|
|
530
559
|
// This is a BullMQ job key that is used to schedule job for this workflow. This is used internally to remove existing job.
|
|
531
560
|
@ColumnAccessControl({
|
|
532
561
|
create: [],
|
|
@@ -2169,6 +2169,50 @@ export default class StatusPageAPI extends BaseAPI<
|
|
|
2169
2169
|
},
|
|
2170
2170
|
});
|
|
2171
2171
|
|
|
2172
|
+
/*
|
|
2173
|
+
* Fetch all incidents (active + resolved) in the timeline date range
|
|
2174
|
+
* for the uptime bar tooltip and click-through
|
|
2175
|
+
*/
|
|
2176
|
+
let timelineIncidents: Array<Incident> = [];
|
|
2177
|
+
if (
|
|
2178
|
+
monitorsOnStatusPage.length > 0 &&
|
|
2179
|
+
statusPage.showIncidentsOnStatusPage
|
|
2180
|
+
) {
|
|
2181
|
+
timelineIncidents = await IncidentService.findBy({
|
|
2182
|
+
query: {
|
|
2183
|
+
monitors: monitorsOnStatusPage as any,
|
|
2184
|
+
declaredAt: QueryHelper.inBetween(startDate, endDate),
|
|
2185
|
+
isVisibleOnStatusPage: true,
|
|
2186
|
+
projectId: statusPage.projectId!,
|
|
2187
|
+
},
|
|
2188
|
+
select: {
|
|
2189
|
+
_id: true,
|
|
2190
|
+
title: true,
|
|
2191
|
+
declaredAt: true,
|
|
2192
|
+
incidentSeverity: {
|
|
2193
|
+
name: true,
|
|
2194
|
+
color: true,
|
|
2195
|
+
},
|
|
2196
|
+
currentIncidentState: {
|
|
2197
|
+
_id: true,
|
|
2198
|
+
name: true,
|
|
2199
|
+
color: true,
|
|
2200
|
+
},
|
|
2201
|
+
monitors: {
|
|
2202
|
+
_id: true,
|
|
2203
|
+
},
|
|
2204
|
+
},
|
|
2205
|
+
sort: {
|
|
2206
|
+
declaredAt: SortOrder.Descending,
|
|
2207
|
+
},
|
|
2208
|
+
skip: 0,
|
|
2209
|
+
limit: LIMIT_PER_PROJECT,
|
|
2210
|
+
props: {
|
|
2211
|
+
isRoot: true,
|
|
2212
|
+
},
|
|
2213
|
+
});
|
|
2214
|
+
}
|
|
2215
|
+
|
|
2172
2216
|
const overallStatus: MonitorStatus | null =
|
|
2173
2217
|
StatusPageService.getOverallMonitorStatus({
|
|
2174
2218
|
statusPageResources,
|
|
@@ -2251,6 +2295,10 @@ export default class StatusPageAPI extends BaseAPI<
|
|
|
2251
2295
|
monitorGroupCurrentStatuses,
|
|
2252
2296
|
),
|
|
2253
2297
|
monitorsInGroup: JSONFunctions.serialize(monitorsInGroup),
|
|
2298
|
+
timelineIncidents: BaseModel.toJSONArray(
|
|
2299
|
+
timelineIncidents,
|
|
2300
|
+
Incident,
|
|
2301
|
+
),
|
|
2254
2302
|
};
|
|
2255
2303
|
|
|
2256
2304
|
return Response.sendJsonObjectResponse(req, res, response);
|
|
@@ -176,15 +176,9 @@ export const AppApiHostname: Hostname = Hostname.fromString(
|
|
|
176
176
|
}`,
|
|
177
177
|
);
|
|
178
178
|
|
|
179
|
-
export const OpenTelemetryIngestHostname: Hostname = Hostname.fromString(
|
|
180
|
-
`${process.env["SERVER_TELEMETRY_HOSTNAME"] || "localhost"}:${
|
|
181
|
-
process.env["TELEMETRY_PORT"] || 80
|
|
182
|
-
}`,
|
|
183
|
-
);
|
|
184
|
-
|
|
185
179
|
export const WorkerHostname: Hostname = Hostname.fromString(
|
|
186
|
-
`${process.env["
|
|
187
|
-
process.env["
|
|
180
|
+
`${process.env["SERVER_APP_HOSTNAME"] || "localhost"}:${
|
|
181
|
+
process.env["APP_PORT"] || 80
|
|
188
182
|
}`,
|
|
189
183
|
);
|
|
190
184
|
|
|
@@ -406,6 +400,9 @@ export const IpWhitelist: string = process.env["IP_WHITELIST"] || "";
|
|
|
406
400
|
export const DisableTelemetry: boolean =
|
|
407
401
|
process.env["DISABLE_TELEMETRY"] === "true";
|
|
408
402
|
|
|
403
|
+
export const EnableProfiling: boolean =
|
|
404
|
+
process.env["ENABLE_PROFILING"] === "true";
|
|
405
|
+
|
|
409
406
|
export const IsEnterpriseEdition: boolean =
|
|
410
407
|
process.env["IS_ENTERPRISE_EDITION"] === "true";
|
|
411
408
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from "typeorm";
|
|
2
|
+
|
|
3
|
+
export class MigrationName1774559064920 implements MigrationInterface {
|
|
4
|
+
public name = "MigrationName1774559064920";
|
|
5
|
+
|
|
6
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
7
|
+
await queryRunner.query(
|
|
8
|
+
`ALTER TABLE "Workflow" ADD "webhookSecretKey" text`,
|
|
9
|
+
);
|
|
10
|
+
|
|
11
|
+
// Set secret key to existing workflow ID so current webhook URLs keep working.
|
|
12
|
+
await queryRunner.query(
|
|
13
|
+
`UPDATE "Workflow" SET "webhookSecretKey" = "_id"::text WHERE "webhookSecretKey" IS NULL`,
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
18
|
+
await queryRunner.query(
|
|
19
|
+
`ALTER TABLE "Workflow" DROP COLUMN "webhookSecretKey"`,
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -274,6 +274,7 @@ import { MigrationName1774524742177 } from "./1774524742177-MigrationName";
|
|
|
274
274
|
import { MigrationName1774524742178 } from "./1774524742178-MigrationName";
|
|
275
275
|
import { MigrationName1774524742179 } from "./1774524742179-MigrationName";
|
|
276
276
|
import { MigrationName1774559064919 } from "./1774559064919-MigrationName";
|
|
277
|
+
import { MigrationName1774559064920 } from "./1774559064920-MigrationName";
|
|
277
278
|
|
|
278
279
|
export default [
|
|
279
280
|
InitialMigration,
|
|
@@ -552,4 +553,5 @@ export default [
|
|
|
552
553
|
MigrationName1774524742178,
|
|
553
554
|
MigrationName1774524742179,
|
|
554
555
|
MigrationName1774559064919,
|
|
556
|
+
MigrationName1774559064920,
|
|
555
557
|
];
|
|
@@ -31,6 +31,8 @@ import { IsBillingEnabled } from "../EnvironmentConfig";
|
|
|
31
31
|
import logger from "../Utils/Logger";
|
|
32
32
|
import TelemetryUtil from "../Utils/Telemetry/Telemetry";
|
|
33
33
|
import MetricService from "./MetricService";
|
|
34
|
+
import GlobalConfigService from "./GlobalConfigService";
|
|
35
|
+
import GlobalConfig from "../../Models/DatabaseModels/GlobalConfig";
|
|
34
36
|
import OneUptimeDate from "../../Types/Date";
|
|
35
37
|
import Metric, {
|
|
36
38
|
MetricPointType,
|
|
@@ -1060,6 +1062,39 @@ ${alertSeverity.name}
|
|
|
1060
1062
|
});
|
|
1061
1063
|
}
|
|
1062
1064
|
|
|
1065
|
+
private static readonly DEFAULT_METRIC_RETENTION_DAYS: number = 180;
|
|
1066
|
+
|
|
1067
|
+
private async getMetricRetentionDays(): Promise<number> {
|
|
1068
|
+
try {
|
|
1069
|
+
const globalConfig: GlobalConfig | null =
|
|
1070
|
+
await GlobalConfigService.findOneBy({
|
|
1071
|
+
query: {
|
|
1072
|
+
_id: ObjectID.getZeroObjectID().toString(),
|
|
1073
|
+
},
|
|
1074
|
+
props: {
|
|
1075
|
+
isRoot: true,
|
|
1076
|
+
},
|
|
1077
|
+
select: {
|
|
1078
|
+
monitorMetricRetentionInDays: true,
|
|
1079
|
+
},
|
|
1080
|
+
});
|
|
1081
|
+
|
|
1082
|
+
if (
|
|
1083
|
+
globalConfig &&
|
|
1084
|
+
globalConfig.monitorMetricRetentionInDays !== undefined &&
|
|
1085
|
+
globalConfig.monitorMetricRetentionInDays !== null &&
|
|
1086
|
+
globalConfig.monitorMetricRetentionInDays > 0
|
|
1087
|
+
) {
|
|
1088
|
+
return globalConfig.monitorMetricRetentionInDays;
|
|
1089
|
+
}
|
|
1090
|
+
} catch (error) {
|
|
1091
|
+
logger.error("Error fetching metric retention config, using default:");
|
|
1092
|
+
logger.error(error);
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
return Service.DEFAULT_METRIC_RETENTION_DAYS;
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1063
1098
|
@CaptureSpan()
|
|
1064
1099
|
public async refreshAlertMetrics(data: { alertId: ObjectID }): Promise<void> {
|
|
1065
1100
|
const alert: Model | null = await this.findOneById({
|
|
@@ -1130,6 +1165,12 @@ ${alertSeverity.name}
|
|
|
1130
1165
|
const itemsToSave: Array<Metric> = [];
|
|
1131
1166
|
const metricTypesMap: Dictionary<MetricType> = {};
|
|
1132
1167
|
|
|
1168
|
+
const metricRetentionDays: number = await this.getMetricRetentionDays();
|
|
1169
|
+
const alertMetricRetentionDate: Date = OneUptimeDate.addRemoveDays(
|
|
1170
|
+
OneUptimeDate.getCurrentDate(),
|
|
1171
|
+
metricRetentionDays,
|
|
1172
|
+
);
|
|
1173
|
+
|
|
1133
1174
|
// now we need to create new metrics for this alert - TimeToAcknowledge, TimeToResolve, AlertCount, AlertDuration
|
|
1134
1175
|
const alertStartsAt: Date =
|
|
1135
1176
|
firstAlertStateTimeline?.startsAt ||
|
|
@@ -1160,6 +1201,7 @@ ${alertSeverity.name}
|
|
|
1160
1201
|
alertCountMetric.time,
|
|
1161
1202
|
);
|
|
1162
1203
|
alertCountMetric.metricPointType = MetricPointType.Sum;
|
|
1204
|
+
alertCountMetric.retentionDate = alertMetricRetentionDate;
|
|
1163
1205
|
|
|
1164
1206
|
itemsToSave.push(alertCountMetric);
|
|
1165
1207
|
|
|
@@ -1214,6 +1256,7 @@ ${alertSeverity.name}
|
|
|
1214
1256
|
timeToAcknowledgeMetric.time,
|
|
1215
1257
|
);
|
|
1216
1258
|
timeToAcknowledgeMetric.metricPointType = MetricPointType.Sum;
|
|
1259
|
+
timeToAcknowledgeMetric.retentionDate = alertMetricRetentionDate;
|
|
1217
1260
|
|
|
1218
1261
|
itemsToSave.push(timeToAcknowledgeMetric);
|
|
1219
1262
|
|
|
@@ -1270,6 +1313,7 @@ ${alertSeverity.name}
|
|
|
1270
1313
|
timeToResolveMetric.time,
|
|
1271
1314
|
);
|
|
1272
1315
|
timeToResolveMetric.metricPointType = MetricPointType.Sum;
|
|
1316
|
+
timeToResolveMetric.retentionDate = alertMetricRetentionDate;
|
|
1273
1317
|
|
|
1274
1318
|
itemsToSave.push(timeToResolveMetric);
|
|
1275
1319
|
|
|
@@ -1319,6 +1363,7 @@ ${alertSeverity.name}
|
|
|
1319
1363
|
alertDurationMetric.time,
|
|
1320
1364
|
);
|
|
1321
1365
|
alertDurationMetric.metricPointType = MetricPointType.Sum;
|
|
1366
|
+
alertDurationMetric.retentionDate = alertMetricRetentionDate;
|
|
1322
1367
|
|
|
1323
1368
|
itemsToSave.push(alertDurationMetric);
|
|
1324
1369
|
|
|
@@ -36,6 +36,8 @@ import MonitorStatusTimeline from "../../Models/DatabaseModels/MonitorStatusTime
|
|
|
36
36
|
import User from "../../Models/DatabaseModels/User";
|
|
37
37
|
import { IsBillingEnabled } from "../EnvironmentConfig";
|
|
38
38
|
import MetricService from "./MetricService";
|
|
39
|
+
import GlobalConfigService from "./GlobalConfigService";
|
|
40
|
+
import GlobalConfig from "../../Models/DatabaseModels/GlobalConfig";
|
|
39
41
|
import IncidentMetricType from "../../Types/Incident/IncidentMetricType";
|
|
40
42
|
import Metric, {
|
|
41
43
|
MetricPointType,
|
|
@@ -1396,6 +1398,12 @@ ${incident.remediationNotes || "No remediation notes provided."}
|
|
|
1396
1398
|
postmortemMetric.time,
|
|
1397
1399
|
);
|
|
1398
1400
|
postmortemMetric.metricPointType = MetricPointType.Sum;
|
|
1401
|
+
const postmortemRetentionDays: number =
|
|
1402
|
+
await this.getMetricRetentionDays();
|
|
1403
|
+
postmortemMetric.retentionDate = OneUptimeDate.addRemoveDays(
|
|
1404
|
+
OneUptimeDate.getCurrentDate(),
|
|
1405
|
+
postmortemRetentionDays,
|
|
1406
|
+
);
|
|
1399
1407
|
|
|
1400
1408
|
await MetricService.create({
|
|
1401
1409
|
data: postmortemMetric,
|
|
@@ -1583,6 +1591,12 @@ ${incidentSeverity.name}
|
|
|
1583
1591
|
severityChangeMetric.time,
|
|
1584
1592
|
);
|
|
1585
1593
|
severityChangeMetric.metricPointType = MetricPointType.Sum;
|
|
1594
|
+
const severityRetentionDays: number =
|
|
1595
|
+
await this.getMetricRetentionDays();
|
|
1596
|
+
severityChangeMetric.retentionDate = OneUptimeDate.addRemoveDays(
|
|
1597
|
+
OneUptimeDate.getCurrentDate(),
|
|
1598
|
+
severityRetentionDays,
|
|
1599
|
+
);
|
|
1586
1600
|
|
|
1587
1601
|
await MetricService.create({
|
|
1588
1602
|
data: severityChangeMetric,
|
|
@@ -2075,6 +2089,39 @@ ${incidentSeverity.name}
|
|
|
2075
2089
|
});
|
|
2076
2090
|
}
|
|
2077
2091
|
|
|
2092
|
+
private static readonly DEFAULT_METRIC_RETENTION_DAYS: number = 180;
|
|
2093
|
+
|
|
2094
|
+
private async getMetricRetentionDays(): Promise<number> {
|
|
2095
|
+
try {
|
|
2096
|
+
const globalConfig: GlobalConfig | null =
|
|
2097
|
+
await GlobalConfigService.findOneBy({
|
|
2098
|
+
query: {
|
|
2099
|
+
_id: ObjectID.getZeroObjectID().toString(),
|
|
2100
|
+
},
|
|
2101
|
+
props: {
|
|
2102
|
+
isRoot: true,
|
|
2103
|
+
},
|
|
2104
|
+
select: {
|
|
2105
|
+
monitorMetricRetentionInDays: true,
|
|
2106
|
+
},
|
|
2107
|
+
});
|
|
2108
|
+
|
|
2109
|
+
if (
|
|
2110
|
+
globalConfig &&
|
|
2111
|
+
globalConfig.monitorMetricRetentionInDays !== undefined &&
|
|
2112
|
+
globalConfig.monitorMetricRetentionInDays !== null &&
|
|
2113
|
+
globalConfig.monitorMetricRetentionInDays > 0
|
|
2114
|
+
) {
|
|
2115
|
+
return globalConfig.monitorMetricRetentionInDays;
|
|
2116
|
+
}
|
|
2117
|
+
} catch (error) {
|
|
2118
|
+
logger.error("Error fetching metric retention config, using default:");
|
|
2119
|
+
logger.error(error);
|
|
2120
|
+
}
|
|
2121
|
+
|
|
2122
|
+
return Service.DEFAULT_METRIC_RETENTION_DAYS;
|
|
2123
|
+
}
|
|
2124
|
+
|
|
2078
2125
|
@CaptureSpan()
|
|
2079
2126
|
public async refreshIncidentMetrics(data: {
|
|
2080
2127
|
incidentId: ObjectID;
|
|
@@ -2223,6 +2270,12 @@ ${incidentSeverity.name}
|
|
|
2223
2270
|
|
|
2224
2271
|
const itemsToSave: Array<Metric> = [];
|
|
2225
2272
|
|
|
2273
|
+
const metricRetentionDays: number = await this.getMetricRetentionDays();
|
|
2274
|
+
const incidentMetricRetentionDate: Date = OneUptimeDate.addRemoveDays(
|
|
2275
|
+
OneUptimeDate.getCurrentDate(),
|
|
2276
|
+
metricRetentionDays,
|
|
2277
|
+
);
|
|
2278
|
+
|
|
2226
2279
|
// now we need to create new metrics for this incident - TimeToAcknowledge, TimeToResolve, IncidentCount, IncidentDuration
|
|
2227
2280
|
|
|
2228
2281
|
const incidentStartsAt: Date =
|
|
@@ -2233,24 +2286,34 @@ ${incidentSeverity.name}
|
|
|
2233
2286
|
|
|
2234
2287
|
const metricTypesMap: Dictionary<MetricType> = {};
|
|
2235
2288
|
|
|
2236
|
-
|
|
2289
|
+
/*
|
|
2290
|
+
* common attributes shared by all incident metrics
|
|
2291
|
+
* All values must be strings for ClickHouse Map(String, String) storage.
|
|
2292
|
+
* Arrays are joined as comma-separated strings.
|
|
2293
|
+
*/
|
|
2237
2294
|
const baseMetricAttributes: JSONObject = {
|
|
2238
2295
|
incidentId: data.incidentId.toString(),
|
|
2239
2296
|
projectId: incident.projectId.toString(),
|
|
2240
|
-
monitorIds:
|
|
2241
|
-
incident.monitors
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2297
|
+
monitorIds: (
|
|
2298
|
+
incident.monitors
|
|
2299
|
+
?.map((monitor: Monitor) => {
|
|
2300
|
+
return monitor._id?.toString();
|
|
2301
|
+
})
|
|
2302
|
+
.filter(Boolean) || []
|
|
2303
|
+
).join(", "),
|
|
2304
|
+
monitorNames: (
|
|
2305
|
+
incident.monitors
|
|
2306
|
+
?.map((monitor: Monitor) => {
|
|
2307
|
+
return monitor.name?.toString();
|
|
2308
|
+
})
|
|
2309
|
+
.filter(Boolean) || []
|
|
2310
|
+
).join(", "),
|
|
2248
2311
|
incidentSeverityId: incident.incidentSeverity?._id?.toString(),
|
|
2249
2312
|
incidentSeverityName: incident.incidentSeverity?.name?.toString(),
|
|
2250
|
-
ownerUserIds: ownerUserIds,
|
|
2251
|
-
ownerUserNames: ownerUserNames,
|
|
2252
|
-
ownerTeamIds: ownerTeamIds,
|
|
2253
|
-
ownerTeamNames: ownerTeamNames,
|
|
2313
|
+
ownerUserIds: ownerUserIds.join(", "),
|
|
2314
|
+
ownerUserNames: ownerUserNames.join(", "),
|
|
2315
|
+
ownerTeamIds: ownerTeamIds.join(", "),
|
|
2316
|
+
ownerTeamNames: ownerTeamNames.join(", "),
|
|
2254
2317
|
};
|
|
2255
2318
|
|
|
2256
2319
|
const incidentCountMetric: Metric = new Metric();
|
|
@@ -2270,6 +2333,7 @@ ${incidentSeverity.name}
|
|
|
2270
2333
|
incidentCountMetric.time,
|
|
2271
2334
|
);
|
|
2272
2335
|
incidentCountMetric.metricPointType = MetricPointType.Sum;
|
|
2336
|
+
incidentCountMetric.retentionDate = incidentMetricRetentionDate;
|
|
2273
2337
|
|
|
2274
2338
|
itemsToSave.push(incidentCountMetric);
|
|
2275
2339
|
|
|
@@ -2321,6 +2385,7 @@ ${incidentSeverity.name}
|
|
|
2321
2385
|
timeToAcknowledgeMetric.time,
|
|
2322
2386
|
);
|
|
2323
2387
|
timeToAcknowledgeMetric.metricPointType = MetricPointType.Sum;
|
|
2388
|
+
timeToAcknowledgeMetric.retentionDate = incidentMetricRetentionDate;
|
|
2324
2389
|
|
|
2325
2390
|
itemsToSave.push(timeToAcknowledgeMetric);
|
|
2326
2391
|
|
|
@@ -2374,6 +2439,7 @@ ${incidentSeverity.name}
|
|
|
2374
2439
|
timeToResolveMetric.time,
|
|
2375
2440
|
);
|
|
2376
2441
|
timeToResolveMetric.metricPointType = MetricPointType.Sum;
|
|
2442
|
+
timeToResolveMetric.retentionDate = incidentMetricRetentionDate;
|
|
2377
2443
|
|
|
2378
2444
|
itemsToSave.push(timeToResolveMetric);
|
|
2379
2445
|
|
|
@@ -2422,6 +2488,7 @@ ${incidentSeverity.name}
|
|
|
2422
2488
|
incidentDurationMetric.time,
|
|
2423
2489
|
);
|
|
2424
2490
|
incidentDurationMetric.metricPointType = MetricPointType.Sum;
|
|
2491
|
+
incidentDurationMetric.retentionDate = incidentMetricRetentionDate;
|
|
2425
2492
|
|
|
2426
2493
|
itemsToSave.push(incidentDurationMetric);
|
|
2427
2494
|
|
|
@@ -2474,6 +2541,7 @@ ${incidentSeverity.name}
|
|
|
2474
2541
|
timeInStateMetric.time,
|
|
2475
2542
|
);
|
|
2476
2543
|
timeInStateMetric.metricPointType = MetricPointType.Sum;
|
|
2544
|
+
timeInStateMetric.retentionDate = incidentMetricRetentionDate;
|
|
2477
2545
|
|
|
2478
2546
|
itemsToSave.push(timeInStateMetric);
|
|
2479
2547
|
}
|
|
@@ -676,6 +676,7 @@ export class LogAggregationService {
|
|
|
676
676
|
bodySearchText?: string | undefined;
|
|
677
677
|
traceIds?: Array<string> | undefined;
|
|
678
678
|
spanIds?: Array<string> | undefined;
|
|
679
|
+
attributes?: Record<string, string> | undefined;
|
|
679
680
|
}): Promise<Array<JSONObject>> {
|
|
680
681
|
const maxLimit: number = Math.min(request.limit || 10000, 10000);
|
|
681
682
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { WorkflowHostname } from "../EnvironmentConfig";
|
|
2
2
|
import ClusterKeyAuthorization from "../Middleware/ClusterKeyAuthorization";
|
|
3
|
-
import { OnUpdate } from "../Types/Database/Hooks";
|
|
3
|
+
import { OnCreate, OnUpdate } from "../Types/Database/Hooks";
|
|
4
4
|
import DatabaseService from "./DatabaseService";
|
|
5
5
|
import EmptyResponseData from "../../Types/API/EmptyResponse";
|
|
6
6
|
import Protocol from "../../Types/API/Protocol";
|
|
@@ -17,12 +17,39 @@ import {
|
|
|
17
17
|
import API from "../../Utils/API";
|
|
18
18
|
import Model from "../../Models/DatabaseModels/Workflow";
|
|
19
19
|
import logger from "../Utils/Logger";
|
|
20
|
+
import UUID from "../../Utils/UUID";
|
|
20
21
|
|
|
21
22
|
export class Service extends DatabaseService<Model> {
|
|
22
23
|
public constructor() {
|
|
23
24
|
super(Model);
|
|
24
25
|
}
|
|
25
26
|
|
|
27
|
+
@CaptureSpan()
|
|
28
|
+
protected override async onCreateSuccess(
|
|
29
|
+
_onCreate: OnCreate<Model>,
|
|
30
|
+
createdItem: Model,
|
|
31
|
+
): Promise<Model> {
|
|
32
|
+
// Auto-generate webhook secret key for new workflows.
|
|
33
|
+
if (!createdItem.webhookSecretKey && createdItem._id) {
|
|
34
|
+
const secretKey: string = UUID.generate();
|
|
35
|
+
|
|
36
|
+
await this.updateOneById({
|
|
37
|
+
id: new ObjectID(createdItem._id),
|
|
38
|
+
data: {
|
|
39
|
+
webhookSecretKey: secretKey,
|
|
40
|
+
} as any,
|
|
41
|
+
props: {
|
|
42
|
+
isRoot: true,
|
|
43
|
+
ignoreHooks: true,
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
createdItem.webhookSecretKey = secretKey;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return createdItem;
|
|
51
|
+
}
|
|
52
|
+
|
|
26
53
|
@CaptureSpan()
|
|
27
54
|
protected override async onUpdateSuccess(
|
|
28
55
|
onUpdate: OnUpdate<Model>,
|
|
@@ -13,6 +13,8 @@ import ComponentMetadata, { Port } from "../../../../Types/Workflow/Component";
|
|
|
13
13
|
import ComponentID from "../../../../Types/Workflow/ComponentID";
|
|
14
14
|
import WebhookComponents from "../../../../Types/Workflow/Components/Webhook";
|
|
15
15
|
import CaptureSpan from "../../../Utils/Telemetry/CaptureSpan";
|
|
16
|
+
import WorkflowService from "../../../Services/WorkflowService";
|
|
17
|
+
import Workflow from "../../../../Models/DatabaseModels/Workflow";
|
|
16
18
|
|
|
17
19
|
export default class WebhookTrigger extends TriggerCode {
|
|
18
20
|
public constructor() {
|
|
@@ -54,7 +56,7 @@ export default class WebhookTrigger extends TriggerCode {
|
|
|
54
56
|
@CaptureSpan()
|
|
55
57
|
public override async init(props: InitProps): Promise<void> {
|
|
56
58
|
props.router.get(
|
|
57
|
-
`/trigger/:
|
|
59
|
+
`/trigger/:secretkey`,
|
|
58
60
|
async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
|
|
59
61
|
try {
|
|
60
62
|
await this.initTrigger(req, res, props);
|
|
@@ -65,7 +67,7 @@ export default class WebhookTrigger extends TriggerCode {
|
|
|
65
67
|
);
|
|
66
68
|
|
|
67
69
|
props.router.post(
|
|
68
|
-
`/trigger/:
|
|
70
|
+
`/trigger/:secretkey`,
|
|
69
71
|
async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
|
|
70
72
|
try {
|
|
71
73
|
await this.initTrigger(req, res, props);
|
|
@@ -82,12 +84,33 @@ export default class WebhookTrigger extends TriggerCode {
|
|
|
82
84
|
res: ExpressResponse,
|
|
83
85
|
props: InitProps,
|
|
84
86
|
): Promise<void> {
|
|
85
|
-
|
|
87
|
+
const secretKey: string = req.params["secretkey"] as string;
|
|
86
88
|
|
|
87
|
-
|
|
89
|
+
if (!secretKey) {
|
|
90
|
+
throw new BadDataException("Secret key is required to trigger workflow.");
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Look up the workflow by webhook secret key.
|
|
94
|
+
const workflow: Workflow | null = await WorkflowService.findOneBy({
|
|
95
|
+
query: {
|
|
96
|
+
webhookSecretKey: secretKey,
|
|
97
|
+
},
|
|
98
|
+
select: {
|
|
99
|
+
_id: true,
|
|
100
|
+
},
|
|
101
|
+
props: {
|
|
102
|
+
isRoot: true,
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
if (!workflow || !workflow._id) {
|
|
107
|
+
throw new BadDataException(
|
|
108
|
+
"Workflow not found for the provided secret key.",
|
|
109
|
+
);
|
|
110
|
+
}
|
|
88
111
|
|
|
89
112
|
const executeWorkflow: ExecuteWorkflowType = {
|
|
90
|
-
workflowId: new ObjectID(
|
|
113
|
+
workflowId: new ObjectID(workflow._id),
|
|
91
114
|
returnValues: {
|
|
92
115
|
"request-headers": req.headers,
|
|
93
116
|
"request-params": req.query,
|
|
@@ -208,6 +208,12 @@ export default class StatementGenerator<TBaseModel extends AnalyticsBaseModel> {
|
|
|
208
208
|
)}')`;
|
|
209
209
|
}
|
|
210
210
|
|
|
211
|
+
if (column.type === TableColumnType.DateTime64 && value instanceof Date) {
|
|
212
|
+
value = `parseDateTimeBestEffortOrNull('${OneUptimeDate.toClickhouseDateTime64(
|
|
213
|
+
value as Date,
|
|
214
|
+
)}')`;
|
|
215
|
+
}
|
|
216
|
+
|
|
211
217
|
if (column.type === TableColumnType.Number) {
|
|
212
218
|
if (typeof value === "string") {
|
|
213
219
|
value = parseInt(value);
|
|
@@ -419,23 +425,33 @@ export default class StatementGenerator<TBaseModel extends AnalyticsBaseModel> {
|
|
|
419
425
|
tableColumn.type === TableColumnType.MapStringString &&
|
|
420
426
|
typeof value === "object"
|
|
421
427
|
) {
|
|
422
|
-
const mapValue: Record<string, string
|
|
423
|
-
string,
|
|
424
|
-
string
|
|
425
|
-
>;
|
|
428
|
+
const mapValue: Record<string, string | Search<string>> =
|
|
429
|
+
value as Record<string, string | Search<string>>;
|
|
426
430
|
for (const mapKey in mapValue) {
|
|
427
431
|
if (mapValue[mapKey] === undefined) {
|
|
428
432
|
continue;
|
|
429
433
|
}
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
434
|
+
if (mapValue[mapKey] instanceof Search) {
|
|
435
|
+
whereStatement.append(
|
|
436
|
+
SQL`AND ${key}[${{
|
|
437
|
+
value: mapKey,
|
|
438
|
+
type: TableColumnType.Text,
|
|
439
|
+
}}] ILIKE ${{
|
|
440
|
+
value: mapValue[mapKey] as Search<string>,
|
|
441
|
+
type: TableColumnType.Text,
|
|
442
|
+
}}`,
|
|
443
|
+
);
|
|
444
|
+
} else {
|
|
445
|
+
whereStatement.append(
|
|
446
|
+
SQL`AND ${key}[${{
|
|
447
|
+
value: mapKey,
|
|
448
|
+
type: TableColumnType.Text,
|
|
449
|
+
}}] = ${{
|
|
450
|
+
value: mapValue[mapKey] as string,
|
|
451
|
+
type: TableColumnType.Text,
|
|
452
|
+
}}`,
|
|
453
|
+
);
|
|
454
|
+
}
|
|
439
455
|
}
|
|
440
456
|
} else if (
|
|
441
457
|
(tableColumn.type === TableColumnType.JSON ||
|