Skip to content

Commit

Permalink
allow filtering for errors with sessions (highlight#6728)
Browse files Browse the repository at this point in the history
## Summary

Adds the `HasSession` column to clickhouse error objects for searching
for errors with sessions.
Stores the session id on clickhouse error objects in case we have a use
for that.

## How did you test this change?

Local deploy
<img width="1644" alt="Screenshot 2023-09-26 at 1 37 31 PM"
src="https://github.com/highlight/highlight/assets/1351531/fe35a175-b890-4bfb-8fe6-3d09b90321da">

<img width="1074" alt="Screenshot 2023-09-26 at 2 03 42 PM"
src="https://github.com/highlight/highlight/assets/1351531/d3938e95-b2f3-40e3-b15d-33bbb52725f5">


## Are there any deployment considerations?

Will backfill data with
https://github.com/highlight/highlight/blob/main/backend/migrations/cmd/backfill-errors-clickhouse/main.go#L1

## Does this work require review from our design team?

Yes @julian-highlight
  • Loading branch information
Vadman97 authored Sep 27, 2023
1 parent 5a521b9 commit 09bde30
Show file tree
Hide file tree
Showing 12 changed files with 84 additions and 18 deletions.
2 changes: 2 additions & 0 deletions backend/clickhouse/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ type ClickhouseErrorObject struct {
ProjectID int32
Timestamp time.Time
ErrorGroupID int64
HasSession bool
ID int64
Browser string
Environment string
Expand Down Expand Up @@ -104,6 +105,7 @@ func (client *Client) WriteErrorObjects(ctx context.Context, objects []*model.Er
ProjectID: int32(object.ProjectID),
Timestamp: object.Timestamp,
ErrorGroupID: int64(object.ErrorGroupID),
HasSession: object.SessionID != nil,
ID: int64(object.ID),
Browser: object.Browser,
Environment: object.Environment,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
alter table error_objects
drop column HasSession;
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
alter table error_objects
add column HasSession Boolean;
1 change: 1 addition & 0 deletions backend/clickhouse/querybuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ const (
var customFieldTypes map[string]FieldType = map[string]FieldType{
"viewed": boolean,
"viewed_by_me": viewedByMe,
"has_session": boolean,
"has_errors": boolean,
"has_rage_clicks": boolean,
"processed": boolean,
Expand Down
1 change: 1 addition & 0 deletions backend/clickhouse/sessions.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ var fieldMap map[string]string = map[string]string{
"processed": "Processed",
"has_rage_clicks": "HasRageClicks",
"has_errors": "HasErrors",
"has_session": "HasSession",
"length": "Length",
"active_length": "ActiveLength",
"environment": "Environment",
Expand Down
5 changes: 5 additions & 0 deletions backend/store/error_groups.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ func (store *Store) ListErrorObjects(errorGroup model.ErrorGroup, params ListErr
Where("sessions.email ILIKE ?", "%"+val[0]+"%")
}
}
if val, ok := filters.Attributes["has_session"]; ok {
if len(val) > 0 && val[0] == "true" {
query.Where("COALESCE(error_objects.session_id, 0) > 0")
}
}
}

var (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@ Filtered errors do not count towards your billing quota.

There are several options for filtering errors, all of which can be found in the "Error Monitoring" tab of your [project settings](https://app.highlight.io/settings). Details on each option are below.

## Show errors that have an associated frontend session recorded.
You can use the `disableSessionRecording` setting to record frontend errors without recording a session.

To find errors that have a session associated, you can use the `Has Sessions` filter in the errors query builder

![](/images/docs/filtering-errors/has-sessions.png)

Once you open an error group instance view, check the `Only instances with recorded sessions` box to filter the instances.
![](/images/docs/filtering-errors/error-object-with-session.png)

## Filter errors emitted by browser extensions
If your users are using browser extensions, you may see errors that are not relevant to your application. You can filter these errors by checking the "Filter errors thrown by browser extensions" box in your [project settings](https://app.highlight.io/settings).

Expand Down
3 changes: 3 additions & 0 deletions frontend/src/components/QueryBuilder/QueryBuilder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -834,6 +834,7 @@ const LABEL_MAP: { [key: string]: string } = {
timestamp: 'Date',
has_rage_clicks: 'Has Rage Clicks',
has_errors: 'Has Errors',
has_session: 'Has Sessions',
pages_visited: 'Pages Visited',
landing_page: 'Landing Page',
exit_page: 'Exit Page',
Expand Down Expand Up @@ -1026,6 +1027,8 @@ const getIcon = (value: string): JSX.Element | undefined => {
return <IconSolidLink />
case 'error-field_service_name':
return <IconSolidCubeTransparent />
case 'error-field_has_session':
return <IconSolidDesktopComputer />
}
const type = getType(value)
const mapped = type === CUSTOM_TYPE ? 'session' : type
Expand Down
68 changes: 50 additions & 18 deletions frontend/src/pages/ErrorsV2/ErrorInstances/ErrorInstances.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@ import {
Callout,
Form,
FormState,
IconSolidCheckCircle,
IconSolidSearch,
Stack,
SwitchButton,
Text,
useFormStore,
} from '@highlight-run/ui'
import useLocalStorage from '@rehooks/local-storage'
import React, { useState } from 'react'

import { Button } from '@/components/Button'
Expand All @@ -32,16 +35,23 @@ type Pagination = {

export interface SearchFormState {
email: string
hasSession: boolean
}

export const ErrorInstances = ({ errorGroup }: Props) => {
const [hasSessionDefault, setHasSessionDefault] = useLocalStorage<boolean>(
'highlight-error-object-instances-has-session',
false,
)
const [currentSearchEmail, setCurrentSearchEmail] = React.useState('')
const formStore = useFormStore<SearchFormState>({
defaultValues: {
email: '',
hasSession: hasSessionDefault,
},
})
const email = formStore.useValue('email')
const hasSession = formStore.useValue('hasSession')
const [query, setQuery] = useState('')

const [pagination, setPagination] = useState<Pagination>({
Expand All @@ -60,10 +70,14 @@ export const ErrorInstances = ({ errorGroup }: Props) => {

const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault()
setQuery(`email:${email}`)
setQuery(`${hasSession ? 'has_session:true ' : ''}email:${email}`)
setCurrentSearchEmail(email)
}

React.useEffect(() => {
setHasSessionDefault(hasSession)
}, [hasSession, setHasSessionDefault])

if (loading) {
return (
<ErrorInstancesContainer
Expand Down Expand Up @@ -181,27 +195,45 @@ const ErrorInstancesContainer: React.FC<
childrenBoxProps.display = 'flex'
childrenBoxProps.alignItems = 'center'
}

const hasSession = form.useValue('hasSession')
return (
<Stack direction="column">
<Box my="8">
<Form store={form} onSubmit={onSubmit}>
<Box
position="relative"
alignItems="stretch"
display="flex"
flexGrow={1}
color="weak"
>
<IconSolidSearch
size={16}
className={styles.searchIcon}
/>
<Form.Input
name={form.names.email}
placeholder="Search for email"
style={{ paddingLeft: 28, width: 310 }}
/>
<Box display="flex" alignItems="center" gap="12">
<Box
position="relative"
alignItems="stretch"
display="flex"
color="weak"
>
<IconSolidSearch
size={16}
className={styles.searchIcon}
/>
<Form.Input
name={form.names.email}
placeholder="Search for email"
style={{ paddingLeft: 28, width: 310 }}
/>
</Box>
<Box display="flex" alignItems="center" gap="6">
<SwitchButton
type="submit"
size="xxSmall"
iconLeft={<IconSolidCheckCircle size={12} />}
checked={hasSession}
onChange={() => {
form.setValue(
form.names.hasSession,
!hasSession,
)
}}
/>
<Text size="xSmall">
Only instances with recorded sessions
</Text>
</Box>
</Box>
</Form>
</Box>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,14 @@ export const CUSTOM_FIELDS: CustomField[] = [
type: 'text',
},
},
{
type: ERROR_FIELD_TYPE,
name: 'has_session',
options: {
operators: ['is', 'is_not'],
type: 'boolean',
},
},
]

const ErrorQueryBuilder = (props: { readonly?: boolean }) => {
Expand Down
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.

0 comments on commit 09bde30

Please sign in to comment.