@oneuptime/common 8.0.5440 → 8.0.5466
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Models/DatabaseModels/StatusPage.ts +80 -0
- package/Models/DatabaseModels/TelemetryUsageBilling.ts +1 -1
- package/Server/API/StatusPageAPI.ts +138 -52
- package/Server/EnvironmentConfig.ts +37 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1761232578396-MigrationName.ts +29 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +2 -0
- package/Server/Services/AnalyticsDatabaseService.ts +71 -11
- package/Server/Services/OpenTelemetryIngestService.ts +1 -39
- package/Server/Services/StatusPageService.ts +117 -0
- package/Server/Services/TelemetryUsageBillingService.ts +268 -15
- package/Server/Types/Billing/MeteredPlan/TelemetryMeteredPlan.ts +5 -0
- package/Server/Utils/Telemetry/Telemetry.ts +135 -81
- package/Server/Utils/VM/VMRunner.ts +3 -4
- package/Types/Date.ts +5 -0
- package/UI/Components/LogsViewer/LogItem.tsx +12 -4
- package/UI/Components/LogsViewer/LogsViewer.tsx +131 -29
- package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +2 -2
- package/UI/Components/Table/TableRow.tsx +89 -77
- package/UI/esbuild-config.js +32 -1
- package/build/dist/Models/DatabaseModels/StatusPage.js +82 -0
- package/build/dist/Models/DatabaseModels/StatusPage.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TelemetryUsageBilling.js +1 -1
- package/build/dist/Models/DatabaseModels/TelemetryUsageBilling.js.map +1 -1
- package/build/dist/Server/API/StatusPageAPI.js +157 -74
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +15 -0
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1761232578396-MigrationName.js +16 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1761232578396-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +2 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js +55 -8
- package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
- package/build/dist/Server/Services/OpenTelemetryIngestService.js +0 -30
- package/build/dist/Server/Services/OpenTelemetryIngestService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageService.js +95 -0
- package/build/dist/Server/Services/StatusPageService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryUsageBillingService.js +211 -8
- package/build/dist/Server/Services/TelemetryUsageBillingService.js.map +1 -1
- package/build/dist/Server/Types/Billing/MeteredPlan/TelemetryMeteredPlan.js +4 -0
- package/build/dist/Server/Types/Billing/MeteredPlan/TelemetryMeteredPlan.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/Telemetry.js +84 -60
- package/build/dist/Server/Utils/Telemetry/Telemetry.js.map +1 -1
- package/build/dist/Server/Utils/VM/VMRunner.js +2 -2
- package/build/dist/Server/Utils/VM/VMRunner.js.map +1 -1
- package/build/dist/Types/Date.js +4 -0
- package/build/dist/Types/Date.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/LogItem.js +5 -3
- package/build/dist/UI/Components/LogsViewer/LogItem.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js +73 -22
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +2 -2
- package/build/dist/UI/Components/Table/TableRow.js +18 -6
- package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
- package/package.json +4 -4
|
@@ -1150,5 +1150,122 @@ export class Service extends DatabaseService<StatusPage> {
|
|
|
1150
1150
|
},
|
|
1151
1151
|
);
|
|
1152
1152
|
}
|
|
1153
|
+
|
|
1154
|
+
@CaptureSpan()
|
|
1155
|
+
public async getMonitorGroupCurrentStatuses(data: {
|
|
1156
|
+
statusPageResources: Array<StatusPageResource>;
|
|
1157
|
+
monitorStatuses: Array<MonitorStatus>;
|
|
1158
|
+
}): Promise<Dictionary<ObjectID>> {
|
|
1159
|
+
const monitorGroupCurrentStatuses: Dictionary<ObjectID> = {};
|
|
1160
|
+
|
|
1161
|
+
for (const resource of data.statusPageResources) {
|
|
1162
|
+
if (resource.monitorGroupId) {
|
|
1163
|
+
const monitorGroupResources: Array<MonitorGroupResource> =
|
|
1164
|
+
await MonitorGroupResourceService.findBy({
|
|
1165
|
+
query: {
|
|
1166
|
+
monitorGroupId: resource.monitorGroupId,
|
|
1167
|
+
},
|
|
1168
|
+
select: {
|
|
1169
|
+
monitorId: true,
|
|
1170
|
+
monitor: {
|
|
1171
|
+
currentMonitorStatusId: true,
|
|
1172
|
+
},
|
|
1173
|
+
},
|
|
1174
|
+
skip: 0,
|
|
1175
|
+
limit: LIMIT_PER_PROJECT,
|
|
1176
|
+
props: {
|
|
1177
|
+
isRoot: true,
|
|
1178
|
+
},
|
|
1179
|
+
});
|
|
1180
|
+
|
|
1181
|
+
const statuses: Array<ObjectID> = monitorGroupResources
|
|
1182
|
+
.filter((item: MonitorGroupResource) => {
|
|
1183
|
+
return (
|
|
1184
|
+
item.monitor &&
|
|
1185
|
+
item.monitor.currentMonitorStatusId &&
|
|
1186
|
+
item.monitorId
|
|
1187
|
+
);
|
|
1188
|
+
})
|
|
1189
|
+
.map((item: MonitorGroupResource) => {
|
|
1190
|
+
return item.monitor!.currentMonitorStatusId!;
|
|
1191
|
+
});
|
|
1192
|
+
|
|
1193
|
+
let worstStatus: MonitorStatus | null = null;
|
|
1194
|
+
|
|
1195
|
+
for (const statusId of statuses) {
|
|
1196
|
+
const status: MonitorStatus | undefined = data.monitorStatuses.find(
|
|
1197
|
+
(status: MonitorStatus) => {
|
|
1198
|
+
return status._id?.toString() === statusId.toString();
|
|
1199
|
+
},
|
|
1200
|
+
);
|
|
1201
|
+
|
|
1202
|
+
if (
|
|
1203
|
+
status &&
|
|
1204
|
+
(!worstStatus || status.priority! < worstStatus.priority!)
|
|
1205
|
+
) {
|
|
1206
|
+
worstStatus = status;
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
if (worstStatus && worstStatus._id) {
|
|
1211
|
+
monitorGroupCurrentStatuses[resource.monitorGroupId.toString()] =
|
|
1212
|
+
new ObjectID(worstStatus._id);
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
return monitorGroupCurrentStatuses;
|
|
1218
|
+
}
|
|
1219
|
+
|
|
1220
|
+
@CaptureSpan()
|
|
1221
|
+
public getOverallMonitorStatus(data: {
|
|
1222
|
+
statusPageResources: Array<StatusPageResource>;
|
|
1223
|
+
monitorStatuses: Array<MonitorStatus>;
|
|
1224
|
+
monitorGroupCurrentStatuses: Dictionary<ObjectID>;
|
|
1225
|
+
}): MonitorStatus | null {
|
|
1226
|
+
let currentStatus: MonitorStatus | null =
|
|
1227
|
+
data.monitorStatuses.length > 0 && data.monitorStatuses[0]
|
|
1228
|
+
? data.monitorStatuses[0]
|
|
1229
|
+
: null;
|
|
1230
|
+
|
|
1231
|
+
const dict: Dictionary<number> = {};
|
|
1232
|
+
|
|
1233
|
+
for (const resource of data.statusPageResources) {
|
|
1234
|
+
if (resource.monitor?.currentMonitorStatusId) {
|
|
1235
|
+
if (
|
|
1236
|
+
!Object.keys(dict).includes(
|
|
1237
|
+
resource.monitor?.currentMonitorStatusId.toString() || "",
|
|
1238
|
+
)
|
|
1239
|
+
) {
|
|
1240
|
+
dict[resource.monitor?.currentMonitorStatusId?.toString()] = 1;
|
|
1241
|
+
} else {
|
|
1242
|
+
dict[resource.monitor!.currentMonitorStatusId!.toString()]!++;
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
// check status of monitor groups.
|
|
1248
|
+
|
|
1249
|
+
for (const groupId in data.monitorGroupCurrentStatuses) {
|
|
1250
|
+
const statusId: ObjectID | undefined =
|
|
1251
|
+
data.monitorGroupCurrentStatuses[groupId];
|
|
1252
|
+
|
|
1253
|
+
if (statusId) {
|
|
1254
|
+
if (!Object.keys(dict).includes(statusId.toString() || "")) {
|
|
1255
|
+
dict[statusId.toString()] = 1;
|
|
1256
|
+
} else {
|
|
1257
|
+
dict[statusId.toString()]!++;
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
|
|
1262
|
+
for (const monitorStatus of data.monitorStatuses) {
|
|
1263
|
+
if (monitorStatus._id && dict[monitorStatus._id]) {
|
|
1264
|
+
currentStatus = monitorStatus;
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
return currentStatus;
|
|
1269
|
+
}
|
|
1153
1270
|
}
|
|
1154
1271
|
export default new Service();
|
|
@@ -1,16 +1,33 @@
|
|
|
1
1
|
import { MeteredPlanUtil } from "../Types/Billing/MeteredPlan/AllMeteredPlans";
|
|
2
2
|
import TelemetryMeteredPlan from "../Types/Billing/MeteredPlan/TelemetryMeteredPlan";
|
|
3
|
-
import QueryHelper from "../Types/Database/QueryHelper";
|
|
4
3
|
import DatabaseService from "./DatabaseService";
|
|
5
4
|
import SortOrder from "../../Types/BaseDatabase/SortOrder";
|
|
6
|
-
import LIMIT_MAX from "../../Types/Database/LimitMax";
|
|
5
|
+
import LIMIT_MAX, { LIMIT_INFINITY } from "../../Types/Database/LimitMax";
|
|
7
6
|
import OneUptimeDate from "../../Types/Date";
|
|
8
7
|
import Decimal from "../../Types/Decimal";
|
|
9
8
|
import BadDataException from "../../Types/Exception/BadDataException";
|
|
10
9
|
import ProductType from "../../Types/MeteredPlan/ProductType";
|
|
11
10
|
import ObjectID from "../../Types/ObjectID";
|
|
12
|
-
import Model
|
|
13
|
-
|
|
11
|
+
import Model, {
|
|
12
|
+
DEFAULT_RETENTION_IN_DAYS,
|
|
13
|
+
} from "../../Models/DatabaseModels/TelemetryUsageBilling";
|
|
14
|
+
import TelemetryServiceService from "./TelemetryServiceService";
|
|
15
|
+
import SpanService from "./SpanService";
|
|
16
|
+
import LogService from "./LogService";
|
|
17
|
+
import MetricService from "./MetricService";
|
|
18
|
+
import ExceptionInstanceService from "./ExceptionInstanceService";
|
|
19
|
+
import AnalyticsQueryHelper from "../Types/AnalyticsDatabase/QueryHelper";
|
|
20
|
+
import DiskSize from "../../Types/DiskSize";
|
|
21
|
+
import logger from "../Utils/Logger";
|
|
22
|
+
import PositiveNumber from "../../Types/PositiveNumber";
|
|
23
|
+
import TelemetryServiceModel from "../../Models/DatabaseModels/TelemetryService";
|
|
24
|
+
import {
|
|
25
|
+
AverageSpanRowSizeInBytes,
|
|
26
|
+
AverageLogRowSizeInBytes,
|
|
27
|
+
AverageMetricRowSizeInBytes,
|
|
28
|
+
AverageExceptionRowSizeInBytes,
|
|
29
|
+
IsBillingEnabled,
|
|
30
|
+
} from "../EnvironmentConfig";
|
|
14
31
|
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
15
32
|
|
|
16
33
|
export class Service extends DatabaseService<Model> {
|
|
@@ -31,9 +48,6 @@ export class Service extends DatabaseService<Model> {
|
|
|
31
48
|
projectId: data.projectId,
|
|
32
49
|
productType: data.productType,
|
|
33
50
|
isReportedToBillingProvider: false,
|
|
34
|
-
createdAt: QueryHelper.lessThan(
|
|
35
|
-
OneUptimeDate.addRemoveDays(OneUptimeDate.getCurrentDate(), -1),
|
|
36
|
-
), // we need to get everything that's not today.
|
|
37
51
|
},
|
|
38
52
|
skip: 0,
|
|
39
53
|
limit: LIMIT_MAX, /// because a project can have MANY telemetry services.
|
|
@@ -47,6 +61,203 @@ export class Service extends DatabaseService<Model> {
|
|
|
47
61
|
});
|
|
48
62
|
}
|
|
49
63
|
|
|
64
|
+
@CaptureSpan()
|
|
65
|
+
public async stageTelemetryUsageForProject(data: {
|
|
66
|
+
projectId: ObjectID;
|
|
67
|
+
productType: ProductType;
|
|
68
|
+
usageDate?: Date;
|
|
69
|
+
}): Promise<void> {
|
|
70
|
+
if (!IsBillingEnabled) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const usageDate: Date = data.usageDate
|
|
75
|
+
? OneUptimeDate.fromString(data.usageDate)
|
|
76
|
+
: OneUptimeDate.addRemoveDays(OneUptimeDate.getCurrentDate(), -1);
|
|
77
|
+
|
|
78
|
+
const averageRowSizeInBytes: number = this.getAverageRowSizeForProduct(
|
|
79
|
+
data.productType,
|
|
80
|
+
);
|
|
81
|
+
const averageExceptionRowSizeInBytes: number =
|
|
82
|
+
this.getAverageExceptionRowSize();
|
|
83
|
+
|
|
84
|
+
if (data.productType !== ProductType.Traces && averageRowSizeInBytes <= 0) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (
|
|
89
|
+
data.productType === ProductType.Traces &&
|
|
90
|
+
averageRowSizeInBytes <= 0 &&
|
|
91
|
+
averageExceptionRowSizeInBytes <= 0
|
|
92
|
+
) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const usageDayString: string = OneUptimeDate.getDateString(usageDate);
|
|
97
|
+
const startOfDay: Date = OneUptimeDate.getStartOfDay(usageDate);
|
|
98
|
+
const endOfDay: Date = OneUptimeDate.getEndOfDay(usageDate);
|
|
99
|
+
|
|
100
|
+
const telemetryServices: Array<TelemetryServiceModel> =
|
|
101
|
+
await TelemetryServiceService.findBy({
|
|
102
|
+
query: {
|
|
103
|
+
projectId: data.projectId,
|
|
104
|
+
},
|
|
105
|
+
select: {
|
|
106
|
+
_id: true,
|
|
107
|
+
retainTelemetryDataForDays: true,
|
|
108
|
+
},
|
|
109
|
+
skip: 0,
|
|
110
|
+
limit: LIMIT_MAX,
|
|
111
|
+
props: {
|
|
112
|
+
isRoot: true,
|
|
113
|
+
},
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
if (!telemetryServices || telemetryServices.length === 0) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
for (const telemetryService of telemetryServices) {
|
|
121
|
+
if (!telemetryService?.id) {
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const existingEntry: Model | null = await this.findOneBy({
|
|
126
|
+
query: {
|
|
127
|
+
projectId: data.projectId,
|
|
128
|
+
productType: data.productType,
|
|
129
|
+
telemetryServiceId: telemetryService.id,
|
|
130
|
+
day: usageDayString,
|
|
131
|
+
},
|
|
132
|
+
select: {
|
|
133
|
+
_id: true,
|
|
134
|
+
},
|
|
135
|
+
props: {
|
|
136
|
+
isRoot: true,
|
|
137
|
+
},
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
if (existingEntry) {
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
let estimatedBytes: number = 0;
|
|
145
|
+
|
|
146
|
+
try {
|
|
147
|
+
if (data.productType === ProductType.Traces) {
|
|
148
|
+
const spanCount: PositiveNumber = await SpanService.countBy({
|
|
149
|
+
query: {
|
|
150
|
+
projectId: data.projectId,
|
|
151
|
+
serviceId: telemetryService.id,
|
|
152
|
+
startTime: AnalyticsQueryHelper.inBetween(startOfDay, endOfDay),
|
|
153
|
+
},
|
|
154
|
+
skip: 0,
|
|
155
|
+
limit: LIMIT_INFINITY,
|
|
156
|
+
props: {
|
|
157
|
+
isRoot: true,
|
|
158
|
+
},
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
const exceptionCount: PositiveNumber =
|
|
162
|
+
await ExceptionInstanceService.countBy({
|
|
163
|
+
query: {
|
|
164
|
+
projectId: data.projectId,
|
|
165
|
+
serviceId: telemetryService.id,
|
|
166
|
+
time: AnalyticsQueryHelper.inBetween(startOfDay, endOfDay),
|
|
167
|
+
},
|
|
168
|
+
skip: 0,
|
|
169
|
+
limit: LIMIT_INFINITY,
|
|
170
|
+
props: {
|
|
171
|
+
isRoot: true,
|
|
172
|
+
},
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
const totalSpanCount: number = spanCount.toNumber();
|
|
176
|
+
const totalExceptionCount: number = exceptionCount.toNumber();
|
|
177
|
+
|
|
178
|
+
if (totalSpanCount <= 0 && totalExceptionCount <= 0) {
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
estimatedBytes =
|
|
183
|
+
totalSpanCount * averageRowSizeInBytes +
|
|
184
|
+
totalExceptionCount * averageExceptionRowSizeInBytes;
|
|
185
|
+
} else if (data.productType === ProductType.Logs) {
|
|
186
|
+
const count: PositiveNumber = await LogService.countBy({
|
|
187
|
+
query: {
|
|
188
|
+
projectId: data.projectId,
|
|
189
|
+
serviceId: telemetryService.id,
|
|
190
|
+
time: AnalyticsQueryHelper.inBetween(startOfDay, endOfDay),
|
|
191
|
+
},
|
|
192
|
+
skip: 0,
|
|
193
|
+
limit: LIMIT_INFINITY,
|
|
194
|
+
props: {
|
|
195
|
+
isRoot: true,
|
|
196
|
+
},
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
const totalRowCount: number = count.toNumber();
|
|
200
|
+
|
|
201
|
+
if (totalRowCount <= 0) {
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
estimatedBytes = totalRowCount * averageRowSizeInBytes;
|
|
206
|
+
} else if (data.productType === ProductType.Metrics) {
|
|
207
|
+
const count: PositiveNumber = await MetricService.countBy({
|
|
208
|
+
query: {
|
|
209
|
+
projectId: data.projectId,
|
|
210
|
+
serviceId: telemetryService.id,
|
|
211
|
+
time: AnalyticsQueryHelper.inBetween(startOfDay, endOfDay),
|
|
212
|
+
},
|
|
213
|
+
skip: 0,
|
|
214
|
+
limit: LIMIT_INFINITY,
|
|
215
|
+
props: {
|
|
216
|
+
isRoot: true,
|
|
217
|
+
},
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
const totalRowCount: number = count.toNumber();
|
|
221
|
+
|
|
222
|
+
if (totalRowCount <= 0) {
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
estimatedBytes = totalRowCount * averageRowSizeInBytes;
|
|
227
|
+
}
|
|
228
|
+
} catch (error) {
|
|
229
|
+
logger.error(
|
|
230
|
+
`Failed to compute telemetry usage for service ${telemetryService.id?.toString()}:`,
|
|
231
|
+
);
|
|
232
|
+
logger.error(error as Error);
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
if (estimatedBytes <= 0) {
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
const estimatedGigabytes: number = DiskSize.byteSizeToGB(estimatedBytes);
|
|
241
|
+
|
|
242
|
+
if (!Number.isFinite(estimatedGigabytes) || estimatedGigabytes <= 0) {
|
|
243
|
+
continue;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
const dataRetentionInDays: number =
|
|
247
|
+
telemetryService.retainTelemetryDataForDays ||
|
|
248
|
+
DEFAULT_RETENTION_IN_DAYS;
|
|
249
|
+
|
|
250
|
+
await this.updateUsageBilling({
|
|
251
|
+
projectId: data.projectId,
|
|
252
|
+
productType: data.productType,
|
|
253
|
+
telemetryServiceId: telemetryService.id,
|
|
254
|
+
dataIngestedInGB: estimatedGigabytes,
|
|
255
|
+
retentionInDays: dataRetentionInDays,
|
|
256
|
+
usageDate: usageDate,
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
50
261
|
@CaptureSpan()
|
|
51
262
|
public async updateUsageBilling(data: {
|
|
52
263
|
projectId: ObjectID;
|
|
@@ -54,6 +265,7 @@ export class Service extends DatabaseService<Model> {
|
|
|
54
265
|
telemetryServiceId: ObjectID;
|
|
55
266
|
dataIngestedInGB: number;
|
|
56
267
|
retentionInDays: number;
|
|
268
|
+
usageDate?: Date;
|
|
57
269
|
}): Promise<void> {
|
|
58
270
|
if (
|
|
59
271
|
data.productType !== ProductType.Traces &&
|
|
@@ -70,6 +282,12 @@ export class Service extends DatabaseService<Model> {
|
|
|
70
282
|
data.productType,
|
|
71
283
|
) as TelemetryMeteredPlan;
|
|
72
284
|
|
|
285
|
+
const usageDate: Date = data.usageDate
|
|
286
|
+
? OneUptimeDate.fromString(data.usageDate)
|
|
287
|
+
: OneUptimeDate.getCurrentDate();
|
|
288
|
+
|
|
289
|
+
const usageDayString: string = OneUptimeDate.getDateString(usageDate);
|
|
290
|
+
|
|
73
291
|
const totalCostOfThisOperationInUSD: number =
|
|
74
292
|
serverMeteredPlan.getTotalCostInUSD({
|
|
75
293
|
dataIngestedInGB: data.dataIngestedInGB,
|
|
@@ -82,10 +300,7 @@ export class Service extends DatabaseService<Model> {
|
|
|
82
300
|
productType: data.productType,
|
|
83
301
|
telemetryServiceId: data.telemetryServiceId,
|
|
84
302
|
isReportedToBillingProvider: false,
|
|
85
|
-
|
|
86
|
-
OneUptimeDate.addRemoveDays(OneUptimeDate.getCurrentDate(), -1),
|
|
87
|
-
OneUptimeDate.getCurrentDate(),
|
|
88
|
-
),
|
|
303
|
+
day: usageDayString,
|
|
89
304
|
},
|
|
90
305
|
select: {
|
|
91
306
|
_id: true,
|
|
@@ -135,11 +350,9 @@ export class Service extends DatabaseService<Model> {
|
|
|
135
350
|
usageBilling.telemetryServiceId = data.telemetryServiceId;
|
|
136
351
|
usageBilling.retainTelemetryDataForDays = data.retentionInDays;
|
|
137
352
|
usageBilling.isReportedToBillingProvider = false;
|
|
138
|
-
usageBilling.createdAt =
|
|
353
|
+
usageBilling.createdAt = usageDate;
|
|
139
354
|
|
|
140
|
-
usageBilling.day =
|
|
141
|
-
OneUptimeDate.getCurrentDate(),
|
|
142
|
-
);
|
|
355
|
+
usageBilling.day = usageDayString;
|
|
143
356
|
|
|
144
357
|
usageBilling.totalCostInUSD = new Decimal(totalCostOfThisOperationInUSD);
|
|
145
358
|
|
|
@@ -151,6 +364,46 @@ export class Service extends DatabaseService<Model> {
|
|
|
151
364
|
});
|
|
152
365
|
}
|
|
153
366
|
}
|
|
367
|
+
|
|
368
|
+
private getAverageRowSizeForProduct(productType: ProductType): number {
|
|
369
|
+
const fallbackSize: number = 1024;
|
|
370
|
+
|
|
371
|
+
// Narrow to telemetry product types before indexing to satisfy TypeScript
|
|
372
|
+
if (
|
|
373
|
+
productType !== ProductType.Traces &&
|
|
374
|
+
productType !== ProductType.Logs &&
|
|
375
|
+
productType !== ProductType.Metrics
|
|
376
|
+
) {
|
|
377
|
+
return fallbackSize;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
const value: number =
|
|
381
|
+
{
|
|
382
|
+
[ProductType.Traces]: AverageSpanRowSizeInBytes,
|
|
383
|
+
[ProductType.Logs]: AverageLogRowSizeInBytes,
|
|
384
|
+
[ProductType.Metrics]: AverageMetricRowSizeInBytes,
|
|
385
|
+
}[productType] ?? fallbackSize;
|
|
386
|
+
|
|
387
|
+
if (!Number.isFinite(value) || value <= 0) {
|
|
388
|
+
return fallbackSize;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
return value;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
private getAverageExceptionRowSize(): number {
|
|
395
|
+
const fallbackSize: number = 1024;
|
|
396
|
+
|
|
397
|
+
if (!Number.isFinite(AverageExceptionRowSizeInBytes)) {
|
|
398
|
+
return fallbackSize;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
if (AverageExceptionRowSizeInBytes <= 0) {
|
|
402
|
+
return fallbackSize;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
return AverageExceptionRowSizeInBytes;
|
|
406
|
+
}
|
|
154
407
|
}
|
|
155
408
|
|
|
156
409
|
export default new Service();
|
|
@@ -56,6 +56,11 @@ export default class TelemetryMeteredPlan extends ServerMeteredPlan {
|
|
|
56
56
|
): Promise<void> {
|
|
57
57
|
// get all unreported logs
|
|
58
58
|
|
|
59
|
+
await TelemetryUsageBillingService.stageTelemetryUsageForProject({
|
|
60
|
+
projectId: projectId,
|
|
61
|
+
productType: this.productType,
|
|
62
|
+
});
|
|
63
|
+
|
|
59
64
|
const usageBillings: Array<TelemetryUsageBilling> =
|
|
60
65
|
await TelemetryUsageBillingService.getUnreportedUsageBilling({
|
|
61
66
|
projectId: projectId,
|