check / check (push) Successful in 3m21s
While an http or slack target's circuit breaker is open, the target's row on the webhook page says its deliveries are paused until the cooldown ends, in UTC and from now. Each of its retrying deliveries shows as waiting in the event log and on the event's page, until the later of the cooldown's end and the end of its own backoff. While the breaker is half-open, the row says deliveries are held while one delivery tests the target, with no time, and deliveries keep their plain status. The engine gains one read, StateAndCooldown(targetID), taking a breaker's state and remaining cooldown under one lock; the handlers reach it through a one-method interface wired like Archives. Model: opus-5-5
116 lines
7.3 KiB
HTML
116 lines
7.3 KiB
HTML
{{template "base" .}}
|
|
|
|
{{define "title"}}Full Event Log - {{.Webhook.Name}} - Webhooker{{end}}
|
|
|
|
{{define "content"}}
|
|
<div class="max-w-6xl mx-auto px-6 py-8">
|
|
<div class="mb-6">
|
|
<a href="/hook/{{.Webhook.ID}}" class="btn-small">← Back to {{.Webhook.Name}}</a>
|
|
<div class="flex justify-between items-center mt-2">
|
|
<h1 class="text-2xl font-medium text-gray-900">Full Event Log</h1>
|
|
<span class="text-sm text-gray-500">{{.TotalEvents}} total event{{if ne .TotalEvents 1}}s{{end}}</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<div class="divide-y divide-gray-100">
|
|
{{range .Events}}
|
|
<div class="p-4" x-data="collapsible">
|
|
<button type="button" class="btn-small w-full flex flex-wrap justify-between gap-2 text-left" @click="toggle">
|
|
<span class="flex flex-wrap items-center gap-3">
|
|
<span class="badge-info">{{.Method}}</span>
|
|
<span class="text-sm font-mono text-gray-700">{{.ID}}</span>
|
|
<span class="text-sm text-gray-500">{{.ContentType}}</span>
|
|
{{if .ResubmittedFrom}}
|
|
<span class="text-xs text-gray-500" title="This event is a copy of {{.ResubmittedFromID}}">resubmitted copy</span>
|
|
{{end}}
|
|
{{if .ResubmitCount}}
|
|
<span class="text-xs text-gray-500">resubmitted {{.ResubmitCount}} time{{if ne .ResubmitCount 1}}s{{end}}</span>
|
|
{{end}}
|
|
</span>
|
|
<span class="flex flex-wrap items-center gap-4">
|
|
{{range .Deliveries}}
|
|
<span class="text-xs {{if eq .Status "delivered"}}text-green-600{{else if eq .Status "failed"}}text-red-600{{else if eq .Status "retrying"}}text-yellow-600{{else}}text-gray-400{{end}}">
|
|
{{.Target.DisplayName}}: {{if .Paused}}waiting{{else}}{{.Status}}{{end}}
|
|
</span>
|
|
{{end}}
|
|
<span class="text-xs text-gray-400">{{.CreatedAt.Format "2006-01-02 15:04:05"}}</span>
|
|
<svg class="w-4 h-4 text-gray-400 transition-transform" :class="caretClass" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
|
|
</svg>
|
|
</span>
|
|
</button>
|
|
|
|
<div x-show="open" x-cloak class="mt-3 p-3 bg-gray-50 rounded-md">
|
|
<div class="mb-3 flex flex-wrap items-center justify-between gap-2">
|
|
<div class="text-xs text-gray-500">
|
|
{{if .ResubmittedFrom}}Resubmitted from event <a href="/hook/{{$.Webhook.ID}}/events/{{.ResubmittedFromID}}" class="btn-small font-mono">{{.ResubmittedFromID}}</a>.{{end}}
|
|
{{if .ResubmitCount}}Resubmitted as {{.ResubmitCount}} new event{{if ne .ResubmitCount 1}}s{{end}}.{{end}}
|
|
</div>
|
|
<form method="POST" action="/hook/{{$.Webhook.ID}}/events/{{.ID}}/resubmit" class="inline">
|
|
<input type="hidden" name="csrf_token" value="{{$.CSRFToken}}">
|
|
<input type="hidden" name="page" value="{{$.Page}}">
|
|
<button type="submit" class="btn-small" title="Submit this event again as a new event, to every currently active target">Resubmit</button>
|
|
</form>
|
|
</div>
|
|
{{template "event_body" .Body}}
|
|
|
|
{{if .Deliveries}}
|
|
<div class="mt-4 border-t border-gray-200 pt-3">
|
|
<h3 class="text-xs font-medium uppercase tracking-wide text-gray-500">Deliveries</h3>
|
|
<div class="mt-2 divide-y divide-gray-200">
|
|
{{range .Deliveries}}
|
|
<div class="py-2" x-data="collapsible">
|
|
<div class="flex items-center gap-3">
|
|
<button type="button" class="btn-small flex-1 flex-wrap justify-between gap-2 text-left" @click="toggle">
|
|
<span class="flex flex-wrap items-center gap-3">
|
|
<span class="text-sm text-gray-700">{{.Target.DisplayName}}</span>
|
|
<span class="text-xs {{if eq .Status "delivered"}}text-green-600{{else if eq .Status "failed"}}text-red-600{{else if eq .Status "retrying"}}text-yellow-600{{else}}text-gray-400{{end}}">{{with .Paused}}waiting: target paused after repeated failures, resumes {{.Until}} ({{.Relative}}){{else}}{{.Status}}{{end}}</span>
|
|
</span>
|
|
<span class="flex flex-wrap items-center gap-3">
|
|
<span class="text-xs text-gray-400">{{.AttemptCount}} attempt{{if ne .AttemptCount 1}}s{{end}}</span>
|
|
<svg class="w-3 h-3 text-gray-400 transition-transform" :class="caretClass" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
|
|
</svg>
|
|
</span>
|
|
</button>
|
|
{{if .Status.Terminal}}
|
|
<form method="POST" action="/hook/{{$.Webhook.ID}}/deliveries/{{.ID}}/replay" class="inline">
|
|
<input type="hidden" name="csrf_token" value="{{$.CSRFToken}}">
|
|
<input type="hidden" name="page" value="{{$.Page}}">
|
|
<button type="submit" class="btn-small" title="Send this event to the target again">Replay</button>
|
|
</form>
|
|
{{end}}
|
|
</div>
|
|
|
|
<div x-show="open" x-cloak class="mt-2 space-y-2">
|
|
{{template "delivery_attempts" .}}
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
</div>
|
|
{{else}}
|
|
<div class="p-12 text-center text-sm text-gray-500">No events recorded yet.</div>
|
|
{{end}}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Pagination -->
|
|
{{if or .HasPrev .HasNext}}
|
|
<div class="flex justify-center gap-2 mt-6">
|
|
{{if .HasPrev}}
|
|
<a href="/hook/{{.Webhook.ID}}/events?page={{.PrevPage}}" class="btn-secondary text-sm">← Previous</a>
|
|
{{end}}
|
|
<span class="inline-flex items-center px-4 py-2 text-sm text-gray-500">Page {{.Page}} of {{.TotalPages}}</span>
|
|
{{if .HasNext}}
|
|
<a href="/hook/{{.Webhook.ID}}/events?page={{.NextPage}}" class="btn-secondary text-sm">Next →</a>
|
|
{{end}}
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
{{end}}
|