Skip to content

Commit e4faf2b

Browse files
jeanp413mustard-mh
andauthored
Add tracing logging for hanging issue (#19346)
* Add tracing logging for hanging issue * 💄 * 💄 * 💄 * log prefix * 💄 * Add user loaded * rename * 💄 --------- Co-authored-by: Huiwen Huang <huiwen@gitpod.io>
1 parent 723d57a commit e4faf2b

File tree

4 files changed

+76
-7
lines changed

4 files changed

+76
-7
lines changed

components/dashboard/src/app/AppLoading.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ import { FunctionComponent, useEffect, useState } from "react";
88
import { Heading3, Subheading } from "../components/typography/headings";
99
import { Delayed } from "@podkit/loading/Delayed";
1010
import { ProductLogo } from "../components/ProductLogo";
11+
import { useReportDashboardLoggingTracing } from "../data/featureflag-query";
12+
import { userLoaded } from "../hooks/use-user-loader";
13+
import { orgsLoaded } from "../data/organizations/orgs-query";
1114

1215
function useDelay(wait: number) {
1316
const [done, setDone] = useState(false);
@@ -21,6 +24,16 @@ function useDelay(wait: number) {
2124

2225
export const AppLoading: FunctionComponent = () => {
2326
const done = useDelay(8000);
27+
const logTracing = useReportDashboardLoggingTracing();
28+
useEffect(() => {
29+
if (done) {
30+
logTracing(async () => {}, "At least 8 seconds has passed trying to resolve an API call", {
31+
userLoaded,
32+
orgsLoaded,
33+
});
34+
}
35+
}, [done, logTracing]);
36+
2437
const connectionProblems = useDelay(25000);
2538
return (
2639
<Delayed wait={3000}>

components/dashboard/src/data/featureflag-query.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ const featureFlags = {
3535
org_workspace_class_restrictions: false,
3636
// dummy specified dataops feature, default false
3737
dataops: false,
38+
// Logging tracing for added for investigate hanging issue
39+
dashboard_logging_tracing: false,
3840
};
3941

4042
type FeatureFlags = typeof featureFlags;
@@ -63,6 +65,47 @@ export const useFeatureFlag = <K extends keyof FeatureFlags>(featureFlag: K): Fe
6365
return query.data !== undefined ? query.data : featureFlags[featureFlag];
6466
};
6567

68+
export const useDedicatedFeatureFlag = <K extends keyof FeatureFlags>(featureFlag: K): FeatureFlags[K] | boolean => {
69+
const queryKey = ["dedicatedFeatureFlag", featureFlag];
70+
71+
const query = useQuery(queryKey, async () => {
72+
const flagValue = await getExperimentsClient().getValueAsync(featureFlag, featureFlags[featureFlag], {
73+
gitpodHost: window.location.host,
74+
});
75+
return flagValue;
76+
});
77+
78+
return query.data !== undefined ? query.data : featureFlags[featureFlag];
79+
};
80+
6681
export const useIsDataOps = () => {
6782
return useFeatureFlag("dataops");
6883
};
84+
85+
export const useReportDashboardLoggingTracing = () => {
86+
const enabled = useDedicatedFeatureFlag("dashboard_logging_tracing");
87+
88+
if (!enabled) {
89+
return async <T>(fn: () => Promise<T>, _msg: string, _meta?: Record<string, any>) => {
90+
return await fn();
91+
};
92+
}
93+
return async <T>(fn: () => Promise<T>, msg: string, meta?: Record<string, any>) => {
94+
try {
95+
const result = await fn();
96+
console.error("[dashboard_tracing] " + msg, {
97+
...meta,
98+
time: performance.now(),
99+
});
100+
return result;
101+
} catch (err) {
102+
console.error("[dashboard_tracing] " + msg, {
103+
...meta,
104+
err: err.toString(),
105+
errorCode: (err as any)?.code,
106+
time: performance.now(),
107+
});
108+
throw err;
109+
}
110+
};
111+
};

components/dashboard/src/data/organizations/orgs-query.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@
55
*/
66

77
import { useQuery, useQueryClient } from "@tanstack/react-query";
8-
import { useCallback } from "react";
8+
import { useCallback, useEffect } from "react";
99
import { useLocation } from "react-router";
1010
import { organizationClient } from "../../service/public-api";
1111
import { useCurrentUser } from "../../user-context";
1212
import { noPersistence } from "../setup";
1313
import { Organization } from "@gitpod/public-api/lib/gitpod/v1/organization_pb";
14+
import { useReportDashboardLoggingTracing } from "../featureflag-query";
1415

1516
export function useOrganizationsInvalidator() {
1617
const user = useCurrentUser();
@@ -22,8 +23,10 @@ export function useOrganizationsInvalidator() {
2223
}, [user?.id, queryClient]);
2324
}
2425

26+
export let orgsLoaded = false;
2527
export function useOrganizations() {
2628
const user = useCurrentUser();
29+
const logTracing = useReportDashboardLoggingTracing();
2730
const query = useQuery<Organization[], Error>(
2831
getQueryKey(user?.id),
2932
async () => {
@@ -32,8 +35,10 @@ export function useOrganizations() {
3235
console.log("useOrganizations with empty user");
3336
return [];
3437
}
35-
36-
const response = await organizationClient.listOrganizations({});
38+
const response = await logTracing(
39+
async () => organizationClient.listOrganizations({}),
40+
"on organization loading",
41+
);
3742
return response.organizations;
3843
},
3944
{
@@ -44,6 +49,9 @@ export function useOrganizations() {
4449
useErrorBoundary: true,
4550
},
4651
);
52+
useEffect(() => {
53+
orgsLoaded = !query.isLoading;
54+
}, [query.isLoading]);
4755
return query;
4856
}
4957

components/dashboard/src/hooks/use-user-loader.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,27 @@
44
* See License.AGPL.txt in the project root for license information.
55
*/
66

7-
import { useContext } from "react";
7+
import { useContext, useEffect } from "react";
88
import { UserContext } from "../user-context";
99
import { trackLocation } from "../Analytics";
1010
import { useQuery } from "@tanstack/react-query";
1111
import { noPersistence } from "../data/setup";
1212
import { ErrorCodes } from "@gitpod/gitpod-protocol/lib/messaging/error";
13-
import { useFeatureFlag } from "../data/featureflag-query";
13+
import { useFeatureFlag, useReportDashboardLoggingTracing } from "../data/featureflag-query";
1414
import { userClient } from "../service/public-api";
1515

16+
export let userLoaded = false;
1617
export const useUserLoader = () => {
1718
const { user, setUser } = useContext(UserContext);
1819
const doRetryUserLoader = useFeatureFlag("doRetryUserLoader");
20+
const logTracing = useReportDashboardLoggingTracing();
1921

2022
// For now, we're using the user context to store the user, but letting react-query handle the loading
2123
// In the future, we should remove the user context and use react-query to access the user
2224
const { isLoading } = useQuery({
2325
queryKey: noPersistence(["current-user"]),
2426
queryFn: async () => {
25-
const user = (await userClient.getAuthenticatedUser({})).user;
26-
27+
const user = (await logTracing(async () => userClient.getAuthenticatedUser({}), "on user loading")).user;
2728
return user || null;
2829
},
2930
// We'll let an ErrorBoundary catch the error
@@ -50,5 +51,9 @@ export const useUserLoader = () => {
5051
},
5152
});
5253

54+
useEffect(() => {
55+
userLoaded = !isLoading;
56+
}, [isLoading]);
57+
5358
return { user, loading: isLoading };
5459
};

0 commit comments

Comments
 (0)