import { Controller, Get, Query, Route, Security } from "tsoa"; import { Client as ElasticsearchClient } from "@elastic/elasticsearch"; function getEnvVar(name: string) { const value = process.env[name]; if (!value) throw new Error(`${name} is required.`); return value; } const ELASTICSEARCH_PROTOCOL = getEnvVar("ELASTICSEARCH_PROTOCOL"); const ELASTICSEARCH_HOST = getEnvVar("ELASTICSEARCH_HOST"); const ELASTICSEARCH_PORT = getEnvVar("ELASTICSEARCH_PORT"); const ELASTICSEARCH_INDEX = getEnvVar("ELASTICSEARCH_INDEX"); const elasticsearch = new ElasticsearchClient({ node: `${ELASTICSEARCH_PROTOCOL}://${ELASTICSEARCH_HOST}:${ELASTICSEARCH_PORT}`, }); @Route("/api/v1/log") @Security("keycloak") export class LogController extends Controller { @Get() async GET( @Query() size: number = 30, @Query() search?: string, @Query() searchAfter?: number, @Query() systemName?: string, @Query() date?: Date, @Query() startDate?: Date, @Query() endDate?: Date, @Query() timezone = "+07:00", @Query() sort: "asc" | "desc" = "desc", ) { let startDateString: string | undefined; let endDateString: string | undefined; let startTimeString = "00:00:00"; let endTimeString = "23:59:59"; if (date && !startDate && !endDate) { startDateString = `${date.getFullYear()}-${`${date.getMonth() + 1}`.padStart(2, "0")}-${`${date.getDate()}`.padStart(2, "0")}T${startTimeString}`; endDateString = `${date.getFullYear()}-${`${date.getMonth() + 1}`.padStart(2, "0")}-${`${date.getDate()}`.padStart(2, "0")}T${endTimeString}`; } if (startDate) startDateString = startDate.toISOString(); if (endDate) endDateString = endDate.toISOString(); const queryData = await elasticsearch.search({ index: ELASTICSEARCH_INDEX, query: { bool: { must: [ ...(systemName ? [{ match: { systemName } }] : []), ...(search ? [ { bool: { should: ["method", "logType", "endpoint", "host", "responseCode"].map( (v) => ({ wildcard: { [v]: "*" + search + "*" }, }), ), }, }, ] : []), ...(startDateString || endDateString ? [ { range: { startTimeStamp: { time_zone: timezone, gte: startDateString, lte: endDateString, }, }, }, ] : []), ], }, }, search_after: searchAfter ? [searchAfter] : undefined, sort: [{ startTimeStamp: sort }], size: size, }); return queryData.hits.hits; } }