Skip to content

Commit

Permalink
Add default trace format that is exported automatically (#28461)
Browse files Browse the repository at this point in the history
Co-authored-by: Steven <steven@ceriously.com>
  • Loading branch information
timneutkens and styfle committed Aug 25, 2021
1 parent 706547e commit 9316dc0
Show file tree
Hide file tree
Showing 15 changed files with 258 additions and 80 deletions.
2 changes: 1 addition & 1 deletion packages/next/build/babel/loader/index.ts
Expand Up @@ -40,7 +40,7 @@ const nextBabelLoaderOuter = function nextBabelLoaderOuter(
) {
const callback = this.async()

const loaderSpan = trace('next-babel-turbo-loader', this.currentTraceSpan?.id)
const loaderSpan = this.currentTraceSpan.traceChild('next-babel-turbo-loader')
loaderSpan
.traceAsyncFn(() =>
nextBabelLoader.call(this, loaderSpan, inputSource, inputSourceMap)
Expand Down
2 changes: 1 addition & 1 deletion packages/next/build/babel/loader/types.d.ts
Expand Up @@ -2,7 +2,7 @@ import { loader } from 'next/dist/compiled/webpack/webpack'
import { Span } from '../../../telemetry/trace'

export interface NextJsLoaderContext extends loader.LoaderContext {
currentTraceSpan?: Span
currentTraceSpan: Span
}

export interface NextBabelLoaderOptions {
Expand Down
4 changes: 3 additions & 1 deletion packages/next/build/index.ts
Expand Up @@ -130,11 +130,13 @@ export default async function build(
const config: NextConfigComplete = await nextBuildSpan
.traceChild('load-next-config')
.traceAsyncFn(() => loadConfig(PHASE_PRODUCTION_BUILD, dir, conf))
const distDir = path.join(dir, config.distDir)
setGlobal('distDir', distDir)

const { target } = config
const buildId: string = await nextBuildSpan
.traceChild('generate-buildid')
.traceAsyncFn(() => generateBuildId(config.generateBuildId, nanoid))
const distDir = path.join(dir, config.distDir)

const customRoutes: CustomRoutes = await nextBuildSpan
.traceChild('load-custom-routes')
Expand Down
2 changes: 1 addition & 1 deletion packages/next/build/webpack-config.ts
Expand Up @@ -240,7 +240,7 @@ export default async function getBaseWebpackConfig(
entrypoints: WebpackEntrypoints
rewrites: CustomRoutes['rewrites']
isDevFallback?: boolean
runWebpackSpan?: Span
runWebpackSpan: Span
}
): Promise<webpack.Configuration> {
const hasRewrites =
Expand Down
98 changes: 47 additions & 51 deletions packages/next/build/webpack/loaders/next-serverless-loader/index.ts
Expand Up @@ -11,7 +11,6 @@ import {
ROUTES_MANIFEST,
REACT_LOADABLE_MANIFEST,
} from '../../../../shared/lib/constants'
import { trace } from '../../../../telemetry/trace'

export type ServerlessLoaderQuery = {
page: string
Expand All @@ -34,63 +33,61 @@ export type ServerlessLoaderQuery = {
}

const nextServerlessLoader: webpack.loader.Loader = function () {
const loaderSpan = trace('next-serverless-loader')
return loaderSpan.traceFn(() => {
const {
distDir,
absolutePagePath,
page,
buildId,
canonicalBase,
assetPrefix,
absoluteAppPath,
absoluteDocumentPath,
absoluteErrorPath,
absolute404Path,
generateEtags,
poweredByHeader,
basePath,
runtimeConfig,
previewProps,
loadedEnvFiles,
i18n,
}: ServerlessLoaderQuery =
typeof this.query === 'string' ? parse(this.query.substr(1)) : this.query

const buildManifest = join(distDir, BUILD_MANIFEST).replace(/\\/g, '/')
const reactLoadableManifest = join(
distDir,
REACT_LOADABLE_MANIFEST
).replace(/\\/g, '/')
const routesManifest = join(distDir, ROUTES_MANIFEST).replace(/\\/g, '/')

const escapedBuildId = escapeRegexp(buildId)
const pageIsDynamicRoute = isDynamicRoute(page)

const encodedPreviewProps = devalue(
JSON.parse(previewProps) as __ApiPreviewProps
)

const envLoading = `
const {
distDir,
absolutePagePath,
page,
buildId,
canonicalBase,
assetPrefix,
absoluteAppPath,
absoluteDocumentPath,
absoluteErrorPath,
absolute404Path,
generateEtags,
poweredByHeader,
basePath,
runtimeConfig,
previewProps,
loadedEnvFiles,
i18n,
}: ServerlessLoaderQuery =
typeof this.query === 'string' ? parse(this.query.substr(1)) : this.query

const buildManifest = join(distDir, BUILD_MANIFEST).replace(/\\/g, '/')
const reactLoadableManifest = join(distDir, REACT_LOADABLE_MANIFEST).replace(
/\\/g,
'/'
)
const routesManifest = join(distDir, ROUTES_MANIFEST).replace(/\\/g, '/')

const escapedBuildId = escapeRegexp(buildId)
const pageIsDynamicRoute = isDynamicRoute(page)

const encodedPreviewProps = devalue(
JSON.parse(previewProps) as __ApiPreviewProps
)

const envLoading = `
const { processEnv } = require('@next/env')
processEnv(${Buffer.from(loadedEnvFiles, 'base64').toString()})
`

const runtimeConfigImports = runtimeConfig
? `
const runtimeConfigImports = runtimeConfig
? `
const { setConfig } = require('next/config')
`
: ''
: ''

const runtimeConfigSetter = runtimeConfig
? `
const runtimeConfigSetter = runtimeConfig
? `
const runtimeConfig = ${runtimeConfig}
setConfig(runtimeConfig)
`
: 'const runtimeConfig = {}'
: 'const runtimeConfig = {}'

if (page.match(API_ROUTE)) {
return `
if (page.match(API_ROUTE)) {
return `
${envLoading}
${runtimeConfigImports}
${
Expand Down Expand Up @@ -125,8 +122,8 @@ const nextServerlessLoader: webpack.loader.Loader = function () {
})
export default apiHandler
`
} else {
return `
} else {
return `
import 'next/dist/server/node-polyfill-fetch'
import routesManifest from '${routesManifest}'
import buildManifest from '${buildManifest}'
Expand Down Expand Up @@ -206,8 +203,7 @@ const nextServerlessLoader: webpack.loader.Loader = function () {
})
export { renderReqToHTML, render }
`
}
})
}
}

export default nextServerlessLoader
2 changes: 1 addition & 1 deletion packages/next/build/webpack/loaders/next-swc-loader.js
Expand Up @@ -123,7 +123,7 @@ async function loaderTransform(parentTrace, source, inputSourceMap) {
}

export default function swcLoader(inputSource, inputSourceMap) {
const loaderSpan = trace('next-swc-loader', this.currentTraceSpan?.id)
const loaderSpan = this.currentTraceSpan.traceChild('next-swc-loader')
const callback = this.async()
loaderSpan
.traceAsyncFn(() =>
Expand Down
2 changes: 1 addition & 1 deletion packages/next/build/webpack/plugins/build-stats-plugin.ts
Expand Up @@ -118,7 +118,7 @@ export default class BuildStatsPlugin {
async (stats, callback) => {
const compilerSpan = spans.get(compiler)
try {
const writeStatsSpan = trace('NextJsBuildStats', compilerSpan?.id)
const writeStatsSpan = compilerSpan!.traceChild('NextJsBuildStats')
await writeStatsSpan.traceAsyncFn(() => {
return new Promise((resolve, reject) => {
const statsJson = reduceSize(
Expand Down
7 changes: 3 additions & 4 deletions packages/next/build/webpack/plugins/css-minimizer-plugin.ts
Expand Up @@ -71,9 +71,8 @@ export class CssMinimizerPlugin {
},
async (assets: any) => {
const compilerSpan = spans.get(compiler)
const cssMinimizerSpan = trace(
'css-minimizer-plugin',
compilerSpan?.id
const cssMinimizerSpan = compilerSpan!.traceChild(
'css-minimizer-plugin'
)
cssMinimizerSpan.setAttribute('webpackVersion', 5)

Expand All @@ -83,7 +82,7 @@ export class CssMinimizerPlugin {
files
.filter((file) => CSS_REGEX.test(file))
.map(async (file) => {
const assetSpan = trace('minify-css', cssMinimizerSpan.id)
const assetSpan = cssMinimizerSpan.traceChild('minify-css')
assetSpan.setAttribute('file', file)

return assetSpan.traceAsyncFn(async () => {
Expand Down
25 changes: 17 additions & 8 deletions packages/next/build/webpack/plugins/profiling-plugin.ts
Expand Up @@ -15,9 +15,9 @@ function getNormalModuleLoaderHook(compilation: any) {

export class ProfilingPlugin {
compiler: any
runWebpackSpan: Span | undefined
runWebpackSpan: Span

constructor({ runWebpackSpan }: { runWebpackSpan: Span | undefined }) {
constructor({ runWebpackSpan }: { runWebpackSpan: Span }) {
this.runWebpackSpan = runWebpackSpan
}
apply(compiler: any) {
Expand All @@ -35,14 +35,17 @@ export class ProfilingPlugin {
attrs,
onSetSpan,
}: {
parentSpan?: () => Span | undefined
parentSpan?: () => Span
attrs?: any
onSetSpan?: (span: Span) => void
} = {}
) {
let span: Span | undefined
startHook.tap(pluginName, () => {
span = trace(spanName, parentSpan?.()?.id, attrs ? attrs() : attrs)
span = parentSpan
? parentSpan().traceChild(spanName, attrs ? attrs() : attrs)
: trace(spanName, undefined, attrs ? attrs() : attrs)

onSetSpan?.(span)
})
stopHook.tap(pluginName, () => {
Expand Down Expand Up @@ -103,10 +106,16 @@ export class ProfilingPlugin {

const issuerModule = compilation?.moduleGraph?.getIssuer(module)

const span = trace(
`build-module${moduleType ? `-${moduleType}` : ''}`,
issuerModule ? spans.get(issuerModule)?.id : compilerSpan.id
)
let span: Span

const spanName = `build-module${moduleType ? `-${moduleType}` : ''}`
const issuerSpan: Span | undefined =
issuerModule && spans.get(issuerModule)
if (issuerSpan) {
span = issuerSpan.traceChild(spanName)
} else {
span = compilerSpan.traceChild(spanName)
}
span.setAttribute('name', module.userRequest)
spans.set(module, span)
})
Expand Down
6 changes: 6 additions & 0 deletions packages/next/server/dev/hot-reloader.ts
Expand Up @@ -27,6 +27,7 @@ import { difference } from '../../build/utils'
import { NextConfigComplete } from '../config-shared'
import { CustomRoutes } from '../../lib/load-custom-routes'
import { DecodeError } from '../../shared/lib/utils'
import { Span, trace } from '../../telemetry/trace'

export async function renderScriptError(
res: ServerResponse,
Expand Down Expand Up @@ -143,6 +144,7 @@ export default class HotReloader {
private watcher: any
private rewrites: CustomRoutes['rewrites']
private fallbackWatcher: any
private hotReloaderSpan: Span
public isWebpack5: any

constructor(
Expand Down Expand Up @@ -174,6 +176,7 @@ export default class HotReloader {
this.previewProps = previewProps
this.rewrites = rewrites
this.isWebpack5 = isWebpack5
this.hotReloaderSpan = trace('hot-reloader')
}

public async run(
Expand Down Expand Up @@ -283,6 +286,7 @@ export default class HotReloader {
pagesDir: this.pagesDir,
rewrites: this.rewrites,
entrypoints: entrypoints.client,
runWebpackSpan: this.hotReloaderSpan,
}),
getBaseWebpackConfig(this.dir, {
dev: true,
Expand All @@ -292,6 +296,7 @@ export default class HotReloader {
pagesDir: this.pagesDir,
rewrites: this.rewrites,
entrypoints: entrypoints.server,
runWebpackSpan: this.hotReloaderSpan,
}),
])
}
Expand All @@ -300,6 +305,7 @@ export default class HotReloader {
if (this.fallbackWatcher) return

const fallbackConfig = await getBaseWebpackConfig(this.dir, {
runWebpackSpan: this.hotReloaderSpan,
dev: true,
isServer: false,
config: this.config,
Expand Down
39 changes: 34 additions & 5 deletions packages/next/telemetry/trace/report/index.ts
Expand Up @@ -3,6 +3,7 @@ import reportToConsole from './to-console'
import reportToZipkin from './to-zipkin'
import reportToJaeger from './to-jaeger'
import reportToTelemetry from './to-telemetry'
import reportToJson from './to-json'

type Reporter = {
flushAll: () => Promise<void> | void
Expand All @@ -16,6 +17,31 @@ type Reporter = {
) => void
}

class MultiReporter implements Reporter {
private reporters: Reporter[] = []

constructor(reporters: Reporter[]) {
this.reporters = reporters
}

async flushAll() {
await Promise.all(this.reporters.map((reporter) => reporter.flushAll()))
}

report(
spanName: string,
duration: number,
timestamp: number,
id: SpanId,
parentId?: SpanId,
attrs?: Object
) {
this.reporters.forEach((reporter) =>
reporter.report(spanName, duration, timestamp, id, parentId, attrs)
)
}
}

const target =
process.env.TRACE_TARGET && process.env.TRACE_TARGET in TARGET
? TARGET[process.env.TRACE_TARGET as TARGET]
Expand All @@ -27,14 +53,17 @@ if (process.env.TRACE_TARGET && !target) {
)
}

export let reporter: Reporter
let traceTargetReporter: Reporter

if (target === TARGET.CONSOLE) {
reporter = reportToConsole
traceTargetReporter = reportToConsole
} else if (target === TARGET.ZIPKIN) {
reporter = reportToZipkin
traceTargetReporter = reportToZipkin
} else if (target === TARGET.JAEGER) {
reporter = reportToJaeger
traceTargetReporter = reportToJaeger
} else {
reporter = reportToTelemetry
traceTargetReporter = reportToTelemetry
}

// JSON is always reported to allow for diagnostics
export const reporter = new MultiReporter([reportToJson, traceTargetReporter])
4 changes: 2 additions & 2 deletions packages/next/telemetry/trace/report/to-jaeger.ts
Expand Up @@ -5,7 +5,7 @@ import * as Log from '../../../build/output/log'
// Jaeger uses Zipkin's reporting
import { batcher } from './to-zipkin'

let traceId = process.env.TRACE_ID
let traceId: string
let batch: ReturnType<typeof batcher> | undefined

const localEndpoint = {
Expand Down Expand Up @@ -33,7 +33,7 @@ const reportToLocalHost = (
attrs?: Object
) => {
if (!traceId) {
traceId = process.env.TRACE_ID = randomBytes(8).toString('hex')
traceId = process.env.TRACE_ID || randomBytes(8).toString('hex')
logWebUrl()
}

Expand Down

0 comments on commit 9316dc0

Please sign in to comment.