feat(api): adopt pino request logging
This commit is contained in:
@@ -1,12 +1,15 @@
|
|||||||
import express from 'express';
|
import express from "express";
|
||||||
import { setRoutes } from './routes/index';
|
import { setRoutes } from "./routes/index";
|
||||||
import { errorHandler } from './middlewares/errorHandler';
|
import { errorHandler } from "./middlewares/errorHandler";
|
||||||
import requestLogger from './middlewares/requestLogger';
|
import pino from "pino";
|
||||||
|
import pinoHttp from "pino-http";
|
||||||
|
|
||||||
|
const logger = pino({ level: process.env.LOG_LEVEL || "info" });
|
||||||
const app = express();
|
const app = express();
|
||||||
const PORT = process.env.PORT || 3000;
|
const PORT = process.env.PORT || 3000;
|
||||||
|
|
||||||
app.use(requestLogger);
|
app.set("logger", logger);
|
||||||
|
app.use(pinoHttp({ logger }));
|
||||||
app.use(express.json());
|
app.use(express.json());
|
||||||
|
|
||||||
setRoutes(app);
|
setRoutes(app);
|
||||||
@@ -14,5 +17,5 @@ setRoutes(app);
|
|||||||
app.use(errorHandler);
|
app.use(errorHandler);
|
||||||
|
|
||||||
app.listen(PORT, () => {
|
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 { Request, Response } from "express";
|
||||||
import StreamService from '../services/streamService';
|
import StreamService from "../services/streamService";
|
||||||
|
import { Logger } from "pino";
|
||||||
|
|
||||||
export default class StreamController {
|
export default class StreamController {
|
||||||
constructor(private streamService: StreamService) { }
|
constructor(
|
||||||
|
private streamService: StreamService,
|
||||||
|
private logger: Logger,
|
||||||
|
) {}
|
||||||
|
|
||||||
// GET /api/streams/:key
|
// GET /api/streams/:key
|
||||||
async streamAudio(req: Request, res: Response) {
|
async streamAudio(req: Request, res: Response) {
|
||||||
const { fileName: key } = req.params as { fileName: string };
|
const { fileName: key } = req.params as { fileName: string };
|
||||||
const range = req.headers.range as string | undefined;
|
const range = req.headers.range as string | undefined;
|
||||||
if (!key) return res.status(400).send('Missing file key');
|
if (!key) return res.status(400).send("Missing file key");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await this.streamService.streamFromS3({ key, range });
|
this.logger.info(
|
||||||
res.writeHead(result.status, result.headers);
|
`Attempting to stream file: ${key}, range: ${range || "none"}`,
|
||||||
result.body.pipe(res);
|
);
|
||||||
} catch (err: any) {
|
const result = await this.streamService.streamFromS3({ key, range });
|
||||||
const message = err?.message || 'Error streaming audio';
|
this.logger.info(
|
||||||
const status = err?.statusCode || 500;
|
`Streaming successful for ${key}, status: ${result.status}, content-length: ${result.headers["Content-Length"]}`,
|
||||||
res.status(status).send(message);
|
);
|
||||||
}
|
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 { Application, Router, Request, Response } from "express";
|
||||||
import StreamController from '../controllers/streamController';
|
import StreamController from "../controllers/streamController";
|
||||||
import StreamService from '../services/streamService';
|
import StreamService from "../services/streamService";
|
||||||
|
|
||||||
const router = Router();
|
const router = Router();
|
||||||
const streamService = new StreamService();
|
|
||||||
const streamController = new StreamController(streamService);
|
|
||||||
|
|
||||||
export function setRoutes(app: Application) {
|
export function setRoutes(app: Application) {
|
||||||
// Health endpoints
|
// Health endpoints
|
||||||
app.get('/', (_req: Request, res: Response) => res.status(200).send('OK'));
|
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.get("/healthz", (_req: Request, res: Response) =>
|
||||||
|
res.status(200).json({ status: "ok" }),
|
||||||
|
);
|
||||||
|
|
||||||
app.use('/api/streams', router);
|
const streamService = new StreamService(
|
||||||
router.get('/:fileName', streamController.streamAudio.bind(streamController));
|
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