Add logs for long-running integration hooks (#4445)

* feat: basic logging for long astro:build:done hooks

* feat: add long time msg to all build hooks

* feat: use logger for long time msg

* chore: changeset
This commit is contained in:
Ben Holmes 2022-08-23 14:07:09 -04:00 committed by GitHub
parent 77f9afa44a
commit df4e999284
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 134 additions and 40 deletions

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
Add "waiting for X integration" log for long-running integration hooks

View file

@ -62,7 +62,7 @@ class AstroBuilder {
debug('build', 'Initial setup...');
const { logging } = this;
this.timer.init = performance.now();
this.config = await runHookConfigSetup({ config: this.config, command: 'build' });
this.config = await runHookConfigSetup({ config: this.config, command: 'build', logging });
this.manifest = createRouteManifest({ config: this.config }, this.logging);
const viteConfig = await createVite(
@ -76,7 +76,7 @@ class AstroBuilder {
},
{ astroConfig: this.config, logging, mode: 'build' }
);
await runHookConfigDone({ config: this.config });
await runHookConfigDone({ config: this.config, logging });
return { viteConfig };
}
@ -87,7 +87,7 @@ class AstroBuilder {
server: new URL('./server/', this.config.outDir),
serverEntry: 'entry.mjs',
};
await runHookBuildStart({ config: this.config, buildConfig });
await runHookBuildStart({ config: this.config, buildConfig, logging: this.logging });
info(this.logging, 'build', `output target: ${colors.green(this.config.output)}`);
if (this.config._ctx.adapter) {
@ -145,6 +145,7 @@ class AstroBuilder {
buildConfig,
pages: pageNames,
routes: Object.values(allPages).map((pd) => pd.route),
logging: this.logging,
});
if (this.logging.level && levels[this.logging.level] <= levels['info']) {

View file

@ -167,6 +167,7 @@ async function ssrBuild(opts: StaticBuildOptions, internals: BuildInternals, inp
pages: internals.pagesByComponent,
vite: viteBuildConfig,
target: 'server',
logging: opts.logging,
});
return await vite.build(viteBuildConfig);
@ -236,6 +237,7 @@ async function clientBuild(
pages: internals.pagesByComponent,
vite: viteBuildConfig,
target: 'client',
logging: opts.logging,
});
const buildResult = await vite.build(viteBuildConfig);

View file

@ -103,7 +103,7 @@ export async function injectManifest(buildOpts: StaticBuildOptions, internals: B
const staticFiles = internals.staticFiles;
const manifest = buildManifest(buildOpts, internals, Array.from(staticFiles));
await runHookBuildSsr({ config: buildOpts.astroConfig, manifest });
await runHookBuildSsr({ config: buildOpts.astroConfig, manifest, logging: buildOpts.logging });
const chunk = internals.ssrEntryChunk;
const code = chunk.code;

View file

@ -83,7 +83,7 @@ export async function createVite(
htmlVitePlugin(),
jsxVitePlugin({ config: astroConfig, logging }),
astroPostprocessVitePlugin({ config: astroConfig }),
astroIntegrationsContainerPlugin({ config: astroConfig }),
astroIntegrationsContainerPlugin({ config: astroConfig, logging }),
astroScriptsPageSSRPlugin({ config: astroConfig }),
],
publicDir: fileURLToPath(astroConfig.publicDir),

View file

@ -31,7 +31,7 @@ export default async function dev(config: AstroConfig, options: DevOptions): Pro
const devStart = performance.now();
applyPolyfill();
await options.telemetry.record([]);
config = await runHookConfigSetup({ config, command: 'dev' });
config = await runHookConfigSetup({ config, command: 'dev', logging: options.logging });
const { host, port } = config.server;
// The client entrypoint for renderers. Since these are imported dynamically
@ -50,9 +50,9 @@ export default async function dev(config: AstroConfig, options: DevOptions): Pro
},
{ astroConfig: config, logging: options.logging, mode: 'dev' }
);
await runHookConfigDone({ config });
await runHookConfigDone({ config, logging: options.logging });
const viteServer = await vite.createServer(viteConfig);
runHookServerSetup({ config, server: viteServer });
runHookServerSetup({ config, server: viteServer, logging: options.logging });
await viteServer.listen(port);
const devServerAddressInfo = viteServer.httpServer!.address() as AddressInfo;
@ -77,7 +77,7 @@ export default async function dev(config: AstroConfig, options: DevOptions): Pro
warn(options.logging, null, msg.fsStrictWarning());
}
await runHookServerStart({ config, address: devServerAddressInfo });
await runHookServerStart({ config, address: devServerAddressInfo, logging: options.logging });
return {
address: devServerAddressInfo,
@ -86,7 +86,7 @@ export default async function dev(config: AstroConfig, options: DevOptions): Pro
},
stop: async () => {
await viteServer.close();
await runHookServerDone({ config });
await runHookServerDone({ config, logging: options.logging });
},
};
}

View file

@ -1,5 +1,6 @@
import type { AddressInfo } from 'net';
import type { ViteDevServer } from 'vite';
import { bold } from 'kleur/colors';
import {
AstroConfig,
AstroRenderer,
@ -11,13 +12,35 @@ import type { SerializedSSRManifest } from '../core/app/types';
import type { PageBuildData } from '../core/build/types';
import { mergeConfig } from '../core/config.js';
import type { ViteConfigWithSSR } from '../core/create-vite.js';
import { info, LogOptions } from '../core/logger/core.js';
async function withTakingALongTimeMsg<T>({
name,
hookResult,
timeoutMs = 3000,
logging,
}: {
name: string;
hookResult: T | Promise<T>;
timeoutMs?: number;
logging: LogOptions;
}): Promise<T> {
const timeout = setTimeout(() => {
info(logging, 'build', `Waiting for the ${bold(name)} integration...`);
}, timeoutMs);
const result = await hookResult;
clearTimeout(timeout);
return result;
}
export async function runHookConfigSetup({
config: _config,
command,
logging,
}: {
config: AstroConfig;
command: 'dev' | 'build';
logging: LogOptions;
}): Promise<AstroConfig> {
// An adapter is an integration, so if one is provided push it.
if (_config.adapter) {
@ -65,25 +88,39 @@ export async function runHookConfigSetup({
writable: false,
enumerable: false,
});
await integration.hooks['astro:config:setup'](hooks);
await withTakingALongTimeMsg({
name: integration.name,
hookResult: integration.hooks['astro:config:setup'](hooks),
logging,
});
}
}
return updatedConfig;
}
export async function runHookConfigDone({ config }: { config: AstroConfig }) {
export async function runHookConfigDone({
config,
logging,
}: {
config: AstroConfig;
logging: LogOptions;
}) {
for (const integration of config.integrations) {
if (integration?.hooks?.['astro:config:done']) {
await integration.hooks['astro:config:done']({
config,
setAdapter(adapter) {
if (config._ctx.adapter && config._ctx.adapter.name !== adapter.name) {
throw new Error(
`Integration "${integration.name}" conflicts with "${config._ctx.adapter.name}". You can only configure one deployment integration.`
);
}
config._ctx.adapter = adapter;
},
await withTakingALongTimeMsg({
name: integration.name,
hookResult: integration.hooks['astro:config:done']({
config,
setAdapter(adapter) {
if (config._ctx.adapter && config._ctx.adapter.name !== adapter.name) {
throw new Error(
`Integration "${integration.name}" conflicts with "${config._ctx.adapter.name}". You can only configure one deployment integration.`
);
}
config._ctx.adapter = adapter;
},
}),
logging,
});
}
}
@ -92,13 +129,19 @@ export async function runHookConfigDone({ config }: { config: AstroConfig }) {
export async function runHookServerSetup({
config,
server,
logging,
}: {
config: AstroConfig;
server: ViteDevServer;
logging: LogOptions;
}) {
for (const integration of config.integrations) {
if (integration?.hooks?.['astro:server:setup']) {
await integration.hooks['astro:server:setup']({ server });
await withTakingALongTimeMsg({
name: integration.name,
hookResult: integration.hooks['astro:server:setup']({ server }),
logging,
});
}
}
}
@ -106,21 +149,37 @@ export async function runHookServerSetup({
export async function runHookServerStart({
config,
address,
logging,
}: {
config: AstroConfig;
address: AddressInfo;
logging: LogOptions;
}) {
for (const integration of config.integrations) {
if (integration?.hooks?.['astro:server:start']) {
await integration.hooks['astro:server:start']({ address });
await withTakingALongTimeMsg({
name: integration.name,
hookResult: integration.hooks['astro:server:start']({ address }),
logging,
});
}
}
}
export async function runHookServerDone({ config }: { config: AstroConfig }) {
export async function runHookServerDone({
config,
logging,
}: {
config: AstroConfig;
logging: LogOptions;
}) {
for (const integration of config.integrations) {
if (integration?.hooks?.['astro:server:done']) {
await integration.hooks['astro:server:done']();
await withTakingALongTimeMsg({
name: integration.name,
hookResult: integration.hooks['astro:server:done'](),
logging,
});
}
}
}
@ -128,13 +187,19 @@ export async function runHookServerDone({ config }: { config: AstroConfig }) {
export async function runHookBuildStart({
config,
buildConfig,
logging,
}: {
config: AstroConfig;
buildConfig: BuildConfig;
logging: LogOptions;
}) {
for (const integration of config.integrations) {
if (integration?.hooks?.['astro:build:start']) {
await integration.hooks['astro:build:start']({ buildConfig });
await withTakingALongTimeMsg({
name: integration.name,
hookResult: integration.hooks['astro:build:start']({ buildConfig }),
logging,
});
}
}
}
@ -144,21 +209,27 @@ export async function runHookBuildSetup({
vite,
pages,
target,
logging,
}: {
config: AstroConfig;
vite: ViteConfigWithSSR;
pages: Map<string, PageBuildData>;
target: 'server' | 'client';
logging: LogOptions;
}) {
for (const integration of config.integrations) {
if (integration?.hooks?.['astro:build:setup']) {
await integration.hooks['astro:build:setup']({
vite,
pages,
target,
updateConfig: (newConfig) => {
mergeConfig(vite, newConfig);
},
await withTakingALongTimeMsg({
name: integration.name,
hookResult: integration.hooks['astro:build:setup']({
vite,
pages,
target,
updateConfig: (newConfig) => {
mergeConfig(vite, newConfig);
},
}),
logging,
});
}
}
@ -167,13 +238,19 @@ export async function runHookBuildSetup({
export async function runHookBuildSsr({
config,
manifest,
logging,
}: {
config: AstroConfig;
manifest: SerializedSSRManifest;
logging: LogOptions;
}) {
for (const integration of config.integrations) {
if (integration?.hooks?.['astro:build:ssr']) {
await integration.hooks['astro:build:ssr']({ manifest });
await withTakingALongTimeMsg({
name: integration.name,
hookResult: integration.hooks['astro:build:ssr']({ manifest }),
logging,
});
}
}
}
@ -183,20 +260,26 @@ export async function runHookBuildDone({
buildConfig,
pages,
routes,
logging,
}: {
config: AstroConfig;
buildConfig: BuildConfig;
pages: string[];
routes: RouteData[];
logging: LogOptions;
}) {
const dir = config.output === 'server' ? buildConfig.client : config.outDir;
for (const integration of config.integrations) {
if (integration?.hooks?.['astro:build:done']) {
await integration.hooks['astro:build:done']({
pages: pages.map((p) => ({ pathname: p })),
dir,
routes,
await withTakingALongTimeMsg({
name: integration.name,
hookResult: integration.hooks['astro:build:done']({
pages: pages.map((p) => ({ pathname: p })),
dir,
routes,
}),
logging,
});
}
}

View file

@ -1,17 +1,20 @@
import { Plugin as VitePlugin } from 'vite';
import { AstroConfig } from '../@types/astro.js';
import { LogOptions } from '../core/logger/core.js';
import { runHookServerSetup } from '../integrations/index.js';
/** Connect Astro integrations into Vite, as needed. */
export default function astroIntegrationsContainerPlugin({
config,
logging,
}: {
config: AstroConfig;
logging: LogOptions;
}): VitePlugin {
return {
name: 'astro:integration-container',
configureServer(server) {
runHookServerSetup({ config, server });
runHookServerSetup({ config, server, logging });
},
};
}