ghorsington 4 лет назад
Родитель
Сommit
9f62c99e0e
2 измененных файлов с 77 добавлено и 2 удалено
  1. 3 2
      .gitignore
  2. 74 0
      web/src/routes/logs/poll.ts

+ 3 - 2
.gitignore

@@ -4,6 +4,8 @@ data/
 lib/
 venv/
 
+
+
 gcloud_key.json
 
 __sapper__/
@@ -14,7 +16,6 @@ __sapper__/
 
 # ---> Node
 # Logs
-logs
 *.log
 npm-debug.log*
 
@@ -159,4 +160,4 @@ dmypy.json
 # Pyre type checker
 .pyre/
 
-# End of https://www.gitignore.io/api/python
+# End of https://www.gitignore.io/api/python

+ 74 - 0
web/src/routes/logs/poll.ts

@@ -0,0 +1,74 @@
+import { Request as ExpressRequest, Response as ExpressResponse } from "express";
+import { Option, tryDo } from "@shared/common/async_utils";
+import { rpcClient } from "src/utils/rpc";
+import { eventLogger } from "src/utils/logging";
+import { QueryOptions } from "winston";
+
+export interface LogEvent {
+    _id: string;
+    label: string;
+    level: string;
+    message: string;
+    timestamp: string;
+}
+
+export interface PollOptions {
+    limit?: string;
+}
+
+function zip(obj: Record<string, unknown[]>): unknown[] {
+    return Object.values(obj).reduce((prev, cur) => [...prev, ...cur], []);
+}
+
+function isNumber(val: unknown): val is number {
+    return !Number.isNaN(Number.parseInt(val as string, 10));
+}
+
+function queryEvents(opts?: QueryOptions | { includeIds?: boolean }):
+        Promise<Record<string, unknown[]>> {
+    return new Promise((resolve, reject) => {
+        eventLogger.query(opts as QueryOptions, (error, results) => {
+            if (error) {
+                reject(error);
+            } else {
+                resolve(results);
+            }
+        });
+    });
+}
+
+export type PollResult = Option<{ events: LogEvent[] }, { error: string }>;
+type GetResult = Promise<ExpressResponse<PollResult>>;
+export const get = async (req: ExpressRequest, res: ExpressResponse): GetResult => {
+    const params = req.query as PollOptions;
+    if (!req.session?.userId) {
+        return res.json({
+            ok: false,
+            error: "Not logged in, please log in",
+        });
+    }
+
+    const { authorised } = await rpcClient.userAuthorised({ userId: req.session.userId });
+    if (!authorised) {
+        return res.json({
+            ok: false,
+            error: "Not authorised, please log in",
+        });
+    }
+
+    const DEFAULT_LIMIT = 50;
+    const result = await tryDo(queryEvents({
+        fields: ["level", "message", "label", "timestamp"],
+        limit: isNumber(params.limit) ? +params.limit : DEFAULT_LIMIT,
+        includeIds: true,
+    }));
+
+    if (!result.ok) {
+        return res.json({
+            ok: false,
+            error: `Failed to query events. Error: ${result.error}`,
+        });
+    }
+
+    return res.json({ ok: true, events: zip(result.result) });
+};