@oneuptime/common 7.0.3365 → 7.0.3387

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.
Files changed (81) hide show
  1. package/Server/EnvironmentConfig.ts +3 -0
  2. package/Server/Services/AnalyticsDatabaseService.ts +4 -0
  3. package/Server/Services/StatusPageService.ts +4 -4
  4. package/Server/Types/AnalyticsDatabase/AggregateBy.ts +4 -0
  5. package/Server/Utils/Monitor/Criteria/APIRequestCriteria.ts +4 -1
  6. package/Server/Utils/Monitor/Criteria/CompareCriteria.ts +26 -16
  7. package/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.ts +127 -0
  8. package/Server/Utils/Monitor/DataToProcess.ts +3 -1
  9. package/Server/Utils/Monitor/MonitorAlert.ts +5 -0
  10. package/Server/Utils/Monitor/MonitorIncident.ts +5 -0
  11. package/Server/Utils/Monitor/MonitorResource.ts +40 -0
  12. package/Server/Utils/Stream.ts +4 -0
  13. package/Types/Date.ts +9 -0
  14. package/Types/Metrics/MetricViewData.ts +6 -0
  15. package/Types/Monitor/CriteriaFilter.ts +9 -0
  16. package/Types/Monitor/MetricMonitor/MetricMonitorResponse.ts +11 -0
  17. package/Types/Monitor/MonitorCriteriaInstance.ts +93 -0
  18. package/Types/Monitor/MonitorStep.ts +26 -0
  19. package/Types/Monitor/MonitorStepMetricMonitor.ts +28 -0
  20. package/Types/Monitor/MonitorType.ts +7 -8
  21. package/Types/RollingTime/RollingTime.ts +24 -0
  22. package/Types/RollingTime/RollingTimeUtil.ts +98 -0
  23. package/Types/Telemetry/TelemetryQuery.ts +3 -2
  24. package/UI/Components/Charts/ChartGroup/ChartGroup.tsx +2 -1
  25. package/UI/Components/Charts/Utils/XAxis.ts +3 -2
  26. package/UI/Components/Date/StartAndEndDate.tsx +65 -71
  27. package/UI/Components/Filters/DateFilter.tsx +1 -1
  28. package/UI/Components/RollingTimePicker/RollingTimePicker.tsx +45 -0
  29. package/build/dist/Server/EnvironmentConfig.js +1 -0
  30. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  31. package/build/dist/Server/Services/AnalyticsDatabaseService.js +3 -0
  32. package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
  33. package/build/dist/Server/Services/StatusPageService.js +3 -2
  34. package/build/dist/Server/Services/StatusPageService.js.map +1 -1
  35. package/build/dist/Server/Types/AnalyticsDatabase/AggregateBy.js +3 -0
  36. package/build/dist/Server/Types/AnalyticsDatabase/AggregateBy.js.map +1 -1
  37. package/build/dist/Server/Utils/Monitor/Criteria/APIRequestCriteria.js +2 -1
  38. package/build/dist/Server/Utils/Monitor/Criteria/APIRequestCriteria.js.map +1 -1
  39. package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js +25 -14
  40. package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js.map +1 -1
  41. package/build/dist/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.js +77 -0
  42. package/build/dist/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.js.map +1 -0
  43. package/build/dist/Server/Utils/Monitor/MonitorAlert.js +4 -0
  44. package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
  45. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +4 -0
  46. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
  47. package/build/dist/Server/Utils/Monitor/MonitorResource.js +30 -0
  48. package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
  49. package/build/dist/Server/Utils/Stream.js +3 -0
  50. package/build/dist/Server/Utils/Stream.js.map +1 -1
  51. package/build/dist/Types/Date.js +5 -0
  52. package/build/dist/Types/Date.js.map +1 -1
  53. package/build/dist/Types/Metrics/MetricViewData.js +2 -0
  54. package/build/dist/Types/Metrics/MetricViewData.js.map +1 -0
  55. package/build/dist/Types/Monitor/CriteriaFilter.js +2 -0
  56. package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
  57. package/build/dist/Types/Monitor/MetricMonitor/MetricMonitorResponse.js +2 -0
  58. package/build/dist/Types/Monitor/MetricMonitor/MetricMonitorResponse.js.map +1 -0
  59. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +79 -1
  60. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
  61. package/build/dist/Types/Monitor/MonitorStep.js +18 -1
  62. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  63. package/build/dist/Types/Monitor/MonitorStepMetricMonitor.js +19 -0
  64. package/build/dist/Types/Monitor/MonitorStepMetricMonitor.js.map +1 -0
  65. package/build/dist/Types/Monitor/MonitorType.js +6 -8
  66. package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
  67. package/build/dist/Types/RollingTime/RollingTime.js +25 -0
  68. package/build/dist/Types/RollingTime/RollingTime.js.map +1 -0
  69. package/build/dist/Types/RollingTime/RollingTimeUtil.js +74 -0
  70. package/build/dist/Types/RollingTime/RollingTimeUtil.js.map +1 -0
  71. package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js +1 -1
  72. package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js.map +1 -1
  73. package/build/dist/UI/Components/Charts/Utils/XAxis.js +3 -2
  74. package/build/dist/UI/Components/Charts/Utils/XAxis.js.map +1 -1
  75. package/build/dist/UI/Components/Date/StartAndEndDate.js +33 -46
  76. package/build/dist/UI/Components/Date/StartAndEndDate.js.map +1 -1
  77. package/build/dist/UI/Components/Filters/DateFilter.js +1 -1
  78. package/build/dist/UI/Components/Filters/DateFilter.js.map +1 -1
  79. package/build/dist/UI/Components/RollingTimePicker/RollingTimePicker.js +23 -0
  80. package/build/dist/UI/Components/RollingTimePicker/RollingTimePicker.js.map +1 -0
  81. package/package.json +2 -2
@@ -198,6 +198,9 @@ export const AnalyticsHost: string = process.env["ANALYTICS_HOST"] || "";
198
198
  export const DisableAutomaticIncidentCreation: boolean =
199
199
  process.env["DISABLE_AUTOMATIC_INCIDENT_CREATION"] === "true";
200
200
 
201
+ export const DisableAutomaticAlertCreation: boolean =
202
+ process.env["DISABLE_AUTOMATIC_ALERT_CREATION"] === "true";
203
+
201
204
  export const ClickhouseHost: Hostname = Hostname.fromString(
202
205
  process.env["CLICKHOUSE_HOST"] || "clickhouse",
203
206
  );
@@ -415,6 +415,10 @@ export default class AnalyticsDatabaseService<
415
415
  strResult: string,
416
416
  columns: string[],
417
417
  ): JSONObject[] {
418
+ if (!strResult || !strResult.trim()) {
419
+ return [];
420
+ }
421
+
418
422
  const jsonItems: Array<JSONObject> = [];
419
423
 
420
424
  const rows: Array<string> = strResult.split("\n");
@@ -750,11 +750,11 @@ export class Service extends DatabaseService<StatusPage> {
750
750
  statusPageId: data.statusPageId,
751
751
  });
752
752
 
753
+ const numberOfDays: number = data.historyDays || 14;
754
+
753
755
  const currentDate: Date = OneUptimeDate.getCurrentDate();
754
- const startDate: Date = OneUptimeDate.getSomeDaysAgo(
755
- data.historyDays || 14,
756
- );
757
- const startAndEndDate: string = `${OneUptimeDate.getDateAsLocalFormattedString(startDate, true)} - ${OneUptimeDate.getDateAsLocalFormattedString(currentDate, true)}`;
756
+ const startDate: Date = OneUptimeDate.getSomeDaysAgo(numberOfDays);
757
+ const startAndEndDate: string = `${numberOfDays} days (${OneUptimeDate.getDateAsLocalFormattedString(startDate, true)} - ${OneUptimeDate.getDateAsLocalFormattedString(currentDate, true)})`;
758
758
 
759
759
  if (statusPageResources.length === 0) {
760
760
  return {
@@ -2,6 +2,7 @@ import AggregationInterval from "Common/Types/BaseDatabase/AggregationInterval";
2
2
  import CommonAggregateBy from "Common/Types/BaseDatabase/AggregateBy";
3
3
  import AnalyticsBaseModel from "Common/Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel";
4
4
  import DatabaseCommonInteractionProps from "Common/Types/BaseDatabase/DatabaseCommonInteractionProps";
5
+ import OneUptimeDate from "../../../Types/Date";
5
6
 
6
7
  export default interface AggregateBy<TBaseModel extends AnalyticsBaseModel>
7
8
  extends CommonAggregateBy<TBaseModel> {
@@ -13,6 +14,9 @@ export class AggregateUtil {
13
14
  startDate: Date;
14
15
  endDate: Date;
15
16
  }): AggregationInterval {
17
+ data.startDate = OneUptimeDate.fromString(data.startDate);
18
+ data.endDate = OneUptimeDate.fromString(data.endDate);
19
+
16
20
  const diff: number = data.endDate.getTime() - data.startDate.getTime();
17
21
 
18
22
  if (diff <= 1000 * 60 * 60 * 3) {
@@ -70,7 +70,10 @@ export default class APIRequestCriteria {
70
70
  }
71
71
 
72
72
  //check response code
73
- if (input.criteriaFilter.checkOn === CheckOn.ResponseStatusCode) {
73
+ if (
74
+ input.criteriaFilter.checkOn === CheckOn.ResponseStatusCode &&
75
+ (input.dataToProcess as ProbeMonitorResponse).responseCode
76
+ ) {
74
77
  threshold = CompareCriteria.convertToNumber(threshold);
75
78
 
76
79
  const value: Array<number> | number =
@@ -313,7 +313,8 @@ export default class CompareCriteria {
313
313
  CompareCriteria.isTrue({
314
314
  value: data.value,
315
315
  evaluationType:
316
- data.criteriaFilter.evaluateOverTimeOptions?.evaluateOverTimeType,
316
+ data.criteriaFilter.evaluateOverTimeOptions?.evaluateOverTimeType ||
317
+ data.criteriaFilter.metricMonitorOptions?.metricAggregationType,
317
318
  })
318
319
  ) {
319
320
  return CompareCriteria.getCompareMessage({
@@ -331,7 +332,8 @@ export default class CompareCriteria {
331
332
  CompareCriteria.isFalse({
332
333
  value: data.value,
333
334
  evaluationType:
334
- data.criteriaFilter.evaluateOverTimeOptions?.evaluateOverTimeType,
335
+ data.criteriaFilter.evaluateOverTimeOptions?.evaluateOverTimeType ||
336
+ data.criteriaFilter.metricMonitorOptions?.metricAggregationType,
335
337
  })
336
338
  ) {
337
339
  return CompareCriteria.getCompareMessage({
@@ -366,7 +368,8 @@ export default class CompareCriteria {
366
368
  threshold: data.threshold as number,
367
369
  value: data.value,
368
370
  evaluationType:
369
- data.criteriaFilter.evaluateOverTimeOptions?.evaluateOverTimeType,
371
+ data.criteriaFilter.evaluateOverTimeOptions?.evaluateOverTimeType ||
372
+ data.criteriaFilter.metricMonitorOptions?.metricAggregationType,
370
373
  })
371
374
  ) {
372
375
  return CompareCriteria.getCompareMessage({
@@ -385,7 +388,8 @@ export default class CompareCriteria {
385
388
  threshold: data.threshold as number,
386
389
  value: data.value,
387
390
  evaluationType:
388
- data.criteriaFilter.evaluateOverTimeOptions?.evaluateOverTimeType,
391
+ data.criteriaFilter.evaluateOverTimeOptions?.evaluateOverTimeType ||
392
+ data.criteriaFilter.metricMonitorOptions?.metricAggregationType,
389
393
  })
390
394
  ) {
391
395
  return CompareCriteria.getCompareMessage({
@@ -404,7 +408,8 @@ export default class CompareCriteria {
404
408
  threshold: data.threshold as number,
405
409
  value: data.value,
406
410
  evaluationType:
407
- data.criteriaFilter.evaluateOverTimeOptions?.evaluateOverTimeType,
411
+ data.criteriaFilter.evaluateOverTimeOptions?.evaluateOverTimeType ||
412
+ data.criteriaFilter.metricMonitorOptions?.metricAggregationType,
408
413
  })
409
414
  ) {
410
415
  return CompareCriteria.getCompareMessage({
@@ -423,7 +428,8 @@ export default class CompareCriteria {
423
428
  threshold: data.threshold as number,
424
429
  value: data.value,
425
430
  evaluationType:
426
- data.criteriaFilter.evaluateOverTimeOptions?.evaluateOverTimeType,
431
+ data.criteriaFilter.evaluateOverTimeOptions?.evaluateOverTimeType ||
432
+ data.criteriaFilter.metricMonitorOptions?.metricAggregationType,
427
433
  })
428
434
  ) {
429
435
  return CompareCriteria.getCompareMessage({
@@ -442,7 +448,8 @@ export default class CompareCriteria {
442
448
  threshold: data.threshold as number,
443
449
  value: data.value,
444
450
  evaluationType:
445
- data.criteriaFilter.evaluateOverTimeOptions?.evaluateOverTimeType,
451
+ data.criteriaFilter.evaluateOverTimeOptions?.evaluateOverTimeType ||
452
+ data.criteriaFilter.metricMonitorOptions?.metricAggregationType,
446
453
  })
447
454
  ) {
448
455
  return CompareCriteria.getCompareMessage({
@@ -461,7 +468,8 @@ export default class CompareCriteria {
461
468
  threshold: data.threshold as number,
462
469
  value: data.value,
463
470
  evaluationType:
464
- data.criteriaFilter.evaluateOverTimeOptions?.evaluateOverTimeType,
471
+ data.criteriaFilter.evaluateOverTimeOptions?.evaluateOverTimeType ||
472
+ data.criteriaFilter.metricMonitorOptions?.metricAggregationType,
465
473
  })
466
474
  ) {
467
475
  return CompareCriteria.getCompareMessage({
@@ -485,17 +493,19 @@ export default class CompareCriteria {
485
493
  // CPU Percent over the last 5 minutes is 10 which is less than the threshold of 20
486
494
  let message: string = "";
487
495
 
488
- if (
489
- data.criteriaFilter.evaluateOverTimeOptions?.evaluateOverTimeType ===
490
- EvaluateOverTimeType.AnyValue
491
- ) {
496
+ let evaluationType: EvaluateOverTimeType | undefined =
497
+ data.criteriaFilter.evaluateOverTimeOptions?.evaluateOverTimeType;
498
+
499
+ if (data.criteriaFilter.metricMonitorOptions?.metricAggregationType) {
500
+ evaluationType =
501
+ data.criteriaFilter.metricMonitorOptions.metricAggregationType;
502
+ }
503
+
504
+ if (evaluationType === EvaluateOverTimeType.AnyValue) {
492
505
  message += "Any value of";
493
506
  }
494
507
 
495
- if (
496
- data.criteriaFilter.evaluateOverTimeOptions?.evaluateOverTimeType ===
497
- EvaluateOverTimeType.AllValues
498
- ) {
508
+ if (evaluationType === EvaluateOverTimeType.AllValues) {
499
509
  message += "All values of";
500
510
  }
501
511
 
@@ -0,0 +1,127 @@
1
+ import AggregateModel from "../../../../Types/BaseDatabase/AggregatedModel";
2
+ import AggregatedResult from "../../../../Types/BaseDatabase/AggregatedResult";
3
+ import MetricFormulaConfigData from "../../../../Types/Metrics/MetricFormulaConfigData";
4
+ import MetricQueryConfigData from "../../../../Types/Metrics/MetricQueryConfigData";
5
+ import MetricMonitorResponse from "../../../../Types/Monitor/MetricMonitor/MetricMonitorResponse";
6
+ import MonitorStep from "../../../../Types/Monitor/MonitorStep";
7
+ import DataToProcess from "../DataToProcess";
8
+ import CompareCriteria from "./CompareCriteria";
9
+ import {
10
+ CheckOn,
11
+ CriteriaFilter,
12
+ EvaluateOverTimeType,
13
+ } from "Common/Types/Monitor/CriteriaFilter";
14
+
15
+ export default class MetricMonitorCriteria {
16
+ public static async isMonitorInstanceCriteriaFilterMet(input: {
17
+ dataToProcess: DataToProcess;
18
+ criteriaFilter: CriteriaFilter;
19
+ monitorStep: MonitorStep;
20
+ }): Promise<string | null> {
21
+ // Metric Monitoring Check
22
+
23
+ if (
24
+ input.criteriaFilter.metricMonitorOptions &&
25
+ !input.criteriaFilter.metricMonitorOptions.metricAggregationType
26
+ ) {
27
+ input.criteriaFilter.metricMonitorOptions.metricAggregationType =
28
+ EvaluateOverTimeType.AnyValue;
29
+ }
30
+
31
+ let threshold: number | string | undefined | null =
32
+ input.criteriaFilter.value;
33
+
34
+ if (input.criteriaFilter.checkOn === CheckOn.MetricValue) {
35
+ threshold = CompareCriteria.convertToNumber(threshold);
36
+
37
+ const metricAggregaredResult: Array<AggregatedResult> =
38
+ (input.dataToProcess as MetricMonitorResponse).metricResult || [];
39
+
40
+ const metricAlias: string =
41
+ input.criteriaFilter.metricMonitorOptions?.metricAlias || "";
42
+
43
+ // Pick based on the alias, or if there's no alias, pick the first one
44
+
45
+ let aliasIndex: number =
46
+ input.monitorStep.data?.metricMonitor?.metricViewConfig?.queryConfigs.findIndex(
47
+ (queryConfig: MetricQueryConfigData) => {
48
+ return queryConfig.metricAliasData?.metricVariable === metricAlias;
49
+ },
50
+ ) || -1;
51
+
52
+ if (aliasIndex < 0) {
53
+ // then try to find in formula
54
+ let formulaIndex: number =
55
+ input.monitorStep.data?.metricMonitor?.metricViewConfig?.formulaConfigs.findIndex(
56
+ (formulaConfig: MetricFormulaConfigData) => {
57
+ return (
58
+ formulaConfig.metricAliasData?.metricVariable === metricAlias
59
+ );
60
+ },
61
+ ) || -1;
62
+
63
+ if (formulaIndex >= 0) {
64
+ // add number of queries to the index
65
+ formulaIndex =
66
+ formulaIndex +
67
+ (input.monitorStep.data?.metricMonitor?.metricViewConfig
68
+ ?.queryConfigs.length || 0);
69
+ aliasIndex = formulaIndex;
70
+ }
71
+ }
72
+ const aggregatedResult: AggregatedResult | undefined =
73
+ metricAggregaredResult &&
74
+ metricAggregaredResult.length >= aliasIndex - 1 &&
75
+ aliasIndex >= 0
76
+ ? metricAggregaredResult[aliasIndex]
77
+ : metricAggregaredResult[0] || undefined;
78
+
79
+ if (metricAlias) {
80
+ // find the index of the alias in the dataToProcess.
81
+ const indexOfAlias: number = (
82
+ input.dataToProcess as MetricMonitorResponse
83
+ ).metricViewConfig.queryConfigs.findIndex(
84
+ (queryConfig: MetricQueryConfigData) => {
85
+ return queryConfig.metricAliasData?.metricVariable === metricAlias;
86
+ },
87
+ );
88
+
89
+ // now get the aggregated result for that alias
90
+ if (indexOfAlias !== -1) {
91
+ const aggregatedResultForAlias: AggregatedResult | undefined =
92
+ metricAggregaredResult[indexOfAlias];
93
+ if (aggregatedResultForAlias) {
94
+ const numbers: Array<number> = aggregatedResultForAlias.data.map(
95
+ (data: AggregateModel) => {
96
+ return data.value;
97
+ },
98
+ );
99
+
100
+ return CompareCriteria.compareCriteriaNumbers({
101
+ value: numbers && numbers.length > 0 ? numbers : 0,
102
+ threshold: threshold as number,
103
+ criteriaFilter: input.criteriaFilter,
104
+ });
105
+ }
106
+ }
107
+ }
108
+
109
+ // if there's no alias then this is the default case
110
+ if (aggregatedResult) {
111
+ const numbers: Array<number> = aggregatedResult.data.map(
112
+ (data: AggregateModel) => {
113
+ return data.value;
114
+ },
115
+ );
116
+
117
+ return CompareCriteria.compareCriteriaNumbers({
118
+ value: numbers && numbers.length > 0 ? numbers : 0,
119
+ threshold: threshold as number,
120
+ criteriaFilter: input.criteriaFilter,
121
+ });
122
+ }
123
+ }
124
+
125
+ return null;
126
+ }
127
+ }
@@ -3,12 +3,14 @@ import ServerMonitorResponse from "Common/Types/Monitor/ServerMonitor/ServerMoni
3
3
  import ProbeMonitorResponse from "Common/Types/Probe/ProbeMonitorResponse";
4
4
  import LogMonitorResponse from "Common/Types/Monitor/LogMonitor/LogMonitorResponse";
5
5
  import TraceMonitorResponse from "Common/Types/Monitor/TraceMonitor/TraceMonitorResponse";
6
+ import MetricMonitorResponse from "../../../Types/Monitor/MetricMonitor/MetricMonitorResponse";
6
7
 
7
8
  type DataToProcess =
8
9
  | ProbeMonitorResponse
9
10
  | IncomingMonitorRequest
10
11
  | ServerMonitorResponse
11
12
  | LogMonitorResponse
12
- | TraceMonitorResponse;
13
+ | TraceMonitorResponse
14
+ | MetricMonitorResponse;
13
15
 
14
16
  export default DataToProcess;
@@ -12,6 +12,7 @@ import MonitorCriteriaInstance from "../../../Types/Monitor/MonitorCriteriaInsta
12
12
  import ObjectID from "../../../Types/ObjectID";
13
13
  import ProbeMonitorResponse from "../../../Types/Probe/ProbeMonitorResponse";
14
14
  import { TelemetryQuery } from "../../../Types/Telemetry/TelemetryQuery";
15
+ import { DisableAutomaticAlertCreation } from "../../EnvironmentConfig";
15
16
  import AlertService from "../../Services/AlertService";
16
17
  import AlertSeverityService from "../../Services/AlertSeverityService";
17
18
  import AlertStateTimelineService from "../../Services/AlertStateTimelineService";
@@ -193,6 +194,10 @@ export default class MonitorAlert {
193
194
  alert.remediationNotes = criteriaAlert.remediationNotes;
194
195
  }
195
196
 
197
+ if (DisableAutomaticAlertCreation) {
198
+ return;
199
+ }
200
+
196
201
  await AlertService.create({
197
202
  data: alert,
198
203
  props: {
@@ -12,6 +12,7 @@ import MonitorCriteriaInstance from "../../../Types/Monitor/MonitorCriteriaInsta
12
12
  import ObjectID from "../../../Types/ObjectID";
13
13
  import ProbeMonitorResponse from "../../../Types/Probe/ProbeMonitorResponse";
14
14
  import { TelemetryQuery } from "../../../Types/Telemetry/TelemetryQuery";
15
+ import { DisableAutomaticIncidentCreation } from "../../EnvironmentConfig";
15
16
  import IncidentService from "../../Services/IncidentService";
16
17
  import IncidentSeverityService from "../../Services/IncidentSeverityService";
17
18
  import IncidentStateTimelineService from "../../Services/IncidentStateTimelineService";
@@ -203,6 +204,10 @@ export default class MonitorIncident {
203
204
  incident.remediationNotes = criteriaIncident.remediationNotes;
204
205
  }
205
206
 
207
+ if (DisableAutomaticIncidentCreation) {
208
+ return;
209
+ }
210
+
206
211
  await IncidentService.create({
207
212
  data: incident,
208
213
  props: {
@@ -55,6 +55,8 @@ import Metric, {
55
55
  import MetricService from "../../Services/MetricService";
56
56
  import MonitorMetricType from "../../../Types/Monitor/MonitorMetricType";
57
57
  import TelemetryUtil from "../Telemetry/Telemetry";
58
+ import MetricMonitorCriteria from "./Criteria/MetricMonitorCriteria";
59
+ import MetricMonitorResponse from "../../../Types/Monitor/MetricMonitor/MetricMonitorResponse";
58
60
 
59
61
  export default class MonitorResourceUtil {
60
62
  public static async monitorResource(
@@ -441,6 +443,7 @@ export default class MonitorResourceUtil {
441
443
  telemetryQuery = {
442
444
  telemetryQuery: (dataToProcess as LogMonitorResponse).logQuery,
443
445
  telemetryType: TelemetryType.Log,
446
+ metricViewData: null,
444
447
  };
445
448
  logger.debug(
446
449
  `${dataToProcess.monitorId.toString()} - Log query found.`,
@@ -451,6 +454,29 @@ export default class MonitorResourceUtil {
451
454
  telemetryQuery = {
452
455
  telemetryQuery: (dataToProcess as TraceMonitorResponse).spanQuery,
453
456
  telemetryType: TelemetryType.Trace,
457
+ metricViewData: null,
458
+ };
459
+ logger.debug(
460
+ `${dataToProcess.monitorId.toString()} - Span query found.`,
461
+ );
462
+ }
463
+
464
+ if (
465
+ dataToProcess &&
466
+ (dataToProcess as MetricMonitorResponse).metricViewConfig &&
467
+ (dataToProcess as MetricMonitorResponse).startAndEndDate
468
+ ) {
469
+ telemetryQuery = {
470
+ telemetryQuery: null,
471
+ telemetryType: TelemetryType.Metric,
472
+ metricViewData: {
473
+ startAndEndDate:
474
+ (dataToProcess as MetricMonitorResponse).startAndEndDate || null,
475
+ queryConfigs: (dataToProcess as MetricMonitorResponse)
476
+ .metricViewConfig.queryConfigs,
477
+ formulaConfigs: (dataToProcess as MetricMonitorResponse)
478
+ .metricViewConfig.formulaConfigs,
479
+ },
454
480
  };
455
481
  logger.debug(
456
482
  `${dataToProcess.monitorId.toString()} - Span query found.`,
@@ -1273,6 +1299,20 @@ export default class MonitorResourceUtil {
1273
1299
  }
1274
1300
  }
1275
1301
 
1302
+ if (input.monitor.monitorType === MonitorType.Metrics) {
1303
+ // check server monitor
1304
+ const logMonitorResult: string | null =
1305
+ await MetricMonitorCriteria.isMonitorInstanceCriteriaFilterMet({
1306
+ dataToProcess: input.dataToProcess,
1307
+ criteriaFilter: input.criteriaFilter,
1308
+ monitorStep: input.monitorStep,
1309
+ });
1310
+
1311
+ if (logMonitorResult) {
1312
+ return logMonitorResult;
1313
+ }
1314
+ }
1315
+
1276
1316
  if (input.monitor.monitorType === MonitorType.Traces) {
1277
1317
  // check server monitor
1278
1318
  const traceMonitorResult: string | null =
@@ -11,6 +11,10 @@ export default class StreamUtil {
11
11
  const chunks: Array<any> = [];
12
12
 
13
13
  stream.on("data", (chunk: any) => {
14
+ if (Array.isArray(chunk) && chunk.length === 0) {
15
+ return;
16
+ }
17
+
14
18
  chunks.push(Buffer.from(chunk));
15
19
  });
16
20
  stream.on("end", () => {
package/Types/Date.ts CHANGED
@@ -9,6 +9,15 @@ import Timezone from "./Timezone";
9
9
  export const Moment: typeof moment = moment;
10
10
 
11
11
  export default class OneUptimeDate {
12
+ public static getInBetweenDatesAsFormattedString(
13
+ inBetween: InBetween<Date>,
14
+ ): string {
15
+ return (
16
+ this.getDateAsFormattedString(inBetween.startValue) +
17
+ " - " +
18
+ this.getDateAsFormattedString(inBetween.endValue)
19
+ );
20
+ }
12
21
  public static convertMinutesToMilliseconds(minutes: number): number {
13
22
  return minutes * 60 * 1000;
14
23
  }
@@ -0,0 +1,6 @@
1
+ import InBetween from "Common/Types/BaseDatabase/InBetween";
2
+ import MetricsViewConfig from "Common/Types/Metrics/MetricsViewConfig";
3
+
4
+ export default interface MetricViewData extends MetricsViewConfig {
5
+ startAndEndDate: InBetween<Date> | null;
6
+ }
@@ -38,6 +38,9 @@ export enum CheckOn {
38
38
 
39
39
  // Trace monitors.
40
40
  SpanCount = "Span Count",
41
+
42
+ // Metric Monitors.
43
+ MetricValue = "Metric Value",
41
44
  }
42
45
 
43
46
  export interface ServerMonitorOptions {
@@ -53,6 +56,11 @@ export enum EvaluateOverTimeType {
53
56
  AnyValue = "Any Value",
54
57
  }
55
58
 
59
+ export interface MetricMonitorOptions {
60
+ metricAlias?: string | undefined;
61
+ metricAggregationType?: EvaluateOverTimeType | undefined;
62
+ }
63
+
56
64
  export enum EvaluateOverTimeMinutes {
57
65
  TwoMinutes = "2",
58
66
  ThreeMinutes = "3",
@@ -73,6 +81,7 @@ export interface EvaluateOverTimeOptions {
73
81
  export interface CriteriaFilter {
74
82
  checkOn: CheckOn;
75
83
  serverMonitorOptions?: ServerMonitorOptions | undefined;
84
+ metricMonitorOptions?: MetricMonitorOptions | undefined;
76
85
  filterType: FilterType | undefined;
77
86
  value: string | number | undefined;
78
87
  eveluateOverTime?: boolean | undefined;
@@ -0,0 +1,11 @@
1
+ import AggregatedResult from "../../BaseDatabase/AggregatedResult";
2
+ import InBetween from "../../BaseDatabase/InBetween";
3
+ import MetricsViewConfig from "../../Metrics/MetricsViewConfig";
4
+ import ObjectID from "../../ObjectID";
5
+
6
+ export default interface MetricMonitorResponse {
7
+ startAndEndDate?: InBetween<Date>;
8
+ metricResult: Array<AggregatedResult>;
9
+ metricViewConfig: MetricsViewConfig;
10
+ monitorId: ObjectID;
11
+ }
@@ -10,6 +10,7 @@ import {
10
10
  CriteriaFilter,
11
11
  FilterCondition,
12
12
  FilterType,
13
+ EvaluateOverTimeType,
13
14
  } from "./CriteriaFilter";
14
15
  import { CriteriaIncident } from "./CriteriaIncident";
15
16
  import MonitorType from "./MonitorType";
@@ -59,6 +60,9 @@ export default class MonitorCriteriaInstance extends DatabaseProperty {
59
60
  monitorType: MonitorType;
60
61
  monitorStatusId: ObjectID;
61
62
  monitorName: string;
63
+ metricOptions?: {
64
+ metricAliases: Array<string>;
65
+ };
62
66
  }): MonitorCriteriaInstance | null {
63
67
  if (arg.monitorType === MonitorType.IncomingRequest) {
64
68
  const monitorCriteriaInstance: MonitorCriteriaInstance =
@@ -114,6 +118,43 @@ export default class MonitorCriteriaInstance extends DatabaseProperty {
114
118
  return monitorCriteriaInstance;
115
119
  }
116
120
 
121
+ if (arg.monitorType === MonitorType.Metrics) {
122
+ const monitorCriteriaInstance: MonitorCriteriaInstance =
123
+ new MonitorCriteriaInstance();
124
+
125
+ monitorCriteriaInstance.data = {
126
+ id: ObjectID.generate().toString(),
127
+ monitorStatusId: arg.monitorStatusId,
128
+ filterCondition: FilterCondition.Any,
129
+ filters: [
130
+ {
131
+ checkOn: CheckOn.MetricValue,
132
+ filterType: FilterType.GreaterThan,
133
+
134
+ metricMonitorOptions: {
135
+ metricAggregationType: EvaluateOverTimeType.AnyValue,
136
+ metricAlias:
137
+ arg.metricOptions &&
138
+ arg.metricOptions.metricAliases &&
139
+ arg.metricOptions.metricAliases.length > 0
140
+ ? arg.metricOptions.metricAliases[0]
141
+ : undefined,
142
+ },
143
+ value: 0, // if there are some logs then monitor is online.
144
+ },
145
+ ],
146
+ incidents: [],
147
+ alerts: [],
148
+ changeMonitorStatus: true,
149
+ createIncidents: false,
150
+ createAlerts: false,
151
+ name: `Check if ${arg.monitorName} is online`,
152
+ description: `This criteria checks if the ${arg.monitorName} is online`,
153
+ };
154
+
155
+ return monitorCriteriaInstance;
156
+ }
157
+
117
158
  if (arg.monitorType === MonitorType.Traces) {
118
159
  const monitorCriteriaInstance: MonitorCriteriaInstance =
119
160
  new MonitorCriteriaInstance();
@@ -278,6 +319,9 @@ export default class MonitorCriteriaInstance extends DatabaseProperty {
278
319
  incidentSeverityId: ObjectID;
279
320
  alertSeverityId: ObjectID;
280
321
  monitorName: string;
322
+ metricOptions?: {
323
+ metricAliases: Array<string>;
324
+ };
281
325
  }): MonitorCriteriaInstance {
282
326
  const monitorCriteriaInstance: MonitorCriteriaInstance =
283
327
  new MonitorCriteriaInstance();
@@ -415,6 +459,55 @@ export default class MonitorCriteriaInstance extends DatabaseProperty {
415
459
  };
416
460
  }
417
461
 
462
+ if (arg.monitorType === MonitorType.Metrics) {
463
+ monitorCriteriaInstance.data = {
464
+ id: ObjectID.generate().toString(),
465
+ monitorStatusId: arg.monitorStatusId,
466
+ filterCondition: FilterCondition.Any,
467
+ filters: [
468
+ {
469
+ checkOn: CheckOn.MetricValue,
470
+ filterType: FilterType.EqualTo,
471
+ metricMonitorOptions: {
472
+ metricAggregationType: EvaluateOverTimeType.AnyValue,
473
+ metricAlias:
474
+ arg.metricOptions &&
475
+ arg.metricOptions.metricAliases &&
476
+ arg.metricOptions.metricAliases.length > 0
477
+ ? arg.metricOptions.metricAliases[0]
478
+ : undefined,
479
+ },
480
+ value: 0, // if there are no logs then the monitor is offline
481
+ },
482
+ ],
483
+ incidents: [
484
+ {
485
+ title: `${arg.monitorName} is offline`,
486
+ description: `${arg.monitorName} is currently offline.`,
487
+ incidentSeverityId: arg.incidentSeverityId,
488
+ autoResolveIncident: true,
489
+ id: ObjectID.generate().toString(),
490
+ onCallPolicyIds: [],
491
+ },
492
+ ],
493
+ alerts: [
494
+ {
495
+ title: `${arg.monitorName} is offline`,
496
+ description: `${arg.monitorName} is currently offline.`,
497
+ alertSeverityId: arg.alertSeverityId,
498
+ autoResolveAlert: true,
499
+ id: ObjectID.generate().toString(),
500
+ onCallPolicyIds: [],
501
+ },
502
+ ],
503
+ createAlerts: false,
504
+ changeMonitorStatus: true,
505
+ createIncidents: true,
506
+ name: `Check if ${arg.monitorName} is offline`,
507
+ description: `This criteria checks if the ${arg.monitorName} is offline`,
508
+ };
509
+ }
510
+
418
511
  if (arg.monitorType === MonitorType.Traces) {
419
512
  monitorCriteriaInstance.data = {
420
513
  id: ObjectID.generate().toString(),