feat(api): adopt pino request logging
This commit is contained in:
@@ -1,12 +1,15 @@
|
||||
import express from 'express';
|
||||
import { setRoutes } from './routes/index';
|
||||
import { errorHandler } from './middlewares/errorHandler';
|
||||
import requestLogger from './middlewares/requestLogger';
|
||||
import express from "express";
|
||||
import { setRoutes } from "./routes/index";
|
||||
import { errorHandler } from "./middlewares/errorHandler";
|
||||
import pino from "pino";
|
||||
import pinoHttp from "pino-http";
|
||||
|
||||
const logger = pino({ level: process.env.LOG_LEVEL || "info" });
|
||||
const app = express();
|
||||
const PORT = process.env.PORT || 3000;
|
||||
|
||||
app.use(requestLogger);
|
||||
app.set("logger", logger);
|
||||
app.use(pinoHttp({ logger }));
|
||||
app.use(express.json());
|
||||
|
||||
setRoutes(app);
|
||||
@@ -14,5 +17,5 @@ setRoutes(app);
|
||||
app.use(errorHandler);
|
||||
|
||||
app.listen(PORT, () => {
|
||||
console.log(`Server is running on port ${PORT}`);
|
||||
});
|
||||
logger.info(`Server is running on port ${PORT}`);
|
||||
});
|
||||
|
||||
@@ -1,23 +1,34 @@
|
||||
import { Request, Response } from 'express';
|
||||
import StreamService from '../services/streamService';
|
||||
import { Request, Response } from "express";
|
||||
import StreamService from "../services/streamService";
|
||||
import { Logger } from "pino";
|
||||
|
||||
export default class StreamController {
|
||||
constructor(private streamService: StreamService) { }
|
||||
constructor(
|
||||
private streamService: StreamService,
|
||||
private logger: Logger,
|
||||
) {}
|
||||
|
||||
// GET /api/streams/:key
|
||||
async streamAudio(req: Request, res: Response) {
|
||||
const { fileName: key } = req.params as { fileName: string };
|
||||
const range = req.headers.range as string | undefined;
|
||||
if (!key) return res.status(400).send('Missing file key');
|
||||
// GET /api/streams/:key
|
||||
async streamAudio(req: Request, res: Response) {
|
||||
const { fileName: key } = req.params as { fileName: string };
|
||||
const range = req.headers.range as string | undefined;
|
||||
if (!key) return res.status(400).send("Missing file key");
|
||||
|
||||
try {
|
||||
const result = await this.streamService.streamFromS3({ key, range });
|
||||
res.writeHead(result.status, result.headers);
|
||||
result.body.pipe(res);
|
||||
} catch (err: any) {
|
||||
const message = err?.message || 'Error streaming audio';
|
||||
const status = err?.statusCode || 500;
|
||||
res.status(status).send(message);
|
||||
}
|
||||
try {
|
||||
this.logger.info(
|
||||
`Attempting to stream file: ${key}, range: ${range || "none"}`,
|
||||
);
|
||||
const result = await this.streamService.streamFromS3({ key, range });
|
||||
this.logger.info(
|
||||
`Streaming successful for ${key}, status: ${result.status}, content-length: ${result.headers["Content-Length"]}`,
|
||||
);
|
||||
res.writeHead(result.status, result.headers);
|
||||
result.body.pipe(res);
|
||||
} catch (err: any) {
|
||||
this.logger.error({ err, key }, `Error streaming audio file ${key}`);
|
||||
const message = err?.message || "Error streaming audio";
|
||||
const status = err?.statusCode || 500;
|
||||
res.status(status).send(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
import { Request, Response, NextFunction } from 'express';
|
||||
|
||||
const requestLogger = (req: Request, res: Response, next: NextFunction) => {
|
||||
console.log(`${req.method} ${req.url}`);
|
||||
next();
|
||||
};
|
||||
|
||||
export default requestLogger;
|
||||
@@ -1,18 +1,28 @@
|
||||
import { Application, Router, Request, Response } from 'express';
|
||||
import StreamController from '../controllers/streamController';
|
||||
import StreamService from '../services/streamService';
|
||||
import { Application, Router, Request, Response } from "express";
|
||||
import StreamController from "../controllers/streamController";
|
||||
import StreamService from "../services/streamService";
|
||||
|
||||
const router = Router();
|
||||
const streamService = new StreamService();
|
||||
const streamController = new StreamController(streamService);
|
||||
|
||||
export function setRoutes(app: Application) {
|
||||
// Health endpoints
|
||||
app.get('/', (_req: Request, res: Response) => res.status(200).send('OK'));
|
||||
app.get('/healthz', (_req: Request, res: Response) => res.status(200).json({ status: 'ok' }));
|
||||
// Health endpoints
|
||||
app.get("/", (_req: Request, res: Response) => res.status(200).send("OK"));
|
||||
app.get("/healthz", (_req: Request, res: Response) =>
|
||||
res.status(200).json({ status: "ok" }),
|
||||
);
|
||||
|
||||
app.use('/api/streams', router);
|
||||
router.get('/:fileName', streamController.streamAudio.bind(streamController));
|
||||
const streamService = new StreamService(
|
||||
app.get("logger"),
|
||||
process.env.S3_BUCKET,
|
||||
process.env.S3_PREFIX,
|
||||
);
|
||||
const streamController = new StreamController(
|
||||
streamService,
|
||||
app.get("logger"),
|
||||
);
|
||||
|
||||
router.get("/:fileName", streamController.streamAudio.bind(streamController));
|
||||
app.use("/api/streams", router);
|
||||
}
|
||||
|
||||
export default router;
|
||||
export default router;
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
import { Router } from 'express';
|
||||
import StreamController from '../controllers/streamController';
|
||||
import StreamService from '../services/streamService';
|
||||
|
||||
const router = Router();
|
||||
const streamService = new StreamService();
|
||||
const streamController = new StreamController(streamService);
|
||||
|
||||
router.get('/:fileName', streamController.streamAudio.bind(streamController));
|
||||
|
||||
export default router;
|
||||
9
s3-nodejs-api/src/types/pino.d.ts
vendored
Normal file
9
s3-nodejs-api/src/types/pino.d.ts
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
import { Logger } from 'pino';
|
||||
|
||||
declare global {
|
||||
namespace Express {
|
||||
interface Request {
|
||||
log: Logger;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user