♻️ set default log analytics time range to. 7days ago

This commit is contained in:
Fred KISSIE
2025-12-08 22:57:05 +01:00
parent 2325e30f26
commit e0a79b7d4d
3 changed files with 52 additions and 45 deletions

View File

@@ -2,7 +2,7 @@ import { db, requestAuditLog, driver } from "@server/db";
import { registry } from "@server/openApi";
import { NextFunction } from "express";
import { Request, Response } from "express";
import { eq, gt, lt, and, count, sql, desc, not, isNull } from "drizzle-orm";
import { eq, gte, lte, and, count, sql, desc, not, isNull } from "drizzle-orm";
import { OpenAPITags } from "@server/openApi";
import { z } from "zod";
import createHttpError from "http-errors";
@@ -11,6 +11,14 @@ import { fromError } from "zod-validation-error";
import response from "@server/lib/response";
import logger from "@server/logger";
function getSevenDaysAgo() {
const today = new Date();
today.setHours(0, 0, 0, 0); // Set to midnight
const sevenDaysAgo = new Date(today);
sevenDaysAgo.setDate(today.getDate() - 7);
return sevenDaysAgo.toISOString();
}
const queryAccessAuditLogsQuery = z.object({
// iso string just validate its a parseable date
timeStart: z
@@ -19,7 +27,8 @@ const queryAccessAuditLogsQuery = z.object({
error: "timeStart must be a valid ISO date string"
})
.transform((val) => Math.floor(new Date(val).getTime() / 1000))
.optional(),
.optional()
.prefault(getSevenDaysAgo),
timeEnd: z
.string()
.refine((val) => !isNaN(Date.parse(val)), {
@@ -55,15 +64,10 @@ type Q = z.infer<typeof queryRequestAuditLogsCombined>;
async function query(query: Q) {
let baseConditions = and(
eq(requestAuditLog.orgId, query.orgId),
lt(requestAuditLog.timestamp, query.timeEnd)
gte(requestAuditLog.timestamp, query.timeStart),
lte(requestAuditLog.timestamp, query.timeEnd)
);
if (query.timeStart) {
baseConditions = and(
baseConditions,
gt(requestAuditLog.timestamp, query.timeStart)
);
}
if (query.resourceId) {
baseConditions = and(
baseConditions,

View File

@@ -1,22 +1,27 @@
"use client";
import { useEnvContext } from "@app/hooks/useEnvContext";
import { createApiClient } from "@app/lib/api";
import { cn } from "@app/lib/cn";
import {
logAnalyticsFiltersSchema,
logQueries,
resourceQueries
} from "@app/lib/queries";
import { useQuery } from "@tanstack/react-query";
import { usePathname, useRouter, useSearchParams } from "next/navigation";
import { useState } from "react";
import { Card, CardContent, CardHeader } from "./ui/card";
import { LoaderIcon, RefreshCw, XIcon } from "lucide-react";
import { useTranslations } from "next-intl";
import { usePathname, useRouter, useSearchParams } from "next/navigation";
import { DateRangePicker, type DateTimeValue } from "./DateTimePicker";
import { Button } from "./ui/button";
import { cn } from "@app/lib/cn";
import { useTranslations } from "next-intl";
import { Card, CardContent, CardHeader } from "./ui/card";
import { countryCodeToFlagEmoji } from "@app/lib/countryCodeToFlagEmoji";
import {
InfoSection,
InfoSectionContent,
InfoSections,
InfoSectionTitle
} from "./InfoSection";
import { Label } from "./ui/label";
import {
Select,
SelectContent,
@@ -24,23 +29,10 @@ import {
SelectTrigger,
SelectValue
} from "./ui/select";
import { Label } from "./ui/label";
import { Separator } from "./ui/separator";
import {
InfoSection,
InfoSectionContent,
InfoSections,
InfoSectionTitle
} from "./InfoSection";
import { WorldMap } from "./WorldMap";
import { countryCodeToFlagEmoji } from "@app/lib/countryCodeToFlagEmoji";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger
} from "./ui/tooltip";
import { CartesianGrid, Line, LineChart, XAxis, YAxis } from "recharts";
import {
ChartContainer,
ChartLegend,
@@ -49,12 +41,25 @@ import {
ChartTooltipContent,
type ChartConfig
} from "./ui/chart";
import { CartesianGrid, Line, LineChart, XAxis, YAxis } from "recharts";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger
} from "./ui/tooltip";
export type AnalyticsContentProps = {
orgId: string;
};
function getSevenDaysAgo() {
const today = new Date();
today.setHours(0, 0, 0, 0); // Set to midnight
const sevenDaysAgo = new Date(today);
sevenDaysAgo.setDate(today.getDate() - 7);
return sevenDaysAgo;
}
export function LogAnalyticsData(props: AnalyticsContentProps) {
const searchParams = useSearchParams();
const path = usePathname();
@@ -67,17 +72,18 @@ export function LogAnalyticsData(props: AnalyticsContentProps) {
const isEmptySearchParams =
!filters.resourceId && !filters.timeStart && !filters.timeEnd;
const env = useEnvContext();
const [api] = useState(() => createApiClient(env));
const router = useRouter();
console.log({ filters });
const dateRange = {
startDate: filters.timeStart ? new Date(filters.timeStart) : undefined,
endDate: filters.timeEnd ? new Date(filters.timeEnd) : undefined
startDate: filters.timeStart
? new Date(filters.timeStart)
: getSevenDaysAgo(),
endDate: filters.timeEnd ? new Date(filters.timeEnd) : new Date()
};
const { data: resources = [], isFetching: isFetchingResources } = useQuery(
resourceQueries.listNamesPerOrg(props.orgId, api)
resourceQueries.listNamesPerOrg(props.orgId)
);
const {
@@ -88,7 +94,6 @@ export function LogAnalyticsData(props: AnalyticsContentProps) {
} = useQuery(
logQueries.requestAnalytics({
orgId: props.orgId,
api,
filters
})
);

View File

@@ -168,17 +168,15 @@ export type LogAnalyticsFilters = z.TypeOf<typeof logAnalyticsFiltersSchema>;
export const logQueries = {
requestAnalytics: ({
orgId,
filters,
api
filters
}: {
orgId: string;
filters: LogAnalyticsFilters;
api: AxiosInstance;
}) =>
queryOptions({
queryKey: ["REQUEST_LOG_ANALYTICS", orgId, filters] as const,
queryFn: async ({ signal }) => {
const res = await api.get<
queryFn: async ({ signal, meta }) => {
const res = await meta!.api.get<
AxiosResponse<QueryRequestAnalyticsResponse>
>(`/org/${orgId}/logs/analytics`, {
params: filters,
@@ -228,11 +226,11 @@ export const resourceQueries = {
return res.data.data.clients;
}
}),
listNamesPerOrg: (orgId: string, api: AxiosInstance) =>
listNamesPerOrg: (orgId: string) =>
queryOptions({
queryKey: ["RESOURCES_NAMES", orgId] as const,
queryFn: async ({ signal }) => {
const res = await api.get<
queryFn: async ({ signal, meta }) => {
const res = await meta!.api.get<
AxiosResponse<ListResourceNamesResponse>
>(`/org/${orgId}/resource-names`, {
signal