Skip to content
This repository has been archived by the owner on Jul 19, 2023. It is now read-only.

feat(ui): explore page #704

Merged
merged 9 commits into from
May 22, 2023
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
Next Next commit
feat: implements explore page
  • Loading branch information
petethepig committed May 19, 2023
commit 60b09c02571bc11c8140d2efc78733842b265251
19 changes: 19 additions & 0 deletions pkg/querier/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/prometheus/common/model"
"github.com/prometheus/prometheus/model/labels"
"github.com/prometheus/prometheus/promql/parser"
"github.com/pyroscope-io/pyroscope/pkg/structs/flamebearer"
"github.com/pyroscope-io/pyroscope/pkg/util/attime"
"golang.org/x/sync/errgroup"
"google.golang.org/grpc/codes"
Expand Down Expand Up @@ -134,6 +135,8 @@ func (q *QueryHandlers) Render(w http.ResponseWriter, req *http.Request) {
return
}

groupBy := req.URL.Query()["groupBy"]

var resFlame *connect.Response[querierv1.SelectMergeStacktracesResponse]
g, ctx := errgroup.WithContext(req.Context())
g.Go(func() error {
Expand All @@ -151,6 +154,7 @@ func (q *QueryHandlers) Render(w http.ResponseWriter, req *http.Request) {
Start: selectParams.Start,
End: selectParams.End,
Step: timelineStep,
GroupBy: groupBy,
}))

return err
Expand All @@ -170,6 +174,21 @@ func (q *QueryHandlers) Render(w http.ResponseWriter, req *http.Request) {
fb := ExportToFlamebearer(resFlame.Msg.Flamegraph, profileType)
fb.Timeline = timeline.New(seriesVal, selectParams.Start, selectParams.End, int64(timelineStep))

if len(groupBy) > 0 {
fb.Groups = make(map[string]*flamebearer.FlamebearerTimelineV1)
for _, s := range resSeries.Msg.Series {
key := "*"
for _, l := range s.Labels {
// right now we only support one group by
if l.Name == groupBy[0] {
key = l.Value
break
}
}
fb.Groups[key] = timeline.New(s, selectParams.Start, selectParams.End, int64(timelineStep))
}
}

w.Header().Add("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(fb); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
Expand Down
4 changes: 4 additions & 0 deletions public/app/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { createBrowserHistory } from 'history';
import { ROUTES } from './pages/routes';
import { SingleView } from './pages/SingleView';
import { ComparisonView } from './pages/ComparisonView';
import { ExploreView } from './pages/ExploreView';
import { DiffView } from './pages/DiffView';
import { LoadAppNames } from './components/LoadAppNames';
import { Sidebar } from './components/Sidebar';
Expand All @@ -31,6 +32,9 @@ function App() {
<div className="pyroscope-app">
<LoadAppNames>
<Switch>
<Route exact path={ROUTES.EXPLORE_VIEW}>
<ExploreView />
</Route>
<Route exact path={ROUTES.CONTINOUS_SINGLE_VIEW}>
<SingleView />
</Route>
Expand Down
14 changes: 13 additions & 1 deletion public/app/components/Sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react';
import { faWindowMaximize } from '@fortawesome/free-regular-svg-icons';
import { faWindowMaximize } from '@fortawesome/free-regular-svg-icons/faWindowMaximize';
import { faSearch } from '@fortawesome/free-solid-svg-icons/faSearch';
import { faChartBar } from '@fortawesome/free-solid-svg-icons/faChartBar';
import { faColumns } from '@fortawesome/free-solid-svg-icons/faColumns';
import { faChevronLeft } from '@fortawesome/free-solid-svg-icons/faChevronLeft';
Expand Down Expand Up @@ -59,6 +60,17 @@ export function Sidebar() {
</SidebarHeader>
<SidebarContent>
<Menu iconShape="square" popperArrow>
<MenuItem
active={isRouteActive(pathname, ROUTES.EXPLORE_VIEW)}
icon={<Icon icon={faSearch} />}
>
Explore View
<NavLink
activeClassName="active-route"
to={{ pathname: ROUTES.EXPLORE_VIEW, search }}
exact
/>
</MenuItem>
<MenuItem
active={isRouteActive(pathname, ROUTES.CONTINOUS_SINGLE_VIEW)}
icon={<Icon icon={faWindowMaximize} />}
Expand Down
56 changes: 52 additions & 4 deletions public/app/overrides/services/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
Profile,
Groups,
FlamebearerProfileSchema,
GroupsSchema,
} from '@pyroscope/models/src';
import { z } from 'zod';
import type { ZodError } from 'zod';
Expand Down Expand Up @@ -112,17 +113,64 @@ export async function renderDiff(
);
}

interface renderExploreProps extends Omit<renderSingleProps, 'maxNodes'> {
groupBy: string;
grouByTagValue: string;
}

export interface RenderExploreOutput {
profile: Profile;
groups: Groups;
}
export async function renderExplore(
props: unknown,
props: renderExploreProps,
controller?: {
signal?: AbortSignal;
}
) {
return Result.err<RenderExploreOutput, { message: string }>({
message: 'TODO: implement ',
): Promise<Result<RenderExploreOutput, RequestError | ZodError>> {
const url = buildRenderURL(props);
const response = await request(`/pyroscope/${url}&format=json`, {
signal: controller?.signal,
});
if (response.isErr) {
return Result.err<RenderExploreOutput, RequestError>(response.error);
}
const parsed = FlamebearerProfileSchema.merge(
z.object({ timeline: TimelineSchema })
)
.merge(
z.object({
telemetry: z.object({}).passthrough().optional(),
annotations: defaultAnnotationsSchema,
})
)
.merge(
z.object({
groups: z.preprocess((groups) => {
const groupNames = Object.keys(groups as Groups);
return groupNames.length
? groupNames
.filter((g) => !!g.trim())
.reduce(
(acc, current) => ({
...acc,
[current]: (groups as Groups)[current],
}),
{}
)
: groups;
}, GroupsSchema),
})
)
.safeParse(response.value);
if (parsed.success) {
const profile = parsed.data;
const { groups, annotations } = parsed.data;
return Result.ok({
profile,
groups,
annotations,
});
}
return Result.err(parsed.error);
}
5 changes: 5 additions & 0 deletions public/app/pages/ExploreView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import TagExplorerView from '@webapp/pages/TagExplorerView';

export function ExploreView() {
return <TagExplorerView />;
}
1 change: 1 addition & 0 deletions public/app/pages/routes.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export enum ROUTES {
CONTINOUS_SINGLE_VIEW = '/',
EXPLORE_VIEW = '/explore',
COMPARISON_VIEW = '/comparison',
COMPARISON_DIFF_VIEW = '/comparison-diff',
}
Expand Down