@oneuptime/common 11.5.13 → 11.6.1
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/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel.ts +41 -24
- package/Models/AnalyticsModels/MetricBaselineHourly.ts +2 -0
- package/Models/AnalyticsModels/MetricItemAggMV1m.ts +5 -2
- package/Models/AnalyticsModels/MetricItemAggMV1mByContainer.ts +5 -2
- package/Models/AnalyticsModels/MetricItemAggMV1mByHostV2.ts +5 -2
- package/Models/AnalyticsModels/MetricItemAggMV1mByK8sCluster.ts +5 -2
- package/Models/AnalyticsModels/MetricItemAggMV1mByService.ts +5 -2
- package/Models/DatabaseModels/EnterpriseLicense.ts +21 -0
- package/Models/DatabaseModels/EnterpriseLicenseInstance.ts +25 -0
- package/Models/DatabaseModels/GlobalConfig.ts +76 -0
- package/Server/API/EnterpriseLicenseAPI.ts +57 -0
- package/Server/API/GlobalConfigAPI.ts +62 -1
- package/Server/EnvironmentConfig.ts +22 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1784659816363-AddInstanceVersionAndLatestReleaseColumns.ts +38 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1784705487674-AddEnterpriseLicenseEvaluationColumns.ts +25 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +4 -0
- package/Server/Services/AnalyticsDatabaseService.ts +61 -46
- package/Server/Services/DatabaseService.ts +66 -1
- package/Server/Services/WorkflowService.ts +100 -39
- package/Server/Types/Workflow/Components/Schedule.ts +57 -32
- package/Server/Utils/AnalyticsDatabase/InsertDedupContext.ts +59 -0
- package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +41 -4
- package/Server/Utils/Express.ts +13 -0
- package/Server/Utils/Telemetry/TelemetryFanInWriter.ts +799 -0
- package/Server/Utils/Telemetry/TelemetryWriterClient.ts +263 -0
- package/Server/Utils/Telemetry/TelemetryWriterServer.ts +240 -0
- package/Server/Utils/Telemetry/TelemetryWriterShedMetrics.ts +93 -0
- package/Tests/Models/AnalyticsModels/AnalyticsBaseModel.test.ts +122 -0
- package/Tests/Server/Services/DatabaseServiceSanitizeUpdateData.test.ts +232 -0
- package/Tests/Server/Services/UpdateOneByIdKeepsRowId.test.ts +107 -0
- package/Tests/Server/Services/WorkflowService.test.ts +308 -0
- package/Tests/Server/Utils/AnalyticsDatabase/ClusterAwareSchema.test.ts +164 -3
- package/Tests/Server/Utils/AnalyticsDatabase/StatementGenerator.test.ts +99 -0
- package/Tests/Server/Utils/Attribution.test.ts +203 -0
- package/Tests/Server/Utils/Marketing/ConversionUploadProvider.test.ts +183 -0
- package/Tests/Server/Utils/Marketing/GoogleAds.test.ts +340 -0
- package/Tests/Server/Utils/Monitor/Criteria/ExceptionMonitorCriteria.test.ts +87 -0
- package/Tests/Server/Utils/Monitor/Criteria/LogMonitorCriteria.test.ts +165 -0
- package/Tests/Server/Utils/Monitor/Criteria/TraceMonitorCriteria.test.ts +86 -0
- package/Tests/Server/Utils/Telemetry/TelemetryFanInWriter.test.ts +1565 -0
- package/Tests/Server/Utils/Telemetry/TelemetryWriterClient.test.ts +313 -0
- package/Tests/Server/Utils/Telemetry/TelemetryWriterServer.test.ts +270 -0
- package/Tests/Server/Utils/Telemetry/TelemetryWriterShedMetrics.test.ts +127 -0
- package/Tests/Types/AI/CodeFixTaskType.test.ts +3 -0
- package/Tests/Types/HashCode.test.ts +41 -0
- package/Tests/Types/Log/LogQueryParser.test.ts +186 -0
- package/Tests/Types/Monitor/MonitorCriteriaMetricVariables.test.ts +228 -0
- package/Tests/Types/Monitor/MonitorStepDefaultTelemetryConfig.test.ts +169 -0
- package/Tests/Types/Monitor/MonitorStepExceptionMonitor.test.ts +289 -0
- package/Tests/Types/Monitor/MonitorStepLogMonitor.test.ts +231 -0
- package/Tests/Types/Monitor/MonitorStepMetricViewConfigUtil.test.ts +245 -0
- package/Tests/Types/Monitor/MonitorStepNetworkDeviceMonitor.test.ts +155 -0
- package/Tests/Types/Monitor/MonitorStepTelemetrySerialization.test.ts +141 -0
- package/Tests/Types/Monitor/MonitorStepTraceMonitor.test.ts +137 -0
- package/Tests/Types/Workspace/NotificationRules/NotificationRuleCondition.test.ts +311 -0
- package/Tests/UI/Utils/Breadcrumb/BreadcrumbTrailResolver.test.ts +461 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +2852 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +758 -0
- package/Tests/UI/Utils/NotificationMethodUtil.test.ts +564 -0
- package/Tests/Utils/Array.test.ts +156 -0
- package/Tests/Utils/CronTab.test.ts +199 -0
- package/Tests/Utils/Dashboard/VariableInterpolation.test.ts +197 -0
- package/Tests/Utils/ModelImportExport.test.ts +101 -0
- package/Tests/Utils/Number.test.ts +179 -0
- package/Tests/Utils/ValueFormatter.test.ts +305 -0
- package/Tests/Utils/VersionUtil.test.ts +348 -0
- package/Tests/jest.setup.ts +1 -0
- package/Types/AnalyticsDatabase/TableColumn.ts +23 -0
- package/Types/EnterpriseLicense/EnterpriseLicenseInstanceSummary.ts +6 -0
- package/Types/Monitor/MonitorStep.ts +24 -4
- package/Types/Monitor/MonitorStepMetricViewConfigUtil.ts +105 -0
- package/UI/Components/EditionLabel/EditionLabel.tsx +445 -12
- package/UI/Components/Workflow/ArgumentsForm.tsx +68 -30
- package/UI/Components/Workflow/CronScheduleField.tsx +411 -0
- package/UI/Utils/Breadcrumb/BreadcrumbTrailResolver.ts +176 -0
- package/UI/Utils/NotificationMethodUtil.ts +310 -0
- package/Utils/CronTab.ts +823 -0
- package/Utils/ModelImportExport.ts +21 -6
- package/Utils/VersionUtil.ts +260 -0
- package/build/dist/Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel.js +25 -20
- package/build/dist/Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/MetricBaselineHourly.js +2 -0
- package/build/dist/Models/AnalyticsModels/MetricBaselineHourly.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/MetricItemAggMV1m.js +5 -2
- package/build/dist/Models/AnalyticsModels/MetricItemAggMV1m.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByContainer.js +5 -2
- package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByContainer.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByHostV2.js +5 -2
- package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByHostV2.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByK8sCluster.js +5 -2
- package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByK8sCluster.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByService.js +5 -2
- package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByService.js.map +1 -1
- package/build/dist/Models/DatabaseModels/EnterpriseLicense.js +22 -0
- package/build/dist/Models/DatabaseModels/EnterpriseLicense.js.map +1 -1
- package/build/dist/Models/DatabaseModels/EnterpriseLicenseInstance.js +26 -0
- package/build/dist/Models/DatabaseModels/EnterpriseLicenseInstance.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalConfig.js +81 -0
- package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
- package/build/dist/Server/API/EnterpriseLicenseAPI.js +47 -0
- package/build/dist/Server/API/EnterpriseLicenseAPI.js.map +1 -1
- package/build/dist/Server/API/GlobalConfigAPI.js +52 -1
- package/build/dist/Server/API/GlobalConfigAPI.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +17 -0
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784659816363-AddInstanceVersionAndLatestReleaseColumns.js +18 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784659816363-AddInstanceVersionAndLatestReleaseColumns.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784705487674-AddEnterpriseLicenseEvaluationColumns.js +14 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784705487674-AddEnterpriseLicenseEvaluationColumns.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +4 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js +53 -17
- package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +53 -1
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/WorkflowService.js +80 -30
- package/build/dist/Server/Services/WorkflowService.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/Schedule.js +44 -19
- package/build/dist/Server/Types/Workflow/Components/Schedule.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/InsertDedupContext.js +24 -0
- package/build/dist/Server/Utils/AnalyticsDatabase/InsertDedupContext.js.map +1 -0
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +29 -4
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
- package/build/dist/Server/Utils/Express.js +12 -0
- package/build/dist/Server/Utils/Express.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/TelemetryFanInWriter.js +496 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryFanInWriter.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryWriterClient.js +165 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryWriterClient.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryWriterServer.js +136 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryWriterServer.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryWriterShedMetrics.js +76 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryWriterShedMetrics.js.map +1 -0
- package/build/dist/Types/AnalyticsDatabase/TableColumn.js +7 -0
- package/build/dist/Types/AnalyticsDatabase/TableColumn.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStep.js +20 -4
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepMetricViewConfigUtil.js +73 -0
- package/build/dist/Types/Monitor/MonitorStepMetricViewConfigUtil.js.map +1 -0
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js +261 -13
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ArgumentsForm.js +30 -6
- package/build/dist/UI/Components/Workflow/ArgumentsForm.js.map +1 -1
- package/build/dist/UI/Components/Workflow/CronScheduleField.js +209 -0
- package/build/dist/UI/Components/Workflow/CronScheduleField.js.map +1 -0
- package/build/dist/UI/Utils/Breadcrumb/BreadcrumbTrailResolver.js +129 -0
- package/build/dist/UI/Utils/Breadcrumb/BreadcrumbTrailResolver.js.map +1 -0
- package/build/dist/UI/Utils/NotificationMethodUtil.js +189 -0
- package/build/dist/UI/Utils/NotificationMethodUtil.js.map +1 -0
- package/build/dist/Utils/CronTab.js +609 -0
- package/build/dist/Utils/CronTab.js.map +1 -0
- package/build/dist/Utils/ModelImportExport.js +20 -6
- package/build/dist/Utils/ModelImportExport.js.map +1 -1
- package/build/dist/Utils/VersionUtil.js +193 -0
- package/build/dist/Utils/VersionUtil.js.map +1 -0
- package/package.json +1 -1
|
@@ -9,6 +9,7 @@ describe("CodeFixTaskTypeHelper", () => {
|
|
|
9
9
|
expect(CodeFixTaskTypeHelper.getUserTriggerableTaskTypes()).toEqual([
|
|
10
10
|
CodeFixTaskType.FixException,
|
|
11
11
|
CodeFixTaskType.WriteRegressionTest,
|
|
12
|
+
CodeFixTaskType.ImproveExceptionHandling,
|
|
12
13
|
]);
|
|
13
14
|
});
|
|
14
15
|
});
|
|
@@ -17,6 +18,7 @@ describe("CodeFixTaskTypeHelper", () => {
|
|
|
17
18
|
test.each([
|
|
18
19
|
CodeFixTaskType.FixException,
|
|
19
20
|
CodeFixTaskType.WriteRegressionTest,
|
|
21
|
+
CodeFixTaskType.ImproveExceptionHandling,
|
|
20
22
|
])("returns true for %s", (taskType: CodeFixTaskType) => {
|
|
21
23
|
expect(CodeFixTaskTypeHelper.isUserTriggerable(taskType)).toBe(true);
|
|
22
24
|
});
|
|
@@ -69,6 +71,7 @@ describe("CodeFixTaskTypeHelper", () => {
|
|
|
69
71
|
test.each([
|
|
70
72
|
CodeFixTaskType.FixException,
|
|
71
73
|
CodeFixTaskType.WriteRegressionTest,
|
|
74
|
+
CodeFixTaskType.ImproveExceptionHandling,
|
|
72
75
|
])("returns true for %s", (taskType: CodeFixTaskType) => {
|
|
73
76
|
expect(CodeFixTaskTypeHelper.requiresTelemetryException(taskType)).toBe(
|
|
74
77
|
true,
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import HashCode from "../../Types/HashCode";
|
|
2
|
+
|
|
3
|
+
describe("HashCode", () => {
|
|
4
|
+
describe("fromString", () => {
|
|
5
|
+
test("returns 0 for an empty string", () => {
|
|
6
|
+
expect(HashCode.fromString("")).toBe(0);
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
test("is deterministic for the same input", () => {
|
|
10
|
+
expect(HashCode.fromString("oneuptime")).toBe(
|
|
11
|
+
HashCode.fromString("oneuptime"),
|
|
12
|
+
);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
test("produces different hashes for different inputs", () => {
|
|
16
|
+
expect(HashCode.fromString("abc")).not.toBe(HashCode.fromString("abd"));
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test("is order-sensitive", () => {
|
|
20
|
+
expect(HashCode.fromString("ab")).not.toBe(HashCode.fromString("ba"));
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test("returns a 32-bit signed integer", () => {
|
|
24
|
+
const hash: number = HashCode.fromString(
|
|
25
|
+
"a fairly long string to exercise the shift/overflow path",
|
|
26
|
+
);
|
|
27
|
+
expect(Number.isInteger(hash)).toBe(true);
|
|
28
|
+
expect(hash).toBeGreaterThanOrEqual(-(2 ** 31));
|
|
29
|
+
expect(hash).toBeLessThanOrEqual(2 ** 31 - 1);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test("matches the known Java-style hashCode value", () => {
|
|
33
|
+
// "hello".hashCode() in Java is 99162322.
|
|
34
|
+
expect(HashCode.fromString("hello")).toBe(99162322);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test("single character equals its char code", () => {
|
|
38
|
+
expect(HashCode.fromString("A")).toBe("A".charCodeAt(0));
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
});
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import parseLogQuery, {
|
|
2
|
+
FilterOperator,
|
|
3
|
+
ParsedToken,
|
|
4
|
+
TokenType,
|
|
5
|
+
tokensToDisplayString,
|
|
6
|
+
} from "../../../Types/Log/LogQueryParser";
|
|
7
|
+
|
|
8
|
+
describe("LogQueryParser", () => {
|
|
9
|
+
describe("parseLogQuery - empty and free text", () => {
|
|
10
|
+
test("returns an empty array for empty / whitespace input", () => {
|
|
11
|
+
expect(parseLogQuery("")).toEqual([]);
|
|
12
|
+
expect(parseLogQuery(" ")).toEqual([]);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
test("combines free text words into a single Contains token", () => {
|
|
16
|
+
const tokens: Array<ParsedToken> = parseLogQuery("connection refused");
|
|
17
|
+
expect(tokens).toHaveLength(1);
|
|
18
|
+
expect(tokens[0]).toMatchObject({
|
|
19
|
+
type: TokenType.FreeText,
|
|
20
|
+
operator: FilterOperator.Contains,
|
|
21
|
+
value: "connection refused",
|
|
22
|
+
negated: false,
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
test("strips quotes from a quoted phrase", () => {
|
|
27
|
+
const tokens: Array<ParsedToken> = parseLogQuery('"connection refused"');
|
|
28
|
+
expect(tokens).toHaveLength(1);
|
|
29
|
+
expect(tokens[0]!.value).toBe("connection refused");
|
|
30
|
+
expect(tokens[0]!.type).toBe(TokenType.FreeText);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
describe("parseLogQuery - field filters and aliases", () => {
|
|
35
|
+
test("resolves the severity alias to severityText", () => {
|
|
36
|
+
const tokens: Array<ParsedToken> = parseLogQuery("severity:error");
|
|
37
|
+
expect(tokens[0]).toMatchObject({
|
|
38
|
+
type: TokenType.FieldFilter,
|
|
39
|
+
field: "severityText",
|
|
40
|
+
operator: FilterOperator.Equals,
|
|
41
|
+
value: "error",
|
|
42
|
+
negated: false,
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test("resolves the service alias to primaryEntityId", () => {
|
|
47
|
+
expect(parseLogQuery("service:api")[0]!.field).toBe("primaryEntityId");
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test("resolves level, message, and trace aliases", () => {
|
|
51
|
+
expect(parseLogQuery("level:warn")[0]!.field).toBe("severityText");
|
|
52
|
+
expect(parseLogQuery("message:hello")[0]!.field).toBe("body");
|
|
53
|
+
expect(parseLogQuery("trace:abc")[0]!.field).toBe("traceId");
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test("keeps unknown field names as-is", () => {
|
|
57
|
+
expect(parseLogQuery("customfield:x")[0]!.field).toBe("customfield");
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
describe("parseLogQuery - attribute filters", () => {
|
|
62
|
+
test("parses @-prefixed attribute access", () => {
|
|
63
|
+
const tokens: Array<ParsedToken> = parseLogQuery("@http.status_code:500");
|
|
64
|
+
expect(tokens[0]).toMatchObject({
|
|
65
|
+
type: TokenType.AttributeFilter,
|
|
66
|
+
field: "http.status_code",
|
|
67
|
+
operator: FilterOperator.Equals,
|
|
68
|
+
value: "500",
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test("does not run aliasing on attribute field names", () => {
|
|
73
|
+
// "service" is an alias for field filters but must stay literal as an attribute.
|
|
74
|
+
expect(parseLogQuery("@service:api")[0]!.field).toBe("service");
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
describe("parseLogQuery - negation", () => {
|
|
79
|
+
test("negated equals becomes NotEquals", () => {
|
|
80
|
+
const tokens: Array<ParsedToken> = parseLogQuery("-severity:debug");
|
|
81
|
+
expect(tokens[0]).toMatchObject({
|
|
82
|
+
field: "severityText",
|
|
83
|
+
operator: FilterOperator.NotEquals,
|
|
84
|
+
value: "debug",
|
|
85
|
+
negated: true,
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
test("negated attribute filter", () => {
|
|
90
|
+
const tokens: Array<ParsedToken> = parseLogQuery("-@http.method:GET");
|
|
91
|
+
expect(tokens[0]).toMatchObject({
|
|
92
|
+
type: TokenType.AttributeFilter,
|
|
93
|
+
field: "http.method",
|
|
94
|
+
operator: FilterOperator.NotEquals,
|
|
95
|
+
negated: true,
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
describe("parseLogQuery - operators", () => {
|
|
101
|
+
test("detects wildcard values", () => {
|
|
102
|
+
const tokens: Array<ParsedToken> = parseLogQuery("service:api-*");
|
|
103
|
+
expect(tokens[0]).toMatchObject({
|
|
104
|
+
operator: FilterOperator.Wildcard,
|
|
105
|
+
value: "api-*",
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test("detects numeric comparison operators", () => {
|
|
110
|
+
expect(parseLogQuery("@duration:>1000")[0]).toMatchObject({
|
|
111
|
+
operator: FilterOperator.GreaterThan,
|
|
112
|
+
value: "1000",
|
|
113
|
+
});
|
|
114
|
+
expect(parseLogQuery("@duration:>=1000")[0]).toMatchObject({
|
|
115
|
+
operator: FilterOperator.GreaterThanOrEqual,
|
|
116
|
+
value: "1000",
|
|
117
|
+
});
|
|
118
|
+
expect(parseLogQuery("@duration:<50")[0]).toMatchObject({
|
|
119
|
+
operator: FilterOperator.LessThan,
|
|
120
|
+
value: "50",
|
|
121
|
+
});
|
|
122
|
+
expect(parseLogQuery("@duration:<=50")[0]).toMatchObject({
|
|
123
|
+
operator: FilterOperator.LessThanOrEqual,
|
|
124
|
+
value: "50",
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
describe("parseLogQuery - boolean keywords and mixed queries", () => {
|
|
130
|
+
test("skips bare AND/OR/NOT keywords", () => {
|
|
131
|
+
const tokens: Array<ParsedToken> = parseLogQuery(
|
|
132
|
+
"severity:error AND service:api",
|
|
133
|
+
);
|
|
134
|
+
expect(tokens).toHaveLength(2);
|
|
135
|
+
expect(tokens[0]!.field).toBe("severityText");
|
|
136
|
+
expect(tokens[1]!.field).toBe("primaryEntityId");
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
test("splits free text around a field filter", () => {
|
|
140
|
+
const tokens: Array<ParsedToken> = parseLogQuery(
|
|
141
|
+
"connection severity:error refused",
|
|
142
|
+
);
|
|
143
|
+
expect(tokens).toHaveLength(3);
|
|
144
|
+
expect(tokens[0]).toMatchObject({
|
|
145
|
+
type: TokenType.FreeText,
|
|
146
|
+
value: "connection",
|
|
147
|
+
});
|
|
148
|
+
expect(tokens[1]).toMatchObject({
|
|
149
|
+
type: TokenType.FieldFilter,
|
|
150
|
+
field: "severityText",
|
|
151
|
+
});
|
|
152
|
+
expect(tokens[2]).toMatchObject({
|
|
153
|
+
type: TokenType.FreeText,
|
|
154
|
+
value: "refused",
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
test("does not split a quoted phrase containing spaces", () => {
|
|
159
|
+
const tokens: Array<ParsedToken> = parseLogQuery(
|
|
160
|
+
'"connection refused" severity:error',
|
|
161
|
+
);
|
|
162
|
+
expect(tokens).toHaveLength(2);
|
|
163
|
+
expect(tokens[0]!.value).toBe("connection refused");
|
|
164
|
+
expect(tokens[1]!.field).toBe("severityText");
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
test("strips quotes from field values", () => {
|
|
168
|
+
const tokens: Array<ParsedToken> = parseLogQuery('message:"a b c"');
|
|
169
|
+
expect(tokens[0]!.value).toBe("a b c");
|
|
170
|
+
expect(tokens[0]!.field).toBe("body");
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
describe("tokensToDisplayString", () => {
|
|
175
|
+
test("rejoins tokens using their raw representation", () => {
|
|
176
|
+
const tokens: Array<ParsedToken> = parseLogQuery(
|
|
177
|
+
"severity:error service:api",
|
|
178
|
+
);
|
|
179
|
+
expect(tokensToDisplayString(tokens)).toBe("severity:error service:api");
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
test("returns an empty string for no tokens", () => {
|
|
183
|
+
expect(tokensToDisplayString([])).toBe("");
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
});
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import MetricsAggregationType from "../../../Types/Metrics/MetricsAggregationType";
|
|
2
|
+
import { CheckOn, CriteriaFilter } from "../../../Types/Monitor/CriteriaFilter";
|
|
3
|
+
import { getAllCephAlertTemplates } from "../../../Types/Monitor/CephAlertTemplates";
|
|
4
|
+
import { getAllDockerAlertTemplates } from "../../../Types/Monitor/DockerAlertTemplates";
|
|
5
|
+
import { getAllDockerSwarmAlertTemplates } from "../../../Types/Monitor/DockerSwarmAlertTemplates";
|
|
6
|
+
import {
|
|
7
|
+
buildHostMonitorConfig,
|
|
8
|
+
getAllHostAlertTemplates,
|
|
9
|
+
} from "../../../Types/Monitor/HostAlertTemplates";
|
|
10
|
+
import { getAllIoTAlertTemplates } from "../../../Types/Monitor/IotAlertTemplates";
|
|
11
|
+
import { getAllKubernetesAlertTemplates } from "../../../Types/Monitor/KubernetesAlertTemplates";
|
|
12
|
+
import { getAllPodmanAlertTemplates } from "../../../Types/Monitor/PodmanAlertTemplates";
|
|
13
|
+
import { getAllProxmoxAlertTemplates } from "../../../Types/Monitor/ProxmoxAlertTemplates";
|
|
14
|
+
import MonitorCriteriaInstance from "../../../Types/Monitor/MonitorCriteriaInstance";
|
|
15
|
+
import MonitorStep, {
|
|
16
|
+
MonitorStepType,
|
|
17
|
+
} from "../../../Types/Monitor/MonitorStep";
|
|
18
|
+
import MonitorStepHostMonitor from "../../../Types/Monitor/MonitorStepHostMonitor";
|
|
19
|
+
import MonitorStepMetricViewConfigUtil from "../../../Types/Monitor/MonitorStepMetricViewConfigUtil";
|
|
20
|
+
import RollingTime from "../../../Types/RollingTime/RollingTime";
|
|
21
|
+
import ObjectID from "../../../Types/ObjectID";
|
|
22
|
+
|
|
23
|
+
/*
|
|
24
|
+
* End-to-end regression guard for the blank "METRIC" dropdown (Issues 1 & 2).
|
|
25
|
+
*
|
|
26
|
+
* For EVERY metric-shaped monitor type, a Quick Setup alert template must
|
|
27
|
+
* produce a monitor step whose metric variables are discoverable through
|
|
28
|
+
* MonitorStepMetricViewConfigUtil — the same resolver the criteria UI uses to
|
|
29
|
+
* fill the "Which metric query should this alert rule check?" dropdown. And
|
|
30
|
+
* every MetricValue criteria the template emits must reference a variable that
|
|
31
|
+
* the dropdown actually offers, otherwise the alert rule points at a metric the
|
|
32
|
+
* user can never (re)select.
|
|
33
|
+
*
|
|
34
|
+
* Before the fix, Host / Podman / DockerSwarm / IoT would all fail the
|
|
35
|
+
* "surfaces at least one metric variable" assertion because the criteria UI
|
|
36
|
+
* never read their metricViewConfig.
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
// Superset of every template's Args — excess fields are ignored per type.
|
|
40
|
+
interface UniversalTemplateArgs {
|
|
41
|
+
hostIdentifier: string;
|
|
42
|
+
clusterIdentifier: string;
|
|
43
|
+
fleetIdentifier: string;
|
|
44
|
+
onlineMonitorStatusId: ObjectID;
|
|
45
|
+
offlineMonitorStatusId: ObjectID;
|
|
46
|
+
defaultIncidentSeverityId: ObjectID;
|
|
47
|
+
defaultAlertSeverityId: ObjectID;
|
|
48
|
+
monitorName: string;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
interface AnyAlertTemplate {
|
|
52
|
+
id: string;
|
|
53
|
+
name: string;
|
|
54
|
+
getMonitorStep: (args: UniversalTemplateArgs) => MonitorStep;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
interface ResourceDescriptor {
|
|
58
|
+
name: string;
|
|
59
|
+
subConfigKey: keyof MonitorStepType;
|
|
60
|
+
templates: Array<AnyAlertTemplate>;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function buildArgs(): UniversalTemplateArgs {
|
|
64
|
+
return {
|
|
65
|
+
hostIdentifier: "host-identifier-1",
|
|
66
|
+
clusterIdentifier: "cluster-identifier-1",
|
|
67
|
+
fleetIdentifier: "fleet-identifier-1",
|
|
68
|
+
onlineMonitorStatusId: ObjectID.generate(),
|
|
69
|
+
offlineMonitorStatusId: ObjectID.generate(),
|
|
70
|
+
defaultIncidentSeverityId: ObjectID.generate(),
|
|
71
|
+
defaultAlertSeverityId: ObjectID.generate(),
|
|
72
|
+
monitorName: "Test Monitor",
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const RESOURCES: Array<ResourceDescriptor> = [
|
|
77
|
+
{
|
|
78
|
+
name: "Host",
|
|
79
|
+
subConfigKey: "hostMonitor",
|
|
80
|
+
templates: getAllHostAlertTemplates() as unknown as Array<AnyAlertTemplate>,
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
name: "Kubernetes",
|
|
84
|
+
subConfigKey: "kubernetesMonitor",
|
|
85
|
+
templates:
|
|
86
|
+
getAllKubernetesAlertTemplates() as unknown as Array<AnyAlertTemplate>,
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
name: "Docker",
|
|
90
|
+
subConfigKey: "dockerMonitor",
|
|
91
|
+
templates:
|
|
92
|
+
getAllDockerAlertTemplates() as unknown as Array<AnyAlertTemplate>,
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
name: "DockerSwarm",
|
|
96
|
+
subConfigKey: "dockerSwarmMonitor",
|
|
97
|
+
templates:
|
|
98
|
+
getAllDockerSwarmAlertTemplates() as unknown as Array<AnyAlertTemplate>,
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
name: "Podman",
|
|
102
|
+
subConfigKey: "podmanMonitor",
|
|
103
|
+
templates:
|
|
104
|
+
getAllPodmanAlertTemplates() as unknown as Array<AnyAlertTemplate>,
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
name: "Proxmox",
|
|
108
|
+
subConfigKey: "proxmoxMonitor",
|
|
109
|
+
templates:
|
|
110
|
+
getAllProxmoxAlertTemplates() as unknown as Array<AnyAlertTemplate>,
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
name: "Ceph",
|
|
114
|
+
subConfigKey: "cephMonitor",
|
|
115
|
+
templates: getAllCephAlertTemplates() as unknown as Array<AnyAlertTemplate>,
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
name: "IoT",
|
|
119
|
+
subConfigKey: "iotMonitor",
|
|
120
|
+
templates: getAllIoTAlertTemplates() as unknown as Array<AnyAlertTemplate>,
|
|
121
|
+
},
|
|
122
|
+
];
|
|
123
|
+
|
|
124
|
+
function getCriteriaInstances(
|
|
125
|
+
step: MonitorStep,
|
|
126
|
+
): Array<MonitorCriteriaInstance> {
|
|
127
|
+
return step.data?.monitorCriteria?.data?.monitorCriteriaInstanceArray || [];
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
describe("Monitor criteria metric-variable resolution (all resource types)", () => {
|
|
131
|
+
test("every resource type exposes at least one alert template", () => {
|
|
132
|
+
for (const resource of RESOURCES) {
|
|
133
|
+
expect(resource.templates.length).toBeGreaterThan(0);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
describe.each(RESOURCES)(
|
|
138
|
+
"$name alert templates",
|
|
139
|
+
(resource: ResourceDescriptor) => {
|
|
140
|
+
test("the resolver reads this resource's metricViewConfig", () => {
|
|
141
|
+
const step: MonitorStep =
|
|
142
|
+
resource.templates[0]!.getMonitorStep(buildArgs());
|
|
143
|
+
|
|
144
|
+
const stepRecord: Record<
|
|
145
|
+
string,
|
|
146
|
+
{ metricViewConfig?: unknown } | undefined
|
|
147
|
+
> = step.data as unknown as Record<
|
|
148
|
+
string,
|
|
149
|
+
{ metricViewConfig?: unknown } | undefined
|
|
150
|
+
>;
|
|
151
|
+
|
|
152
|
+
const expectedConfig: unknown =
|
|
153
|
+
stepRecord[resource.subConfigKey as string]?.metricViewConfig;
|
|
154
|
+
|
|
155
|
+
expect(expectedConfig).toBeDefined();
|
|
156
|
+
expect(
|
|
157
|
+
MonitorStepMetricViewConfigUtil.getMetricViewConfig(step.data),
|
|
158
|
+
).toBe(expectedConfig);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
test.each(
|
|
162
|
+
resource.templates.map(
|
|
163
|
+
(t: AnyAlertTemplate): [string, AnyAlertTemplate] => {
|
|
164
|
+
return [t.id, t];
|
|
165
|
+
},
|
|
166
|
+
),
|
|
167
|
+
)(
|
|
168
|
+
"%s surfaces metric variables and resolves its criteria aliases",
|
|
169
|
+
(_id: string, template: AnyAlertTemplate) => {
|
|
170
|
+
const step: MonitorStep = template.getMonitorStep(buildArgs());
|
|
171
|
+
|
|
172
|
+
// 1. The dropdown would offer at least one option (the actual bug).
|
|
173
|
+
const variables: Array<string> =
|
|
174
|
+
MonitorStepMetricViewConfigUtil.getMetricVariables(step.data);
|
|
175
|
+
expect(variables.length).toBeGreaterThan(0);
|
|
176
|
+
// No blank options leak through.
|
|
177
|
+
expect(variables).not.toContain("");
|
|
178
|
+
|
|
179
|
+
// 2. Every MetricValue criteria references an offered variable.
|
|
180
|
+
const referencedAliases: Set<string> = new Set<string>();
|
|
181
|
+
for (const instance of getCriteriaInstances(step)) {
|
|
182
|
+
for (const filter of (instance.data?.filters ||
|
|
183
|
+
[]) as Array<CriteriaFilter>) {
|
|
184
|
+
if (
|
|
185
|
+
filter.checkOn === CheckOn.MetricValue &&
|
|
186
|
+
filter.metricMonitorOptions?.metricAlias
|
|
187
|
+
) {
|
|
188
|
+
referencedAliases.add(filter.metricMonitorOptions.metricAlias);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// These templates must produce at least one metric criteria.
|
|
194
|
+
expect(referencedAliases.size).toBeGreaterThan(0);
|
|
195
|
+
|
|
196
|
+
for (const alias of referencedAliases) {
|
|
197
|
+
expect(variables).toContain(alias);
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
);
|
|
201
|
+
},
|
|
202
|
+
);
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
describe("Custom Metric flow (buildHostMonitorConfig)", () => {
|
|
206
|
+
test("a long descriptive alias is surfaced by the resolver", () => {
|
|
207
|
+
const config: MonitorStepHostMonitor = buildHostMonitorConfig({
|
|
208
|
+
hostIdentifier: "host-1",
|
|
209
|
+
metricName: "process.cpu.utilization",
|
|
210
|
+
metricAlias: "process_cpu_utilization",
|
|
211
|
+
rollingTime: RollingTime.Past5Minutes,
|
|
212
|
+
aggregationType: MetricsAggregationType.Max,
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
const stepData: MonitorStepType = {
|
|
216
|
+
hostMonitor: config,
|
|
217
|
+
} as unknown as MonitorStepType;
|
|
218
|
+
|
|
219
|
+
expect(
|
|
220
|
+
MonitorStepMetricViewConfigUtil.getMetricVariables(stepData),
|
|
221
|
+
).toEqual(["process_cpu_utilization"]);
|
|
222
|
+
|
|
223
|
+
// The alias also lands on the query config so the criteria join key holds.
|
|
224
|
+
expect(
|
|
225
|
+
config.metricViewConfig.queryConfigs[0]?.metricAliasData?.metricVariable,
|
|
226
|
+
).toBe("process_cpu_utilization");
|
|
227
|
+
});
|
|
228
|
+
});
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import MonitorStep from "../../../Types/Monitor/MonitorStep";
|
|
2
|
+
import MonitorType from "../../../Types/Monitor/MonitorType";
|
|
3
|
+
import ObjectID from "../../../Types/ObjectID";
|
|
4
|
+
import { MonitorStepLogMonitorUtil } from "../../../Types/Monitor/MonitorStepLogMonitor";
|
|
5
|
+
import { MonitorStepTraceMonitorUtil } from "../../../Types/Monitor/MonitorStepTraceMonitor";
|
|
6
|
+
import { MonitorStepMetricMonitorUtil } from "../../../Types/Monitor/MonitorStepMetricMonitor";
|
|
7
|
+
import { MonitorStepExceptionMonitorUtil } from "../../../Types/Monitor/MonitorStepExceptionMonitor";
|
|
8
|
+
|
|
9
|
+
/*
|
|
10
|
+
* Regression coverage for the "log monitors do not work" bug: a telemetry
|
|
11
|
+
* monitor step created on defaults must persist its own type's sub-config
|
|
12
|
+
* (logMonitor / traceMonitor / metricMonitor / exceptionMonitor) rather than
|
|
13
|
+
* leaving it undefined. When it was left undefined, the worker's
|
|
14
|
+
* monitorLogs()/monitorTrace()/... threw "<type> query/config is missing" on
|
|
15
|
+
* every evaluation, so the monitor never ran and its criteria never applied.
|
|
16
|
+
*/
|
|
17
|
+
describe("MonitorStep.getDefaultMonitorStep telemetry sub-config seeding", () => {
|
|
18
|
+
const buildArgs: (
|
|
19
|
+
monitorType: MonitorType,
|
|
20
|
+
) => Parameters<typeof MonitorStep.getDefaultMonitorStep>[0] = (
|
|
21
|
+
monitorType: MonitorType,
|
|
22
|
+
) => {
|
|
23
|
+
const id: ObjectID = ObjectID.generate();
|
|
24
|
+
return {
|
|
25
|
+
monitorName: `${monitorType} monitor`,
|
|
26
|
+
monitorType,
|
|
27
|
+
onlineMonitorStatusId: id,
|
|
28
|
+
offlineMonitorStatusId: id,
|
|
29
|
+
defaultIncidentSeverityId: id,
|
|
30
|
+
defaultAlertSeverityId: id,
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
describe("seeds exactly the matching type's sub-config", () => {
|
|
35
|
+
test("Logs monitor seeds logMonitor equal to its util default", () => {
|
|
36
|
+
const step: MonitorStep = MonitorStep.getDefaultMonitorStep(
|
|
37
|
+
buildArgs(MonitorType.Logs),
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
expect(step.data?.logMonitor).toBeDefined();
|
|
41
|
+
expect(step.data?.logMonitor).toEqual(
|
|
42
|
+
MonitorStepLogMonitorUtil.getDefault(),
|
|
43
|
+
);
|
|
44
|
+
// The default query config must be usable (positive time window).
|
|
45
|
+
expect(step.data?.logMonitor?.lastXSecondsOfLogs).toBeGreaterThan(0);
|
|
46
|
+
expect(step.data?.traceMonitor).toBeUndefined();
|
|
47
|
+
expect(step.data?.metricMonitor).toBeUndefined();
|
|
48
|
+
expect(step.data?.exceptionMonitor).toBeUndefined();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test("Traces monitor seeds traceMonitor equal to its util default", () => {
|
|
52
|
+
const step: MonitorStep = MonitorStep.getDefaultMonitorStep(
|
|
53
|
+
buildArgs(MonitorType.Traces),
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
expect(step.data?.traceMonitor).toBeDefined();
|
|
57
|
+
expect(step.data?.traceMonitor).toEqual(
|
|
58
|
+
MonitorStepTraceMonitorUtil.getDefault(),
|
|
59
|
+
);
|
|
60
|
+
expect(step.data?.traceMonitor?.lastXSecondsOfSpans).toBeGreaterThan(0);
|
|
61
|
+
expect(step.data?.logMonitor).toBeUndefined();
|
|
62
|
+
expect(step.data?.metricMonitor).toBeUndefined();
|
|
63
|
+
expect(step.data?.exceptionMonitor).toBeUndefined();
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
test("Metrics monitor seeds metricMonitor equal to its util default", () => {
|
|
67
|
+
const step: MonitorStep = MonitorStep.getDefaultMonitorStep(
|
|
68
|
+
buildArgs(MonitorType.Metrics),
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
expect(step.data?.metricMonitor).toBeDefined();
|
|
72
|
+
expect(step.data?.metricMonitor).toEqual(
|
|
73
|
+
MonitorStepMetricMonitorUtil.getDefault(),
|
|
74
|
+
);
|
|
75
|
+
expect(step.data?.metricMonitor?.metricViewConfig).toBeDefined();
|
|
76
|
+
expect(step.data?.logMonitor).toBeUndefined();
|
|
77
|
+
expect(step.data?.traceMonitor).toBeUndefined();
|
|
78
|
+
expect(step.data?.exceptionMonitor).toBeUndefined();
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test("Exceptions monitor seeds exceptionMonitor equal to its util default", () => {
|
|
82
|
+
const step: MonitorStep = MonitorStep.getDefaultMonitorStep(
|
|
83
|
+
buildArgs(MonitorType.Exceptions),
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
expect(step.data?.exceptionMonitor).toBeDefined();
|
|
87
|
+
expect(step.data?.exceptionMonitor).toEqual(
|
|
88
|
+
MonitorStepExceptionMonitorUtil.getDefault(),
|
|
89
|
+
);
|
|
90
|
+
expect(step.data?.logMonitor).toBeUndefined();
|
|
91
|
+
expect(step.data?.traceMonitor).toBeUndefined();
|
|
92
|
+
expect(step.data?.metricMonitor).toBeUndefined();
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
describe("does not seed a telemetry sub-config for other types", () => {
|
|
97
|
+
/*
|
|
98
|
+
* Only the four telemetry types offered by the Telemetry picker are
|
|
99
|
+
* seeded here. Infra metric monitors (Kubernetes/Docker/Host/...) carry
|
|
100
|
+
* their own sub-config from templates, and non-telemetry monitors have
|
|
101
|
+
* no telemetry sub-config at all — none must get a logMonitor/traceMonitor
|
|
102
|
+
* /metricMonitor/exceptionMonitor from the generic default step.
|
|
103
|
+
*/
|
|
104
|
+
const nonSeededTypes: Array<MonitorType> = [
|
|
105
|
+
MonitorType.Ping,
|
|
106
|
+
MonitorType.IP,
|
|
107
|
+
MonitorType.Port,
|
|
108
|
+
MonitorType.Website,
|
|
109
|
+
MonitorType.API,
|
|
110
|
+
MonitorType.Server,
|
|
111
|
+
MonitorType.SSLCertificate,
|
|
112
|
+
MonitorType.IncomingRequest,
|
|
113
|
+
MonitorType.SyntheticMonitor,
|
|
114
|
+
MonitorType.CustomJavaScriptCode,
|
|
115
|
+
MonitorType.SQLQuery,
|
|
116
|
+
MonitorType.Manual,
|
|
117
|
+
MonitorType.Profiles,
|
|
118
|
+
MonitorType.Kubernetes,
|
|
119
|
+
MonitorType.Docker,
|
|
120
|
+
MonitorType.Host,
|
|
121
|
+
MonitorType.Podman,
|
|
122
|
+
MonitorType.DockerSwarm,
|
|
123
|
+
MonitorType.Proxmox,
|
|
124
|
+
MonitorType.Ceph,
|
|
125
|
+
MonitorType.IoTDevice,
|
|
126
|
+
];
|
|
127
|
+
|
|
128
|
+
test.each(nonSeededTypes)(
|
|
129
|
+
"%s seeds no telemetry sub-config",
|
|
130
|
+
(monitorType: MonitorType) => {
|
|
131
|
+
const step: MonitorStep = MonitorStep.getDefaultMonitorStep(
|
|
132
|
+
buildArgs(monitorType),
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
expect(step.data?.logMonitor).toBeUndefined();
|
|
136
|
+
expect(step.data?.traceMonitor).toBeUndefined();
|
|
137
|
+
expect(step.data?.metricMonitor).toBeUndefined();
|
|
138
|
+
expect(step.data?.exceptionMonitor).toBeUndefined();
|
|
139
|
+
},
|
|
140
|
+
);
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
test("still seeds the default criteria and a step id", () => {
|
|
144
|
+
const step: MonitorStep = MonitorStep.getDefaultMonitorStep(
|
|
145
|
+
buildArgs(MonitorType.Logs),
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
expect(step.data?.id).toBeDefined();
|
|
149
|
+
expect(step.data?.monitorCriteria).toBeDefined();
|
|
150
|
+
expect(
|
|
151
|
+
step.data?.monitorCriteria.data?.monitorCriteriaInstanceArray.length,
|
|
152
|
+
).toBeGreaterThan(0);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
test("seeds a fresh sub-config object per call (no shared mutable state)", () => {
|
|
156
|
+
const a: MonitorStep = MonitorStep.getDefaultMonitorStep(
|
|
157
|
+
buildArgs(MonitorType.Logs),
|
|
158
|
+
);
|
|
159
|
+
const b: MonitorStep = MonitorStep.getDefaultMonitorStep(
|
|
160
|
+
buildArgs(MonitorType.Logs),
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
expect(a.data?.logMonitor).not.toBe(b.data?.logMonitor);
|
|
164
|
+
|
|
165
|
+
// Mutating one must not bleed into the other.
|
|
166
|
+
a.data!.logMonitor!.lastXSecondsOfLogs = 999;
|
|
167
|
+
expect(b.data?.logMonitor?.lastXSecondsOfLogs).not.toBe(999);
|
|
168
|
+
});
|
|
169
|
+
});
|