Skip to content

Commit

Permalink
move components and utils to integration
Browse files Browse the repository at this point in the history
  • Loading branch information
Lms24 committed Oct 31, 2023
1 parent 6ff90aa commit 5ed8c0f
Show file tree
Hide file tree
Showing 23 changed files with 94 additions and 121 deletions.
76 changes: 12 additions & 64 deletions src/components/Overview.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,16 @@
import { useState } from 'react';
import { useSentryEvents } from '../lib/useSentryEvents';
import Tabs from './Tabs';
import TraceList from './TraceList';
import EventList from './EventList';
import useKeyPress from '~/lib/useKeyPress';
import EventDetails from './EventDetails';
import TraceDetails from './TraceDetails';
import dataCache from '~/lib/dataCache';
import { useNavigation } from '~/lib/useNavigation';
import SdkList from './SdkList';
import { useSentryTraces } from '~/lib/useSentryTraces';
import { IntegrationTab } from '~/integrations/integration';
import EventDetails from '~/integrations/sentry/components/EventDetails';
import TraceDetails from '~/integrations/sentry/components/TraceDetails';

const DEFAULT_TAB = 'errors';

export default function Overview({ integrationData }: { integrationData: Record<string, Array<unknown>> }) {
const [activeTab, setActiveTab] = useState(DEFAULT_TAB);

const events = useSentryEvents();
const traces = useSentryTraces();

const { integrations, traceId, setTraceId, eventId, setEventId, setSpanId } = useNavigation();

useKeyPress('Escape', () => {
Expand All @@ -28,57 +19,22 @@ export default function Overview({ integrationData }: { integrationData: Record<
setSpanId(null);
});

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const tabs: IntegrationTab<any>[] = [
{
id: 'errors',
title: 'Errors',
count: events.filter(e => 'exception' in e).length,
active: activeTab === 'errors' && (!traceId || !!eventId),
onSelect: () => {
setEventId(null);
setTraceId(null);
setActiveTab('errors');
},
},
{
id: 'traces',
title: 'Traces',
count: traces.length,
active: activeTab === 'traces' && (!eventId || !!traceId),
onSelect: () => {
setEventId(null);
setTraceId(null);
setActiveTab('traces');
},
},
{
id: 'sdks',
title: 'SDKs',
active: activeTab === 'sdks' && !eventId && !traceId,
onSelect: () => {
setEventId(null);
setTraceId(null);
setActiveTab('sdks');
},
},
];

integrations.forEach(integration => {
if (integration.tabs) {
integration.tabs.forEach(tab => {
tabs.push({
const tabs = integrations
.map(integration => {
if (integration.tabs) {
return integration.tabs.map(tab => ({
...tab,
active: activeTab === tab.id,
onSelect: () => {
setEventId(null);
setTraceId(null);
setActiveTab(tab.id);
},
});
});
}
});
}));
}
return [];
})
.flat();

if (eventId) {
const activeEvent = dataCache.getEventById(eventId);
Expand Down Expand Up @@ -110,15 +66,7 @@ export default function Overview({ integrationData }: { integrationData: Record<
return (
<>
<Tabs tabs={tabs} />
{activeTab === 'traces' ? (
<TraceList />
) : activeTab === 'errors' ? (
<EventList events={events} />
) : activeTab === 'sdks' ? (
<SdkList />
) : (
<TabContent integrationData={integrationData} />
)}
<TabContent integrationData={integrationData} />
</>
);
}
1 change: 1 addition & 0 deletions src/components/Trigger.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useSentryTraces } from '~/lib/useSentryTraces';
import { useSentryEvents } from '../lib/useSentryEvents';

export default function Trigger({ isOpen, setOpen }: { isOpen: boolean; setOpen: (value: boolean) => void }) {
// TODO: replace w/ generic counter
const events = useSentryEvents();
const traces = useSentryTraces();

Expand Down
38 changes: 4 additions & 34 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@ import ReactDOM from 'react-dom/client';
import fontStyles from '@fontsource/raleway/index.css?inline';

import App from './App.tsx';
import { SentryEvent } from './types.ts';
import type { Integration } from './integrations/integration';
import { initIntegrations } from './integrations/integration';
import globalStyles from './index.css?inline';
import dataCache from './lib/dataCache.ts';

import type { Envelope } from '@sentry/types';
// TODO: get rid of this here
import dataCache from './lib/dataCache.ts';

export { default as sentry } from './integrations/sentry';
export { default as console } from './integrations/console';
Expand Down Expand Up @@ -85,14 +84,6 @@ export async function init({
});
}

export function pushEvent(event: SentryEvent) {
dataCache.pushEvent(event);
}

export function pushEnvelope(envelope: Envelope) {
dataCache.pushEnvelope(envelope);
}

export function connectToSidecar(
sidecarUrl: string,
contentTypeToIntegrations: Map<string, Integration<unknown>[]>,
Expand All @@ -101,31 +92,9 @@ export function connectToSidecar(
console.log('[Spotlight] Connecting to sidecar at', sidecarUrl);
const source = new EventSource(sidecarUrl);

source.addEventListener('application/x-sentry-envelope', event => {
console.log('[spotlight] Received new envelope');
const [rawHeader, ...rawEntries] = event.data.split('\n');
const header = JSON.parse(rawHeader) as Envelope[0];
console.log(`[Spotlight] Received new envelope from SDK ${header.sdk?.name || '(unknown)'}`);

const items: Envelope[1][] = [];
for (let i = 0; i < rawEntries.length; i += 2) {
items.push([JSON.parse(rawEntries[i]), JSON.parse(rawEntries[i + 1])]);
}

const envelope = [header, items] as Envelope;
console.log('[Spotlight]', envelope);

dataCache.pushEnvelope(envelope);
});

const contentTypeListeners: [contentType: string, listener: (event: MessageEvent) => void][] = [];

for (const [contentType, integrations] of contentTypeToIntegrations.entries()) {
// TODO: remove this, for now this isolates the sentry stuff from the new integrations API
if (contentType === 'application/x-sentry-envelope') {
continue;
}

const listener = (event: MessageEvent): void => {
console.log(`[spotlight] Received new ${contentType} event`);
integrations.forEach(integration => {
Expand Down Expand Up @@ -161,12 +130,13 @@ export function connectToSidecar(

source.addEventListener('open', () => {
console.log('[Spotlight] open');
// TODO: remove from datacache and useEffect instead
dataCache.setOnline(true);
});

source.addEventListener('error', err => {
dataCache.setOnline(false);

// TODO: remove from datacache and useEffect instead
console.error('EventSource failed:', err);
});

Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { SentryEvent } from '../types';
import { SentryEvent } from '~/types';
import Time from './Time';

const EXAMPLE_BREADCRUMB = `Sentry.addBreadcrumb({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { SentryEvent } from '../types';
import { SentryEvent } from '~/types';

const EXAMPLE_CONTEXT = `Sentry.setContext("character", {
name: "Mighty Fighter",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { useState } from 'react';
import { SentryEvent } from '../types';
import Error, { ErrorTitle } from './Events/Error';
import Tabs from './Tabs';
import EventContexts from './EventContexts';
import useKeyPress from '~/lib/useKeyPress';
import PlatformIcon from './PlatformIcon';
import { useNavigation } from '~/lib/useNavigation';
import EventBreadcrumbs from './EventBreadcrumbs';
import { SentryEvent } from '~/types';
import Tabs from '~/components/Tabs';

function renderEvent(event: SentryEvent) {
if ('exception' in event) return <Error event={event} />;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@ import { ErrorSummary } from './Events/Error';
import TimeSince from './TimeSince';
import PlatformIcon from './PlatformIcon';
import { useNavigation } from '~/lib/useNavigation';
import { useSentryEvents } from '~/lib/useSentryEvents';

function renderEvent(event: SentryEvent) {
if ('exception' in event) return <ErrorSummary event={event} />;
return null;
}

export default function EventList({ events }: { events: SentryEvent[] }) {
export default function EventList() {
const { setEventId } = useNavigation();
const events = useSentryEvents();

const matchingEvents = events.filter(e => e.type !== 'transaction');

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { SentryErrorEvent } from '../../types';
import { SentryErrorEvent } from '~/types';
import Frame from './Error/Frame';

export function ErrorTitle({ event }: { event: SentryErrorEvent }) {
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import DateTime from '~/components/DateTime';
import useKeyPress from '~/lib/useKeyPress';

import { format as formatSQL } from 'sql-formatter';
import { getDuration } from '~/lib/duration';
import SpanTree from './SpanTree';
import { SentryErrorEvent, Span, TraceContext } from '~/types';
import { ErrorTitle } from './Events/Error';
import dataCache from '~/lib/dataCache';
import { useNavigation } from '~/lib/useNavigation';
import DateTime from './DateTime';
import { getDuration } from '../utils/duration';

function formatSpanDescription(desc: string) {
if (desc.match(/^(SELECT|INSERT|UPDATE|DELETE|TRUNCATE|ALTER) /i)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import classNames from '~/lib/classNames';
import { Span, TraceContext } from '~/types';
import PlatformIcon from './PlatformIcon';
import { getDuration, getSpanDurationClassName } from '~/lib/duration';
import { useNavigation } from '~/lib/useNavigation';
import { getDuration, getSpanDurationClassName } from '../utils/duration';

export default function SpanTree({
traceContext,
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { Trace } from '../types';
import useKeyPress from '~/lib/useKeyPress';
import SpanDetails from './SpanDetails';
import SpanTree from './SpanTree';
import { getDuration } from '~/lib/duration';
import DateTime from './DateTime';
import PlatformIcon from './PlatformIcon';
import { useNavigation } from '~/lib/useNavigation';
import dataCache from '~/lib/dataCache';
import { Trace } from '~/types';
import { getDuration } from '../utils/duration';

export default function TraceDetails({ trace }: { trace: Trace }) {
useKeyPress('Escape', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { getDuration } from '~/lib/duration';
import classNames from '~/lib/classNames';
import TimeSince from './TimeSince';
import PlatformIcon from './PlatformIcon';
import { useSentryTraces } from '~/lib/useSentryTraces';
import { useNavigation } from '~/lib/useNavigation';
import { getDuration } from '../utils/duration';

export default function TraceList() {
const traceList = useSentryTraces();
Expand Down
63 changes: 59 additions & 4 deletions src/integrations/sentry/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,79 @@ import { serializeEnvelope } from '@sentry/utils';

import type { Integration } from '../integration';

import dataCache from '../../lib/dataCache';
import EventList from './components/EventList';
import TraceList from './components/TraceList';
import SdkList from './components/SdkList';

const HEADER = 'application/x-sentry-envelope';

export default function sentryIntegration() {
return {
name: 'sentry',
forwardedContentType: [HEADER],

setup: () => {
console.log('sentry integration init 2');
hookIntoSentry();
},
} satisfies Integration;

processEvent({ data }) {
console.log('[spotlight] Received new envelope');
const [rawHeader, ...rawEntries] = data.split('\n');
const header = JSON.parse(rawHeader) as Envelope[0];
console.log(`[Spotlight] Received new envelope from SDK ${header.sdk?.name || '(unknown)'}`);

const items: Envelope[1][] = [];
for (let i = 0; i < rawEntries.length; i += 2) {
items.push([JSON.parse(rawEntries[i]), JSON.parse(rawEntries[i + 1])]);
}

const envelope = [header, items] as Envelope;
dataCache.pushEnvelope(envelope);

return envelope;
},
tabs: [
{
id: 'errors',
title: 'Errors',
content: EventList,
},
{
id: 'traces',
title: 'Traces',
content: TraceList,
},
{
id: 'sdks',
title: 'SDKs',
content: SdkList,
},
],
} satisfies Integration<Envelope>;
}

type WindowWithSentry = Window & {
__SENTRY__?: {
hub: {
_stack: {
client: {
setupIntegrations: (val: boolean) => void;
on: (event: string, callback: (envelope: Envelope) => void) => void;
};
}[];
};
};
};

function hookIntoSentry() {
// A very hacky way to hook into Sentry's SDK
// but we love hacks
(window as any).__SENTRY__.hub._stack[0].client.setupIntegrations(true);
(window as any).__SENTRY__.hub._stack[0].client.on('beforeEnvelope', (envelope: Envelope) => {
const sentryHub = (window as WindowWithSentry).__SENTRY__?.hub;
const sentryClient = sentryHub?._stack[0]?.client;

sentryClient?.setupIntegrations(true);
sentryClient?.on('beforeEnvelope', (envelope: Envelope) => {
fetch('http://localhost:8969/stream', {
method: 'POST',
body: serializeEnvelope(envelope),
Expand Down
File renamed without changes.
3 changes: 0 additions & 3 deletions src/lib/math.ts

This file was deleted.

2 changes: 1 addition & 1 deletion website/src/spotlight/overlay/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export default {
id: 'spotlight-plugin',
name: 'Sentry Spotlight',
icon: sentrylogo,
init(canvas, eventTarget) {
init(_canvas, eventTarget) {
eventTarget.dispatchEvent(
new CustomEvent('plugin-notification', {
detail: {
Expand Down
Loading

0 comments on commit 5ed8c0f

Please sign in to comment.