feat(auth): add recent activity logging to access tracker
CI / build-and-test (push) Failing after 0s
CI / build-and-test (push) Failing after 0s
* Introduced AccessLogEntry type for logging access details * Updated AccessTracker to maintain a recent activity log * Modified Metrics to include recent activity log in response * Added RecentActivityLog component to display logged activities
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
import type { StatusResponse } from '../../types';
|
||||
import AccessTable from './AccessTable.svelte';
|
||||
import ConnectionBreakdown from './ConnectionBreakdown.svelte';
|
||||
import RecentActivityLog from './RecentActivityLog.svelte';
|
||||
import StatusCards from './StatusCards.svelte';
|
||||
|
||||
const {
|
||||
@@ -67,4 +68,7 @@
|
||||
emptyLabel="No MCP tool calls recorded yet."
|
||||
/>
|
||||
</div>
|
||||
<div class="mt-6">
|
||||
<RecentActivityLog entries={data.metrics.recent_log ?? []} />
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
<script lang="ts">
|
||||
import type { AccessLogEntry } from '../../types';
|
||||
|
||||
const { entries }: { entries: AccessLogEntry[] } = $props();
|
||||
|
||||
function formatTime(value: string): string {
|
||||
return new Date(value).toLocaleString();
|
||||
}
|
||||
</script>
|
||||
|
||||
<section class="rounded-3xl border border-white/10 bg-slate-900/80 p-6 shadow-xl shadow-slate-950/20 sm:p-8">
|
||||
<h3 class="text-xl font-semibold text-white">Recent activity <span class="ml-2 text-sm font-normal text-slate-500">(last {entries.length})</span></h3>
|
||||
{#if entries.length === 0}
|
||||
<div class="mt-6 rounded-2xl border border-dashed border-white/10 bg-slate-950/40 px-4 py-10 text-center text-slate-500">
|
||||
No activity recorded yet.
|
||||
</div>
|
||||
{:else}
|
||||
<div class="mt-6 overflow-hidden rounded-2xl border border-white/10">
|
||||
<div class="overflow-x-auto">
|
||||
<table class="min-w-full divide-y divide-white/10 text-left text-sm text-slate-300">
|
||||
<thead class="bg-white/5 text-xs uppercase tracking-[0.2em] text-slate-500">
|
||||
<tr>
|
||||
<th class="px-4 py-3 font-medium">Time</th>
|
||||
<th class="px-4 py-3 font-medium">Principal</th>
|
||||
<th class="px-4 py-3 font-medium">IP</th>
|
||||
<th class="px-4 py-3 font-medium">User Agent</th>
|
||||
<th class="px-4 py-3 font-medium">Tool</th>
|
||||
<th class="px-4 py-3 font-medium">Path</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-white/5 bg-slate-950/30">
|
||||
{#each entries as entry}
|
||||
<tr class="hover:bg-white/[0.03]">
|
||||
<td class="whitespace-nowrap px-4 py-2.5 text-xs text-slate-400">{formatTime(entry.timestamp)}</td>
|
||||
<td class="px-4 py-2.5"><code class="rounded bg-white/5 px-2 py-0.5 font-mono text-xs text-cyan-100">{entry.key_id}</code></td>
|
||||
<td class="px-4 py-2.5"><code class="text-xs text-slate-200">{entry.ip || '—'}</code></td>
|
||||
<td class="max-w-[16rem] truncate px-4 py-2.5 text-xs text-slate-400" title={entry.user_agent}>{entry.user_agent || '—'}</td>
|
||||
<td class="px-4 py-2.5">
|
||||
{#if entry.tool}
|
||||
<code class="rounded bg-indigo-500/10 px-2 py-0.5 text-xs text-indigo-300">{entry.tool}</code>
|
||||
{:else}
|
||||
<span class="text-slate-600">—</span>
|
||||
{/if}
|
||||
</td>
|
||||
<td class="max-w-[14rem] truncate px-4 py-2.5"><code class="text-xs text-slate-300">{entry.path}</code></td>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</section>
|
||||
@@ -12,6 +12,15 @@ export type RequestAggregate = {
|
||||
request_count: number;
|
||||
};
|
||||
|
||||
export type AccessLogEntry = {
|
||||
timestamp: string;
|
||||
key_id: string;
|
||||
ip: string;
|
||||
user_agent: string;
|
||||
tool: string;
|
||||
path: string;
|
||||
};
|
||||
|
||||
export type AccessMetrics = {
|
||||
total_requests: number;
|
||||
unique_principals: number;
|
||||
@@ -21,6 +30,7 @@ export type AccessMetrics = {
|
||||
top_ips: RequestAggregate[];
|
||||
top_agents: RequestAggregate[];
|
||||
top_tools: RequestAggregate[];
|
||||
recent_log: AccessLogEntry[];
|
||||
};
|
||||
|
||||
export type StatusResponse = {
|
||||
|
||||
Reference in New Issue
Block a user