QuickZTNA User Guide
Home Audit Log Filter by Date Range

Filter by Date Range

What We’re Testing

When date_from and date_to are set on the search_audit_logs request body, the queryAuditLogs() function in services/loki.ts converts them to Unix epoch seconds and passes them as start and end parameters to the Loki query_range API:

GET /loki/api/v1/query_range
  ?query={job="audit",org_id="..."}
  &start=1742000000      ← date_from in seconds
  &end=1742086400        ← date_to in seconds
  &limit=50
  &direction=backward

When neither date_from nor date_to is provided, queryAuditLogs() defaults to the last 90 days (Date.now() - 90 * 86400 * 1000).

The AuditLogPage.tsx component offers five date presets via DATE_PRESETS:

Preset labelValue sent to API
All Timedate_from and date_to omitted (uses 90-day default)
Todaydate_from = start of current day (midnight local time)
Last 7 Daysdate_from = now minus 7 days
Last 30 Daysdate_from = now minus 30 days
Last 90 Daysdate_from = now minus 90 days

All date values are sent as ISO 8601 strings (e.g., "2026-03-17T00:00:00.000Z"). The Loki service converts them with Math.floor(new Date(date_from).getTime() / 1000).

Your Test Setup

MachineRole
Win-A Browser (dashboard) + PowerShell API calls

Prerequisites:

  • Audit events exist from at least two different days (yesterday and today). If your org is new, log out and log back in on two different calendar days to generate entries on separate dates.
  • The Filters panel is open on the Audit Log page (click Filters).

ST1 — “Today” Preset Returns Only Today’s Events

What it verifies: Selecting “Today” sends date_from equal to midnight of the current day and date_to equal to the current timestamp, so only events from today are returned.

Steps:

  1. On Win-A , open the Audit Log page and click Filters.

  2. In the date range dropdown (calendar icon, labelled “All Time” by default), select “Today”.

  3. Observe the event count in the heading. It should be equal to or less than the “All Time” count.

  4. Verify via API. Note today’s midnight in ISO format:

$today = (Get-Date -Hour 0 -Minute 0 -Second 0 -Millisecond 0).ToUniversalTime().ToString("o")
$now   = (Get-Date).ToUniversalTime().ToString("o")

$body = @{
    action    = "search_audit_logs"
    org_id    = $ORG_ID
    date_from = $today
    date_to   = $now
    page      = 0
    page_size = 50
} | ConvertTo-Json

$resp = Invoke-RestMethod `
    -Uri "https://login.quickztna.com/api/governance" `
    -Method POST `
    -Headers @{ Authorization = "Bearer $TOKEN"; "Content-Type" = "application/json" } `
    -Body $body

$resp.data.logs | Select-Object action, created_at
  1. For every returned entry, confirm created_at is today’s date (UTC):
$resp.data.logs | ForEach-Object {
    $d = [datetime]$_.created_at
    if ($d.Date -ne (Get-Date).Date) { Write-Host "FAIL: $($_.created_at) is not today" }
}

Pass: All created_at values are within today’s UTC date; no entries from previous days appear.

Fail / Common issues:

  • All events disappear (“No events match your filters”) — no events have been generated today. Log out and log back in to create an auth.login entry, then retest.
  • Events from yesterday appear — this can happen if the client’s local clock is in a different timezone from UTC and midnight calculation uses local time. The getDateRange("today") function in the frontend uses new Date(now.getFullYear(), now.getMonth(), now.getDate()) in local time, then calls .toISOString() which converts to UTC. Verify the browser’s locale timezone is correct.

ST2 — “Last 7 Days” Preset

What it verifies: The 7-day preset sends date_from = now - 7 * 86400000 (milliseconds) and all returned events fall within the last 7 days.

Steps:

  1. On Win-A , select “Last 7 Days” from the date dropdown.

  2. Note the event count in the heading.

  3. Verify via API:

$sevenDaysAgo = (Get-Date).AddDays(-7).ToUniversalTime().ToString("o")
$now          = (Get-Date).ToUniversalTime().ToString("o")

$body = @{
    action    = "search_audit_logs"
    org_id    = $ORG_ID
    date_from = $sevenDaysAgo
    date_to   = $now
    page      = 0
    page_size = 200
} | ConvertTo-Json

$resp = Invoke-RestMethod `
    -Uri "https://login.quickztna.com/api/governance" `
    -Method POST `
    -Headers @{ Authorization = "Bearer $TOKEN"; "Content-Type" = "application/json" } `
    -Body $body

Write-Host "Total (last 7 days): $($resp.data.total)"
  1. Confirm total is less than or equal to the “All Time” event count from ST1 in the previous chapter.

  2. Confirm no entry has a created_at older than 7 days:

$cutoff = (Get-Date).AddDays(-7)
$resp.data.logs | ForEach-Object {
    $d = [datetime]$_.created_at
    if ($d -lt $cutoff) { Write-Host "FAIL: $($_.created_at) is older than 7 days" }
}

Pass: total is less than or equal to the unfiltered count; no entry pre-dates the 7-day boundary.

Fail / Common issues:

  • total equals the unfiltered count — all events were generated within the last 7 days. This is expected for a new org and is not a failure.

ST3 — “Last 30 Days” and “Last 90 Days” Presets

What it verifies: Both 30-day and 90-day presets work and return progressively more events. The 90-day preset matches the queryAuditLogs default range when no date filter is set.

Steps:

  1. On Win-A , select “Last 30 Days” from the date dropdown. Note the count in the heading.

  2. Select “Last 90 Days”. Note the count in the heading.

  3. Select “All Time”. Note the count.

  4. Confirm: count(Last 30 Days) is less than or equal to count(Last 90 Days), which is less than or equal to count(All Time).

  5. Verify the 90-day preset matches the default Loki query window (90 days) by calling the API with no date params and comparing:

$ninetyDaysAgo = (Get-Date).AddDays(-90).ToUniversalTime().ToString("o")
$now           = (Get-Date).ToUniversalTime().ToString("o")

$withDate = @{
    action    = "search_audit_logs"
    org_id    = $ORG_ID
    date_from = $ninetyDaysAgo
    date_to   = $now
    page      = 0
    page_size = 1
} | ConvertTo-Json

$withoutDate = @{
    action    = "search_audit_logs"
    org_id    = $ORG_ID
    page      = 0
    page_size = 1
} | ConvertTo-Json

$r1 = Invoke-RestMethod -Uri "https://login.quickztna.com/api/governance" -Method POST `
    -Headers @{ Authorization = "Bearer $TOKEN"; "Content-Type" = "application/json" } -Body $withDate
$r2 = Invoke-RestMethod -Uri "https://login.quickztna.com/api/governance" -Method POST `
    -Headers @{ Authorization = "Bearer $TOKEN"; "Content-Type" = "application/json" } -Body $withoutDate

Write-Host "With 90-day date filter: $($r1.data.total)"
Write-Host "Without date filter (default 90 days): $($r2.data.total)"

Expected: Both totals are approximately equal (within a few events due to timing differences in the cutoff calculation).

Pass: 30d count is at most 90d count, which is at most All Time count. The 90-day explicit range approximately matches the default range.

Fail / Common issues:

  • 90-day count is much larger than the no-date count — the “All Time” default in the frontend omits date_from, causing queryAuditLogs to use its own 90-day default. If “All Time” is truly meant to have no lower bound, this is a known UI/service discrepancy. For the purposes of this test, the assertion is that the 90-day filter and the default behave similarly.

ST4 — Custom Date Range via Direct API Call

What it verifies: Arbitrary date_from / date_to values are accepted and return the correct time-bounded slice of events.

Steps:

  1. On Win-A , choose a specific narrow date window — for example, a 1-hour window from yesterday:
$start = (Get-Date).AddDays(-1).Date.AddHours(12).ToUniversalTime().ToString("o")  # yesterday noon UTC
$end   = (Get-Date).AddDays(-1).Date.AddHours(13).ToUniversalTime().ToString("o")  # yesterday 1 PM UTC

$body = @{
    action    = "search_audit_logs"
    org_id    = $ORG_ID
    date_from = $start
    date_to   = $end
    page      = 0
    page_size = 50
} | ConvertTo-Json

$resp = Invoke-RestMethod `
    -Uri "https://login.quickztna.com/api/governance" `
    -Method POST `
    -Headers @{ Authorization = "Bearer $TOKEN"; "Content-Type" = "application/json" } `
    -Body $body

Write-Host "Events in 1-hour window: $($resp.data.total)"
$resp.data.logs | Select-Object action, created_at
  1. For each returned entry, confirm created_at falls within the specified window:
$startDt = [datetime]$start
$endDt   = [datetime]$end
$resp.data.logs | ForEach-Object {
    $d = [datetime]$_.created_at
    if ($d -lt $startDt -or $d -gt $endDt) {
        Write-Host "FAIL: $($_.created_at) outside window"
    }
}

Pass: All returned entries fall within the specified 1-hour window; events outside the window are excluded.

Fail / Common issues:

  • Zero results — no events were generated in that specific hour. Adjust the window to a time when you know activity occurred (check the unfiltered log first).
  • Events outside the window appear — this would be a Loki start/end parameter bug. Verify that queryAuditLogs is converting the ISO string to Unix seconds correctly: Math.floor(new Date(date_from).getTime() / 1000).

ST5 — Date Filter Combined With Action Category

What it verifies: Date and action category filters can be combined, and the LogQL stream selector includes both action_prefix and the time window.

Steps:

  1. On Win-A , on the Audit Log page, select “Today” as the date preset and auth as the Action Type.

  2. Observe the filtered count in the heading.

  3. Verify via API:

$today = (Get-Date -Hour 0 -Minute 0 -Second 0 -Millisecond 0).ToUniversalTime().ToString("o")
$now   = (Get-Date).ToUniversalTime().ToString("o")

$body = @{
    action          = "search_audit_logs"
    org_id          = $ORG_ID
    action_category = "auth"
    date_from       = $today
    date_to         = $now
    page            = 0
    page_size       = 50
} | ConvertTo-Json

$resp = Invoke-RestMethod `
    -Uri "https://login.quickztna.com/api/governance" `
    -Method POST `
    -Headers @{ Authorization = "Bearer $TOKEN"; "Content-Type" = "application/json" } `
    -Body $body

Write-Host "Auth events today: $($resp.data.total)"
$resp.data.logs | Select-Object action, created_at
  1. Confirm every entry has:
    • action starting with auth.
    • created_at within today’s date

Pass: All entries are auth events from today; no cross-category or prior-day events appear.

Fail / Common issues:

  • Zero results — no auth events today. Log out and log back in to generate auth.login, then retest immediately.
  • Results include non-auth events — the action_prefix label selector is not being applied. Check that action_category was sent (not action) in the request body.

Summary

Sub-testWhat it provesKey assertion
ST1”Today” preset limits results to the current calendar dayAll created_at values are within today’s UTC date
ST2”Last 7 Days” preset excludes older eventsNo entry pre-dates the 7-day boundary
ST330d and 90d presets produce increasing counts; 90d matches the default30d count is at most 90d count, at most All Time count
ST4Custom date range via API returns only events within the windowAll entries fall within the specified start/end
ST5Date and action category filters combine correctlyOnly auth events from today; no cross-category or prior-day leakage