@oneuptime/common 7.0.3225 → 7.0.3233

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 (105) hide show
  1. package/Models/AnalyticsModels/Index.ts +0 -2
  2. package/Models/AnalyticsModels/Metric.ts +39 -1
  3. package/Models/DatabaseModels/Alert.ts +0 -1
  4. package/Models/DatabaseModels/Incident.ts +0 -1
  5. package/Models/DatabaseModels/IncidentStateTimeline.ts +0 -1
  6. package/Models/DatabaseModels/MonitorStatusTimeline.ts +0 -1
  7. package/Server/API/BaseAnalyticsAPI.ts +11 -0
  8. package/Server/Infrastructure/Postgres/SchemaMigrations/1731433043136-MigrationName.ts +17 -0
  9. package/Server/Infrastructure/Postgres/SchemaMigrations/1731433309124-MigrationName.ts +17 -0
  10. package/Server/Infrastructure/Postgres/SchemaMigrations/1731435267537-MigrationName.ts +17 -0
  11. package/Server/Infrastructure/Postgres/SchemaMigrations/1731435514287-MigrationName.ts +17 -0
  12. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +8 -0
  13. package/Server/Services/AnalyticsDatabaseService.ts +17 -7
  14. package/Server/Services/DatabaseService.ts +11 -3
  15. package/Server/Services/Index.ts +0 -2
  16. package/Server/Types/AnalyticsDatabase/AggregateBy.ts +4 -4
  17. package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +18 -4
  18. package/Server/Utils/Browser.ts +194 -0
  19. package/Server/Utils/Monitor/Criteria/CompareCriteria.ts +3 -0
  20. package/Server/Utils/Monitor/Criteria/EvaluateOverTime.ts +21 -21
  21. package/Server/Utils/Monitor/MonitorIncident.ts +0 -2
  22. package/Server/Utils/Monitor/MonitorResource.ts +186 -127
  23. package/Server/Utils/Telemetry/Telemetry.ts +154 -0
  24. package/Types/BaseDatabase/AggregateBy.ts +2 -0
  25. package/Types/BaseDatabase/AggregatedModel.ts +3 -0
  26. package/Types/Html.ts +11 -0
  27. package/Types/Metrics/MetricsQuery.ts +8 -0
  28. package/Types/Monitor/CriteriaFilter.ts +0 -36
  29. package/Types/Monitor/MonitorMetricType.ts +11 -0
  30. package/Types/Monitor/MonitorType.ts +18 -0
  31. package/UI/Components/Charts/ChartGroup/ChartGroup.tsx +1 -1
  32. package/UI/Components/Charts/ChartLibrary/LineChart/LineChart.tsx +2 -2
  33. package/UI/Components/Charts/Line/LineChart.tsx +2 -2
  34. package/UI/Components/ModelTable/TableView.tsx +1 -0
  35. package/UI/Components/MoreMenu/MoreMenuItem.tsx +2 -0
  36. package/Utils/Monitor/MonitorMetricType.ts +142 -0
  37. package/build/dist/Models/AnalyticsModels/Index.js +0 -2
  38. package/build/dist/Models/AnalyticsModels/Index.js.map +1 -1
  39. package/build/dist/Models/AnalyticsModels/Metric.js +36 -1
  40. package/build/dist/Models/AnalyticsModels/Metric.js.map +1 -1
  41. package/build/dist/Models/DatabaseModels/Alert.js +0 -1
  42. package/build/dist/Models/DatabaseModels/Alert.js.map +1 -1
  43. package/build/dist/Models/DatabaseModels/Incident.js +0 -1
  44. package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
  45. package/build/dist/Models/DatabaseModels/IncidentStateTimeline.js +0 -1
  46. package/build/dist/Models/DatabaseModels/IncidentStateTimeline.js.map +1 -1
  47. package/build/dist/Models/DatabaseModels/MonitorStatusTimeline.js +0 -1
  48. package/build/dist/Models/DatabaseModels/MonitorStatusTimeline.js.map +1 -1
  49. package/build/dist/Server/API/BaseAnalyticsAPI.js +7 -0
  50. package/build/dist/Server/API/BaseAnalyticsAPI.js.map +1 -1
  51. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1731433043136-MigrationName.js +12 -0
  52. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1731433043136-MigrationName.js.map +1 -0
  53. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1731433309124-MigrationName.js +12 -0
  54. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1731433309124-MigrationName.js.map +1 -0
  55. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1731435267537-MigrationName.js +12 -0
  56. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1731435267537-MigrationName.js.map +1 -0
  57. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1731435514287-MigrationName.js +12 -0
  58. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1731435514287-MigrationName.js.map +1 -0
  59. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +8 -0
  60. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  61. package/build/dist/Server/Services/AnalyticsDatabaseService.js +7 -0
  62. package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
  63. package/build/dist/Server/Services/DatabaseService.js +6 -1
  64. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  65. package/build/dist/Server/Services/Index.js +0 -2
  66. package/build/dist/Server/Services/Index.js.map +1 -1
  67. package/build/dist/Server/Types/AnalyticsDatabase/AggregateBy.js +4 -4
  68. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +13 -4
  69. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
  70. package/build/dist/Server/Utils/Browser.js +128 -0
  71. package/build/dist/Server/Utils/Browser.js.map +1 -0
  72. package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js +3 -0
  73. package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js.map +1 -1
  74. package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js +9 -8
  75. package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js.map +1 -1
  76. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +0 -1
  77. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
  78. package/build/dist/Server/Utils/Monitor/MonitorResource.js +164 -98
  79. package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
  80. package/build/dist/Server/Utils/Telemetry/Telemetry.js +100 -0
  81. package/build/dist/Server/Utils/Telemetry/Telemetry.js.map +1 -0
  82. package/build/dist/Types/Html.js +8 -0
  83. package/build/dist/Types/Html.js.map +1 -1
  84. package/build/dist/Types/Monitor/CriteriaFilter.js +0 -29
  85. package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
  86. package/build/dist/Types/Monitor/MonitorMetricType.js +12 -0
  87. package/build/dist/Types/Monitor/MonitorMetricType.js.map +1 -0
  88. package/build/dist/Types/Monitor/MonitorType.js +14 -0
  89. package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
  90. package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js +1 -1
  91. package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js +1 -1
  92. package/build/dist/UI/Components/Charts/Line/LineChart.js +1 -1
  93. package/build/dist/UI/Components/ModelTable/TableView.js +1 -1
  94. package/build/dist/UI/Components/ModelTable/TableView.js.map +1 -1
  95. package/build/dist/UI/Components/MoreMenu/MoreMenuItem.js +1 -1
  96. package/build/dist/UI/Components/MoreMenu/MoreMenuItem.js.map +1 -1
  97. package/build/dist/Utils/Monitor/MonitorMetricType.js +118 -0
  98. package/build/dist/Utils/Monitor/MonitorMetricType.js.map +1 -0
  99. package/package.json +3 -2
  100. package/Models/AnalyticsModels/MonitorMetricsByMinute.ts +0 -177
  101. package/Server/Services/MonitorMetricsByMinuteService.ts +0 -14
  102. package/build/dist/Models/AnalyticsModels/MonitorMetricsByMinute.js +0 -149
  103. package/build/dist/Models/AnalyticsModels/MonitorMetricsByMinute.js.map +0 -1
  104. package/build/dist/Server/Services/MonitorMetricsByMinuteService.js +0 -12
  105. package/build/dist/Server/Services/MonitorMetricsByMinuteService.js.map +0 -1
@@ -1,7 +1,6 @@
1
1
  import AnalyticsBaseModel from "./AnalyticsBaseModel/AnalyticsBaseModel";
2
2
  import Log from "./Log";
3
3
  import Metric from "./Metric";
4
- import MonitorMetricsByMinute from "./MonitorMetricsByMinute";
5
4
  import Span from "./Span";
6
5
  import TelemetryAttribute from "./TelemetryAttribute";
7
6
  import ExceptionInstance from "./ExceptionInstance";
@@ -10,7 +9,6 @@ const AnalyticsModels: Array<{ new (): AnalyticsBaseModel }> = [
10
9
  Log,
11
10
  Span,
12
11
  Metric,
13
- MonitorMetricsByMinute,
14
12
  TelemetryAttribute,
15
13
  ExceptionInstance,
16
14
  ];
@@ -19,6 +19,11 @@ export enum MetricPointType {
19
19
  ExponentialHistogram = "ExponentialHistogram",
20
20
  }
21
21
 
22
+ export enum ServiceType {
23
+ OpenTelemetry = "OpenTelemetry",
24
+ Monitor = "Monitor",
25
+ }
26
+
22
27
  export default class Metric extends AnalyticsBaseModel {
23
28
  public constructor() {
24
29
  super({
@@ -78,10 +83,11 @@ export default class Metric extends AnalyticsBaseModel {
78
83
  },
79
84
  }),
80
85
 
86
+ // this can also be the monitor id or the telemetry service id.
81
87
  new AnalyticsTableColumn({
82
88
  key: "serviceId",
83
89
  title: "Service ID",
84
- description: "ID of the Service which created the log",
90
+ description: "ID of the Service which created the Metric",
85
91
  required: true,
86
92
  type: TableColumnType.ObjectID,
87
93
  accessControl: {
@@ -101,6 +107,30 @@ export default class Metric extends AnalyticsBaseModel {
101
107
  },
102
108
  }),
103
109
 
110
+ // this can also be the monitor id or the telemetry service id.
111
+ new AnalyticsTableColumn({
112
+ key: "serviceType",
113
+ title: "Service Type",
114
+ description: "Type of the service that this telemetry belongs to",
115
+ required: false,
116
+ type: TableColumnType.Text,
117
+ accessControl: {
118
+ read: [
119
+ Permission.ProjectOwner,
120
+ Permission.ProjectAdmin,
121
+ Permission.ProjectMember,
122
+ Permission.ReadTelemetryServiceLog,
123
+ ],
124
+ create: [
125
+ Permission.ProjectOwner,
126
+ Permission.ProjectAdmin,
127
+ Permission.ProjectMember,
128
+ Permission.CreateTelemetryServiceLog,
129
+ ],
130
+ update: [],
131
+ },
132
+ }),
133
+
104
134
  // add name and description
105
135
 
106
136
  new AnalyticsTableColumn({
@@ -539,6 +569,10 @@ export default class Metric extends AnalyticsBaseModel {
539
569
  return this.getColumnValue("serviceId") as ObjectID | undefined;
540
570
  }
541
571
 
572
+ public get serviceType(): ServiceType | undefined {
573
+ return this.getColumnValue("serviceType") as ServiceType | undefined;
574
+ }
575
+
542
576
  public get name(): string | undefined {
543
577
  return this.getColumnValue("name") as string | undefined;
544
578
  }
@@ -595,6 +629,10 @@ export default class Metric extends AnalyticsBaseModel {
595
629
  this.setColumnValue("serviceId", v);
596
630
  }
597
631
 
632
+ public set serviceType(v: ServiceType | undefined) {
633
+ this.setColumnValue("serviceType", v);
634
+ }
635
+
598
636
  public get time(): Date | undefined {
599
637
  return this.getColumnValue("time") as Date | undefined;
600
638
  }
@@ -801,7 +801,6 @@ export default class Alert extends BaseModel {
801
801
  ],
802
802
  update: [],
803
803
  })
804
- @Index()
805
804
  @TableColumn({
806
805
  type: TableColumnType.Markdown,
807
806
  required: false,
@@ -855,7 +855,6 @@ export default class Incident extends BaseModel {
855
855
  ],
856
856
  update: [],
857
857
  })
858
- @Index()
859
858
  @TableColumn({
860
859
  type: TableColumnType.Markdown,
861
860
  required: false,
@@ -507,7 +507,6 @@ export default class IncidentStateTimeline extends BaseModel {
507
507
  ],
508
508
  update: [],
509
509
  })
510
- @Index()
511
510
  @TableColumn({
512
511
  type: TableColumnType.Markdown,
513
512
  required: false,
@@ -455,7 +455,6 @@ export default class MonitorStatusTimeline extends BaseModel {
455
455
  ],
456
456
  update: [],
457
457
  })
458
- @Index()
459
458
  @TableColumn({
460
459
  type: TableColumnType.Markdown,
461
460
  required: false,
@@ -291,6 +291,17 @@ export default class BaseAnalyticsAPI<
291
291
  ) as any;
292
292
  }
293
293
 
294
+ let groupBy: GroupBy<AnalyticsDataModel> | null =
295
+ req.body["groupBy"] || null;
296
+
297
+ if (groupBy && Object.keys(groupBy).length > 0) {
298
+ groupBy = JSONFunctions.deserialize(groupBy as JSONObject) as any;
299
+ }
300
+
301
+ if (groupBy && Object.keys(groupBy).length === 0) {
302
+ groupBy = null;
303
+ }
304
+
294
305
  if (!aggregateBy) {
295
306
  throw new BadRequestException("AggregateBy is required");
296
307
  }
@@ -0,0 +1,17 @@
1
+ import { MigrationInterface, QueryRunner } from "typeorm";
2
+
3
+ export class MigrationName1731433043136 implements MigrationInterface {
4
+ public name = "MigrationName1731433043136";
5
+
6
+ public async up(queryRunner: QueryRunner): Promise<void> {
7
+ await queryRunner.query(
8
+ `DROP INDEX "public"."IDX_5218e92f700d91afe6a8db79cb"`,
9
+ );
10
+ }
11
+
12
+ public async down(queryRunner: QueryRunner): Promise<void> {
13
+ await queryRunner.query(
14
+ `CREATE INDEX "IDX_5218e92f700d91afe6a8db79cb" ON "Incident" ("rootCause") `,
15
+ );
16
+ }
17
+ }
@@ -0,0 +1,17 @@
1
+ import { MigrationInterface, QueryRunner } from "typeorm";
2
+
3
+ export class MigrationName1731433309124 implements MigrationInterface {
4
+ public name = "MigrationName1731433309124";
5
+
6
+ public async up(queryRunner: QueryRunner): Promise<void> {
7
+ await queryRunner.query(
8
+ `DROP INDEX "public"."IDX_fc40ea6a9ad55f29bca4f4a15d"`,
9
+ );
10
+ }
11
+
12
+ public async down(queryRunner: QueryRunner): Promise<void> {
13
+ await queryRunner.query(
14
+ `CREATE INDEX "IDX_fc40ea6a9ad55f29bca4f4a15d" ON "Alert" ("rootCause") `,
15
+ );
16
+ }
17
+ }
@@ -0,0 +1,17 @@
1
+ import { MigrationInterface, QueryRunner } from "typeorm";
2
+
3
+ export class MigrationName1731435267537 implements MigrationInterface {
4
+ public name = "MigrationName1731435267537";
5
+
6
+ public async up(queryRunner: QueryRunner): Promise<void> {
7
+ await queryRunner.query(
8
+ `DROP INDEX "public"."IDX_01ac1d1ef9e72aeb6dac6575dd"`,
9
+ );
10
+ }
11
+
12
+ public async down(queryRunner: QueryRunner): Promise<void> {
13
+ await queryRunner.query(
14
+ `CREATE INDEX "IDX_01ac1d1ef9e72aeb6dac6575dd" ON "MonitorStatusTimeline" ("rootCause") `,
15
+ );
16
+ }
17
+ }
@@ -0,0 +1,17 @@
1
+ import { MigrationInterface, QueryRunner } from "typeorm";
2
+
3
+ export class MigrationName1731435514287 implements MigrationInterface {
4
+ public name = "MigrationName1731435514287";
5
+
6
+ public async up(queryRunner: QueryRunner): Promise<void> {
7
+ await queryRunner.query(
8
+ `DROP INDEX "public"."IDX_7db6b1a8fbbc9eb44c2e7f5047"`,
9
+ );
10
+ }
11
+
12
+ public async down(queryRunner: QueryRunner): Promise<void> {
13
+ await queryRunner.query(
14
+ `CREATE INDEX "IDX_7db6b1a8fbbc9eb44c2e7f5047" ON "IncidentStateTimeline" ("rootCause") `,
15
+ );
16
+ }
17
+ }
@@ -78,6 +78,10 @@ import { MigrationName1729682875503 } from "./1729682875503-MigrationName";
78
78
  import { MigrationName1730117995642 } from "./1730117995642-MigrationName";
79
79
  import { MigrationName1730209089495 } from "./1730209089495-MigrationName";
80
80
  import { MigrationName1730223198692 } from "./1730223198692-MigrationName";
81
+ import { MigrationName1731433043136 } from "./1731433043136-MigrationName";
82
+ import { MigrationName1731433309124 } from "./1731433309124-MigrationName";
83
+ import { MigrationName1731435267537 } from "./1731435267537-MigrationName";
84
+ import { MigrationName1731435514287 } from "./1731435514287-MigrationName";
81
85
 
82
86
  export default [
83
87
  InitialMigration,
@@ -160,4 +164,8 @@ export default [
160
164
  MigrationName1730117995642,
161
165
  MigrationName1730209089495,
162
166
  MigrationName1730223198692,
167
+ MigrationName1731433043136,
168
+ MigrationName1731433309124,
169
+ MigrationName1731435267537,
170
+ MigrationName1731435514287,
163
171
  ];
@@ -259,6 +259,11 @@ export default class AnalyticsDatabaseService<
259
259
 
260
260
  // convert date column from string to date.
261
261
 
262
+ const groupByColumnName: keyof TBaseModel | undefined =
263
+ aggregateBy.groupBy && Object.keys(aggregateBy.groupBy).length > 0
264
+ ? (Object.keys(aggregateBy.groupBy)[0] as keyof TBaseModel)
265
+ : undefined;
266
+
262
267
  for (const item of items) {
263
268
  if (
264
269
  !(item as JSONObject)[
@@ -277,6 +282,9 @@ export default class AnalyticsDatabaseService<
277
282
  value: (item as JSONObject)[
278
283
  aggregateBy.aggregateColumnName as string
279
284
  ] as number,
285
+ [groupByColumnName as string]: (item as JSONObject)[
286
+ groupByColumnName as string
287
+ ],
280
288
  };
281
289
 
282
290
  aggregatedItems.push(aggregatedModel);
@@ -457,7 +465,7 @@ export default class AnalyticsDatabaseService<
457
465
  count()
458
466
  FROM ${databaseName}.${this.model.tableName}
459
467
  WHERE TRUE `.append(whereStatement);
460
-
468
+
461
469
 
462
470
  if (countBy.groupBy && Object.keys(countBy.groupBy).length > 0) {
463
471
  statement.append(
@@ -519,9 +527,11 @@ export default class AnalyticsDatabaseService<
519
527
  statement.append(SQL` FROM ${databaseName}.${this.model.tableName}`);
520
528
  statement.append(SQL` WHERE TRUE `).append(whereStatement);
521
529
 
522
-
523
- statement.append(SQL` GROUP BY `).append(`${aggregateBy.aggregationTimestampColumnName.toString()}`);
524
-
530
+ statement.append(SQL` GROUP BY `).append(`${aggregateBy.aggregationTimestampColumnName.toString()}`);
531
+
532
+ if (aggregateBy.groupBy && Object.keys(aggregateBy.groupBy).length > 0) {
533
+ statement.append(SQL` , `).append(this.statementGenerator.toGroupByStatement(aggregateBy.groupBy));
534
+ }
525
535
 
526
536
  statement.append(SQL` ORDER BY `).append(sortStatement);
527
537
 
@@ -538,7 +548,7 @@ export default class AnalyticsDatabaseService<
538
548
  }}
539
549
  `);
540
550
 
541
-
551
+
542
552
 
543
553
  logger.debug(`${this.model.tableName} Aggregate Statement`);
544
554
  logger.debug(statement);
@@ -604,7 +614,7 @@ export default class AnalyticsDatabaseService<
604
614
  }}
605
615
  `);
606
616
 
607
-
617
+
608
618
 
609
619
  logger.debug(`${this.model.tableName} Find Statement`);
610
620
  logger.debug(statement);
@@ -626,7 +636,7 @@ export default class AnalyticsDatabaseService<
626
636
  const statement: Statement = SQL`
627
637
  ALTER TABLE ${databaseName}.${this.model.tableName}
628
638
  DELETE WHERE TRUE `.append(whereStatement);
629
-
639
+
630
640
 
631
641
  logger.debug(`${this.model.tableName} Delete Statement`);
632
642
  logger.debug(statement);
@@ -437,10 +437,10 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
437
437
  const columns: Columns = this.model.getTableColumns();
438
438
 
439
439
  for (const columnName of columns.columns) {
440
- if (this.model.isEntityColumn(columnName)) {
441
- const tableColumnMetadata: TableColumnMetadata =
442
- this.model.getTableColumnMetadata(columnName);
440
+ const tableColumnMetadata: TableColumnMetadata =
441
+ this.model.getTableColumnMetadata(columnName);
443
442
 
443
+ if (this.model.isEntityColumn(columnName)) {
444
444
  const columnValue: JSONValue = (data as any)[columnName];
445
445
 
446
446
  if (
@@ -507,6 +507,14 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
507
507
  (data as any)[columnName] = columnValue.toString();
508
508
  }
509
509
  }
510
+
511
+ // if its a Date column and if date is null then set it to null.
512
+ if (
513
+ (data as any)[columnName] === "" &&
514
+ tableColumnMetadata.type === TableColumnType.Date
515
+ ) {
516
+ (data as any)[columnName] = null;
517
+ }
510
518
  }
511
519
 
512
520
  // check createByUserId.
@@ -41,7 +41,6 @@ import MonitorGroupOwnerTeamService from "./MonitorGroupOwnerTeamService";
41
41
  import MonitorGroupOwnerUserService from "./MonitorGroupOwnerUserService";
42
42
  import MonitorGroupResourceService from "./MonitorGroupResourceService";
43
43
  import MonitorGroupService from "./MonitorGroupService";
44
- import MonitorMetricsByMinuteService from "./MonitorMetricsByMinuteService";
45
44
  import MonitorOwnerTeamService from "./MonitorOwnerTeamService";
46
45
  import MonitorOwnerUserService from "./MonitorOwnerUserService";
47
46
  import MonitorProbeService from "./MonitorProbeService";
@@ -316,7 +315,6 @@ export const AnalyticsServices: Array<
316
315
  LogService,
317
316
  SpanService,
318
317
  MetricService,
319
- MonitorMetricsByMinuteService,
320
318
  TelemetryAttributeService,
321
319
  ExceptionInstanceService,
322
320
  ];
@@ -18,16 +18,16 @@ export class AggregateUtil {
18
18
  if (diff <= 1000 * 60 * 60 * 3) {
19
19
  // if less than 3 hours, then get minute precision
20
20
  return AggregationInterval.Minute;
21
- } else if (diff <= 1000 * 60 * 60 * 24 * 3) {
21
+ } else if (diff <= 1000 * 60 * 60 * 24 * 7) {
22
22
  // 3 days
23
23
  return AggregationInterval.Hour;
24
- } else if (diff <= 1000 * 60 * 60 * 24 * 7 * 3) {
24
+ } else if (diff <= 1000 * 60 * 60 * 24 * 7 * 6) {
25
25
  // 3 weeks
26
26
  return AggregationInterval.Day;
27
- } else if (diff <= 1000 * 60 * 60 * 24 * 30 * 3) {
27
+ } else if (diff <= 1000 * 60 * 60 * 24 * 30 * 6) {
28
28
  // 3 months
29
29
  return AggregationInterval.Week;
30
- } else if (diff <= 1000 * 60 * 60 * 24 * 365 * 3) {
30
+ } else if (diff <= 1000 * 60 * 60 * 24 * 365 * 6) {
31
31
  // 3 years
32
32
  return AggregationInterval.Month;
33
33
  }
@@ -548,11 +548,25 @@ export default class StatementGenerator<TBaseModel extends AnalyticsBaseModel> {
548
548
  `${aggregationMethod}(${aggregateBy.aggregateColumnName.toString()}) as ${aggregateBy.aggregateColumnName.toString()}, date_trunc('${aggregationInterval.toLowerCase()}', toStartOfInterval(${aggregateBy.aggregationTimestampColumnName.toString()}, INTERVAL 1 ${aggregationInterval.toLowerCase()})) as ${aggregateBy.aggregationTimestampColumnName.toString()}`,
549
549
  );
550
550
 
551
+ const columns: Array<string> = [
552
+ aggregateBy.aggregateColumnName.toString(),
553
+ aggregateBy.aggregationTimestampColumnName.toString(),
554
+ ];
555
+
556
+ if (aggregateBy.groupBy && Object.keys(aggregateBy.groupBy).length > 0) {
557
+ const groupByStatement: Statement = this.toGroupByStatement(
558
+ aggregateBy.groupBy,
559
+ );
560
+ selectStatement.append(SQL`, `).append(groupByStatement);
561
+
562
+ // add to columns.
563
+ for (const key in aggregateBy.groupBy) {
564
+ columns.push(key);
565
+ }
566
+ }
567
+
551
568
  return {
552
- columns: [
553
- aggregateBy.aggregateColumnName.toString(),
554
- aggregateBy.aggregationTimestampColumnName.toString(),
555
- ],
569
+ columns: columns,
556
570
  statement: selectStatement,
557
571
  };
558
572
  }
@@ -0,0 +1,194 @@
1
+ import {
2
+ Page as PlaywrightPage,
3
+ Browser as PlaywrightBrowser,
4
+ chromium,
5
+ firefox,
6
+ } from "playwright";
7
+ import LocalFile from "./LocalFile";
8
+ import BadDataException from "../../Types/Exception/BadDataException";
9
+ import ScreenSizeType from "../../Types/ScreenSizeType";
10
+ import BrowserType from "../../Types/BrowserType";
11
+ import logger from "./Logger";
12
+
13
+ export type Page = PlaywrightPage;
14
+ export type Browser = PlaywrightBrowser;
15
+
16
+ export default class BrowserUtil {
17
+ public static async convertHtmlToBase64Screenshot(data: {
18
+ html: string;
19
+ }): Promise<string | null> {
20
+ try {
21
+ const html: string = data.html;
22
+
23
+ const pageAndBrowser: {
24
+ page: Page;
25
+ browser: Browser;
26
+ } = await BrowserUtil.getPageByBrowserType({
27
+ browserType: BrowserType.Chromium,
28
+ screenSizeType: ScreenSizeType.Desktop,
29
+ });
30
+
31
+ const page: Page = pageAndBrowser.page;
32
+ const browser: Browser = pageAndBrowser.browser;
33
+ await page.setContent(html, {
34
+ waitUntil: "domcontentloaded",
35
+ });
36
+ const screenshot: Buffer = await page.screenshot({ type: "png" });
37
+
38
+ await browser.close();
39
+
40
+ return screenshot.toString("base64");
41
+ } catch (e) {
42
+ logger.debug(e);
43
+ return null;
44
+ }
45
+ }
46
+
47
+ public static async getPageByBrowserType(data: {
48
+ browserType: BrowserType;
49
+ screenSizeType: ScreenSizeType;
50
+ }): Promise<{
51
+ page: Page;
52
+ browser: Browser;
53
+ }> {
54
+ const viewport: {
55
+ height: number;
56
+ width: number;
57
+ } = BrowserUtil.getViewportHeightAndWidth({
58
+ screenSizeType: data.screenSizeType,
59
+ });
60
+
61
+ let page: Page | null = null;
62
+ let browser: Browser | null = null;
63
+
64
+ if (data.browserType === BrowserType.Chromium) {
65
+ browser = await chromium.launch({
66
+ executablePath: await BrowserUtil.getChromeExecutablePath(),
67
+ });
68
+ page = await browser.newPage();
69
+ }
70
+
71
+ if (data.browserType === BrowserType.Firefox) {
72
+ browser = await firefox.launch({
73
+ executablePath: await BrowserUtil.getFirefoxExecutablePath(),
74
+ });
75
+ page = await browser.newPage();
76
+ }
77
+
78
+ // if (data.browserType === BrowserType.Webkit) {
79
+ // browser = await webkit.launch();
80
+ // page = await browser.newPage();
81
+ // }
82
+
83
+ await page?.setViewportSize({
84
+ width: viewport.width,
85
+ height: viewport.height,
86
+ });
87
+
88
+ if (!browser) {
89
+ throw new BadDataException("Invalid Browser Type.");
90
+ }
91
+
92
+ if (!page) {
93
+ // close the browser if page is not created
94
+ await browser.close();
95
+ throw new BadDataException("Invalid Browser Type.");
96
+ }
97
+
98
+ return {
99
+ page: page,
100
+ browser: browser,
101
+ };
102
+ }
103
+
104
+ public static getViewportHeightAndWidth(options: {
105
+ screenSizeType: ScreenSizeType;
106
+ }): {
107
+ height: number;
108
+ width: number;
109
+ } {
110
+ let viewPortHeight: number = 0;
111
+ let viewPortWidth: number = 0;
112
+
113
+ switch (options.screenSizeType) {
114
+ case ScreenSizeType.Desktop:
115
+ viewPortHeight = 1080;
116
+ viewPortWidth = 1920;
117
+ break;
118
+ case ScreenSizeType.Mobile:
119
+ viewPortHeight = 640;
120
+ viewPortWidth = 360;
121
+ break;
122
+ case ScreenSizeType.Tablet:
123
+ viewPortHeight = 768;
124
+ viewPortWidth = 1024;
125
+ break;
126
+ default:
127
+ viewPortHeight = 1080;
128
+ viewPortWidth = 1920;
129
+ break;
130
+ }
131
+
132
+ return { height: viewPortHeight, width: viewPortWidth };
133
+ }
134
+
135
+ public static async getChromeExecutablePath(): Promise<string> {
136
+ const doesDirectoryExist: boolean = await LocalFile.doesDirectoryExist(
137
+ "/root/.cache/ms-playwright",
138
+ );
139
+ if (!doesDirectoryExist) {
140
+ throw new BadDataException("Chrome executable path not found.");
141
+ }
142
+
143
+ // get list of files in the directory
144
+ const directories: string[] = await LocalFile.getListOfDirectories(
145
+ "/root/.cache/ms-playwright",
146
+ );
147
+
148
+ if (directories.length === 0) {
149
+ throw new BadDataException("Chrome executable path not found.");
150
+ }
151
+
152
+ const chromeInstallationName: string | undefined = directories.find(
153
+ (directory: string) => {
154
+ return directory.includes("chromium");
155
+ },
156
+ );
157
+
158
+ if (!chromeInstallationName) {
159
+ throw new BadDataException("Chrome executable path not found.");
160
+ }
161
+
162
+ return `/root/.cache/ms-playwright/${chromeInstallationName}/chrome-linux/chrome`;
163
+ }
164
+
165
+ public static async getFirefoxExecutablePath(): Promise<string> {
166
+ const doesDirectoryExist: boolean = await LocalFile.doesDirectoryExist(
167
+ "/root/.cache/ms-playwright",
168
+ );
169
+ if (!doesDirectoryExist) {
170
+ throw new BadDataException("Firefox executable path not found.");
171
+ }
172
+
173
+ // get list of files in the directory
174
+ const directories: string[] = await LocalFile.getListOfDirectories(
175
+ "/root/.cache/ms-playwright",
176
+ );
177
+
178
+ if (directories.length === 0) {
179
+ throw new BadDataException("Firefox executable path not found.");
180
+ }
181
+
182
+ const firefoxInstallationName: string | undefined = directories.find(
183
+ (directory: string) => {
184
+ return directory.includes("firefox");
185
+ },
186
+ );
187
+
188
+ if (!firefoxInstallationName) {
189
+ throw new BadDataException("Firefox executable path not found.");
190
+ }
191
+
192
+ return `/root/.cache/ms-playwright/${firefoxInstallationName}/firefox/firefox`;
193
+ }
194
+ }
@@ -544,6 +544,9 @@ export default class CompareCriteria {
544
544
  case FilterType.NotEqualTo:
545
545
  message += ` not equal to ${data.threshold}. `;
546
546
  break;
547
+ case FilterType.EqualTo:
548
+ message += ` equal to ${data.threshold}. `;
549
+ break;
547
550
  case FilterType.Contains:
548
551
  message += ` contains ${data.threshold}. `;
549
552
  break;