Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion packages/spotlight/src/server/parser/processEnvelope.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import type { Envelope, EnvelopeItem } from "@sentry/core";
import { type UUID, uuidv7obj } from "uuidv7";
import { RAW_TYPES } from "../constants.ts";
import { type SourceType, inferEnvelopeSource } from "../formatters/human/utils.ts";
import { logger } from "../logger.ts";
import type { RawEventContext } from "./types.ts";

export type ParsedEnvelope = {
envelope: [Envelope[0] & { __spotlight_envelope_id: UUID }, Envelope[1]];
envelope: [Envelope[0] & { __spotlight_envelope_id: UUID; __spotlight_inferred_source?: SourceType }, Envelope[1]];
rawEnvelope: RawEventContext;
};

Expand Down Expand Up @@ -91,6 +92,10 @@ export function processEnvelope(rawEvent: RawEventContext, senderUserAgent?: str
items.push([itemHeader, itemPayload] as EnvelopeItem);
}

// Infer the envelope source (browser, server, or mobile) for UI display
const firstEvent = items.length > 0 ? items[0][1] : undefined;
envelopeHeader.__spotlight_inferred_source = inferEnvelopeSource(envelopeHeader, firstEvent);

return {
envelope: [envelopeHeader, items] as ParsedEnvelope["envelope"],
rawEnvelope: rawEvent,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import CardList from "@spotlight/ui/telemetry/components/shared/CardList";
import { OriginBadge } from "@spotlight/ui/telemetry/components/shared/OriginBadge";
import TimeSince from "@spotlight/ui/telemetry/components/shared/TimeSince";
import { Link } from "react-router-dom";
import { useSentryEvents } from "../../data/useSentryEvents";
Expand All @@ -25,6 +26,7 @@ export default function EventList({ traceId }: { traceId?: string }) {
<div className="text-primary-300 flex w-48 flex-col truncate font-mono text-sm">
<div className="flex items-center gap-x-2">
<div>{truncateId(e.event_id)}</div>
<OriginBadge sourceType={e.__sourceType} />
</div>
<span />
<TimeSince date={e.timestamp} />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { Badge } from "@spotlight/ui/ui/badge";

type SourceType = "browser" | "server" | "mobile";

type OriginBadgeProps = {
sourceType: SourceType | undefined;
};

const SOURCE_CONFIG: Record<SourceType, { label: string; className: string; title: string }> = {
browser: {
label: "Browser",
// Yellow matching terminal output (#FDB81B)
className: "bg-yellow-500/20 text-yellow-200 border-yellow-500/30",
title: "This event originated from a browser",
},
server: {
label: "Server",
// Magenta matching terminal output (#FF45A8)
className: "bg-pink-500/20 text-pink-200 border-pink-500/30",
title: "This event originated from a server",
},
mobile: {
label: "Mobile",
// Blue matching terminal output (#226DFC)
className: "bg-blue-500/20 text-blue-200 border-blue-500/30",
title: "This event originated from a mobile device",
},
};

export function OriginBadge({ sourceType }: OriginBadgeProps) {
if (!sourceType) {
return null;
}

const config = SOURCE_CONFIG[sourceType];

return (
<Badge title={config.title} className={config.className}>
{config.label}
</Badge>
);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { cn } from "@spotlight/ui/lib/cn";
import { OriginBadge } from "@spotlight/ui/telemetry/components/shared/OriginBadge";
import TimeSince from "@spotlight/ui/telemetry/components/shared/TimeSince";
import { Badge } from "@spotlight/ui/ui/badge";
import { Link, useParams } from "react-router-dom";
Expand Down Expand Up @@ -89,6 +90,7 @@ export default function TraceItem({ trace, className }: TraceItemProps) {
<div className="text-primary-300 flex w-48 flex-col truncate font-mono text-sm">
<div className="flex items-center gap-x-2">
<div>{truncatedId}</div>
<OriginBadge sourceType={trace.rootTransaction?.__sourceType} />
</div>
<TimeSince date={trace.start_timestamp} />
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ export const createEnvelopesSlice: StateCreator<SentryStore, [], [], EnvelopesSl
pushEnvelope: (envelope: Envelope) => {
const [header, items] = envelope;
const lastSeen = new Date(header.sent_at as string).getTime();
// Read the inferred source type from the envelope header (set by server)
const sourceType = (header as { __spotlight_inferred_source?: "browser" | "server" | "mobile" })
.__spotlight_inferred_source;
let sdk: Sdk;

if (header.sdk?.name && header.sdk.version) {
Expand Down Expand Up @@ -86,6 +89,10 @@ export const createEnvelopesSlice: StateCreator<SentryStore, [], [], EnvelopesSl
}
item.contexts.trace ??= traceContext;
}
// Attach the inferred source type to the event for UI display
if (sourceType) {
(item as { __sourceType?: typeof sourceType }).__sourceType = sourceType;
}
const eventId =
item.event_id ?? ("event_id" in itemHeader ? (itemHeader.event_id as string | undefined) : undefined);
let attachmentsForEvent = eventId ? attachmentsByEventId.get(eventId) : undefined;
Expand Down
2 changes: 2 additions & 0 deletions packages/spotlight/src/ui/telemetry/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ type CommonEventAttrs = {
sdk?: Sdk;
measurements?: Measurements;
attachments?: EventAttachment[];
// Inferred source type for distinguishing browser/server/mobile events
__sourceType?: "browser" | "server" | "mobile";
};

// Note: For some reason the `sentry/core` module doesn't have these additional properties
Expand Down
Loading