Skip to content

feature: add StatsCollector for basic metrics aggregation#16

Open
p1gushka wants to merge 1 commit intomainfrom
feature/stats-collector
Open

feature: add StatsCollector for basic metrics aggregation#16
p1gushka wants to merge 1 commit intomainfrom
feature/stats-collector

Conversation

@p1gushka
Copy link
Collaborator

What

Thread-safe StatsCollector for aggregating per-request metrics.
Collects status codes and latencies, provides snapshot with
total/success/error counts, avg/min/max latency.
Uses LongAdder and LongAccumulator for lock-free concurrency.

How to verify

./mvnw test

Closes #11

@p1gushka p1gushka requested a review from devcrocod March 12, 2026 17:44
private final LongAccumulator maxLatencyMs = new LongAccumulator(Math::max, Long.MIN_VALUE);
private final LongAccumulator minLatencyMs = new LongAccumulator(Math::min, Long.MAX_VALUE);

public void record(int statusCode, long latencyMs) throws IllegalArgumentException {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please keep in mind that this code is not thread-safe, so errorCount may end up becoming negative

private final LongAccumulator maxLatencyMs = new LongAccumulator(Math::max, Long.MIN_VALUE);
private final LongAccumulator minLatencyMs = new LongAccumulator(Math::min, Long.MAX_VALUE);

public void record(int statusCode, long latencyMs) throws IllegalArgumentException {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IllegalArgumentException is unchecked exception


totalRequests.increment();
if (200 <= statusCode && statusCode < 300) {
successCount.increment();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are 1xx or 3xx statuses as errors?

Comment on lines +30 to +55
public StatsSnapshot getSnapshot() {
long snapshotTotalRequests = totalRequests.sum();
long snapshotSuccessCount = successCount.sum();
long snapshotTotalLatencyMs = totalLatencyMs.sum();

long snapshotMinLatencyMs = (snapshotTotalRequests == 0 ? 0 : minLatencyMs.get());
long snapshotMaxLatencyMs = (snapshotTotalRequests == 0 ? 0 : maxLatencyMs.get());
long snapshotAvgLatencyMs =
(snapshotTotalRequests == 0 ? 0 : snapshotTotalLatencyMs / snapshotTotalRequests);

return new StatsSnapshot(
snapshotTotalRequests,
snapshotSuccessCount,
snapshotTotalRequests - snapshotSuccessCount,
snapshotAvgLatencyMs,
snapshotMinLatencyMs,
snapshotMaxLatencyMs);
}

public void reset() {
totalRequests.reset();
successCount.reset();
totalLatencyMs.reset();
minLatencyMs.reset();
maxLatencyMs.reset();
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add method getSnapshotAndReset()

long snapshotMinLatencyMs = (snapshotTotalRequests == 0 ? 0 : minLatencyMs.get());
long snapshotMaxLatencyMs = (snapshotTotalRequests == 0 ? 0 : maxLatencyMs.get());
long snapshotAvgLatencyMs =
(snapshotTotalRequests == 0 ? 0 : snapshotTotalLatencyMs / snapshotTotalRequests);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try to use double-precision arithmetic where possible. Integer arithmetic can introduce significant error

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement StatsCollector for basic metrics aggregation

2 participants