diff --git a/app/browser/dataset-preview.tsx b/app/browser/dataset-preview.tsx
index 112db9b915..7aa9546e5f 100644
--- a/app/browser/dataset-preview.tsx
+++ b/app/browser/dataset-preview.tsx
@@ -12,6 +12,7 @@ import Flex from "@/components/flex";
import { HintRed, Loading, LoadingDataError } from "@/components/hint";
import { DataSource } from "@/config-types";
import { sourceToLabel } from "@/domain/datasource";
+import { getQueryRequestContext } from "@/graphql/hooks";
import {
useDataCubeMetadataQuery,
useDataCubePreviewQuery,
@@ -86,6 +87,11 @@ export interface Preview {
label: string;
}
+const DATA_CUBE_PREVIEW_QUERY_REQUEST_CONTEXT = getQueryRequestContext({
+ querySource: "DataSetPreview / dataset-preview.tsx",
+ queryReason: "Needed to display a dataset preview in the /browse page.",
+});
+
export const DataSetPreview = ({
dataSetIri,
dataSource,
@@ -110,7 +116,10 @@ export const DataSetPreview = ({
useDataCubeMetadataQuery({ variables });
const [
{ data: previewData, fetching: fetchingPreview, error: previewError },
- ] = useDataCubePreviewQuery({ variables });
+ ] = useDataCubePreviewQuery({
+ variables,
+ context: DATA_CUBE_PREVIEW_QUERY_REQUEST_CONTEXT,
+ });
const classes = useStyles({
descriptionPresent: !!metadata?.dataCubeMetadata.description,
});
diff --git a/app/gql-flamegraph/devtool.tsx b/app/gql-flamegraph/devtool.tsx
index e11f6a3b31..158296982e 100644
--- a/app/gql-flamegraph/devtool.tsx
+++ b/app/gql-flamegraph/devtool.tsx
@@ -330,14 +330,29 @@ const Queries = ({ queries }: { queries: RequestQueryMeta[] }) => {
return (
+ {q.source && (
+ <>
+
+ {q.source}
+
+ {" – "}
+ >
+ )}
{q.endTime - q.startTime}ms
{" "}
- -{" "}
+ –{" "}
Copy
+ {q.reason && (
+
+
+ ℹ️ {q.reason}
+
+
+ )}
{
const debug = flag("debug");
const disableCache = flag("server-side-cache.disable");
return {
- "x-visualize-debug": debug ? "true" : "",
- "x-visualize-cache-control": disableCache ? "no-cache" : "",
+ [GQL_DEBUG_HEADER]: debug ? "true" : "",
+ [GQL_CACHE_CONTROL_HEADER]: disableCache ? "no-cache" : "",
+ [GQL_QUERY_SOURCE_HEADER]: querySource ?? "",
+ [GQL_QUERY_REASON_HEADER]: queryReason ?? "",
};
-}
+};
+
+export const client = createClient({
+ url: graphqlEndpointFlag ?? GRAPHQL_ENDPOINT,
+ exchanges: [...devtoolsExchanges, ...defaultExchanges],
+ fetchOptions: {
+ headers: getGraphqlHeaders(),
+ },
+});
diff --git a/app/graphql/context.tsx b/app/graphql/context.tsx
index 4222a1b234..e274b26cc4 100644
--- a/app/graphql/context.tsx
+++ b/app/graphql/context.tsx
@@ -12,6 +12,12 @@ import { SPARQL_GEO_ENDPOINT } from "@/domain/env";
import { Awaited } from "@/domain/types";
import { Timings } from "@/gql-flamegraph/resolvers";
import { getMaybeCachedSparqlUrl } from "@/graphql/caching-utils";
+import {
+ GQL_CACHE_CONTROL_HEADER,
+ GQL_DEBUG_HEADER,
+ GQL_QUERY_REASON_HEADER,
+ GQL_QUERY_SOURCE_HEADER,
+} from "@/graphql/client";
import { RequestQueryMeta } from "@/graphql/query-meta";
import {
QueryResolvers,
@@ -84,10 +90,17 @@ const createLoaders = async (
export type Loaders = Awaited>;
-const setupSparqlClients = (
- ctx: VisualizeGraphQLContext,
- sourceUrl: string
-) => {
+const setupSparqlClients = ({
+ ctx,
+ sourceUrl,
+ querySource,
+ queryReason,
+}: {
+ ctx: VisualizeGraphQLContext;
+ sourceUrl: string;
+ querySource: string | undefined;
+ queryReason: string | undefined;
+}) => {
const sparqlClient = new ParsingClient({
endpointUrl: sourceUrl,
});
@@ -105,6 +118,8 @@ const setupSparqlClients = (
startTime: t.start,
endTime: t.end,
text: args[0],
+ source: querySource,
+ reason: queryReason,
});
};
@@ -147,11 +162,11 @@ const sparqlCache = new LRUCache({
});
const shouldUseServerSideCache = (req: IncomingMessage) => {
- return req.headers["x-visualize-cache-control"] !== "no-cache";
+ return req.headers[GQL_CACHE_CONTROL_HEADER] !== "no-cache";
};
const isDebugMode = (req: IncomingMessage) => {
- return req.headers["x-visualize-debug"] === "true";
+ return req.headers[GQL_DEBUG_HEADER] === "true";
};
const createContextContent = async ({
@@ -164,7 +179,12 @@ const createContextContent = async ({
req: IncomingMessage;
}) => {
const { sparqlClient, sparqlClientStream, geoSparqlClient } =
- setupSparqlClients(ctx, sourceUrl);
+ setupSparqlClients({
+ ctx,
+ sourceUrl,
+ querySource: req.headers[GQL_QUERY_SOURCE_HEADER]?.toString(),
+ queryReason: req.headers[GQL_QUERY_REASON_HEADER]?.toString(),
+ });
const contextCache = shouldUseServerSideCache(req) ? sparqlCache : undefined;
const loaders = await createLoaders(
sparqlClient,
diff --git a/app/graphql/hooks.ts b/app/graphql/hooks.ts
index 5d6ad323a9..57b9bec01f 100644
--- a/app/graphql/hooks.ts
+++ b/app/graphql/hooks.ts
@@ -1,5 +1,5 @@
import { useCallback, useEffect, useMemo, useState } from "react";
-import { Client, useClient } from "urql";
+import { Client, OperationContext, useClient } from "urql";
import { ConfiguratorState, hasChartConfigs } from "@/configurator";
import {
@@ -7,10 +7,8 @@ import {
DataCubeMetadata,
DataCubesObservations,
} from "@/domain/data";
-import { Locale } from "@/locales/locales";
-import { assert } from "@/utils/assert";
-
-import { joinDimensions, mergeObservations } from "./join";
+import { getGraphqlHeaders } from "@/graphql/client";
+import { joinDimensions, mergeObservations } from "@/graphql/join";
import {
DataCubeComponentFilter,
DataCubeComponentsDocument,
@@ -24,7 +22,24 @@ import {
DataCubeObservationsDocument,
DataCubeObservationsQuery,
DataCubeObservationsQueryVariables,
-} from "./query-hooks";
+} from "@/graphql/query-hooks";
+import { Locale } from "@/locales/locales";
+import { assert } from "@/utils/assert";
+
+export const getQueryRequestContext = (options: {
+ querySource?: string;
+ queryReason?: string;
+}): Partial => {
+ if (!options) {
+ return {};
+ }
+
+ return {
+ fetchOptions: {
+ headers: getGraphqlHeaders(options),
+ },
+ };
+};
const useQueryKey = (options: object) => {
return useMemo(() => {
diff --git a/app/graphql/query-meta.ts b/app/graphql/query-meta.ts
index 840fbe264b..1781442adf 100644
--- a/app/graphql/query-meta.ts
+++ b/app/graphql/query-meta.ts
@@ -2,5 +2,6 @@ export type RequestQueryMeta = {
text: string;
startTime: number;
endTime: number;
- label?: string;
+ source?: string;
+ reason?: string;
};