Response Time Tracking
EdgeInteract measures the elapsed time from when an interaction is first displayed to the user to when a response is received. These measurements are recorded as the interaction_response_time_ms histogram and surfaced via BizFirst Observe dashboards.
What Is Measured
Response time in EdgeInteract is defined as the duration from the displayed pipeline state to the responded pipeline state — i.e., the time from the moment the UI rendered the interaction to the moment the user submitted their response.
The clock starts when the client emits the displayed acknowledgement, and stops when the response is received server-side.
The Metric: interaction_response_time_ms
| Attribute | Value |
|---|---|
| Metric name | interaction_response_time_ms |
| Type | Histogram |
| Unit | milliseconds |
| Labels | type (approval, confirmation, form, picker, notification), outcome (approved, rejected, confirmed, cancelled, submitted, selected, acknowledged) |
| Buckets | 500ms, 1s, 2s, 5s, 10s, 30s, 60s, 120s, 300s, 600s, 1800s, 3600s |
| Emitted by | MetricsInteractionHook (must be registered) |
Accessing Response Time in Code
Use the useInteractionMetrics() hook from edge-interact-observability to access response time data in React admin views:
import { useInteractionMetrics } from 'edge-interact-observability';
function ResponseTimePanel() {
const { responseTime } = useInteractionMetrics({
type: 'approval', // optional filter
window: '24h' // time window
});
// responseTime contains P50, P95, P99, mean, count
return (
<div>
<h3>Approval Response Times (last 24h)</h3>
<p>P50: {responseTime.p50}ms</p>
<p>P95: {responseTime.p95}ms</p>
<p>P99: {responseTime.p99}ms</p>
<p>Sample count: {responseTime.count}</p>
</div>
);
}
Server-Side: Accessing Response Time
On the server, you can query response time statistics from the audit store:
// In a diagnostics service or admin controller
public class ResponseTimeService(IInteractionAuditStore auditStore)
{
public async Task<ResponseTimeStats> GetResponseTimeStatsAsync(
string? type = null,
TimeSpan? window = null,
CancellationToken ct = default)
{
var since = window.HasValue
? DateTime.UtcNow - window.Value
: DateTime.UtcNow.AddDays(-1);
var entries = await auditStore.QueryAsync(new AuditQuery
{
Type = type,
RespondedAfter = since,
Statuses = [InteractionStatus.Responded]
}, ct);
var times = entries
.Where(e => e.DisplayedAt.HasValue && e.RespondedAt.HasValue)
.Select(e => (e.RespondedAt!.Value - e.DisplayedAt!.Value).TotalMilliseconds)
.OrderBy(ms => ms)
.ToList();
if (times.Count == 0)
return ResponseTimeStats.Empty;
return new ResponseTimeStats
{
Count = times.Count,
P50 = times[(int)(times.Count * 0.50)],
P95 = times[(int)(times.Count * 0.95)],
P99 = times[(int)(times.Count * 0.99)],
Mean = times.Average(),
Min = times.First(),
Max = times.Last()
};
}
}
Typical Percentile Targets
Grafana Query
To visualize response time percentiles in a BizFirst Observe dashboard panel:
// PromQL — P95 response time for approval interactions (5-minute rate)
histogram_quantile(0.95,
sum(rate(interaction_response_time_ms_bucket{type="approval"}[5m]))
by (le)
)
// PromQL — P50 response time across all types
histogram_quantile(0.50,
sum(rate(interaction_response_time_ms_bucket[5m]))
by (le, type)
)
interaction_response_time_ms only records entries for interactions that received a response. Timed-out interactions are counted separately in interaction_timeout_total. This means response time P95 reflects users who did respond — not the full population.
Factors That Skew Response Times
- Interaction type — notification < confirmation < form < approval in typical order
- Priority — high-priority interactions rendered at the top of the queue are responded to faster
- Business hours — approval interactions created at end of day or on weekends show higher P95
- Delegation — role-targeted interactions where the first-to-respond wins can produce faster P95 than single-user targeting