javascript - ¿Cómo puedo acceder al manejador de archivos para ejecutar el método flush en el módulo de registro de deno usando Typescript?
Necesito acceder al objeto fileHandler de mi registrador para poder vaciar el búfer en el archivo.
Este es mi programa:
import * as log from "https://deno.land/[email /log/mod.ts"
import { Application } from "https://deno.land/x/[email /mod.ts";
const app = new Application()
const port = 7001
await log.setup({
handlers:{
file: new log.handlers.FileHandler("DEBUG",{
filename: "logger.log",
formatter: lr => {
return `${lr.datetime.toISOString()} [${lr.levelName}] ${lr.msg}`
}
})
},
loggers: {
default: {
level: "DEBUG",
handlers: ["file"]
}
}
})
const logger = log.getLogger()
logger.debug("hi there")
app.use((ctx) => {
ctx.response.body = 'Hi there'
})
console.log(`listening on port ${port}`)
app.listen({ port })
Mi problema es que el mensaje de registro nunca se escribe en el archivo. Si quito la última línea (app.listen()) sí se escribe en el archivo porque el proceso termina. Pero si lo dejo escuchando, el proceso nunca termina, así que el búfer de registro nunca se vacía.
Si interrumpo el proceso con Ctrl-C, tampoco lo escribe
La documentación (https://deno.land/[email /log/README.md) dice que puedo forzar el vaciado de registros usando el método flush de FileHandler. Pero no sé cómo acceder al objeto fileHandler.
Así que he intentado esto:
const logger = log.getLogger()
logger.debug("hi there")
logger.handlers[0].flush()
¡Y funciona! pero solo como javascript, NO como typescript
Como typescript obtengo este error:
error: TS2339 [ERROR]: Property 'flush' does not exist on type 'BaseHandler'.
logger.handlers[0].flush()
Respuesta #1
Bueno, encontré una solución.
Solo tengo que importar la clase FileHandler y convertir mi handler de BaseHandler a FileHandler. Así que agregué esta línea entre los imports:
import { FileHandler } from "https://deno.land/[email /log/handlers.ts"
Y luego, después de crear el registrador:
logger.debug("hi there")
const fileHandler = <FileHandler> logger.handlers[0]
fileHandler.flush()
Se ve un poco raro, todavía creo que debe haber una solución menos peculiar/más semántica para esto. Pero funciona bien.
Respuesta #2
Recapitulemos con la ayuda de la respuesta de Santi.
En mi experiencia, los registros en archivo funcionan bien en un programa que termina. Me refiero a un programa que se cierra por sí mismo o con Deno.exit(0). El problema ocurre en un bucle que nunca termina. En este caso, los registros no se agregan a sus archivos. A continuación se muestra cómo superar esta situación:
// dev.js : "I want my logs" example
import {serve} from "https://deno.land/[email /http/server_legacy.ts";
import * as log from "https://deno.land/[email /log/mod.ts";
// very simple setup, adapted from the official standard lib https://deno.land/[email /log
await log.setup({
handlers: {
file: new log.handlers.FileHandler("WARNING", {
filename: "./log.txt",
formatter: "{levelName} {msg}",
}),
},
loggers: {
default: {
level: "DEBUG",
handlers: ["file"],
},
},
});
// here we go
let logger;
logger = log.getLogger();
logger.warning('started');
const fileHandler = logger.handlers[0];
await fileHandler.flush(); // <---- the trick, need to flush ! Thanks Santi
// loop on requests
const srv = serve(`:4321`);
for await (const request of srv) {
request.respond({body: 'bonjour', status: 200});
logger.warning('hit !');
fileHandler.flush(); // <---- flush again
}
Correr con
deno run -A dev.js
Y revisa el archivo log.txt con el siguiente desencadenante
curl localhost:4321
Esto es de muy baja tecnología, probablemente añadiendo un retraso importante al proceso. El siguiente nivel será disparar un evento de tiempo para vaciar cada minuto más o menos.
