@oneuptime/common 8.0.5579 → 8.0.5580

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 (45) hide show
  1. package/Server/Utils/Monitor/Criteria/CompareCriteria.ts +9 -1
  2. package/Server/Utils/Monitor/Criteria/ExceptionMonitorCriteria.ts +34 -0
  3. package/Server/Utils/Monitor/DataToProcess.ts +3 -1
  4. package/Server/Utils/Monitor/MonitorCriteriaDataExtractor.ts +13 -0
  5. package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +13 -0
  6. package/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.ts +20 -0
  7. package/Server/Utils/Monitor/MonitorResource.ts +18 -0
  8. package/Server/Utils/Telemetry.ts +15 -0
  9. package/Types/Monitor/CriteriaFilter.ts +3 -0
  10. package/Types/Monitor/ExceptionMonitor/ExceptionMonitorResponse.ts +12 -0
  11. package/Types/Monitor/MonitorCriteriaInstance.ts +67 -0
  12. package/Types/Monitor/MonitorStep.ts +30 -0
  13. package/Types/Monitor/MonitorStepExceptionMonitor.ts +94 -0
  14. package/Types/Monitor/MonitorType.ts +10 -1
  15. package/Types/Telemetry/TelemetryQuery.ts +2 -1
  16. package/Types/Telemetry/TelemetryType.ts +1 -0
  17. package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js +6 -1
  18. package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js.map +1 -1
  19. package/build/dist/Server/Utils/Monitor/Criteria/ExceptionMonitorCriteria.js +34 -0
  20. package/build/dist/Server/Utils/Monitor/Criteria/ExceptionMonitorCriteria.js.map +1 -0
  21. package/build/dist/Server/Utils/Monitor/MonitorCriteriaDataExtractor.js +6 -0
  22. package/build/dist/Server/Utils/Monitor/MonitorCriteriaDataExtractor.js.map +1 -1
  23. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +10 -0
  24. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
  25. package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js +9 -0
  26. package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js.map +1 -1
  27. package/build/dist/Server/Utils/Monitor/MonitorResource.js +10 -0
  28. package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
  29. package/build/dist/Server/Utils/Telemetry.js +8 -1
  30. package/build/dist/Server/Utils/Telemetry.js.map +1 -1
  31. package/build/dist/Types/Monitor/CriteriaFilter.js +2 -0
  32. package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
  33. package/build/dist/Types/Monitor/ExceptionMonitor/ExceptionMonitorResponse.js +2 -0
  34. package/build/dist/Types/Monitor/ExceptionMonitor/ExceptionMonitorResponse.js.map +1 -0
  35. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +62 -0
  36. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
  37. package/build/dist/Types/Monitor/MonitorStep.js +20 -1
  38. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  39. package/build/dist/Types/Monitor/MonitorStepExceptionMonitor.js +58 -0
  40. package/build/dist/Types/Monitor/MonitorStepExceptionMonitor.js.map +1 -0
  41. package/build/dist/Types/Monitor/MonitorType.js +9 -1
  42. package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
  43. package/build/dist/Types/Telemetry/TelemetryType.js +1 -0
  44. package/build/dist/Types/Telemetry/TelemetryType.js.map +1 -1
  45. package/package.json +1 -1
@@ -636,7 +636,15 @@ export default class CompareCriteria {
636
636
  }
637
637
 
638
638
  if (typeof value === Typeof.Number) {
639
- return (value as number).toFixed(2);
639
+ const numericValue: number = value as number;
640
+
641
+ if (Number.isInteger(numericValue)) {
642
+ return numericValue.toString();
643
+ }
644
+
645
+ const roundedValue: number = Number(numericValue.toFixed(2));
646
+
647
+ return roundedValue.toString();
640
648
  }
641
649
 
642
650
  if (typeof value === Typeof.Boolean) {
@@ -0,0 +1,34 @@
1
+ import ExceptionMonitorResponse from "../../../../Types/Monitor/ExceptionMonitor/ExceptionMonitorResponse";
2
+ import CaptureSpan from "../../Telemetry/CaptureSpan";
3
+ import DataToProcess from "../DataToProcess";
4
+ import CompareCriteria from "./CompareCriteria";
5
+ import {
6
+ CheckOn,
7
+ CriteriaFilter,
8
+ } from "../../../../Types/Monitor/CriteriaFilter";
9
+
10
+ export default class ExceptionMonitorCriteria {
11
+ @CaptureSpan()
12
+ public static async isMonitorInstanceCriteriaFilterMet(input: {
13
+ dataToProcess: DataToProcess;
14
+ criteriaFilter: CriteriaFilter;
15
+ }): Promise<string | null> {
16
+ let threshold: number | string | undefined | null =
17
+ input.criteriaFilter.value;
18
+
19
+ if (input.criteriaFilter.checkOn === CheckOn.ExceptionCount) {
20
+ threshold = CompareCriteria.convertToNumber(threshold);
21
+
22
+ const currentExceptionCount: number =
23
+ (input.dataToProcess as ExceptionMonitorResponse).exceptionCount || 0;
24
+
25
+ return CompareCriteria.compareCriteriaNumbers({
26
+ value: currentExceptionCount,
27
+ threshold: threshold as number,
28
+ criteriaFilter: input.criteriaFilter,
29
+ });
30
+ }
31
+
32
+ return null;
33
+ }
34
+ }
@@ -4,6 +4,7 @@ import ProbeMonitorResponse from "../../../Types/Probe/ProbeMonitorResponse";
4
4
  import LogMonitorResponse from "../../../Types/Monitor/LogMonitor/LogMonitorResponse";
5
5
  import TraceMonitorResponse from "../../../Types/Monitor/TraceMonitor/TraceMonitorResponse";
6
6
  import MetricMonitorResponse from "../../../Types/Monitor/MetricMonitor/MetricMonitorResponse";
7
+ import ExceptionMonitorResponse from "../../../Types/Monitor/ExceptionMonitor/ExceptionMonitorResponse";
7
8
 
8
9
  type DataToProcess =
9
10
  | ProbeMonitorResponse
@@ -11,6 +12,7 @@ type DataToProcess =
11
12
  | ServerMonitorResponse
12
13
  | LogMonitorResponse
13
14
  | TraceMonitorResponse
14
- | MetricMonitorResponse;
15
+ | MetricMonitorResponse
16
+ | ExceptionMonitorResponse;
15
17
 
16
18
  export default DataToProcess;
@@ -14,6 +14,7 @@ import AggregatedResult from "../../../Types/BaseDatabase/AggregatedResult";
14
14
  import AggregateModel from "../../../Types/BaseDatabase/AggregatedModel";
15
15
  import MetricQueryConfigData from "../../../Types/Metrics/MetricQueryConfigData";
16
16
  import MetricFormulaConfigData from "../../../Types/Metrics/MetricFormulaConfigData";
17
+ import ExceptionMonitorResponse from "../../../Types/Monitor/ExceptionMonitor/ExceptionMonitorResponse";
17
18
 
18
19
  export default class MonitorCriteriaDataExtractor {
19
20
  public static getProbeMonitorResponse(
@@ -79,6 +80,18 @@ export default class MonitorCriteriaDataExtractor {
79
80
  return null;
80
81
  }
81
82
 
83
+ public static getExceptionMonitorResponse(
84
+ dataToProcess: DataToProcess,
85
+ ): ExceptionMonitorResponse | null {
86
+ if (
87
+ (dataToProcess as ExceptionMonitorResponse).exceptionCount !== undefined
88
+ ) {
89
+ return dataToProcess as ExceptionMonitorResponse;
90
+ }
91
+
92
+ return null;
93
+ }
94
+
82
95
  public static getCustomCodeMonitorResponse(
83
96
  dataToProcess: DataToProcess,
84
97
  ): CustomCodeMonitorResponse | null {
@@ -9,6 +9,7 @@ import SyntheticMonitoringCriteria from "./Criteria/SyntheticMonitor";
9
9
  import LogMonitorCriteria from "./Criteria/LogMonitorCriteria";
10
10
  import MetricMonitorCriteria from "./Criteria/MetricMonitorCriteria";
11
11
  import TraceMonitorCriteria from "./Criteria/TraceMonitorCriteria";
12
+ import ExceptionMonitorCriteria from "./Criteria/ExceptionMonitorCriteria";
12
13
  import MonitorCriteriaMessageBuilder from "./MonitorCriteriaMessageBuilder";
13
14
  import DataToProcess from "./DataToProcess";
14
15
  import Monitor from "../../../Models/DatabaseModels/Monitor";
@@ -434,6 +435,18 @@ export default class MonitorCriteriaEvaluator {
434
435
  }
435
436
  }
436
437
 
438
+ if (input.monitor.monitorType === MonitorType.Exceptions) {
439
+ const exceptionMonitorResult: string | null =
440
+ await ExceptionMonitorCriteria.isMonitorInstanceCriteriaFilterMet({
441
+ dataToProcess: input.dataToProcess,
442
+ criteriaFilter: input.criteriaFilter,
443
+ });
444
+
445
+ if (exceptionMonitorResult) {
446
+ return exceptionMonitorResult;
447
+ }
448
+ }
449
+
437
450
  return null;
438
451
  }
439
452
  }
@@ -19,6 +19,7 @@ import SyntheticMonitorResponse from "../../../Types/Monitor/SyntheticMonitors/S
19
19
  import CustomCodeMonitorResponse from "../../../Types/Monitor/CustomCodeMonitor/CustomCodeMonitorResponse";
20
20
  import LogMonitorResponse from "../../../Types/Monitor/LogMonitor/LogMonitorResponse";
21
21
  import TraceMonitorResponse from "../../../Types/Monitor/TraceMonitor/TraceMonitorResponse";
22
+ import ExceptionMonitorResponse from "../../../Types/Monitor/ExceptionMonitor/ExceptionMonitorResponse";
22
23
  import MonitorCriteriaMessageFormatter from "./MonitorCriteriaMessageFormatter";
23
24
  import MonitorCriteriaDataExtractor from "./MonitorCriteriaDataExtractor";
24
25
  import MonitorCriteriaExpectationBuilder from "./MonitorCriteriaExpectationBuilder";
@@ -161,6 +162,10 @@ export default class MonitorCriteriaObservationBuilder {
161
162
  return MonitorCriteriaObservationBuilder.describeMetricValueObservation(
162
163
  input,
163
164
  );
165
+ case CheckOn.ExceptionCount:
166
+ return MonitorCriteriaObservationBuilder.describeExceptionCountObservation(
167
+ input,
168
+ );
164
169
  default:
165
170
  return null;
166
171
  }
@@ -1083,6 +1088,21 @@ export default class MonitorCriteriaObservationBuilder {
1083
1088
  return `Span count was ${traceResponse.spanCount}.`;
1084
1089
  }
1085
1090
 
1091
+ private static describeExceptionCountObservation(input: {
1092
+ dataToProcess: DataToProcess;
1093
+ }): string | null {
1094
+ const exceptionResponse: ExceptionMonitorResponse | null =
1095
+ MonitorCriteriaDataExtractor.getExceptionMonitorResponse(
1096
+ input.dataToProcess,
1097
+ );
1098
+
1099
+ if (!exceptionResponse) {
1100
+ return null;
1101
+ }
1102
+
1103
+ return `Exception count was ${exceptionResponse.exceptionCount}.`;
1104
+ }
1105
+
1086
1106
  private static describeMetricValueObservation(input: {
1087
1107
  criteriaFilter: CriteriaFilter;
1088
1108
  dataToProcess: DataToProcess;
@@ -31,6 +31,7 @@ import LogMonitorResponse from "../../../Types/Monitor/LogMonitor/LogMonitorResp
31
31
  import MetricMonitorResponse from "../../../Types/Monitor/MetricMonitor/MetricMonitorResponse";
32
32
  import TelemetryType from "../../../Types/Telemetry/TelemetryType";
33
33
  import TraceMonitorResponse from "../../../Types/Monitor/TraceMonitor/TraceMonitorResponse";
34
+ import ExceptionMonitorResponse from "../../../Types/Monitor/ExceptionMonitor/ExceptionMonitorResponse";
34
35
  import { TelemetryQuery } from "../../../Types/Telemetry/TelemetryQuery";
35
36
  import MonitorIncident from "./MonitorIncident";
36
37
  import MonitorAlert from "./MonitorAlert";
@@ -557,6 +558,23 @@ export default class MonitorResourceUtil {
557
558
  );
558
559
  }
559
560
 
561
+ if (
562
+ dataToProcess &&
563
+ (dataToProcess as ExceptionMonitorResponse).exceptionQuery
564
+ ) {
565
+ const exceptionResponse: ExceptionMonitorResponse =
566
+ dataToProcess as ExceptionMonitorResponse;
567
+ telemetryQuery = {
568
+ telemetryQuery: exceptionResponse.exceptionQuery,
569
+ telemetryType: TelemetryType.Exception,
570
+ metricViewData: null,
571
+ };
572
+
573
+ logger.debug(
574
+ `${dataToProcess.monitorId.toString()} - Exception query found.`,
575
+ );
576
+ }
577
+
560
578
  const matchedCriteriaInstance: MonitorCriteriaInstance =
561
579
  criteriaInstanceMap[response.criteriaMetId!]!;
562
580
 
@@ -27,6 +27,7 @@ import {
27
27
  } from "@opentelemetry/sdk-logs";
28
28
  import type { Resource as LogsResource } from "@opentelemetry/sdk-logs/node_modules/@opentelemetry/resources/build/src/Resource";
29
29
  import {
30
+ Aggregation,
30
31
  MeterProvider,
31
32
  PeriodicExportingMetricReader,
32
33
  } from "@opentelemetry/sdk-metrics";
@@ -174,6 +175,20 @@ export default class Telemetry {
174
175
  compression: CompressionAlgorithm.GZIP,
175
176
  }) as unknown as PushMetricExporter;
176
177
 
178
+ // Force an SDK-side aggregation selector that matches the modern metrics API.
179
+ if (
180
+ typeof (metricExporter as { selectAggregation?: unknown })
181
+ .selectAggregation === "function"
182
+ ) {
183
+ (
184
+ metricExporter as unknown as {
185
+ selectAggregation: (..._args: Array<unknown>) => Aggregation;
186
+ }
187
+ ).selectAggregation = () => {
188
+ return Aggregation.Default();
189
+ };
190
+ }
191
+
177
192
  this.metricReader = new PeriodicExportingMetricReader({
178
193
  exporter: metricExporter,
179
194
  });
@@ -42,6 +42,9 @@ export enum CheckOn {
42
42
  // Trace monitors.
43
43
  SpanCount = "Span Count",
44
44
 
45
+ // Exception monitors.
46
+ ExceptionCount = "Exception Count",
47
+
45
48
  // Metric Monitors.
46
49
  MetricValue = "Metric Value",
47
50
  }
@@ -0,0 +1,12 @@
1
+ import Query from "../../BaseDatabase/Query";
2
+ import ObjectID from "../../ObjectID";
3
+ import ExceptionInstance from "../../../Models/AnalyticsModels/ExceptionInstance";
4
+ import MonitorEvaluationSummary from "../MonitorEvaluationSummary";
5
+
6
+ export default interface ExceptionMonitorResponse {
7
+ projectId: ObjectID;
8
+ exceptionCount: number;
9
+ exceptionQuery: Query<ExceptionInstance>;
10
+ monitorId: ObjectID;
11
+ evaluationSummary?: MonitorEvaluationSummary | undefined;
12
+ }
@@ -121,6 +121,33 @@ export default class MonitorCriteriaInstance extends DatabaseProperty {
121
121
  return monitorCriteriaInstance;
122
122
  }
123
123
 
124
+ if (arg.monitorType === MonitorType.Exceptions) {
125
+ const monitorCriteriaInstance: MonitorCriteriaInstance =
126
+ new MonitorCriteriaInstance();
127
+
128
+ monitorCriteriaInstance.data = {
129
+ id: ObjectID.generate().toString(),
130
+ monitorStatusId: arg.monitorStatusId,
131
+ filterCondition: FilterCondition.Any,
132
+ filters: [
133
+ {
134
+ checkOn: CheckOn.ExceptionCount,
135
+ filterType: FilterType.EqualTo,
136
+ value: 0,
137
+ },
138
+ ],
139
+ incidents: [],
140
+ alerts: [],
141
+ changeMonitorStatus: true,
142
+ createIncidents: false,
143
+ createAlerts: false,
144
+ name: `Check if ${arg.monitorName} has no exceptions`,
145
+ description: `This criteria checks if the ${arg.monitorName} has no exceptions.`,
146
+ };
147
+
148
+ return monitorCriteriaInstance;
149
+ }
150
+
124
151
  if (arg.monitorType === MonitorType.Metrics) {
125
152
  const monitorCriteriaInstance: MonitorCriteriaInstance =
126
153
  new MonitorCriteriaInstance();
@@ -462,6 +489,46 @@ export default class MonitorCriteriaInstance extends DatabaseProperty {
462
489
  };
463
490
  }
464
491
 
492
+ if (arg.monitorType === MonitorType.Exceptions) {
493
+ monitorCriteriaInstance.data = {
494
+ id: ObjectID.generate().toString(),
495
+ monitorStatusId: arg.monitorStatusId,
496
+ filterCondition: FilterCondition.Any,
497
+ filters: [
498
+ {
499
+ checkOn: CheckOn.ExceptionCount,
500
+ filterType: FilterType.GreaterThan,
501
+ value: 0,
502
+ },
503
+ ],
504
+ incidents: [
505
+ {
506
+ title: `${arg.monitorName} has exceptions`,
507
+ description: `${arg.monitorName} has active exceptions.`,
508
+ incidentSeverityId: arg.incidentSeverityId,
509
+ autoResolveIncident: true,
510
+ id: ObjectID.generate().toString(),
511
+ onCallPolicyIds: [],
512
+ },
513
+ ],
514
+ alerts: [
515
+ {
516
+ title: `${arg.monitorName} has exceptions`,
517
+ description: `${arg.monitorName} has active exceptions.`,
518
+ alertSeverityId: arg.alertSeverityId,
519
+ autoResolveAlert: true,
520
+ id: ObjectID.generate().toString(),
521
+ onCallPolicyIds: [],
522
+ },
523
+ ],
524
+ createAlerts: false,
525
+ changeMonitorStatus: true,
526
+ createIncidents: true,
527
+ name: `Check if ${arg.monitorName} has exceptions`,
528
+ description: `This criteria checks if the ${arg.monitorName} has exceptions.`,
529
+ };
530
+ }
531
+
465
532
  if (arg.monitorType === MonitorType.Metrics) {
466
533
  monitorCriteriaInstance.data = {
467
534
  id: ObjectID.generate().toString(),
@@ -23,6 +23,9 @@ import MonitorStepTraceMonitor, {
23
23
  import MonitorStepMetricMonitor, {
24
24
  MonitorStepMetricMonitorUtil,
25
25
  } from "./MonitorStepMetricMonitor";
26
+ import MonitorStepExceptionMonitor, {
27
+ MonitorStepExceptionMonitorUtil,
28
+ } from "./MonitorStepExceptionMonitor";
26
29
  import Zod, { ZodSchema } from "../../Utils/Schema/Zod";
27
30
 
28
31
  export interface MonitorStepType {
@@ -57,6 +60,9 @@ export interface MonitorStepType {
57
60
 
58
61
  // Metric Monitor
59
62
  metricMonitor: MonitorStepMetricMonitor | undefined;
63
+
64
+ // Exception monitor
65
+ exceptionMonitor?: MonitorStepExceptionMonitor | undefined;
60
66
  }
61
67
 
62
68
  export default class MonitorStep extends DatabaseProperty {
@@ -80,6 +86,7 @@ export default class MonitorStep extends DatabaseProperty {
80
86
  logMonitor: undefined,
81
87
  traceMonitor: undefined,
82
88
  metricMonitor: undefined,
89
+ exceptionMonitor: undefined,
83
90
  };
84
91
  }
85
92
 
@@ -108,6 +115,7 @@ export default class MonitorStep extends DatabaseProperty {
108
115
  logMonitor: undefined,
109
116
  traceMonitor: undefined,
110
117
  metricMonitor: undefined,
118
+ exceptionMonitor: undefined,
111
119
  };
112
120
 
113
121
  return monitorStep;
@@ -186,6 +194,13 @@ export default class MonitorStep extends DatabaseProperty {
186
194
  return this;
187
195
  }
188
196
 
197
+ public setExceptionMonitor(
198
+ exceptionMonitor: MonitorStepExceptionMonitor,
199
+ ): MonitorStep {
200
+ this.data!.exceptionMonitor = exceptionMonitor;
201
+ return this;
202
+ }
203
+
189
204
  public setCustomCode(customCode: string): MonitorStep {
190
205
  this.data!.customCode = customCode;
191
206
  return this;
@@ -212,6 +227,7 @@ export default class MonitorStep extends DatabaseProperty {
212
227
  screenSizeTypes: undefined,
213
228
  browserTypes: undefined,
214
229
  lgoMonitor: undefined,
230
+ exceptionMonitor: undefined,
215
231
  },
216
232
  };
217
233
  }
@@ -310,6 +326,12 @@ export default class MonitorStep extends DatabaseProperty {
310
326
  MonitorStepTraceMonitorUtil.getDefault(),
311
327
  )
312
328
  : undefined,
329
+ exceptionMonitor: this.data.exceptionMonitor
330
+ ? MonitorStepExceptionMonitorUtil.toJSON(
331
+ this.data.exceptionMonitor ||
332
+ MonitorStepExceptionMonitorUtil.getDefault(),
333
+ )
334
+ : undefined,
313
335
  },
314
336
  });
315
337
  }
@@ -408,6 +430,9 @@ export default class MonitorStep extends DatabaseProperty {
408
430
  traceMonitor: json["traceMonitor"]
409
431
  ? (json["traceMonitor"] as JSONObject)
410
432
  : undefined,
433
+ exceptionMonitor: json["exceptionMonitor"]
434
+ ? (json["exceptionMonitor"] as JSONObject)
435
+ : undefined,
411
436
  }) as any;
412
437
 
413
438
  if (monitorStep.data && !monitorStep.data?.logMonitor) {
@@ -423,6 +448,11 @@ export default class MonitorStep extends DatabaseProperty {
423
448
  MonitorStepMetricMonitorUtil.getDefault();
424
449
  }
425
450
 
451
+ if (monitorStep.data && !monitorStep.data?.exceptionMonitor) {
452
+ monitorStep.data.exceptionMonitor =
453
+ MonitorStepExceptionMonitorUtil.getDefault();
454
+ }
455
+
426
456
  return monitorStep;
427
457
  }
428
458
 
@@ -0,0 +1,94 @@
1
+ import ExceptionInstance from "../../Models/AnalyticsModels/ExceptionInstance";
2
+ import InBetween from "../BaseDatabase/InBetween";
3
+ import Includes from "../BaseDatabase/Includes";
4
+ import Query from "../BaseDatabase/Query";
5
+ import Search from "../BaseDatabase/Search";
6
+ import OneUptimeDate from "../Date";
7
+ import { JSONObject } from "../JSON";
8
+ import ObjectID from "../ObjectID";
9
+
10
+ export default interface MonitorStepExceptionMonitor {
11
+ telemetryServiceIds: Array<ObjectID>;
12
+ exceptionTypes: Array<string>;
13
+ message: string;
14
+ includeResolved: boolean;
15
+ includeArchived: boolean;
16
+ lastXSecondsOfExceptions: number;
17
+ }
18
+
19
+ export class MonitorStepExceptionMonitorUtil {
20
+ public static toAnalyticsQuery(
21
+ monitorStepExceptionMonitor: MonitorStepExceptionMonitor,
22
+ ): Query<ExceptionInstance> {
23
+ const query: Query<ExceptionInstance> = {};
24
+
25
+ if (
26
+ monitorStepExceptionMonitor.telemetryServiceIds &&
27
+ monitorStepExceptionMonitor.telemetryServiceIds.length > 0
28
+ ) {
29
+ query.serviceId = new Includes(
30
+ monitorStepExceptionMonitor.telemetryServiceIds,
31
+ );
32
+ }
33
+
34
+ if (
35
+ monitorStepExceptionMonitor.exceptionTypes &&
36
+ monitorStepExceptionMonitor.exceptionTypes.length > 0
37
+ ) {
38
+ query.exceptionType = new Includes(
39
+ monitorStepExceptionMonitor.exceptionTypes,
40
+ );
41
+ }
42
+
43
+ if (monitorStepExceptionMonitor.message) {
44
+ query.message = new Search(monitorStepExceptionMonitor.message);
45
+ }
46
+
47
+ if (monitorStepExceptionMonitor.lastXSecondsOfExceptions) {
48
+ const endDate: Date = OneUptimeDate.getCurrentDate();
49
+ const startDate: Date = OneUptimeDate.addRemoveSeconds(
50
+ endDate,
51
+ monitorStepExceptionMonitor.lastXSecondsOfExceptions * -1,
52
+ );
53
+ query.time = new InBetween(startDate, endDate);
54
+ }
55
+
56
+ return query;
57
+ }
58
+
59
+ public static getDefault(): MonitorStepExceptionMonitor {
60
+ return {
61
+ telemetryServiceIds: [],
62
+ exceptionTypes: [],
63
+ message: "",
64
+ includeResolved: false,
65
+ includeArchived: false,
66
+ lastXSecondsOfExceptions: 60,
67
+ };
68
+ }
69
+
70
+ public static fromJSON(json: JSONObject): MonitorStepExceptionMonitor {
71
+ return {
72
+ telemetryServiceIds: ObjectID.fromJSONArray(
73
+ (json["telemetryServiceIds"] as Array<JSONObject>) || [],
74
+ ),
75
+ exceptionTypes: (json["exceptionTypes"] as Array<string>) || [],
76
+ message: (json["message"] as string) || "",
77
+ includeResolved: Boolean(json["includeResolved"]) || false,
78
+ includeArchived: Boolean(json["includeArchived"]) || false,
79
+ lastXSecondsOfExceptions:
80
+ (json["lastXSecondsOfExceptions"] as number | undefined) || 60,
81
+ };
82
+ }
83
+
84
+ public static toJSON(monitor: MonitorStepExceptionMonitor): JSONObject {
85
+ return {
86
+ telemetryServiceIds: ObjectID.toJSONArray(monitor.telemetryServiceIds),
87
+ exceptionTypes: monitor.exceptionTypes,
88
+ message: monitor.message,
89
+ includeResolved: monitor.includeResolved,
90
+ includeArchived: monitor.includeArchived,
91
+ lastXSecondsOfExceptions: monitor.lastXSecondsOfExceptions,
92
+ };
93
+ }
94
+ }
@@ -20,6 +20,7 @@ enum MonitorType {
20
20
  Logs = "Logs",
21
21
  Metrics = "Metrics",
22
22
  Traces = "Traces",
23
+ Exceptions = "Exceptions",
23
24
  }
24
25
 
25
26
  export default MonitorType;
@@ -35,7 +36,8 @@ export class MonitorTypeHelper {
35
36
  return (
36
37
  monitorType === MonitorType.Logs ||
37
38
  monitorType === MonitorType.Metrics ||
38
- monitorType === MonitorType.Traces
39
+ monitorType === MonitorType.Traces ||
40
+ monitorType === MonitorType.Exceptions
39
41
  );
40
42
  }
41
43
 
@@ -123,6 +125,12 @@ export class MonitorTypeHelper {
123
125
  title: "Logs",
124
126
  description: "This monitor type lets you monitor logs from any source.",
125
127
  },
128
+ {
129
+ monitorType: MonitorType.Exceptions,
130
+ title: "Exceptions",
131
+ description:
132
+ "This monitor type lets you monitor exceptions and error groups from any source.",
133
+ },
126
134
  {
127
135
  monitorType: MonitorType.Traces,
128
136
  title: "Traces",
@@ -198,6 +206,7 @@ export class MonitorTypeHelper {
198
206
  MonitorType.Logs,
199
207
  MonitorType.Metrics,
200
208
  MonitorType.Traces,
209
+ MonitorType.Exceptions,
201
210
  ];
202
211
  }
203
212
 
@@ -3,9 +3,10 @@ import Span from "../../Models/AnalyticsModels/Span";
3
3
  import Query from "../BaseDatabase/Query";
4
4
  import MetricViewData from "../Metrics/MetricViewData";
5
5
  import TelemetryType from "./TelemetryType";
6
+ import ExceptionInstance from "../../Models/AnalyticsModels/ExceptionInstance";
6
7
 
7
8
  export interface TelemetryQuery {
8
9
  telemetryType: TelemetryType;
9
- telemetryQuery: Query<Log> | Query<Span> | null;
10
+ telemetryQuery: Query<Log> | Query<Span> | Query<ExceptionInstance> | null;
10
11
  metricViewData: MetricViewData | null;
11
12
  }
@@ -2,6 +2,7 @@ enum TelemetryType {
2
2
  Metric = "Metric",
3
3
  Trace = "Trace",
4
4
  Log = "Log",
5
+ Exception = "Exception",
5
6
  }
6
7
 
7
8
  export default TelemetryType;
@@ -451,7 +451,12 @@ export default class CompareCriteria {
451
451
  return "unknown";
452
452
  }
453
453
  if (typeof value === Typeof.Number) {
454
- return value.toFixed(2);
454
+ const numericValue = value;
455
+ if (Number.isInteger(numericValue)) {
456
+ return numericValue.toString();
457
+ }
458
+ const roundedValue = Number(numericValue.toFixed(2));
459
+ return roundedValue.toString();
455
460
  }
456
461
  if (typeof value === Typeof.Boolean) {
457
462
  return value ? "true" : "false";