refactor: Add exception span status code and name to ExceptionInstance model

This commit is contained in:
Simon Larsen 2024-08-29 11:25:43 +01:00
parent fd0a95d436
commit 5c4d4b2c63
No known key found for this signature in database
GPG Key ID: 96C5DCA24769DBCA
5 changed files with 245 additions and 0 deletions

View File

@ -5,6 +5,7 @@ import AnalyticsTableColumn from "../../Types/AnalyticsDatabase/TableColumn";
import TableColumnType from "../../Types/AnalyticsDatabase/TableColumnType";
import ObjectID from "../../Types/ObjectID";
import Permission from "../../Types/Permission";
import { SpanStatus } from "./Span";
export default class ExceptionInstance extends AnalyticsBaseModel {
public constructor() {
@ -206,6 +207,29 @@ export default class ExceptionInstance extends AnalyticsBaseModel {
},
}),
new AnalyticsTableColumn({
key: "spanStatusCode",
title: "Span Status Code",
description: "Span Status Code",
required: false,
type: TableColumnType.Number,
accessControl: {
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadTelemetryException,
],
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateTelemetryException,
],
update: [],
},
}),
new AnalyticsTableColumn({
key: "escaped",
title: "Exception Escaped",
@ -298,6 +322,29 @@ export default class ExceptionInstance extends AnalyticsBaseModel {
},
}),
new AnalyticsTableColumn({
key: "spanName",
title: "Span Name",
description: "Name of the span",
required: false,
type: TableColumnType.Text,
accessControl: {
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadTelemetryServiceTraces,
],
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateTelemetryServiceTraces,
],
update: [],
},
}),
new AnalyticsTableColumn({
key: "attributes",
title: "Attributes",
@ -422,4 +469,22 @@ export default class ExceptionInstance extends AnalyticsBaseModel {
public set attributes(v: Record<string, any>) {
this.setColumnValue("attributes", v);
}
public get spanStatusCode(): SpanStatus | undefined {
return this.getColumnValue("spanStatusCode") as SpanStatus | undefined;
}
public set spanStatusCode(v: SpanStatus | undefined) {
this.setColumnValue("spanStatusCode", v);
}
public get spanName(): string | undefined {
return this.getColumnValue("spanName") as string | undefined;
}
public set spanName(v: string | undefined) {
this.setColumnValue("spanName", v);
}
}

View File

@ -17,6 +17,7 @@ import IconProp from "Common/Types/Icon/IconProp";
import OneUptimeDate from "Common/Types/Date";
import User from "Common/UI/Utils/User";
import { ButtonStyleType } from "Common/UI/Components/Button/Button";
import OccouranceTable from "./OccuranceTable";
export interface ComponentProps {
telemetryExceptionId: ObjectID;
@ -188,6 +189,8 @@ const ExceptionExplorer: FunctionComponent<ComponentProps> = (
{/** Occurance Table */}
{telemetryException.fingerprint && <OccouranceTable exceptionFingerprint={telemetryException.fingerprint} />}
{/** Archive / Unarchive Button Button */}
{isResolved && (

View File

@ -11,6 +11,7 @@ import TelemetryExceptionElement from "./ExceptionElement";
import RouteMap, { RouteUtil } from "../../Utils/RouteMap";
import Route from "Common/Types/API/Route";
import PageMap from "../../Utils/PageMap";
import User from "Common/Models/DatabaseModels/User";
export interface ComponentProps {
telemetryServiceId?: ObjectID | undefined;
@ -100,6 +101,28 @@ const TelemetryExceptionTable: FunctionComponent<ComponentProps> = (
title: "Resolved",
type: FieldType.Boolean,
},
{
field: {
markedAsResolvedAt: true,
},
title: "Marked As Resolved At",
type: FieldType.Date,
},
{
field: {
markedAsResolvedByUser: true,
},
title: "Marked As Resolved At",
type: FieldType.EntityArray,
filterEntityType: User,
filterQuery: {
projectId: DashboardNavigation.getProjectId()!,
},
filterDropdownField: {
label: "name",
value: "_id",
},
},
{
field: {
isArchived: true,
@ -107,6 +130,28 @@ const TelemetryExceptionTable: FunctionComponent<ComponentProps> = (
title: "Archived",
type: FieldType.Boolean,
},
{
field: {
markedAsArchivedAt: true,
},
title: "Marked As Archived At",
type: FieldType.Date,
},
{
field: {
markedAsArchivedByUser: true,
},
title: "Marked As Archived At",
type: FieldType.EntityArray,
filterEntityType: User,
filterQuery: {
projectId: DashboardNavigation.getProjectId()!,
},
filterDropdownField: {
label: "name",
value: "_id",
},
},
]}
selectMoreFields={{
isResolved: true,

View File

@ -0,0 +1,130 @@
import SpanStatusElement from "../Span/SpanStatusElement";
import DashboardNavigation from "../../Utils/Navigation";
import SortOrder from "Common/Types/BaseDatabase/SortOrder";
import ExceptionInstance from "Common/Models/AnalyticsModels/ExceptionInstance";
import AnalyticsModelTable from "Common/UI/Components/ModelTable/AnalyticsModelTable";
import FieldType from "Common/UI/Components/Types/FieldType";
import React, {
Fragment,
FunctionComponent,
ReactElement,
} from "react";
export interface ComponentProps {
exceptionFingerprint: string;
}
const OccouranceTable: FunctionComponent<ComponentProps> = (
props: ComponentProps,
): ReactElement => {
return (
<Fragment>
<div className="rounded">
<AnalyticsModelTable<ExceptionInstance>
modelType={ExceptionInstance}
id="traces-table"
isDeleteable={false}
isEditable={false}
isCreateable={false}
singularName="Exception"
pluralName="Exceptions"
name="Exception"
isViewable={false}
cardProps={
{
title: "Exception Occurrences",
description:
"View all the traces that are related to this exception.",
}
}
query={{
projectId: DashboardNavigation.getProjectId()!,
fingerprint: props.exceptionFingerprint,
}}
showViewIdButton={true}
noItemsMessage={
"No exception found."
}
showRefreshButton={true}
sortBy="time"
sortOrder={SortOrder.Descending}
filters={[
{
field: {
traceId: true,
},
type: FieldType.Text,
title: "Trace ID",
},
{
field: {
spanId: true,
},
type: FieldType.Text,
title: "Span ID",
},
{
field: {
time: true,
},
type: FieldType.DateTime,
title: "Time of Occurrence",
},
{
field: {
spanName: true,
},
type: FieldType.Text,
title: "Span Name",
}
]}
columns={[
{
field: {
spanId: true,
},
title: "Span ID",
type: FieldType.Element,
getElement: (exceptionInstance: ExceptionInstance): ReactElement => {
return (
<Fragment>
<SpanStatusElement
traceId={exceptionInstance.traceId?.toString()}
spanStatusCode={exceptionInstance.spanStatusCode!}
title={exceptionInstance.spanId?.toString()}
/>
</Fragment>
);
},
},
{
field: {
traceId: true,
},
title: "Trace ID",
type: FieldType.Text,
},
{
field: {
spanName: true,
},
title: "Span Name",
type: FieldType.Text,
},
{
field: {
time: true,
},
title: "Time of Occurrence",
type: FieldType.DateTime,
}
]}
/>
</div>
</Fragment>
);
};
export default OccouranceTable;

View File

@ -308,6 +308,8 @@ router.post(
exception.traceId = dbSpan.traceId;
exception.time = eventTime;
exception.timeUnixNano = eventTimeUnixNano;
exception.spanStatusCode = dbSpan.statusCode;
exception.spanName = dbSpan.name;
exception.message =
(eventAttributes["exception.message"] as string) || "";
exception.stackTrace =