Skip to content

Commit

Permalink
feat: display line context in stack frames (#26254)
Browse files Browse the repository at this point in the history
  • Loading branch information
daibhin authored Nov 21, 2024
1 parent 5f61d32 commit fb17df2
Show file tree
Hide file tree
Showing 22 changed files with 389 additions and 167 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 9 additions & 4 deletions frontend/src/lib/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ import {
} from '~/types'

import { AlertType, AlertTypeWrite } from './components/Alerts/types'
import { ErrorTrackingStackFrameContext } from './components/Errors/types'
import {
ACTIVITY_PAGE_SIZE,
DashboardPrivilegeLevel,
Expand Down Expand Up @@ -719,8 +720,12 @@ class ApiRequest {
return this.errorTracking().addPathComponent('upload_source_maps')
}

public errorTrackingStackFrames(ids: string[]): ApiRequest {
return this.errorTracking().addPathComponent('stack_frames').withQueryString({ ids })
public errorTrackingStackFrames(): ApiRequest {
return this.errorTracking().addPathComponent('stack_frames')
}

public errorTrackingStackFrameContexts(ids: string[]): ApiRequest {
return this.errorTrackingStackFrames().addPathComponent('contexts').withQueryString(toParams({ ids }, true))
}

// # Warehouse
Expand Down Expand Up @@ -1862,8 +1867,8 @@ const api = {
return await new ApiRequest().errorTrackingUploadSourceMaps().create({ data })
},

async fetchStackFrames(ids: string[]): Promise<{ content: string }> {
return await new ApiRequest().errorTrackingStackFrames(ids).get()
async fetchStackFrames(ids: string[]): Promise<Record<string, ErrorTrackingStackFrameContext>> {
return await new ApiRequest().errorTrackingStackFrameContexts(ids).get()
},
},

Expand Down
1 change: 0 additions & 1 deletion frontend/src/lib/components/CodeSnippet/CodeSnippet.scss
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@

pre {
padding: 0.75rem 1rem;
margin: 0; // Reset
background: var(--accent-3000) !important;
border: solid 1px var(--border-3000) !important;
border-radius: var(--radius) !important;
Expand Down
82 changes: 72 additions & 10 deletions frontend/src/lib/components/CodeSnippet/CodeSnippet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,53 @@ export enum Language {
Kotlin = 'kotlin',
}

export const getLanguage = (lang: string): Language => {
switch (lang) {
case 'bash':
return Language.Bash
case 'jsx':
return Language.JSX
case 'javascript':
return Language.JavaScript
case 'java':
return Language.Java
case 'ruby':
return Language.Ruby
case 'objectivec':
return Language.ObjectiveC
case 'swift':
return Language.Swift
case 'elixir':
return Language.Elixir
case 'php':
return Language.PHP
case 'python':
return Language.Python
case 'dart':
return Language.Dart
case 'go':
return Language.Go
case 'json':
return Language.JSON
case 'yaml':
return Language.YAML
case 'html':
return Language.HTML
case 'xml':
return Language.XML
case 'http':
return Language.HTTP
case 'markup':
return Language.Markup
case 'sql':
return Language.SQL
case 'kotlin':
return Language.Kotlin
default:
return Language.Text
}
}

SyntaxHighlighter.registerLanguage(Language.Bash, bash)
SyntaxHighlighter.registerLanguage(Language.JSX, jsx)
SyntaxHighlighter.registerLanguage(Language.JavaScript, javascript)
Expand Down Expand Up @@ -98,8 +145,6 @@ export function CodeSnippet({
thing = 'snippet',
maxLinesWithoutExpansion,
}: CodeSnippetProps): JSX.Element | null {
const { isDarkModeOn } = useValues(themeLogic)

const [expanded, setExpanded] = useState(false)
const [indexOfLimitNewline, setIndexOfLimitNewline] = useState(
maxLinesWithoutExpansion ? indexOfNth(text || '', '\n', maxLinesWithoutExpansion) : -1
Expand Down Expand Up @@ -136,14 +181,7 @@ export function CodeSnippet({
noPadding
/>
</div>
<SyntaxHighlighter
style={isDarkModeOn ? darkTheme : lightTheme}
language={language}
wrapLines={wrap}
lineProps={{ style: { whiteSpace: 'pre-wrap', overflowWrap: 'anywhere' } }}
>
{displayedText}
</SyntaxHighlighter>
<CodeLine text={displayedText} language={language} wrapLines={wrap} />
{indexOfLimitNewline !== -1 && (
<LemonButton
onClick={() => setExpanded(!expanded)}
Expand All @@ -163,6 +201,30 @@ export function CodeSnippet({
)
}

export function CodeLine({
text,
wrapLines,
language,
}: {
text: string
wrapLines: boolean
language: Language
}): JSX.Element {
const { isDarkModeOn } = useValues(themeLogic)

return (
<SyntaxHighlighter
style={isDarkModeOn ? darkTheme : lightTheme}
language={language}
wrapLines={wrapLines}
lineProps={{ style: { whiteSpace: 'pre-wrap', overflowWrap: 'anywhere' } }}
PreTag={({ children }) => <pre className="bg-transparent m-0">{children}</pre>}
>
{text}
</SyntaxHighlighter>
)
}

function indexOfNth(string: string, character: string, n: number): number {
let count = 0,
indexSoFar = 0
Expand Down
167 changes: 85 additions & 82 deletions frontend/src/lib/components/Errors/ErrorDisplay.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,45 @@
import { Meta } from '@storybook/react'
import { ErrorDisplay } from 'lib/components/Errors/ErrorDisplay'

import { mswDecorator } from '~/mocks/browser'
import { EventType } from '~/types'

const meta: Meta<typeof ErrorDisplay> = {
title: 'Components/Errors/Error Display',
component: ErrorDisplay,
decorators: [
mswDecorator({
get: {
'/api/projects/:team_id/error_tracking/stack_frames/contexts/': {
rawId: {
before: [
{
number: 7,
line: ' const displayFrames = showAllFrames ? frames : frames.filter((f) => f.in_app)',
},
{
number: 8,
line: '',
},
{ number: 9, line: ' useEffect(() => {' },
],
line: { number: 10, line: ' loadFrameContexts({ frames })' },
after: [
{ number: 11, line: ' }, [frames, loadFrameContexts])' },
{
number: 12,
line: '',
},
{
number: 13,
line: ' const initiallyActiveIndex = displayFrames.findIndex((f) => f.in_app) || 0',
},
],
},
},
},
}),
],
}
export default meta

Expand Down Expand Up @@ -55,13 +89,14 @@ function errorProperties(properties: Record<string, any>): EventType['properties
synthetic: true,
},
stacktrace: {
type: 'resolved',
frames: [
{
colno: 0,
filename: 'https://app.posthog.com/home',
function: '?',
column: 0,
source: 'https://app.posthog.com/home',
resolved_name: '?',
in_app: true,
lineno: 0,
line: 0,
},
],
},
Expand Down Expand Up @@ -141,13 +176,14 @@ export function AnonymousErrorWithStackTrace(): JSX.Element {
type: 'Error',
value: 'wat123',
stacktrace: {
type: 'resolved',
frames: [
{
filename: '<anonymous>',
function: '?',
source: '<anonymous>',
resolved_name: '?',
in_app: true,
lineno: 1,
colno: 26,
line: 1,
column: 26,
},
],
},
Expand All @@ -172,48 +208,14 @@ export function ChainedErrorStack(): JSX.Element {
stacktrace: {
frames: [
{
filename: 'example2.py',
abs_path: '/posthog-python/example2.py',
function: 'will_raise',
module: '__main__',
lineno: 33,
pre_context: [
'def more_obfuscation():',
' print(3 / 0)',
'',
'def will_raise():',
' try:',
],
context_line: ' more_obfuscation()',
post_context: [
' except Exception as e:',
' raise CustomException("This is a custom exception") from e',
'',
'will_raise()',
'exit()',
],
source: '/posthog-python/example2.py',
resolved_name: 'will_raise',
line: 33,
},
{
filename: 'example2.py',
abs_path: '/posthog-python/example2.py',
function: 'more_obfuscation',
module: '__main__',
lineno: 29,
pre_context: [
'',
'class CustomException(Exception):',
' pass',
'',
'def more_obfuscation():',
],
context_line: ' print(3 / 0)',
post_context: [
'',
'def will_raise():',
' try:',
' more_obfuscation()',
' except Exception as e:',
],
source: '/posthog-python/example2.py',
resolved_name: 'more_obfuscation',
line: 29,
},
],
},
Expand All @@ -225,42 +227,43 @@ export function ChainedErrorStack(): JSX.Element {
stacktrace: {
frames: [
{
filename: 'example2.py',
abs_path: '/Users/neilkakkar/Project/posthog-python/example2.py',
function: '<module>',
module: '__main__',
lineno: 37,
pre_context: [
' try:',
' more_obfuscation()',
' except Exception as e:',
' raise CustomException("This is a custom exception") from e',
'',
],
context_line: 'will_raise()',
post_context: [
'exit()',
'',
'',
'# print(posthog.get_all_flags("distinct_id_random_22"))',
'# print(',
],
source: '/Users/neilkakkar/Project/posthog-python/example2.py',
resolved_name: '<module>',
line: 37,
},
{
filename: 'example2.py',
abs_path: '/Users/neilkakkar/Project/posthog-python/example2.py',
function: 'will_raise',
module: '__main__',
lineno: 35,
pre_context: [
'',
'def will_raise():',
' try:',
' more_obfuscation()',
' except Exception as e:',
],
context_line: ' raise CustomException("This is a custom exception") from e',
post_context: ['', 'will_raise()', 'exit()', '', ''],
source: '/Users/neilkakkar/Project/posthog-python/example2.py',
resolved_name: 'will_raise',
line: 35,
},
],
},
},
],
})}
/>
)
}

export function StackTraceWithLineContext(): JSX.Element {
return (
<ErrorDisplay
eventProperties={errorProperties({
$exception_list: [
{
type: 'Error',
value: 'wat123',
stacktrace: {
type: 'resolved',
frames: [
{
raw_id: 'rawId',
source: '<anonymous>',
resolved_name: '?',
in_app: true,
line: 1,
column: 26,
lang: 'javascript',
},
],
},
Expand Down
Loading

0 comments on commit fb17df2

Please sign in to comment.