From a6a5f189c3bc6f6a2bb9ec2e1baf1ff1bcabff5e Mon Sep 17 00:00:00 2001 From: Simon Larsen Date: Sun, 25 Aug 2024 18:40:40 +0100 Subject: [PATCH] refactor: Add TelemetryExceptionStatus model to DatabaseModels and update Permission enum with Telemetry Exception permissions --- Common/Models/AnalyticsModels/Exception.ts | 62 +- Common/Models/DatabaseModels/Index.ts | 4 + .../TelemetryExceptionStatus.ts | 798 ++++++++++++++++++ .../1724607603707-MigrationName.ts | 38 + .../Postgres/SchemaMigrations/Index.ts | 1 + Common/Types/Permission.ts | 16 +- Ingestor/API/OTelIngest.ts | 2 +- 7 files changed, 881 insertions(+), 40 deletions(-) create mode 100644 Common/Models/DatabaseModels/TelemetryExceptionStatus.ts create mode 100644 Common/Server/Infrastructure/Postgres/SchemaMigrations/1724607603707-MigrationName.ts diff --git a/Common/Models/AnalyticsModels/Exception.ts b/Common/Models/AnalyticsModels/Exception.ts index 7dc63e001d..282c653c04 100644 --- a/Common/Models/AnalyticsModels/Exception.ts +++ b/Common/Models/AnalyticsModels/Exception.ts @@ -20,25 +20,25 @@ export default class Exception extends AnalyticsBaseModel { Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, - Permission.ReadTelemetryServiceException, + Permission.ReadTelemetryException, ], create: [ Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, - Permission.CreateTelemetryServiceException, + Permission.CreateTelemetryException, ], update: [ Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, - Permission.EditTelemetryServiceException, + Permission.EditTelemetryException, ], delete: [ Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, - Permission.DeleteTelemetryServiceException, + Permission.DeleteTelemetryException, ], }, pluralName: "Exceptions", @@ -56,13 +56,13 @@ export default class Exception extends AnalyticsBaseModel { Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, - Permission.ReadTelemetryServiceException, + Permission.ReadTelemetryException, ], create: [ Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, - Permission.CreateTelemetryServiceException, + Permission.CreateTelemetryException, ], update: [], }, @@ -79,13 +79,13 @@ export default class Exception extends AnalyticsBaseModel { Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, - Permission.ReadTelemetryServiceException, + Permission.ReadTelemetryException, ], create: [ Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, - Permission.CreateTelemetryServiceException, + Permission.CreateTelemetryException, ], update: [], }, @@ -102,13 +102,13 @@ export default class Exception extends AnalyticsBaseModel { Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, - Permission.ReadTelemetryServiceException, + Permission.ReadTelemetryException, ], create: [ Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, - Permission.CreateTelemetryServiceException, + Permission.CreateTelemetryException, ], update: [], }, @@ -125,13 +125,13 @@ export default class Exception extends AnalyticsBaseModel { Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, - Permission.ReadTelemetryServiceException, + Permission.ReadTelemetryException, ], create: [ Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, - Permission.CreateTelemetryServiceException, + Permission.CreateTelemetryException, ], update: [], }, @@ -148,13 +148,13 @@ export default class Exception extends AnalyticsBaseModel { Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, - Permission.ReadTelemetryServiceException, + Permission.ReadTelemetryException, ], create: [ Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, - Permission.CreateTelemetryServiceException, + Permission.CreateTelemetryException, ], update: [], }, @@ -171,13 +171,13 @@ export default class Exception extends AnalyticsBaseModel { Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, - Permission.ReadTelemetryServiceException, + Permission.ReadTelemetryException, ], create: [ Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, - Permission.CreateTelemetryServiceException, + Permission.CreateTelemetryException, ], update: [], }, @@ -194,20 +194,20 @@ export default class Exception extends AnalyticsBaseModel { Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, - Permission.ReadTelemetryServiceException, + Permission.ReadTelemetryException, ], create: [ Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, - Permission.CreateTelemetryServiceException, + Permission.CreateTelemetryException, ], update: [], }, }), new AnalyticsTableColumn({ - key: "escapted", + key: "escaped", title: "Exception Escaped", description: "Exception Escaped", // SHOULD be set to true if the exception event is recorded at a point where it is known that the exception is escaping the scope of the span. required: false, @@ -217,13 +217,13 @@ export default class Exception extends AnalyticsBaseModel { Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, - Permission.ReadTelemetryServiceException, + Permission.ReadTelemetryException, ], create: [ Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, - Permission.CreateTelemetryServiceException, + Permission.CreateTelemetryException, ], update: [], }, @@ -240,13 +240,13 @@ export default class Exception extends AnalyticsBaseModel { Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, - Permission.ReadTelemetryServiceException, + Permission.ReadTelemetryException, ], create: [ Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, - Permission.CreateTelemetryServiceException, + Permission.CreateTelemetryException, ], update: [], }, @@ -263,13 +263,13 @@ export default class Exception extends AnalyticsBaseModel { Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, - Permission.ReadTelemetryServiceException, + Permission.ReadTelemetryException, ], create: [ Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, - Permission.CreateTelemetryServiceException, + Permission.CreateTelemetryException, ], update: [], }, @@ -286,13 +286,13 @@ export default class Exception extends AnalyticsBaseModel { Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, - Permission.ReadTelemetryServiceException, + Permission.ReadTelemetryException, ], create: [ Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, - Permission.CreateTelemetryServiceException, + Permission.CreateTelemetryException, ], update: [], }, @@ -381,12 +381,12 @@ export default class Exception extends AnalyticsBaseModel { this.setColumnValue("message", v); } - public get escapted(): boolean | undefined { - return this.getColumnValue("escapted") as boolean | undefined; + public get escaped(): boolean | undefined { + return this.getColumnValue("escaped") as boolean | undefined; } - public set escapted(v: boolean | undefined) { - this.setColumnValue("escapted", v); + public set escaped(v: boolean | undefined) { + this.setColumnValue("escaped", v); } public get fingerprint(): string | undefined { diff --git a/Common/Models/DatabaseModels/Index.ts b/Common/Models/DatabaseModels/Index.ts index 8cdd46e189..818b9e593d 100644 --- a/Common/Models/DatabaseModels/Index.ts +++ b/Common/Models/DatabaseModels/Index.ts @@ -135,6 +135,8 @@ import UserTwoFactorAuth from "./UserTwoFactorAuth"; import TelemetryIngestionKey from "./TelemetryIngestionKey"; +import TelemetryExceptionStatus from "./TelemetryExceptionStatus"; + export default [ User, Probe, @@ -289,4 +291,6 @@ export default [ UserTwoFactorAuth, TelemetryIngestionKey, + + TelemetryExceptionStatus ]; diff --git a/Common/Models/DatabaseModels/TelemetryExceptionStatus.ts b/Common/Models/DatabaseModels/TelemetryExceptionStatus.ts new file mode 100644 index 0000000000..2ccfab6f0b --- /dev/null +++ b/Common/Models/DatabaseModels/TelemetryExceptionStatus.ts @@ -0,0 +1,798 @@ +import Project from "./Project"; +import User from "./User"; +import Team from "./Team"; +import Route from "../../Types/API/Route"; +import ColumnAccessControl from "../../Types/Database/AccessControl/ColumnAccessControl"; +import TableAccessControl from "../../Types/Database/AccessControl/TableAccessControl"; +import ColumnLength from "../../Types/Database/ColumnLength"; +import ColumnType from "../../Types/Database/ColumnType"; +import CrudApiEndpoint from "../../Types/Database/CrudApiEndpoint"; +import EnableDocumentation from "../../Types/Database/EnableDocumentation"; +import EnableWorkflow from "../../Types/Database/EnableWorkflow"; +import TableColumn from "../../Types/Database/TableColumn"; +import TableColumnType from "../../Types/Database/TableColumnType"; +import TableMetadata from "../../Types/Database/TableMetadata"; +import TenantColumn from "../../Types/Database/TenantColumn"; +import IconProp from "../../Types/Icon/IconProp"; +import ObjectID from "../../Types/ObjectID"; +import Permission from "../../Types/Permission"; +import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm"; +import DatabaseBaseModel from "./DatabaseBaseModel/DatabaseBaseModel"; +import TelemetryService from "./TelemetryService"; + +@EnableDocumentation() +@TenantColumn("projectId") +@TableAccessControl({ + create: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.CreateTelemetryException, + ], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadTelemetryException, + ], + delete: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.DeleteTelemetryException, + ], + update: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.EditTelemetryException, + ], +}) +@EnableWorkflow({ + create: true, + delete: true, + update: true, + read: true, +}) +@CrudApiEndpoint(new Route("/telemetry-exception-status")) +@TableMetadata({ + tableName: "TelemetryExceptionStatus", + singularName: "TelemetryExceptionStatus", + pluralName: "TelemetryExceptionsStatus", + icon: IconProp.Error, + tableDescription: + "List of all Telemetry Exceptions created for the telemetry service for this OneUptime project and it's status.", +}) +@Entity({ + name: "TelemetryExceptionStatus", +}) +export default class TelemetryExceptionStatus extends DatabaseBaseModel { + @ColumnAccessControl({ + create: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.CreateTelemetryException, + ], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadTelemetryException, + ], + update: [], + }) + @TableColumn({ + manyToOneRelationColumn: "projectId", + type: TableColumnType.Entity, + modelType: Project, + title: "Project", + description: "Relation to Project Resource in which this object belongs", + }) + @ManyToOne( + () => { + return Project; + }, + { + eager: false, + nullable: true, + onDelete: "CASCADE", + orphanedRowAction: "nullify", + }, + ) + @JoinColumn({ name: "projectId" }) + public project?: Project = undefined; + + @ColumnAccessControl({ + create: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.CreateTelemetryException, + ], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadTelemetryException, + ], + update: [], + }) + @Index() + @TableColumn({ + type: TableColumnType.ObjectID, + required: true, + canReadOnRelationQuery: true, + title: "Project ID", + description: "ID of your OneUptime Project in which this object belongs", + }) + @Column({ + type: ColumnType.ObjectID, + nullable: false, + transformer: ObjectID.getDatabaseTransformer(), + }) + public projectId?: ObjectID = undefined; + + + @ColumnAccessControl({ + create: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.CreateTelemetryException, + ], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadTelemetryException, + ], + update: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.EditTelemetryException, + ], + }) + @TableColumn({ + manyToOneRelationColumn: "telemetryServiceId", + type: TableColumnType.Entity, + modelType: TelemetryService, + title: "Telemetry Service", + description: + "Relation to Telemetry Service Resource in which this object belongs", + }) + @ManyToOne( + () => { + return TelemetryService; + }, + { + eager: false, + nullable: true, + onDelete: "CASCADE", + orphanedRowAction: "nullify", + }, + ) + @JoinColumn({ name: "telemetryServiceId" }) + public telemetryService?: TelemetryService = undefined; + + @ColumnAccessControl({ + create: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.CreateTelemetryException, + ], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadTelemetryException, + ], + update: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.EditTelemetryException, + ], + }) + @Index() + @TableColumn({ + type: TableColumnType.ObjectID, + required: true, + title: "Telemetry Service ID", + description: + "ID of your Telemetry Service resource where this object belongs", + }) + @Column({ + type: ColumnType.ObjectID, + nullable: false, + transformer: ObjectID.getDatabaseTransformer(), + }) + public telemetryServiceId?: ObjectID = undefined; + + @ColumnAccessControl({ + create: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.CreateTelemetryException, + ], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadTelemetryException, + ], + update: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.EditTelemetryException, + ], + }) + @TableColumn({ + required: false, + type: TableColumnType.LongText, + canReadOnRelationQuery: false, + title: "Exception Message", + description: "Exception message that was thrown by the telemetry service", + }) + @Column({ + nullable: true, + type: ColumnType.LongText, + }) + public message?: string = undefined; + + + @ColumnAccessControl({ + create: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.CreateTelemetryException, + ], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadTelemetryException, + ], + update: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.EditTelemetryException, + ], + }) + @TableColumn({ + required: false, + type: TableColumnType.LongText, + canReadOnRelationQuery: false, + title: "Stack Trace", + description: "Stack trace of the exception that was thrown by the telemetry service", + }) + @Column({ + nullable: true, + type: ColumnType.LongText, + }) + public stackTrace?: string = undefined; + + + @ColumnAccessControl({ + create: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.CreateTelemetryException, + ], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadTelemetryException, + ], + update: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.EditTelemetryException, + ], + }) + @TableColumn({ + required: false, + type: TableColumnType.LongText, + canReadOnRelationQuery: false, + title: "Exception Type", + description: "Type of the exception that was thrown by the telemetry service", + }) + @Column({ + nullable: true, + type: ColumnType.LongText, + }) + public exceptionType?: string = undefined; + + @ColumnAccessControl({ + create: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.CreateTelemetryException, + ], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadTelemetryException, + ], + update: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.EditTelemetryException, + ], + }) + @TableColumn({ + required: false, + type: TableColumnType.ShortText, + canReadOnRelationQuery: false, + title: "Finger Print", + description: "Finger print of the exception that was thrown by the telemetry service", + }) + @Column({ + nullable: true, + type: ColumnType.ShortText, + length: ColumnLength.ShortText, + }) + public fingerPrint?: string = undefined; + + @ColumnAccessControl({ + create: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.CreateTelemetryException, + ], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadTelemetryException, + ], + update: [], + }) + @TableColumn({ + manyToOneRelationColumn: "createdByUserId", + type: TableColumnType.Entity, + modelType: User, + title: "Created by User", + description: + "Relation to User who created this object (if this object was created by a User)", + }) + @ManyToOne( + () => { + return User; + }, + { + eager: false, + nullable: true, + onDelete: "CASCADE", + orphanedRowAction: "nullify", + }, + ) + @JoinColumn({ name: "createdByUserId" }) + public createdByUser?: User = undefined; + + @ColumnAccessControl({ + create: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.CreateTelemetryException, + ], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadTelemetryException, + ], + update: [], + }) + @TableColumn({ + type: TableColumnType.ObjectID, + title: "Created by User ID", + description: + "User ID who created this object (if this object was created by a User)", + }) + @Column({ + type: ColumnType.ObjectID, + nullable: true, + transformer: ObjectID.getDatabaseTransformer(), + }) + public createdByUserId?: ObjectID = undefined; + + @ColumnAccessControl({ + create: [], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadTelemetryException, + ], + update: [], + }) + @TableColumn({ + manyToOneRelationColumn: "deletedByUserId", + type: TableColumnType.Entity, + title: "Deleted by User", + description: + "Relation to User who deleted this object (if this object was deleted by a User)", + }) + @ManyToOne( + () => { + return User; + }, + { + cascade: false, + eager: false, + nullable: true, + onDelete: "CASCADE", + orphanedRowAction: "nullify", + }, + ) + @JoinColumn({ name: "deletedByUserId" }) + public deletedByUser?: User = undefined; + + @ColumnAccessControl({ + create: [], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadTelemetryException, + ], + update: [], + }) + @TableColumn({ + type: TableColumnType.ObjectID, + title: "Deleted by User ID", + description: + "User ID who deleted this object (if this object was deleted by a User)", + }) + @Column({ + type: ColumnType.ObjectID, + nullable: true, + transformer: ObjectID.getDatabaseTransformer(), + }) + public deletedByUserId?: ObjectID = undefined; + + @ColumnAccessControl({ + create: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.CreateProjectTeam, + Permission.InviteProjectTeamMembers, + ], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ReadProjectTeam, + ], + update: [Permission.CurrentUser], + }) + @TableColumn({ + required: false, + type: TableColumnType.Date, + title: "Accepted Invitation At", + description: "When did this team member accept invitation", + }) + @Column({ + type: ColumnType.Date, + nullable: true, + unique: false, + }) + public markedAsResolvedAt?: Date = undefined; + + + + @ColumnAccessControl({ + create: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.CreateProjectTeam, + Permission.InviteProjectTeamMembers, + ], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ReadProjectTeam, + ], + update: [Permission.CurrentUser], + }) + @TableColumn({ + required: false, + type: TableColumnType.Date, + title: "Accepted Invitation At", + description: "When did this team member accept invitation", + }) + @Column({ + type: ColumnType.Date, + nullable: true, + unique: false, + }) + public markedAsMutedAt?: Date = undefined; + + + @ColumnAccessControl({ + create: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.CreateProjectTeam, + Permission.InviteProjectTeamMembers, + ], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ReadProjectTeam, + ], + update: [Permission.CurrentUser], + }) + @TableColumn({ + required: false, + type: TableColumnType.Date, + title: "Accepted Invitation At", + description: "When did this team member accept invitation", + }) + @Column({ + type: ColumnType.Date, + nullable: true, + unique: false, + }) + public firstSeenAt?: Date = undefined; + + @ColumnAccessControl({ + create: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.CreateProjectTeam, + Permission.InviteProjectTeamMembers, + ], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ReadProjectTeam, + ], + update: [Permission.CurrentUser], + }) + @TableColumn({ + required: false, + type: TableColumnType.Date, + title: "Accepted Invitation At", + description: "When did this team member accept invitation", + }) + @Column({ + type: ColumnType.Date, + nullable: true, + unique: false, + }) + public lastSeenAt?: Date = undefined; + + + // assign to. + @ColumnAccessControl({ + create: [], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadTelemetryException, + ], + update: [], + }) + @TableColumn({ + manyToOneRelationColumn: "assignToUserId", + type: TableColumnType.Entity, + title: "Assign to User", + description: + "Relation to User who this exception is assigned to.", + }) + @ManyToOne( + () => { + return User; + }, + { + cascade: false, + eager: false, + nullable: true, + onDelete: "CASCADE", + orphanedRowAction: "nullify", + }, + ) + @JoinColumn({ name: "assignToUserId" }) + public assignToUser?: User = undefined; + + @ColumnAccessControl({ + create: [], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadTelemetryException, + ], + update: [], + }) + @TableColumn({ + type: TableColumnType.ObjectID, + title: "Assign to User ID", + description: + "User ID who this exception is assigned to.", + }) + @Column({ + type: ColumnType.ObjectID, + nullable: true, + transformer: ObjectID.getDatabaseTransformer(), + }) + public assignToUserId?: ObjectID = undefined; + + + + // assign to team. + + // assign to. + @ColumnAccessControl({ + create: [], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadTelemetryException, + ], + update: [], + }) + @TableColumn({ + manyToOneRelationColumn: "assignToTeamId", + type: TableColumnType.Entity, + title: "Assign to Team", + description: + "Relation to Team who this exception is assigned to.", + }) + @ManyToOne( + () => { + return Team; + }, + { + cascade: false, + eager: false, + nullable: true, + onDelete: "CASCADE", + orphanedRowAction: "nullify", + }, + ) + @JoinColumn({ name: "assignToTeamId" }) + public assignToTeam?: Team = undefined; + + @ColumnAccessControl({ + create: [], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadTelemetryException, + ], + update: [], + }) + @TableColumn({ + type: TableColumnType.ObjectID, + title: "Assign to Team ID", + description: + "Team ID who this exception is assigned to.", + }) + @Column({ + type: ColumnType.ObjectID, + nullable: true, + transformer: ObjectID.getDatabaseTransformer(), + }) + public assignToTeamId?: ObjectID = undefined; + + + // mark as resolved by. + + @ColumnAccessControl({ + create: [], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadTelemetryException, + ], + update: [], + }) + @TableColumn({ + manyToOneRelationColumn: "markedAsResolvedByUserId", + type: TableColumnType.Entity, + title: "Marked as Resolved By User", + description: + "Mark as resolved by User who marked this exception as resolved.", + }) + @ManyToOne( + () => { + return User; + }, + { + cascade: false, + eager: false, + nullable: true, + onDelete: "CASCADE", + orphanedRowAction: "nullify", + }, + ) + @JoinColumn({ name: "markedAsResolvedByUserId" }) + public markedAsResolvedByUser?: User = undefined; + + @ColumnAccessControl({ + create: [], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadTelemetryException, + ], + update: [], + }) + @TableColumn({ + type: TableColumnType.ObjectID, + title: "Marked as Resolved By User ID", + description: + "User ID who marked this exception as resolved.", + }) + @Column({ + type: ColumnType.ObjectID, + nullable: true, + transformer: ObjectID.getDatabaseTransformer(), + }) + public markedAsResolvedByUserId?: ObjectID = undefined; + + + + // Mark as muted by. + + @ColumnAccessControl({ + create: [], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadTelemetryException, + ], + update: [], + }) + @TableColumn({ + manyToOneRelationColumn: "markedAsMutedByUserId", + type: TableColumnType.Entity, + title: "Mark as Muted By User", + description: + "Mark as muted by User", + }) + @ManyToOne( + () => { + return User; + }, + { + cascade: false, + eager: false, + nullable: true, + onDelete: "CASCADE", + orphanedRowAction: "nullify", + }, + ) + @JoinColumn({ name: "markedAsMutedByUserId" }) + public markedAsMutedByUser?: User = undefined; + + @ColumnAccessControl({ + create: [], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadTelemetryException, + ], + update: [], + }) + @TableColumn({ + type: TableColumnType.ObjectID, + title: "Mark as Muted By User ID", + description: + "User ID who marked this exception as muted.", + }) + @Column({ + type: ColumnType.ObjectID, + nullable: true, + transformer: ObjectID.getDatabaseTransformer(), + }) + public markedAsMutedByUserId?: ObjectID = undefined; + + + + +} \ No newline at end of file diff --git a/Common/Server/Infrastructure/Postgres/SchemaMigrations/1724607603707-MigrationName.ts b/Common/Server/Infrastructure/Postgres/SchemaMigrations/1724607603707-MigrationName.ts new file mode 100644 index 0000000000..b2835de108 --- /dev/null +++ b/Common/Server/Infrastructure/Postgres/SchemaMigrations/1724607603707-MigrationName.ts @@ -0,0 +1,38 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class MigrationName1724607603707 implements MigrationInterface { + public name = 'MigrationName1724607603707' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`CREATE TABLE "TelemetryExceptionStatus" ("_id" uuid NOT NULL DEFAULT uuid_generate_v4(), "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), "deletedAt" TIMESTAMP, "version" integer NOT NULL, "projectId" uuid NOT NULL, "telemetryServiceId" uuid NOT NULL, "message" character varying, "stackTrace" character varying, "exceptionType" character varying, "fingerPrint" character varying(100), "createdByUserId" uuid, "deletedByUserId" uuid, "markedAsResolvedAt" TIMESTAMP WITH TIME ZONE, "markedAsMutedAt" TIMESTAMP WITH TIME ZONE, "firstSeenAt" TIMESTAMP WITH TIME ZONE, "lastSeenAt" TIMESTAMP WITH TIME ZONE, "assignToUserId" uuid, "assignToTeamId" uuid, "markedAsResolvedByUserId" uuid, "markedAsMutedByUserId" uuid, CONSTRAINT "PK_8db287c0fc7516e22d53876137c" PRIMARY KEY ("_id"))`); + await queryRunner.query(`CREATE INDEX "IDX_7c02d07bf73bfdac7301a6c86d" ON "TelemetryExceptionStatus" ("projectId") `); + await queryRunner.query(`CREATE INDEX "IDX_0f66442452b5a89efa085ede0f" ON "TelemetryExceptionStatus" ("telemetryServiceId") `); + await queryRunner.query(`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type":"Recurring","value":{"intervalType":"Day","intervalCount":{"_type":"PositiveNumber","value":1}}}'`); + await queryRunner.query(`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type":"RestrictionTimes","value":{"restictionType":"None","dayRestrictionTimes":null,"weeklyRestrictionTimes":[]}}'`); + await queryRunner.query(`ALTER TABLE "TelemetryExceptionStatus" ADD CONSTRAINT "FK_7c02d07bf73bfdac7301a6c86d5" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE "TelemetryExceptionStatus" ADD CONSTRAINT "FK_0f66442452b5a89efa085ede0fd" FOREIGN KEY ("telemetryServiceId") REFERENCES "TelemetryService"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE "TelemetryExceptionStatus" ADD CONSTRAINT "FK_fe9e43b2cf2278894f9fe67c92f" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE "TelemetryExceptionStatus" ADD CONSTRAINT "FK_3b402ffb6fe47992c38f4cd5e7a" FOREIGN KEY ("deletedByUserId") REFERENCES "User"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE "TelemetryExceptionStatus" ADD CONSTRAINT "FK_88a1d97d74c54cd80b384f2a911" FOREIGN KEY ("assignToUserId") REFERENCES "User"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE "TelemetryExceptionStatus" ADD CONSTRAINT "FK_1c8cc9368c92f60cb093af277f8" FOREIGN KEY ("assignToTeamId") REFERENCES "Team"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE "TelemetryExceptionStatus" ADD CONSTRAINT "FK_fe156e1dce6bdae3f349d33e293" FOREIGN KEY ("markedAsResolvedByUserId") REFERENCES "User"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE "TelemetryExceptionStatus" ADD CONSTRAINT "FK_9d7647bf6d537f5afbd00ef4a8b" FOREIGN KEY ("markedAsMutedByUserId") REFERENCES "User"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "TelemetryExceptionStatus" DROP CONSTRAINT "FK_9d7647bf6d537f5afbd00ef4a8b"`); + await queryRunner.query(`ALTER TABLE "TelemetryExceptionStatus" DROP CONSTRAINT "FK_fe156e1dce6bdae3f349d33e293"`); + await queryRunner.query(`ALTER TABLE "TelemetryExceptionStatus" DROP CONSTRAINT "FK_1c8cc9368c92f60cb093af277f8"`); + await queryRunner.query(`ALTER TABLE "TelemetryExceptionStatus" DROP CONSTRAINT "FK_88a1d97d74c54cd80b384f2a911"`); + await queryRunner.query(`ALTER TABLE "TelemetryExceptionStatus" DROP CONSTRAINT "FK_3b402ffb6fe47992c38f4cd5e7a"`); + await queryRunner.query(`ALTER TABLE "TelemetryExceptionStatus" DROP CONSTRAINT "FK_fe9e43b2cf2278894f9fe67c92f"`); + await queryRunner.query(`ALTER TABLE "TelemetryExceptionStatus" DROP CONSTRAINT "FK_0f66442452b5a89efa085ede0fd"`); + await queryRunner.query(`ALTER TABLE "TelemetryExceptionStatus" DROP CONSTRAINT "FK_7c02d07bf73bfdac7301a6c86d5"`); + await queryRunner.query(`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type": "RestrictionTimes", "value": {"restictionType": "None", "dayRestrictionTimes": null, "weeklyRestrictionTimes": []}}'`); + await queryRunner.query(`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type": "Recurring", "value": {"intervalType": "Day", "intervalCount": {"_type": "PositiveNumber", "value": 1}}}'`); + await queryRunner.query(`DROP INDEX "public"."IDX_0f66442452b5a89efa085ede0f"`); + await queryRunner.query(`DROP INDEX "public"."IDX_7c02d07bf73bfdac7301a6c86d"`); + await queryRunner.query(`DROP TABLE "TelemetryExceptionStatus"`); + } + +} diff --git a/Common/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts b/Common/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts index 47477c5d9e..dac6e5b4f0 100644 --- a/Common/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +++ b/Common/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts @@ -86,4 +86,5 @@ export default [ MigrationName1723825511054, MigrationName1723828588502, MigrationName1724078044172, + MigrationName1720812937067 ]; diff --git a/Common/Types/Permission.ts b/Common/Types/Permission.ts index f3b2ba2097..f4e3b56972 100644 --- a/Common/Types/Permission.ts +++ b/Common/Types/Permission.ts @@ -54,10 +54,10 @@ enum Permission { ReadTelemetryServiceLog = "ReadTelemetryServiceLog", // Exceptions - CreateTelemetryServiceException = "CreateTelemetryServiceException", - DeleteTelemetryServiceException = "DeleteTelemetryServiceException", - EditTelemetryServiceException = "EditTelemetryServiceException", - ReadTelemetryServiceException = "ReadTelemetryServiceException", + CreateTelemetryException = "CreateTelemetryException", + DeleteTelemetryException = "DeleteTelemetryException", + EditTelemetryException = "EditTelemetryException", + ReadTelemetryException = "ReadTelemetryException", // Spans CreateTelemetryServiceTraces = "CreateTelemetryServiceTraces", @@ -2452,7 +2452,7 @@ export class PermissionHelper { }, { - permission: Permission.CreateTelemetryServiceException, + permission: Permission.CreateTelemetryException, title: "Create Telemetry Service Exception", description: "This permission can create Telemetry Service Exception this project.", @@ -2460,7 +2460,7 @@ export class PermissionHelper { isAccessControlPermission: false, }, { - permission: Permission.DeleteTelemetryServiceException, + permission: Permission.DeleteTelemetryException, title: "Delete Telemetry Service Exception", description: "This permission can delete Telemetry Service Exception of this project.", @@ -2468,7 +2468,7 @@ export class PermissionHelper { isAccessControlPermission: false, }, { - permission: Permission.EditTelemetryServiceException, + permission: Permission.EditTelemetryException, title: "Edit Telemetry Service Exception", description: "This permission can edit Telemetry Service Exception of this project.", @@ -2476,7 +2476,7 @@ export class PermissionHelper { isAccessControlPermission: false, }, { - permission: Permission.ReadTelemetryServiceException, + permission: Permission.ReadTelemetryException, title: "Read Telemetry Service Exception", description: "This permission can read Telemetry Service Exception of this project.", diff --git a/Ingestor/API/OTelIngest.ts b/Ingestor/API/OTelIngest.ts index 0b4b99e7e6..88f0c7bbd9 100644 --- a/Ingestor/API/OTelIngest.ts +++ b/Ingestor/API/OTelIngest.ts @@ -313,7 +313,7 @@ router.post( "stacktrace" ] as string; exception.exceptionType = eventAttributes["type"] as string; - exception.escapted = eventAttributes["escaped"] as boolean; + exception.escaped = eventAttributes["escaped"] as boolean; exception.fingerprint = ExceptionUtil.getFingerprint(exception); // add exception to dbExceptions