Skip to content

Commit 4dcd45a

Browse files
authored
feat(app): coordinate insights metadata (#6771)
1 parent 759e233 commit 4dcd45a

File tree

7 files changed

+95
-11
lines changed

7 files changed

+95
-11
lines changed

.changeset/brave-lobsters-raise.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'hive': minor
3+
---
4+
5+
Add meta and subgraph data to coordinate insights page; Fix SubgraphChip service link

packages/services/api/src/modules/operations/resolvers/SchemaCoordinateStats.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ import { hash } from '../../../shared/helpers';
22
import { OperationsManager } from '../providers/operations-manager';
33
import type { SchemaCoordinateStatsResolvers } from './../../../__generated__/types';
44

5-
export const SchemaCoordinateStats: SchemaCoordinateStatsResolvers = {
5+
export const SchemaCoordinateStats: Pick<
6+
SchemaCoordinateStatsResolvers,
7+
'clients' | 'operations' | 'requestsOverTime' | 'totalRequests' | '__isTypeOf'
8+
> = {
69
totalRequests: ({ organization, project, target, period, schemaCoordinate }, _, { injector }) => {
710
return injector.get(OperationsManager).countRequestsWithSchemaCoordinate({
811
organizationId: organization,

packages/services/api/src/modules/schema/module.graphql.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -857,6 +857,11 @@ export default gql`
857857
subscription: GraphQLObjectType
858858
}
859859
860+
extend type SchemaCoordinateStats {
861+
# If associated with a federated project, this contains the metadata for this coordinate.
862+
supergraphMetadata: SupergraphMetadata
863+
}
864+
860865
type UnusedSchemaExplorer {
861866
types: [GraphQLNamedType!]!
862867
}

packages/services/api/src/modules/schema/providers/schema-manager.ts

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { SchemaVersionMapper as SchemaVersion } from '../module.graphql.mappers';
2+
import DataLoader from 'dataloader';
23
import { parse, print } from 'graphql';
34
import { Inject, Injectable, Scope } from 'graphql-modules';
45
import lodash from 'lodash';
@@ -70,6 +71,7 @@ const externalSchemaCompositionTestDocument = parse(externalSchemaCompositionTes
7071
})
7172
export class SchemaManager {
7273
private logger: Logger;
74+
private latestSchemaVersionLoader: DataLoader<TargetSelector, SchemaVersion>;
7375

7476
constructor(
7577
logger: Logger,
@@ -89,6 +91,25 @@ export class SchemaManager {
8991
@Inject(SCHEMA_MODULE_CONFIG) private schemaModuleConfig: SchemaModuleConfig,
9092
) {
9193
this.logger = logger.child({ source: 'SchemaManager' });
94+
this.latestSchemaVersionLoader = new DataLoader(
95+
selectors => {
96+
return Promise.all(
97+
selectors.map(async selector => {
98+
return {
99+
...(await this.storage.getLatestValidVersion(selector)),
100+
projectId: selector.projectId,
101+
targetId: selector.targetId,
102+
organizationId: selector.organizationId,
103+
};
104+
}),
105+
);
106+
},
107+
{
108+
cacheKeyFn(selector) {
109+
return selector.targetId;
110+
},
111+
},
112+
);
92113
}
93114

94115
async hasSchema(target: Target) {
@@ -280,12 +301,7 @@ export class SchemaManager {
280301

281302
async getLatestValidVersion(selector: TargetSelector) {
282303
this.logger.debug('Fetching latest valid version (selector=%o)', selector);
283-
return {
284-
...(await this.storage.getLatestValidVersion(selector)),
285-
projectId: selector.projectId,
286-
targetId: selector.targetId,
287-
organizationId: selector.organizationId,
288-
};
304+
return this.latestSchemaVersionLoader.load(selector);
289305
}
290306

291307
async getMaybeLatestVersion(target: Target) {
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { extractSuperGraphInformation } from '../lib/federation-super-graph';
2+
import { SchemaManager } from '../providers/schema-manager';
3+
import { SchemaVersionHelper } from '../providers/schema-version-helper';
4+
import type { SchemaCoordinateStatsResolvers } from './../../../__generated__/types';
5+
6+
export const SchemaCoordinateStats: Pick<
7+
SchemaCoordinateStatsResolvers,
8+
'supergraphMetadata' | '__isTypeOf'
9+
> = {
10+
supergraphMetadata: async (
11+
{ organization, project, target, schemaCoordinate },
12+
_,
13+
{ injector },
14+
) => {
15+
// @note: SchemaManager.getLatestValidVersion uses DataLoader to avoid multiple fetches per operation
16+
const latestVersion = await injector.get(SchemaManager).getLatestValidVersion({
17+
targetId: target,
18+
projectId: project,
19+
organizationId: organization,
20+
});
21+
// @note: `SchemaVersionHelper.getSupergraphAst` is cached
22+
const supergraphAst = await injector.get(SchemaVersionHelper).getSupergraphAst(latestVersion);
23+
const supergraph = supergraphAst ? extractSuperGraphInformation(supergraphAst) : null;
24+
supergraph?.schemaCoordinateServicesMappings;
25+
26+
return {
27+
__typename: 'SupergraphMetadata',
28+
metadata: latestVersion.schemaMetadata?.[schemaCoordinate]?.map(m => ({
29+
...m,
30+
__typename: 'SchemaMetadata',
31+
})),
32+
ownedByServiceNames: supergraph?.schemaCoordinateServicesMappings.get(schemaCoordinate),
33+
};
34+
},
35+
};

packages/web/app/src/components/target/explorer/super-graph-metadata.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,9 @@ function SubgraphChip(props: {
5252
projectSlug: props.projectSlug,
5353
targetSlug: props.targetSlug,
5454
}}
55-
// TODO(router)
56-
hash={`service-${props.text}`}
55+
search={{
56+
service: props.text,
57+
}}
5758
style={{ backgroundColor: stringToHslColor(props.text) }}
5859
className="my-[2px] ml-[6px] inline-block h-[22px] max-w-[100px] cursor-pointer items-center justify-between truncate rounded-[16px] py-0 pl-[8px] pr-[6px] text-[10px] font-normal normal-case leading-loose text-[#4f4f4f] drop-shadow-md"
5960
>
@@ -98,14 +99,16 @@ const SupergraphMetadataList_SupergraphMetadataFragment = graphql(`
9899
`);
99100

100101
const tooltipColor = 'rgb(36, 39, 46)';
101-
const previewThreshold = 3;
102+
const DEFAULT_PREVIEW_THRESHOLD = 3;
102103

103104
export function SupergraphMetadataList(props: {
104105
organizationSlug: string;
105106
projectSlug: string;
106107
targetSlug: string;
107108
supergraphMetadata: FragmentType<typeof SupergraphMetadataList_SupergraphMetadataFragment>;
109+
previewThreshold?: number;
108110
}) {
111+
const previewThreshold = props.previewThreshold ?? DEFAULT_PREVIEW_THRESHOLD;
109112
const supergraphMetadata = useFragment(
110113
SupergraphMetadataList_SupergraphMetadataFragment,
111114
props.supergraphMetadata,

packages/web/app/src/pages/target-insights-coordinate.tsx

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
import AutoSizer from 'react-virtualized-auto-sizer';
1313
import { useQuery } from 'urql';
1414
import { Page, TargetLayout } from '@/components/layouts/target';
15+
import { SupergraphMetadataList } from '@/components/target/explorer/super-graph-metadata';
1516
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
1617
import { Button } from '@/components/ui/button';
1718
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
@@ -35,6 +36,9 @@ const SchemaCoordinateView_SchemaCoordinateStatsQuery = graphql(`
3536
$resolution: Int!
3637
) {
3738
schemaCoordinateStats(selector: $selector) {
39+
supergraphMetadata {
40+
...SupergraphMetadataList_SupergraphMetadataFragment
41+
}
3842
requestsOverTime(resolution: $resolution) {
3943
date
4044
value
@@ -113,6 +117,8 @@ function SchemaCoordinateView(props: {
113117
const totalOperations = query.data?.schemaCoordinateStats?.operations.nodes.length ?? 0;
114118
const totalClients = query.data?.schemaCoordinateStats?.clients.nodes.length ?? 0;
115119

120+
const supergraphMetadata = query.data?.schemaCoordinateStats?.supergraphMetadata;
121+
116122
if (query.error) {
117123
return <QueryError organizationSlug={props.organizationSlug} error={query.error} />;
118124
}
@@ -121,7 +127,18 @@ function SchemaCoordinateView(props: {
121127
<>
122128
<div className="flex flex-row items-center justify-between py-6">
123129
<div>
124-
<Title>{props.coordinate}</Title>
130+
<div className="flex flex-row items-center justify-between">
131+
<Title className="pr-8">{props.coordinate}</Title>
132+
{supergraphMetadata ? (
133+
<SupergraphMetadataList
134+
organizationSlug={props.organizationSlug}
135+
projectSlug={props.projectSlug}
136+
targetSlug={props.targetSlug}
137+
supergraphMetadata={supergraphMetadata}
138+
previewThreshold={5}
139+
/>
140+
) : null}
141+
</div>
125142
<Subtitle>Schema coordinate insights</Subtitle>
126143
</div>
127144
<div className="flex justify-end gap-x-2">

0 commit comments

Comments
 (0)