Skip to content

Commit

Permalink
fix(gatsby): Improve readability of page data / long running query wa…
Browse files Browse the repository at this point in the history
…rnings (#37220) (#37229)

* show better page data information

* clean up longrunning queries

Alternative to #36876

Co-authored-by: Tyler Barnes <tylerdbarnes@gmail.com>
Co-authored-by: Daniel Lew <danielshlomolew@gmail.com>

Co-authored-by: Tyler Barnes <tylerdbarnes@gmail.com>
Co-authored-by: Daniel Lew <danielshlomolew@gmail.com>
(cherry picked from commit 031a08f)

Co-authored-by: Lennart <lekoarts@gmail.com>
  • Loading branch information
gatsbybot and LekoArts authored Dec 9, 2022
1 parent 3b75594 commit 9e14203
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 48 deletions.
29 changes: 8 additions & 21 deletions packages/gatsby/src/commands/build-html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Bluebird from "bluebird"
import fs from "fs-extra"
import reporter from "gatsby-cli/lib/reporter"
import { createErrorFromString } from "gatsby-cli/lib/reporter/errors"
import { chunk, truncate } from "lodash"
import { chunk } from "lodash"
import { build, watch } from "../utils/webpack/bundle"
import * as path from "path"
import fastq from "fastq"
Expand All @@ -18,14 +18,14 @@ import { Span } from "opentracing"
import { IProgram, Stage } from "./types"
import { ROUTES_DIRECTORY } from "../constants"
import { PackageJson } from "../.."
import { IPageDataWithQueryResult } from "../utils/page-data"
import { getPublicPath } from "../utils/get-public-path"

import type { GatsbyWorkerPool } from "../utils/worker/pool"
import { stitchSliceForAPage } from "../utils/slices/stitching"
import type { ISlicePropsEntry } from "../utils/worker/child/render-html"
import { getPageMode } from "../utils/page-mode"
import { extractUndefinedGlobal } from "../utils/extract-undefined-global"
import { modifyPageDataForErrorMessage } from "../utils/page-data"

type IActivity = any // TODO

Expand Down Expand Up @@ -532,20 +532,6 @@ class BuildHTMLError extends Error {
}
}

const truncateObjStrings = (obj): IPageDataWithQueryResult => {
// Recursively truncate strings nested in object
// These objs can be quite large, but we want to preserve each field
for (const key in obj) {
if (typeof obj[key] === `object`) {
truncateObjStrings(obj[key])
} else if (typeof obj[key] === `string`) {
obj[key] = truncate(obj[key], { length: 250 })
}
}

return obj
}

export const doBuildPages = async (
rendererPath: string,
pagePaths: Array<string>,
Expand All @@ -563,22 +549,23 @@ export const doBuildPages = async (

if (error?.context?.path) {
const pageData = await getPageData(error.context.path)
const truncatedPageData = truncateObjStrings(pageData)
const modifiedPageDataForErrorMessage =
modifyPageDataForErrorMessage(pageData)

const pageDataMessage = `Page data from page-data.json for the failed page "${
const errorMessage = `Truncated page data information for the failed page "${
error.context.path
}": ${JSON.stringify(truncatedPageData, null, 2)}`
}": ${JSON.stringify(modifiedPageDataForErrorMessage, null, 2)}`

// This is our only error during preview so customize it a bit + add the
// pretty build error.
if (isPreview) {
reporter.error({
id: `95314`,
context: { pageData: pageDataMessage },
context: { errorMessage },
error: buildError,
})
} else {
reporter.error(pageDataMessage)
reporter.error(errorMessage)
}
}

Expand Down
13 changes: 4 additions & 9 deletions packages/gatsby/src/query/query-runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,19 +37,14 @@ export interface IQueryJob {
pluginCreatorId?: string
}

function reportLongRunningQueryJob(queryJob): void {
function reportLongRunningQueryJob(queryJob: IQueryJob): void {
const messageParts = [
`This query took more than 15s to run — which is unusually long and might indicate you're querying too much or have some unoptimized code:`,
`This query took more than 15s to run — which might indicate you're querying too much or have some unoptimized code:`,
`File path: ${queryJob.componentPath}`,
]

if (queryJob.isPage) {
const { path, context } = queryJob.context
messageParts.push(`URL path: ${path}`)

if (!_.isEmpty(context)) {
messageParts.push(`Context: ${JSON.stringify(context, null, 4)}`)
}
if (queryJob.queryType === `page`) {
messageParts.push(`URL path: ${queryJob.context.path}`)
}

report.warn(messageParts.join(`\n`))
Expand Down
110 changes: 110 additions & 0 deletions packages/gatsby/src/utils/__tests__/page-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import {
savePageQueryResult,
readPageQueryResult,
waitUntilPageQueryResultsAreStored,
modifyPageDataForErrorMessage,
IPageDataWithQueryResult,
} from "../page-data"

describe(`savePageQueryResults / readPageQueryResults`, () => {
Expand All @@ -24,3 +26,111 @@ describe(`savePageQueryResults / readPageQueryResults`, () => {
expect(JSON.parse(result)).toEqual(inputResult)
})
})

describe(`modifyPageDataForErrorMessage`, () => {
it(`handles optional data gracefully`, () => {
const input: IPageDataWithQueryResult = {
path: `/foo/`,
componentChunkName: `component`,
matchPath: `/`,
slicesMap: {},
staticQueryHashes: [],
result: {},
}
expect(modifyPageDataForErrorMessage(input)).toMatchInlineSnapshot(`
Object {
"errors": Object {},
"matchPath": "/",
"path": "/foo/",
"slicesMap": Object {},
}
`)
})
it(`outputs expected result shape`, () => {
const input: IPageDataWithQueryResult = {
path: `/foo/`,
componentChunkName: `component`,
matchPath: `/`,
slicesMap: {
foo: `bar`,
},
getServerDataError: [
{
level: `ERROR`,
text: `error`,
stack: [{ fileName: `a` }],
type: `UNKNOWN`,
},
],
staticQueryHashes: [`123`],
result: {
data: undefined,
// @ts-ignore - Can ignore for this test
errors: [`error`],
extensions: {
foo: `bar`,
},
pageContext: {
foo: `bar`,
},
serverData: {
foo: `bar`,
},
},
}
expect(modifyPageDataForErrorMessage(input)).toMatchInlineSnapshot(`
Object {
"errors": Object {
"getServerData": Array [
Object {
"level": "ERROR",
"stack": Array [
Object {
"fileName": "a",
},
],
"text": "error",
"type": "UNKNOWN",
},
],
"graphql": Array [
"error",
],
},
"matchPath": "/",
"pageContext": Object {
"foo": "bar",
},
"path": "/foo/",
"slicesMap": Object {
"foo": "bar",
},
}
`)
})
it(`doesn't print out the GraphQL result and serverData result`, () => {
const input: IPageDataWithQueryResult = {
path: `/foo/`,
componentChunkName: `component`,
matchPath: `/`,
slicesMap: {},
staticQueryHashes: [],
result: {
data: {
foo: `bar`,
},
serverData: {
foo: `bar`,
},
},
}
expect(modifyPageDataForErrorMessage(input)).toMatchInlineSnapshot(`
Object {
"errors": Object {},
"matchPath": "/",
"path": "/foo/",
"slicesMap": Object {},
}
`)
})
})
42 changes: 42 additions & 0 deletions packages/gatsby/src/utils/page-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -452,3 +452,45 @@ export async function handleStalePageData(parentSpan: Span): Promise<void> {

activity.end()
}

interface IModifyPageDataForErrorMessage {
errors: {
graphql?: IPageDataWithQueryResult["result"]["errors"]
getServerData?: IPageDataWithQueryResult["getServerDataError"]
}
graphqlExtensions?: IPageDataWithQueryResult["result"]["extensions"]
pageContext?: IPageDataWithQueryResult["result"]["pageContext"]
path: IPageDataWithQueryResult["path"]
matchPath: IPageDataWithQueryResult["matchPath"]
slicesMap: IPageDataWithQueryResult["slicesMap"]
}

export function modifyPageDataForErrorMessage(
input: IPageDataWithQueryResult
): IModifyPageDataForErrorMessage {
const optionalData = {
...(input.result?.pageContext
? { pageContext: input.result.pageContext }
: {}),
...(input.result?.pageContext
? { pageContext: input.result.pageContext }
: {}),
}

const optionalErrors = {
...(input.result?.errors ? { graphql: input.result.errors } : {}),
...(input.getServerDataError
? { getServerData: input.getServerDataError }
: {}),
}

return {
errors: {
...optionalErrors,
},
path: input.path,
matchPath: input.matchPath,
slicesMap: input.slicesMap,
...optionalData,
}
}
26 changes: 8 additions & 18 deletions packages/gatsby/src/utils/worker/child/render-html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import Bluebird from "bluebird"
import * as path from "path"
import { generateHtmlPath } from "gatsby-core-utils/page-html"
import { generatePageDataPath } from "gatsby-core-utils/page-data"
import { truncate } from "lodash"

import {
readWebpackStats,
Expand All @@ -14,6 +13,7 @@ import {
} from "../../client-assets-for-template"
import {
IPageDataWithQueryResult,
modifyPageDataForErrorMessage,
readPageData,
readSliceData,
} from "../../page-data"
Expand Down Expand Up @@ -135,20 +135,6 @@ async function getResourcesForTemplate(
return resources
}

const truncateObjStrings = (obj): IPageDataWithQueryResult => {
// Recursively truncate strings nested in object
// These objs can be quite large, but we want to preserve each field
for (const key in obj) {
if (typeof obj[key] === `object` && obj[key] !== null) {
truncateObjStrings(obj[key])
} else if (typeof obj[key] === `string`) {
obj[key] = truncate(obj[key], { length: 250 })
}
}

return obj
}

interface IPreviewErrorProps {
pagePath: string
publicDir: string
Expand All @@ -161,7 +147,7 @@ const generatePreviewErrorPage = async ({
error,
}: IPreviewErrorProps): Promise<string> => {
const pageData = await readPageData(publicDir, pagePath)
const truncatedPageData = truncateObjStrings(pageData)
const pageDataForErrorMessage = modifyPageDataForErrorMessage(pageData)

const html = `<!doctype html>
<html lang="en">
Expand Down Expand Up @@ -359,8 +345,12 @@ const generatePreviewErrorPage = async ({
<p>Below you'll find additional data that might help you debug the error.</p>
<details>
<summary>Page Data</summary>
<p>The page data contains some metadata about the affected page but also the GraphQL data if you have queries in your page. If e.g. data from the GraphQL query is undefined, check if it's available here.</p>
<pre><code>${JSON.stringify(truncatedPageData, null, 2)}</code></pre>
<p>The page data contains some metadata about the affected page. If data from the GraphQL is undefined, try running the query in the GraphiQL IDE.</p>
<pre><code>${JSON.stringify(
pageDataForErrorMessage,
null,
2
)}</code></pre>
</details>
</main>
</body>
Expand Down

0 comments on commit 9e14203

Please sign in to comment.