@oneuptime/common 8.0.5387 → 8.0.5409
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/Index.ts +0 -2
- package/Models/DatabaseModels/TelemetryException.ts +0 -7
- package/Server/API/MicrosoftTeamsAPI.ts +3 -4
- package/Server/API/UserOnCallLogTimelineAPI.ts +21 -17
- package/Server/DatabaseConfig.ts +7 -2
- package/Server/EnvironmentConfig.ts +20 -7
- package/Server/Infrastructure/GlobalCache.ts +12 -5
- package/Server/Services/AlertService.ts +0 -10
- package/Server/Services/AnalyticsDatabaseService.ts +5 -0
- package/Server/Services/IncidentService.ts +0 -10
- package/Server/Services/Index.ts +0 -2
- package/Server/Services/TeamMemberService.ts +11 -2
- package/Server/Services/TelemetryAttributeService.ts +261 -48
- package/Server/Services/WorkspaceProjectAuthTokenService.ts +33 -0
- package/Server/Utils/Monitor/MonitorResource.ts +0 -16
- package/Server/Utils/Telemetry/Telemetry.ts +0 -61
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +149 -14
- package/Types/Permission.ts +0 -3
- package/UI/Components/Filters/FilterViewer.tsx +5 -1
- package/UI/Components/Filters/FiltersForm.tsx +8 -1
- package/UI/Components/List/List.tsx +4 -0
- package/UI/Components/LogsViewer/LogsViewer.tsx +102 -55
- package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +1 -1
- package/UI/Components/ModelTable/BaseModelTable.tsx +6 -0
- package/UI/Components/Table/Table.tsx +4 -0
- package/UI/Config.ts +28 -19
- package/UI/Utils/API/ApiDocsAPI.ts +6 -1
- package/UI/Utils/API/DashboardAPI.ts +2 -1
- package/UI/Utils/API/IdentityAPI.ts +6 -1
- package/build/dist/Models/AnalyticsModels/Index.js +0 -2
- package/build/dist/Models/AnalyticsModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TelemetryException.js +0 -7
- package/build/dist/Models/DatabaseModels/TelemetryException.js.map +1 -1
- package/build/dist/Server/API/MicrosoftTeamsAPI.js +4 -4
- package/build/dist/Server/API/MicrosoftTeamsAPI.js.map +1 -1
- package/build/dist/Server/API/UserOnCallLogTimelineAPI.js +6 -3
- package/build/dist/Server/API/UserOnCallLogTimelineAPI.js.map +1 -1
- package/build/dist/Server/DatabaseConfig.js +3 -2
- package/build/dist/Server/DatabaseConfig.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +8 -7
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/GlobalCache.js +11 -9
- package/build/dist/Server/Infrastructure/GlobalCache.js.map +1 -1
- package/build/dist/Server/Services/AlertService.js +0 -9
- package/build/dist/Server/Services/AlertService.js.map +1 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
- package/build/dist/Server/Services/IncidentService.js +0 -9
- package/build/dist/Server/Services/IncidentService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +0 -2
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/TeamMemberService.js +3 -2
- package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryAttributeService.js +165 -46
- package/build/dist/Server/Services/TelemetryAttributeService.js.map +1 -1
- package/build/dist/Server/Services/WorkspaceProjectAuthTokenService.js +25 -0
- package/build/dist/Server/Services/WorkspaceProjectAuthTokenService.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorResource.js +0 -15
- package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/Telemetry.js +0 -41
- package/build/dist/Server/Utils/Telemetry/Telemetry.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +84 -15
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
- package/build/dist/Types/Permission.js +0 -2
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/UI/Components/Filters/FilterViewer.js +2 -2
- package/build/dist/UI/Components/Filters/FilterViewer.js.map +1 -1
- package/build/dist/UI/Components/Filters/FiltersForm.js +6 -1
- package/build/dist/UI/Components/Filters/FiltersForm.js.map +1 -1
- package/build/dist/UI/Components/List/List.js +1 -1
- package/build/dist/UI/Components/List/List.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js +43 -16
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +1 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +2 -2
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/Table/Table.js +1 -1
- package/build/dist/UI/Components/Table/Table.js.map +1 -1
- package/build/dist/UI/Config.js +20 -19
- package/build/dist/UI/Config.js.map +1 -1
- package/build/dist/UI/Utils/API/ApiDocsAPI.js +2 -1
- package/build/dist/UI/Utils/API/ApiDocsAPI.js.map +1 -1
- package/build/dist/UI/Utils/API/DashboardAPI.js +2 -1
- package/build/dist/UI/Utils/API/DashboardAPI.js.map +1 -1
- package/build/dist/UI/Utils/API/IdentityAPI.js +2 -1
- package/build/dist/UI/Utils/API/IdentityAPI.js.map +1 -1
- package/package.json +1 -1
- package/Models/AnalyticsModels/TelemetryAttribute.ts +0 -164
- package/build/dist/Models/AnalyticsModels/TelemetryAttribute.js +0 -154
- package/build/dist/Models/AnalyticsModels/TelemetryAttribute.js.map +0 -1
|
@@ -1,13 +1,66 @@
|
|
|
1
|
+
import { SQL, Statement } from "../Utils/AnalyticsDatabase/Statement";
|
|
1
2
|
import TelemetryType from "../../Types/Telemetry/TelemetryType";
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
3
|
+
import LogDatabaseService from "./LogService";
|
|
4
|
+
import MetricDatabaseService from "./MetricService";
|
|
5
|
+
import SpanDatabaseService from "./SpanService";
|
|
6
|
+
import TableColumnType from "../../Types/AnalyticsDatabase/TableColumnType";
|
|
7
|
+
import { JSONObject } from "../../Types/JSON";
|
|
5
8
|
import ObjectID from "../../Types/ObjectID";
|
|
9
|
+
import OneUptimeDate from "../../Types/Date";
|
|
10
|
+
import GlobalCache from "../Infrastructure/GlobalCache";
|
|
6
11
|
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
12
|
+
import AnalyticsDatabaseService, {
|
|
13
|
+
DbJSONResponse,
|
|
14
|
+
Results,
|
|
15
|
+
} from "./AnalyticsDatabaseService";
|
|
7
16
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
17
|
+
type TelemetrySource = {
|
|
18
|
+
service: AnalyticsDatabaseService<any>;
|
|
19
|
+
tableName: string;
|
|
20
|
+
attributesColumn: string;
|
|
21
|
+
timeColumn: string;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
type TelemetryAttributesCacheEntry = {
|
|
25
|
+
attributes: Array<string>;
|
|
26
|
+
refreshedAt: Date;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export class TelemetryAttributeService {
|
|
30
|
+
private static readonly ATTRIBUTES_LIMIT: number = 5000;
|
|
31
|
+
private static readonly ROW_SCAN_LIMIT: number = 10000;
|
|
32
|
+
private static readonly CACHE_NAMESPACE: string = "telemetry-attributes";
|
|
33
|
+
private static readonly CACHE_STALE_AFTER_MINUTES: number = 5;
|
|
34
|
+
private static readonly LOOKBACK_WINDOW_IN_DAYS: number = 30;
|
|
35
|
+
|
|
36
|
+
private getTelemetrySource(
|
|
37
|
+
telemetryType: TelemetryType,
|
|
38
|
+
): TelemetrySource | null {
|
|
39
|
+
switch (telemetryType) {
|
|
40
|
+
case TelemetryType.Log:
|
|
41
|
+
return {
|
|
42
|
+
service: LogDatabaseService,
|
|
43
|
+
tableName: LogDatabaseService.model.tableName,
|
|
44
|
+
attributesColumn: "attributes",
|
|
45
|
+
timeColumn: "time",
|
|
46
|
+
};
|
|
47
|
+
case TelemetryType.Metric:
|
|
48
|
+
return {
|
|
49
|
+
service: MetricDatabaseService,
|
|
50
|
+
tableName: MetricDatabaseService.model.tableName,
|
|
51
|
+
attributesColumn: "attributes",
|
|
52
|
+
timeColumn: "time",
|
|
53
|
+
};
|
|
54
|
+
case TelemetryType.Trace:
|
|
55
|
+
return {
|
|
56
|
+
service: SpanDatabaseService,
|
|
57
|
+
tableName: SpanDatabaseService.model.tableName,
|
|
58
|
+
attributesColumn: "attributes",
|
|
59
|
+
timeColumn: "startTime",
|
|
60
|
+
};
|
|
61
|
+
default:
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
11
64
|
}
|
|
12
65
|
|
|
13
66
|
@CaptureSpan()
|
|
@@ -15,57 +68,217 @@ export class TelemetryAttributeService extends AnalyticsDatabaseService<Telemetr
|
|
|
15
68
|
projectId: ObjectID;
|
|
16
69
|
telemetryType: TelemetryType;
|
|
17
70
|
}): Promise<string[]> {
|
|
18
|
-
const
|
|
19
|
-
|
|
71
|
+
const source: TelemetrySource | null = this.getTelemetrySource(
|
|
72
|
+
data.telemetryType,
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
if (!source) {
|
|
76
|
+
return [];
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const cacheKey: string = TelemetryAttributeService.getCacheKey(
|
|
80
|
+
data.projectId,
|
|
81
|
+
data.telemetryType,
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
const cachedEntry: TelemetryAttributesCacheEntry | null =
|
|
85
|
+
await TelemetryAttributeService.getCachedAttributes(cacheKey);
|
|
86
|
+
|
|
87
|
+
if (cachedEntry && TelemetryAttributeService.isCacheFresh(cachedEntry)) {
|
|
88
|
+
return cachedEntry.attributes;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
let attributes: Array<string> = [];
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
attributes = await TelemetryAttributeService.fetchAttributesFromDatabase({
|
|
20
95
|
projectId: data.projectId,
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
96
|
+
source,
|
|
97
|
+
});
|
|
98
|
+
} catch (error) {
|
|
99
|
+
if (cachedEntry) {
|
|
100
|
+
return cachedEntry.attributes;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
throw error;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
await TelemetryAttributeService.storeAttributesInCache(
|
|
107
|
+
cacheKey,
|
|
108
|
+
attributes,
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
if (attributes.length === 0 && cachedEntry) {
|
|
112
|
+
return cachedEntry.attributes;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return attributes;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
private static getCacheKey(
|
|
119
|
+
projectId: ObjectID,
|
|
120
|
+
telemetryType: TelemetryType,
|
|
121
|
+
): string {
|
|
122
|
+
return `${projectId.toString()}:${telemetryType}`;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
private static getLookbackStartDate(): Date {
|
|
126
|
+
return OneUptimeDate.addRemoveDays(
|
|
127
|
+
OneUptimeDate.getCurrentDate(),
|
|
128
|
+
-TelemetryAttributeService.LOOKBACK_WINDOW_IN_DAYS,
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
private static async getCachedAttributes(
|
|
133
|
+
cacheKey: string,
|
|
134
|
+
): Promise<TelemetryAttributesCacheEntry | null> {
|
|
135
|
+
let payload: JSONObject | null = null;
|
|
136
|
+
|
|
137
|
+
try {
|
|
138
|
+
payload = await GlobalCache.getJSONObject(
|
|
139
|
+
TelemetryAttributeService.CACHE_NAMESPACE,
|
|
140
|
+
cacheKey,
|
|
141
|
+
);
|
|
142
|
+
} catch {
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (!payload) {
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const attributesValue: JSONObject["attributes"] = payload["attributes"];
|
|
151
|
+
const refreshedAtValue: JSONObject["refreshedAt"] = payload["refreshedAt"];
|
|
152
|
+
|
|
153
|
+
if (
|
|
154
|
+
!Array.isArray(attributesValue) ||
|
|
155
|
+
typeof refreshedAtValue !== "string"
|
|
156
|
+
) {
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const attributeCandidates: Array<unknown> =
|
|
161
|
+
attributesValue as Array<unknown>;
|
|
162
|
+
|
|
163
|
+
const attributes: Array<string> = attributeCandidates.filter(
|
|
164
|
+
(attribute: unknown): attribute is string => {
|
|
165
|
+
return typeof attribute === "string";
|
|
28
166
|
},
|
|
29
|
-
|
|
167
|
+
);
|
|
30
168
|
|
|
31
|
-
return
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
: [];
|
|
169
|
+
return {
|
|
170
|
+
attributes,
|
|
171
|
+
refreshedAt: OneUptimeDate.fromString(refreshedAtValue),
|
|
172
|
+
};
|
|
36
173
|
}
|
|
37
174
|
|
|
38
|
-
|
|
39
|
-
|
|
175
|
+
private static isCacheFresh(
|
|
176
|
+
cacheEntry: TelemetryAttributesCacheEntry,
|
|
177
|
+
): boolean {
|
|
178
|
+
const now: Date = OneUptimeDate.getCurrentDate();
|
|
179
|
+
const minutesSinceRefresh: number = Math.abs(
|
|
180
|
+
OneUptimeDate.getNumberOfMinutesBetweenDates(cacheEntry.refreshedAt, now),
|
|
181
|
+
);
|
|
182
|
+
|
|
183
|
+
return (
|
|
184
|
+
minutesSinceRefresh <= TelemetryAttributeService.CACHE_STALE_AFTER_MINUTES
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
private static async storeAttributesInCache(
|
|
189
|
+
cacheKey: string,
|
|
190
|
+
attributes: Array<string>,
|
|
191
|
+
): Promise<void> {
|
|
192
|
+
const payload: JSONObject = {
|
|
193
|
+
attributes,
|
|
194
|
+
refreshedAt: OneUptimeDate.getCurrentDate().toISOString(),
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
try {
|
|
198
|
+
await GlobalCache.setJSON(
|
|
199
|
+
TelemetryAttributeService.CACHE_NAMESPACE,
|
|
200
|
+
cacheKey,
|
|
201
|
+
payload,
|
|
202
|
+
{
|
|
203
|
+
expiresInSeconds:
|
|
204
|
+
TelemetryAttributeService.CACHE_STALE_AFTER_MINUTES * 60,
|
|
205
|
+
},
|
|
206
|
+
);
|
|
207
|
+
} catch {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
private static buildAttributesStatement(data: {
|
|
40
213
|
projectId: ObjectID;
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
await this.deleteBy({
|
|
48
|
-
query: {
|
|
49
|
-
projectId,
|
|
50
|
-
telemetryType,
|
|
51
|
-
},
|
|
52
|
-
props: {
|
|
53
|
-
isRoot: true,
|
|
54
|
-
},
|
|
55
|
-
});
|
|
214
|
+
tableName: string;
|
|
215
|
+
attributesColumn: string;
|
|
216
|
+
timeColumn: string;
|
|
217
|
+
}): Statement {
|
|
218
|
+
const lookbackStartDate: Date =
|
|
219
|
+
TelemetryAttributeService.getLookbackStartDate();
|
|
56
220
|
|
|
57
|
-
const
|
|
221
|
+
const statement: Statement = SQL`
|
|
222
|
+
WITH filtered AS (
|
|
223
|
+
SELECT ${data.attributesColumn} AS attrs
|
|
224
|
+
FROM ${data.tableName}
|
|
225
|
+
WHERE projectId = ${{
|
|
226
|
+
type: TableColumnType.ObjectID,
|
|
227
|
+
value: data.projectId,
|
|
228
|
+
}}
|
|
229
|
+
AND ${data.attributesColumn} IS NOT NULL
|
|
230
|
+
AND ${data.attributesColumn} != ''
|
|
231
|
+
AND ${data.timeColumn} >= ${{
|
|
232
|
+
type: TableColumnType.Date,
|
|
233
|
+
value: lookbackStartDate,
|
|
234
|
+
}}
|
|
235
|
+
ORDER BY ${data.timeColumn} DESC
|
|
236
|
+
LIMIT ${{
|
|
237
|
+
type: TableColumnType.Number,
|
|
238
|
+
value: TelemetryAttributeService.ROW_SCAN_LIMIT,
|
|
239
|
+
}}
|
|
240
|
+
)
|
|
241
|
+
SELECT DISTINCT arrayJoin(JSONExtractKeys(attrs)) AS attribute
|
|
242
|
+
FROM filtered
|
|
243
|
+
ORDER BY attribute ASC
|
|
244
|
+
LIMIT ${{
|
|
245
|
+
type: TableColumnType.Number,
|
|
246
|
+
value: TelemetryAttributeService.ATTRIBUTES_LIMIT,
|
|
247
|
+
}}
|
|
248
|
+
`;
|
|
58
249
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
telemetryAttribute.attributes = attributes;
|
|
250
|
+
return statement;
|
|
251
|
+
}
|
|
62
252
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
253
|
+
private static async fetchAttributesFromDatabase(data: {
|
|
254
|
+
projectId: ObjectID;
|
|
255
|
+
source: TelemetrySource;
|
|
256
|
+
}): Promise<Array<string>> {
|
|
257
|
+
const statement: Statement =
|
|
258
|
+
TelemetryAttributeService.buildAttributesStatement({
|
|
259
|
+
projectId: data.projectId,
|
|
260
|
+
tableName: data.source.tableName,
|
|
261
|
+
attributesColumn: data.source.attributesColumn,
|
|
262
|
+
timeColumn: data.source.timeColumn,
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
const dbResult: Results = await data.source.service.executeQuery(statement);
|
|
266
|
+
const response: DbJSONResponse = await dbResult.json<{
|
|
267
|
+
data?: Array<JSONObject>;
|
|
268
|
+
}>();
|
|
269
|
+
|
|
270
|
+
const rows: Array<JSONObject> = response.data || [];
|
|
271
|
+
|
|
272
|
+
const attributeKeys: Array<string> = rows
|
|
273
|
+
.map((row: JSONObject) => {
|
|
274
|
+
const attribute: unknown = row["attribute"];
|
|
275
|
+
return typeof attribute === "string" ? attribute.trim() : null;
|
|
276
|
+
})
|
|
277
|
+
.filter((attribute: string | null): attribute is string => {
|
|
278
|
+
return Boolean(attribute);
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
return Array.from(new Set(attributeKeys));
|
|
69
282
|
}
|
|
70
283
|
}
|
|
71
284
|
|
|
@@ -5,6 +5,7 @@ import Model, {
|
|
|
5
5
|
WorkspaceMiscData,
|
|
6
6
|
} from "../../Models/DatabaseModels/WorkspaceProjectAuthToken";
|
|
7
7
|
import { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";
|
|
8
|
+
import BadDataException from "../../Types/Exception/BadDataException";
|
|
8
9
|
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
9
10
|
|
|
10
11
|
export class Service extends DatabaseService<Model> {
|
|
@@ -17,6 +18,14 @@ export class Service extends DatabaseService<Model> {
|
|
|
17
18
|
projectId: ObjectID;
|
|
18
19
|
workspaceType: WorkspaceType;
|
|
19
20
|
}): Promise<Model | null> {
|
|
21
|
+
if (!data.projectId) {
|
|
22
|
+
throw new BadDataException("projectId is required");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (!data.workspaceType) {
|
|
26
|
+
throw new BadDataException("workspaceType is required");
|
|
27
|
+
}
|
|
28
|
+
|
|
20
29
|
return await this.findOneBy({
|
|
21
30
|
query: {
|
|
22
31
|
projectId: data.projectId,
|
|
@@ -38,6 +47,10 @@ export class Service extends DatabaseService<Model> {
|
|
|
38
47
|
public async getProjectAuths(data: {
|
|
39
48
|
projectId: ObjectID;
|
|
40
49
|
}): Promise<Array<Model>> {
|
|
50
|
+
if (!data.projectId) {
|
|
51
|
+
throw new BadDataException("projectId is required");
|
|
52
|
+
}
|
|
53
|
+
|
|
41
54
|
return await this.findBy({
|
|
42
55
|
query: {
|
|
43
56
|
projectId: data.projectId,
|
|
@@ -72,6 +85,26 @@ export class Service extends DatabaseService<Model> {
|
|
|
72
85
|
workspaceProjectId: string;
|
|
73
86
|
miscData: WorkspaceMiscData;
|
|
74
87
|
}): Promise<void> {
|
|
88
|
+
if (!data.projectId) {
|
|
89
|
+
throw new BadDataException("projectId is required");
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (!data.workspaceType) {
|
|
93
|
+
throw new BadDataException("workspaceType is required");
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (!data.authToken) {
|
|
97
|
+
throw new BadDataException("authToken is required");
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (!data.workspaceProjectId) {
|
|
101
|
+
throw new BadDataException("workspaceProjectId is required");
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (!data.miscData) {
|
|
105
|
+
throw new BadDataException("miscData is required");
|
|
106
|
+
}
|
|
107
|
+
|
|
75
108
|
let projectAuth: Model | null = await this.findOneBy({
|
|
76
109
|
query: {
|
|
77
110
|
projectId: data.projectId,
|
|
@@ -1059,22 +1059,6 @@ export default class MonitorResourceUtil {
|
|
|
1059
1059
|
logger.error(err);
|
|
1060
1060
|
});
|
|
1061
1061
|
|
|
1062
|
-
// index attributes.
|
|
1063
|
-
TelemetryUtil.indexAttributes({
|
|
1064
|
-
attributes: [
|
|
1065
|
-
"monitorId",
|
|
1066
|
-
"projectId",
|
|
1067
|
-
"probeId",
|
|
1068
|
-
"browserType",
|
|
1069
|
-
"screenSizeType",
|
|
1070
|
-
"diskPath",
|
|
1071
|
-
],
|
|
1072
|
-
projectId: data.projectId,
|
|
1073
|
-
telemetryType: TelemetryType.Metric,
|
|
1074
|
-
}).catch((err: Error) => {
|
|
1075
|
-
logger.error(err);
|
|
1076
|
-
});
|
|
1077
|
-
|
|
1078
1062
|
// save monitor log.
|
|
1079
1063
|
const monitorLog: MonitorLog = new MonitorLog();
|
|
1080
1064
|
monitorLog.monitorId = data.monitorId;
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import { JSONArray, JSONObject, JSONValue } from "../../../Types/JSON";
|
|
2
2
|
import ObjectID from "../../../Types/ObjectID";
|
|
3
|
-
import TelemetryType from "../../../Types/Telemetry/TelemetryType";
|
|
4
|
-
import GlobalCache from "../../Infrastructure/GlobalCache";
|
|
5
|
-
import TelemetryAttributeService from "../../Services/TelemetryAttributeService";
|
|
6
3
|
import CaptureSpan from "./CaptureSpan";
|
|
7
|
-
import logger from "../Logger";
|
|
8
4
|
import MetricType from "../../../Models/DatabaseModels/MetricType";
|
|
9
5
|
import MetricTypeService from "../../Services/MetricTypeService";
|
|
10
6
|
import TelemetryService from "../../../Models/DatabaseModels/TelemetryService";
|
|
@@ -127,63 +123,6 @@ export default class TelemetryUtil {
|
|
|
127
123
|
}
|
|
128
124
|
}
|
|
129
125
|
|
|
130
|
-
@CaptureSpan()
|
|
131
|
-
public static async indexAttributes(data: {
|
|
132
|
-
attributes: Array<string>;
|
|
133
|
-
projectId: ObjectID;
|
|
134
|
-
telemetryType: TelemetryType;
|
|
135
|
-
}): Promise<void> {
|
|
136
|
-
// index attributes
|
|
137
|
-
|
|
138
|
-
logger.debug("Indexing attributes");
|
|
139
|
-
logger.debug("data: " + JSON.stringify(data, null, 2));
|
|
140
|
-
|
|
141
|
-
const cacheKey: string =
|
|
142
|
-
data.projectId.toString() + "_" + data.telemetryType;
|
|
143
|
-
|
|
144
|
-
// get keys from cache
|
|
145
|
-
const cacheKeys: string[] =
|
|
146
|
-
(await GlobalCache.getStringArray("telemetryAttributesKeys", cacheKey)) ||
|
|
147
|
-
[];
|
|
148
|
-
|
|
149
|
-
let isKeysMissingInCache: boolean = false;
|
|
150
|
-
|
|
151
|
-
// check if keys are missing in cache
|
|
152
|
-
|
|
153
|
-
const attributeKeys: string[] = data.attributes;
|
|
154
|
-
|
|
155
|
-
for (const key of attributeKeys) {
|
|
156
|
-
if (!cacheKeys.includes(key)) {
|
|
157
|
-
isKeysMissingInCache = true;
|
|
158
|
-
break;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// merge keys and remove duplicates
|
|
163
|
-
if (isKeysMissingInCache) {
|
|
164
|
-
const dbKeys: string[] = await TelemetryAttributeService.fetchAttributes({
|
|
165
|
-
projectId: data.projectId,
|
|
166
|
-
telemetryType: data.telemetryType,
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
const mergedKeys: Array<string> = Array.from(
|
|
170
|
-
new Set([...dbKeys, ...attributeKeys, ...cacheKeys]),
|
|
171
|
-
);
|
|
172
|
-
|
|
173
|
-
await GlobalCache.setStringArray(
|
|
174
|
-
"telemetryAttributesKeys",
|
|
175
|
-
cacheKey,
|
|
176
|
-
mergedKeys,
|
|
177
|
-
);
|
|
178
|
-
|
|
179
|
-
await TelemetryAttributeService.refreshAttributes({
|
|
180
|
-
projectId: data.projectId,
|
|
181
|
-
telemetryType: data.telemetryType,
|
|
182
|
-
attributes: mergedKeys,
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
126
|
public static getAttributesForServiceIdAndServiceName(data: {
|
|
188
127
|
serviceId: ObjectID;
|
|
189
128
|
serviceName: string;
|