Skip to content

Commit 036388f

Browse files
committed
feat: pass logger to integrations (#7816)
1 parent 364d861 commit 036388f

7 files changed

Lines changed: 154 additions & 30 deletions

File tree

.changeset/odd-books-live.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
'astro': minor
3+
---
4+
5+
Integrations can now log messages using Astro’s built-in logger.
6+
7+
The logger is available to all hooks as an additional parameter:
8+
9+
```ts
10+
import {AstroIntegration} from "./astro";
11+
12+
// integration.js
13+
export function myIntegration(): AstroIntegration {
14+
return {
15+
name: "my-integration",
16+
hooks: {
17+
"astro:config:done": ({ logger }) => {
18+
logger.info("Configure integration...");
19+
}
20+
}
21+
}
22+
}
23+
```

packages/astro/src/@types/astro.ts

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import type { AstroCookies } from '../core/cookies';
2222
import type { LogOptions, LoggerLevel } from '../core/logger/core';
2323
import type { AstroComponentFactory, AstroComponentInstance } from '../runtime/server';
2424
import type { SUPPORTED_MARKDOWN_FILE_EXTENSIONS } from './../core/constants.js';
25+
import { AstroIntegrationLogger } from '../core/logger/core';
2526
export type {
2627
MarkdownHeading,
2728
MarkdownMetadata,
@@ -1879,6 +1880,7 @@ export interface AstroIntegration {
18791880
injectScript: (stage: InjectedScriptStage, content: string) => void;
18801881
injectRoute: (injectRoute: InjectedRoute) => void;
18811882
addClientDirective: (directive: ClientDirectiveConfig) => void;
1883+
logger: AstroIntegrationLogger;
18821884
// TODO: Add support for `injectElement()` for full HTML element injection, not just scripts.
18831885
// This may require some refactoring of `scripts`, `styles`, and `links` into something
18841886
// more generalized. Consider the SSR use-case as well.
@@ -1887,10 +1889,17 @@ export interface AstroIntegration {
18871889
'astro:config:done'?: (options: {
18881890
config: AstroConfig;
18891891
setAdapter: (adapter: AstroAdapter) => void;
1892+
logger: AstroIntegrationLogger;
18901893
}) => void | Promise<void>;
1891-
'astro:server:setup'?: (options: { server: vite.ViteDevServer }) => void | Promise<void>;
1892-
'astro:server:start'?: (options: { address: AddressInfo }) => void | Promise<void>;
1893-
'astro:server:done'?: () => void | Promise<void>;
1894+
'astro:server:setup'?: (options: {
1895+
server: vite.ViteDevServer;
1896+
logger: AstroIntegrationLogger;
1897+
}) => void | Promise<void>;
1898+
'astro:server:start'?: (options: {
1899+
address: AddressInfo;
1900+
logger: AstroIntegrationLogger;
1901+
}) => void | Promise<void>;
1902+
'astro:server:done'?: (options: { logger: AstroIntegrationLogger }) => void | Promise<void>;
18941903
'astro:build:ssr'?: (options: {
18951904
manifest: SerializedSSRManifest;
18961905
/**
@@ -1902,19 +1911,25 @@ export interface AstroIntegration {
19021911
* File path of the emitted middleware
19031912
*/
19041913
middlewareEntryPoint: URL | undefined;
1914+
logger: AstroIntegrationLogger;
19051915
}) => void | Promise<void>;
1906-
'astro:build:start'?: () => void | Promise<void>;
1916+
'astro:build:start'?: (options: { logger: AstroIntegrationLogger }) => void | Promise<void>;
19071917
'astro:build:setup'?: (options: {
19081918
vite: vite.InlineConfig;
19091919
pages: Map<string, PageBuildData>;
19101920
target: 'client' | 'server';
19111921
updateConfig: (newConfig: vite.InlineConfig) => void;
1922+
logger: AstroIntegrationLogger;
1923+
}) => void | Promise<void>;
1924+
'astro:build:generated'?: (options: {
1925+
dir: URL;
1926+
logger: AstroIntegrationLogger;
19121927
}) => void | Promise<void>;
1913-
'astro:build:generated'?: (options: { dir: URL }) => void | Promise<void>;
19141928
'astro:build:done'?: (options: {
19151929
pages: { pathname: string }[];
19161930
dir: URL;
19171931
routes: RouteData[];
1932+
logger: AstroIntegrationLogger;
19181933
}) => void | Promise<void>;
19191934
};
19201935
}

packages/astro/src/core/logger/console.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export const consoleLogDestination = {
1515

1616
function getPrefix() {
1717
let prefix = '';
18-
let type = event.type;
18+
let type = event.label;
1919
if (type) {
2020
// hide timestamp when type is undefined
2121
prefix += dim(dateTimeFormat.format(new Date()) + ' ');

packages/astro/src/core/logger/core.ts

Lines changed: 59 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ interface LogWritable<T> {
66
}
77

88
export type LoggerLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent'; // same as Pino
9-
export type LoggerEvent = 'info' | 'warn' | 'error';
109

1110
export interface LogOptions {
1211
dest: LogWritable<LogMessage>;
@@ -29,7 +28,7 @@ export const dateTimeFormat = new Intl.DateTimeFormat([], {
2928
});
3029

3130
export interface LogMessage {
32-
type: string | null;
31+
label: string | null;
3332
level: LoggerLevel;
3433
message: string;
3534
}
@@ -43,11 +42,11 @@ export const levels: Record<LoggerLevel, number> = {
4342
};
4443

4544
/** Full logging API */
46-
export function log(opts: LogOptions, level: LoggerLevel, type: string | null, message: string) {
45+
export function log(opts: LogOptions, level: LoggerLevel, label: string | null, message: string) {
4746
const logLevel = opts.level;
4847
const dest = opts.dest;
4948
const event: LogMessage = {
50-
type,
49+
label,
5150
level,
5251
message,
5352
};
@@ -61,18 +60,18 @@ export function log(opts: LogOptions, level: LoggerLevel, type: string | null, m
6160
}
6261

6362
/** Emit a user-facing message. Useful for UI and other console messages. */
64-
export function info(opts: LogOptions, type: string | null, message: string) {
65-
return log(opts, 'info', type, message);
63+
export function info(opts: LogOptions, label: string | null, message: string) {
64+
return log(opts, 'info', label, message);
6665
}
6766

6867
/** Emit a warning message. Useful for high-priority messages that aren't necessarily errors. */
69-
export function warn(opts: LogOptions, type: string | null, message: string) {
70-
return log(opts, 'warn', type, message);
68+
export function warn(opts: LogOptions, label: string | null, message: string) {
69+
return log(opts, 'warn', label, message);
7170
}
7271

7372
/** Emit a error message, Useful when Astro can't recover from some error. */
74-
export function error(opts: LogOptions, type: string | null, message: string) {
75-
return log(opts, 'error', type, message);
73+
export function error(opts: LogOptions, label: string | null, message: string) {
74+
return log(opts, 'error', label, message);
7675
}
7776

7877
type LogFn = typeof info | typeof warn | typeof error;
@@ -127,3 +126,53 @@ export function timerMessage(message: string, startTime: number = Date.now()) {
127126
timeDiff < 750 ? `${Math.round(timeDiff)}ms` : `${(timeDiff / 1000).toFixed(1)}s`;
128127
return `${message} ${dim(timeDisplay)}`;
129128
}
129+
130+
export class Logger {
131+
options: LogOptions;
132+
constructor(options: LogOptions) {
133+
this.options = options;
134+
}
135+
136+
info(label: string, message: string) {
137+
info(this.options, label, message);
138+
}
139+
warn(label: string, message: string) {
140+
warn(this.options, label, message);
141+
}
142+
error(label: string, message: string) {
143+
error(this.options, label, message);
144+
}
145+
debug(label: string, message: string) {
146+
debug(this.options, label, message);
147+
}
148+
}
149+
150+
export class AstroIntegrationLogger {
151+
options: LogOptions;
152+
label: string;
153+
154+
constructor(logging: LogOptions, label: string) {
155+
this.options = logging;
156+
this.label = label;
157+
}
158+
159+
/**
160+
* Creates a new logger instance with a new label, but the same log options.
161+
*/
162+
fork(label: string): AstroIntegrationLogger {
163+
return new AstroIntegrationLogger(this.options, label);
164+
}
165+
166+
info(message: string) {
167+
info(this.options, this.label, message);
168+
}
169+
warn(message: string) {
170+
warn(this.options, this.label, message);
171+
}
172+
error(message: string) {
173+
error(this.options, this.label, message);
174+
}
175+
debug(message: string) {
176+
debug(this.options, this.label, message);
177+
}
178+
}

packages/astro/src/core/logger/node.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,19 @@ export const nodeLogDestination = new Writable({
2121

2222
function getPrefix() {
2323
let prefix = '';
24-
let type = event.type;
25-
if (type) {
24+
let label = event.label;
25+
if (label) {
2626
// hide timestamp when type is undefined
2727
prefix += dim(dateTimeFormat.format(new Date()) + ' ');
2828
if (event.level === 'info') {
29-
type = bold(cyan(`[${type}]`));
29+
label = bold(cyan(`[${label}]`));
3030
} else if (event.level === 'warn') {
31-
type = bold(yellow(`[${type}]`));
31+
label = bold(yellow(`[${label}]`));
3232
} else if (event.level === 'error') {
33-
type = bold(red(`[${type}]`));
33+
label = bold(red(`[${label}]`));
3434
}
3535

36-
prefix += `${type} `;
36+
prefix += `${label} `;
3737
}
3838
return reset(prefix);
3939
}
@@ -87,7 +87,7 @@ export const nodeLogOptions: Required<LogOptions> = {
8787
};
8888

8989
export interface LogMessage {
90-
type: string | null;
90+
label: string | null;
9191
level: LoggerLevel;
9292
message: string;
9393
}

0 commit comments

Comments
 (0)