Skip to content

Commit

Permalink
ranking: Show progress in UI (#51888)
Browse files Browse the repository at this point in the history
  • Loading branch information
efritz committed May 17, 2023
1 parent b7af519 commit 22abdcb
Show file tree
Hide file tree
Showing 36 changed files with 1,084 additions and 36 deletions.
2 changes: 2 additions & 0 deletions client/web/BUILD.bazel

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions client/web/src/enterprise/codeintel/admin/AdminCodeIntelArea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { CodeIntelInferenceConfigurationPageProps } from '../configuration/pages
import { GlobalDashboardPageProps } from '../dashboard/pages/GlobalDashboardPage'
import { CodeIntelPreciseIndexesPageProps } from '../indexes/pages/CodeIntelPreciseIndexesPage'
import { CodeIntelPreciseIndexPageProps } from '../indexes/pages/CodeIntelPreciseIndexPage'
import { CodeIntelRankingPageProps } from '../ranking/pages/CodeIntelRankingPage'

export interface AdminCodeIntelAreaRouteContext extends TelemetryProps {
authenticatedUser: AuthenticatedUser | null
Expand All @@ -40,6 +41,11 @@ const CodeIntelInferenceConfigurationPage = lazyComponent<
'CodeIntelInferenceConfigurationPage'
>(() => import('../configuration/pages/CodeIntelInferenceConfigurationPage'), 'CodeIntelInferenceConfigurationPage')

const CodeIntelRankingPage = lazyComponent<CodeIntelRankingPageProps, 'CodeIntelRankingPage'>(
() => import('../ranking/pages/CodeIntelRankingPage'),
'CodeIntelRankingPage'
)

const CodeIntelConfigurationPolicyPage = lazyComponent<
CodeIntelConfigurationPolicyPageProps,
'CodeIntelConfigurationPolicyPage'
Expand Down Expand Up @@ -87,6 +93,12 @@ export const codeIntelAreaRoutes: readonly AdminCodeIntelAreaRoute[] = (
condition: () => window.context?.codeIntelAutoIndexingEnabled,
},

// Ranking
{
path: '/ranking',
render: props => <CodeIntelRankingPage {...props} />,
},

// Legacy routes
{
path: '/uploads/:id',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
.title-container {
font-size: 0.9rem;
display: grid;
grid-template-columns: 1fr 1fr;
padding-bottom: 1.25rem;
}

.table-container {
padding-bottom: 1.875rem;

h4 {
font-size: 0.85rem;
font-weight: 600;
border-bottom: 1px solid #808080;
}
}

.row {
display: grid;
grid-template-columns: 0.5fr 1fr;
font-size: 0.8rem;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
import { FunctionComponent, useEffect } from 'react'

import { formatDistance, format, parseISO } from 'date-fns'

import { Timestamp } from '@sourcegraph/branded/src/components/Timestamp'
import { TelemetryProps, TelemetryService } from '@sourcegraph/shared/src/telemetry/telemetryService'
import { Container, ErrorAlert, LoadingSpinner, PageHeader, H4, H3 } from '@sourcegraph/wildcard'

import { Collapsible } from '../../../../components/Collapsible'

import { useRankingSummary as defaultUseRankingSummary } from './backend'

import styles from './CodeIntelRankingPage.module.scss'

export interface CodeIntelRankingPageProps extends TelemetryProps {
useRankingSummary?: typeof defaultUseRankingSummary
telemetryService: TelemetryService
}

export const CodeIntelRankingPage: FunctionComponent<CodeIntelRankingPageProps> = ({
useRankingSummary = defaultUseRankingSummary,
telemetryService,
}) => {
useEffect(() => telemetryService.logViewEvent('CodeIntelRankingPage'), [telemetryService])

const { data, loading, error } = useRankingSummary({})

if (loading && !data) {
return <LoadingSpinner />
}

if (error) {
return <ErrorAlert prefix="Failed to load code intelligence summary for repository" error={error} />
}

return (
<>
<PageHeader
headingElement="h2"
path={[
{
text: <>Ranking calculation history</>,
},
]}
description="View the history of ranking calculation."
className="mb-3"
/>

<Container>
{data &&
(data.rankingSummary.length === 0 ? (
<>No data.</>
) : (
<>
<H3>Current ranking calculation</H3>

<div className="py-3">
<Summary key={data.rankingSummary[0].graphKey} summary={data.rankingSummary[0]} />
</div>
</>
))}
</Container>

{data && data.rankingSummary.length > 1 && (
<Container>
<Collapsible title="Historic ranking calculations" titleAtStart={true} titleClassName="h3">
<div className="py-3">
{data.rankingSummary.slice(1).map(summary => (
<Summary key={summary.graphKey} summary={summary} />
))}
</div>
</Collapsible>
</Container>
)}
</>
)
}

interface Summary {
graphKey: string
pathMapperProgress: Progress
referenceMapperProgress: Progress
reducerProgress: Progress | null
}

interface Progress {
startedAt: string
completedAt: string | null
processed: number
total: number
}

interface SummaryProps {
summary: Summary
}

const Summary: FunctionComponent<SummaryProps> = ({ summary }) => (
<div>
<Progress title="Path Aggregation Process" progress={summary.pathMapperProgress} />
<Progress title="Reference Aggregation Process" progress={summary.referenceMapperProgress} />
{summary.reducerProgress && <Progress title="Reducing Process" progress={summary.reducerProgress} />}
</div>
)

interface ProgressProps {
title: string
progress: Progress
}

const Progress: FunctionComponent<ProgressProps> = ({ title, progress }) => (
<div>
<div className={styles.tableContainer}>
<H4>{title}</H4>
<div className={styles.row}>
<div>Queued records</div>
<div>
{progress.processed === 0 ? (
<>Process finished</>
) : (
<>
{progress.processed} of {progress.total} records processed
</>
)}
</div>
</div>
<div className={styles.row}>
<div>Started</div>
<div>
{format(parseISO(progress.startedAt), 'MMM L y h:mm:ss a')} (
<Timestamp date={progress.startedAt} />){' '}
</div>
</div>
<div className={styles.row}>
<div>Completed</div>
<div>
{progress.completedAt ? (
<>
{format(parseISO(progress.completedAt), 'MMM L y h:mm:ss a')} (
<Timestamp date={progress.completedAt} />){' '}
</>
) : (
'-'
)}
</div>
</div>
<div className={styles.row}>
<div>Duration</div>
<div>
{progress.completedAt && (
<> Ran for {formatDistance(new Date(progress.completedAt), new Date(progress.startedAt))}</>
)}
</div>
</div>

<div className={styles.row}>
<div>Progress</div>
<div>
{progress.processed === 0
? 100
: Math.floor(((progress.processed / progress.total) * 100 * 100) / 100)}
%
</div>
</div>
</div>
</div>
)
49 changes: 49 additions & 0 deletions client/web/src/enterprise/codeintel/ranking/pages/backend.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { ApolloError } from '@apollo/client'

import { gql, useQuery } from '@sourcegraph/http-client'

import { RankingSummaryResult, RankingSummaryVariables } from '../../../../graphql-operations'

export const RankingSummaryFieldsFragment = gql`
fragment RankingSummaryFields on RankingSummary {
graphKey
pathMapperProgress {
...RankingSummaryProgressFields
}
referenceMapperProgress {
...RankingSummaryProgressFields
}
reducerProgress {
...RankingSummaryProgressFields
}
}
fragment RankingSummaryProgressFields on RankingSummaryProgress {
startedAt
completedAt
processed
total
}
`

export const RANKING_SUMMARY = gql`
query RankingSummary {
rankingSummary {
...RankingSummaryFields
}
}
${RankingSummaryFieldsFragment}
`

export const useRankingSummary = (
variables: RankingSummaryVariables
): {
error?: ApolloError
loading: boolean
data: RankingSummaryResult | undefined
} =>
useQuery<RankingSummaryResult, RankingSummaryVariables>(RANKING_SUMMARY, {
variables,
fetchPolicy: 'cache-first',
})
4 changes: 4 additions & 0 deletions client/web/src/enterprise/site-admin/sidebaritems.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,10 @@ const codeIntelGroup: SiteAdminSideBarGroup = {
label: 'Inference',
condition: () => window.context?.codeIntelAutoIndexingEnabled,
},
{
to: '/site-admin/code-graph/ranking',
label: 'Ranking',
},
{
label: 'Ownership signals',
to: '/site-admin/own-signal-page',
Expand Down
1 change: 1 addition & 0 deletions cmd/frontend/graphqlbackend/BUILD.bazel

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 50 additions & 0 deletions cmd/frontend/graphqlbackend/codeintel.ranking.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
extend type Query {
"""
Gets the progress of the current and historic precise ranking jobs.
"""
rankingSummary: [RankingSummary!]!
}

"""
Summary of one precise ranking job.
"""
type RankingSummary {
"""
Identifier of the current ranking job. Corresponds to values in the site configuration.
"""
graphKey: String!
"""
Progress of the path mapping stage.
"""
pathMapperProgress: RankingSummaryProgress!
"""
Progress of the reference mapping stage.
"""
referenceMapperProgress: RankingSummaryProgress!
"""
Progress of the reducer stage.
"""
reducerProgress: RankingSummaryProgress
}

"""
Progress of one stage of a precise ranking job.
"""
type RankingSummaryProgress {
"""
When the job started.
"""
startedAt: DateTime!
"""
When the job completed (if finished).
"""
completedAt: DateTime
"""
How many records have been processed.
"""
processed: Int!
"""
How many total items will be processed.
"""
total: Int!
}
1 change: 1 addition & 0 deletions enterprise/cmd/frontend/internal/codeintel/BUILD.bazel

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions enterprise/cmd/frontend/internal/codeintel/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
autoindexinggraphql "github.com/sourcegraph/sourcegraph/enterprise/internal/codeintel/autoindexing/transport/graphql"
codenavgraphql "github.com/sourcegraph/sourcegraph/enterprise/internal/codeintel/codenav/transport/graphql"
policiesgraphql "github.com/sourcegraph/sourcegraph/enterprise/internal/codeintel/policies/transport/graphql"
rankinggraphql "github.com/sourcegraph/sourcegraph/enterprise/internal/codeintel/ranking/transport/graphql"
sentinelgraphql "github.com/sourcegraph/sourcegraph/enterprise/internal/codeintel/sentinel/transport/graphql"
"github.com/sourcegraph/sourcegraph/enterprise/internal/codeintel/shared/lsifuploadstore"
sharedresolvers "github.com/sourcegraph/sourcegraph/enterprise/internal/codeintel/shared/resolvers"
Expand Down Expand Up @@ -117,12 +118,19 @@ func Init(
preciseIndexResolverFactory,
)

rankingRootResolver := rankinggraphql.NewRootResolver(
scopedContext("ranking"),
codeIntelServices.RankingService,
siteAdminChecker,
)

enterpriseServices.CodeIntelResolver = graphqlbackend.NewCodeIntelResolver(resolvers.NewCodeIntelResolver(
autoindexingRootResolver,
codenavRootResolver,
policyRootResolver,
uploadRootResolver,
sentinelRootResolver,
rankingRootResolver,
))
enterpriseServices.NewCodeIntelUploadHandler = newUploadHandler
enterpriseServices.RankingService = codeIntelServices.RankingService
Expand Down
1 change: 1 addition & 0 deletions enterprise/internal/codeintel/ranking/BUILD.bazel

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 22abdcb

Please sign in to comment.