-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[New] Added a statistics API for TX, search and services
- Loading branch information
Showing
9 changed files
with
233 additions
and
49 deletions.
There are no files selected for viewing
39 changes: 39 additions & 0 deletions
39
strolch-agent/src/main/java/li/strolch/agent/api/AgentStatistics.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package li.strolch.agent.api; | ||
|
||
import com.google.gson.JsonObject; | ||
import li.strolch.persistence.api.TransactionResult; | ||
|
||
import java.time.Duration; | ||
|
||
public class AgentStatistics { | ||
|
||
private final Statistics transactions; | ||
private final Statistics searches; | ||
private final Statistics services; | ||
|
||
public AgentStatistics() { | ||
this.transactions = new Statistics(); | ||
this.searches = new Statistics(); | ||
this.services = new Statistics(); | ||
} | ||
|
||
public JsonObject toJson() { | ||
JsonObject json = new JsonObject(); | ||
json.add("transactions", this.transactions.toJson()); | ||
json.add("searches", this.searches.toJson()); | ||
json.add("services", this.services.toJson()); | ||
return json; | ||
} | ||
|
||
public void recordTransaction(TransactionResult result) { | ||
this.transactions.recordEvent(Duration.ofNanos(result.getTxDuration())); | ||
} | ||
|
||
public void recordSearch(long durationNanos) { | ||
this.searches.recordEvent(Duration.ofNanos(durationNanos)); | ||
} | ||
|
||
public void recordService(long durationNanos) { | ||
this.services.recordEvent(Duration.ofNanos(durationNanos)); | ||
} | ||
} |
111 changes: 111 additions & 0 deletions
111
strolch-agent/src/main/java/li/strolch/agent/api/Statistics.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
package li.strolch.agent.api; | ||
|
||
import com.google.gson.JsonObject; | ||
import com.google.gson.JsonPrimitive; | ||
|
||
import java.time.Duration; | ||
import java.time.LocalDateTime; | ||
import java.time.temporal.ChronoUnit; | ||
import java.util.LinkedList; | ||
import java.util.List; | ||
import java.util.Queue; | ||
import java.util.stream.Collectors; | ||
|
||
import static java.time.temporal.ChronoUnit.*; | ||
|
||
public class Statistics { | ||
|
||
private final Queue<Statistic> events; | ||
|
||
public Statistics() { | ||
this.events = new LinkedList<>(); | ||
} | ||
|
||
public void recordEvent(Duration duration) { | ||
LocalDateTime now = LocalDateTime.now(); | ||
this.events.add(new Statistic(now, duration)); | ||
removeOldEvents(now); | ||
} | ||
|
||
private void removeOldEvents(LocalDateTime now) { | ||
while (!this.events.isEmpty() && DAYS.between(this.events.peek().timestamp, now) >= 1) { | ||
this.events.poll(); | ||
} | ||
} | ||
|
||
public int getLastMinute() { | ||
return getInTimeFrame(1, MINUTES); | ||
} | ||
|
||
public int getLast5Minutes() { | ||
return getInTimeFrame(5, MINUTES); | ||
} | ||
|
||
public int getLast15Minutes() { | ||
return getInTimeFrame(15, MINUTES); | ||
} | ||
|
||
public int getLastHour() { | ||
return getInTimeFrame(1, HOURS); | ||
} | ||
|
||
public int getLastDay() { | ||
return getInTimeFrame(1, DAYS); | ||
} | ||
|
||
private int getInTimeFrame(long amount, ChronoUnit unit) { | ||
LocalDateTime now = LocalDateTime.now(); | ||
return (int) this.events | ||
.stream() | ||
.filter(tx -> SECONDS.between(tx.timestamp, now) < unit.getDuration().getSeconds() * amount) | ||
.count(); | ||
} | ||
|
||
public JsonObject toJson() { | ||
List<Duration> durations = this.events.stream().map(e -> e.duration).toList(); | ||
|
||
long count = durations.size(); | ||
long sum = durations.stream().mapToLong(Duration::toMillis).sum(); | ||
int avg = count == 0 ? 0 : (int) ((double) sum / count); | ||
|
||
Duration min = durations.stream().min(Duration::compareTo).orElse(Duration.ZERO); | ||
Duration max = durations.stream().max(Duration::compareTo).orElse(Duration.ZERO); | ||
Duration median = getMedian(durations); | ||
|
||
JsonObject jsonObject = new JsonObject(); | ||
jsonObject.addProperty("lastMinute", getLastMinute()); | ||
jsonObject.addProperty("last5Minutes", getLast5Minutes()); | ||
jsonObject.addProperty("last15Minutes", getLast15Minutes()); | ||
jsonObject.addProperty("lastHour", getLastHour()); | ||
jsonObject.addProperty("lastDay", getLastDay()); | ||
jsonObject.addProperty("minDuration", min.toMillis()); | ||
jsonObject.addProperty("maxDuration", max.toMillis()); | ||
jsonObject.addProperty("avgDuration", avg); | ||
jsonObject.addProperty("medianDuration", median.toMillis()); | ||
|
||
return jsonObject; | ||
} | ||
|
||
private Duration getMedian(List<Duration> durations) { | ||
if (durations.isEmpty()) { | ||
return Duration.ZERO; | ||
} | ||
List<Duration> sorted = durations.stream().sorted().toList(); | ||
int middle = sorted.size() / 2; | ||
if (sorted.size() % 2 == 0) { | ||
return sorted.get(middle - 1).plus(sorted.get(middle)).dividedBy(2); | ||
} else { | ||
return sorted.get(middle); | ||
} | ||
} | ||
|
||
private static class Statistic { | ||
LocalDateTime timestamp; | ||
Duration duration; | ||
|
||
Statistic(LocalDateTime timestamp, Duration duration) { | ||
this.timestamp = timestamp; | ||
this.duration = duration; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,12 @@ | ||
/* | ||
* Copyright 2013 Robert von Burg <[email protected]> | ||
* | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
|
@@ -17,7 +17,7 @@ | |
|
||
import li.strolch.utils.helper.StringHelper; | ||
|
||
import java.util.Date; | ||
import java.time.LocalDateTime; | ||
|
||
public class TransactionResult { | ||
|
||
|
@@ -26,7 +26,7 @@ public class TransactionResult { | |
private Exception failCause; | ||
|
||
private final long startNanos; | ||
private Date startTime; | ||
private LocalDateTime startTime; | ||
private long txDuration; | ||
private long closeDuration; | ||
|
||
|
@@ -35,7 +35,7 @@ public class TransactionResult { | |
private long updated; | ||
private long deleted; | ||
|
||
public TransactionResult(String realm, long startNanos, Date startDate) { | ||
public TransactionResult(String realm, long startNanos, LocalDateTime startDate) { | ||
this.realm = realm; | ||
this.startNanos = startNanos; | ||
this.startTime = startDate; | ||
|
@@ -57,8 +57,7 @@ public TransactionState getState() { | |
} | ||
|
||
/** | ||
* @param state | ||
* the state to set | ||
* @param state the state to set | ||
*/ | ||
public void setState(TransactionState state) { | ||
this.state = state; | ||
|
@@ -72,8 +71,7 @@ public Exception getFailCause() { | |
} | ||
|
||
/** | ||
* @param failCause | ||
* the failCause to set | ||
* @param failCause the failCause to set | ||
*/ | ||
public void setFailCause(Exception failCause) { | ||
this.failCause = failCause; | ||
|
@@ -89,15 +87,14 @@ public long getStartNanos() { | |
/** | ||
* @return the startTime | ||
*/ | ||
public Date getStartTime() { | ||
public LocalDateTime getStartTime() { | ||
return this.startTime; | ||
} | ||
|
||
/** | ||
* @param startTime | ||
* the startTime to set | ||
* @param startTime the startTime to set | ||
*/ | ||
public void setStartTime(Date startTime) { | ||
public void setStartTime(LocalDateTime startTime) { | ||
this.startTime = startTime; | ||
} | ||
|
||
|
@@ -109,8 +106,7 @@ public long getTxDuration() { | |
} | ||
|
||
/** | ||
* @param txDuration | ||
* the txDuration to set | ||
* @param txDuration the txDuration to set | ||
*/ | ||
public void setTxDuration(long txDuration) { | ||
this.txDuration = txDuration; | ||
|
@@ -124,8 +120,7 @@ public long getCloseDuration() { | |
} | ||
|
||
/** | ||
* @param closeDuration | ||
* the closeDuration to set | ||
* @param closeDuration the closeDuration to set | ||
*/ | ||
public void setCloseDuration(long closeDuration) { | ||
this.closeDuration = closeDuration; | ||
|
@@ -139,8 +134,7 @@ public long getCreated() { | |
} | ||
|
||
/** | ||
* @param created | ||
* the created to set | ||
* @param created the created to set | ||
*/ | ||
public void setCreated(long created) { | ||
this.created = created; | ||
|
@@ -154,8 +148,7 @@ public long getRead() { | |
} | ||
|
||
/** | ||
* @param read | ||
* the read to set | ||
* @param read the read to set | ||
*/ | ||
public void setRead(long read) { | ||
this.read = read; | ||
|
@@ -169,8 +162,7 @@ public long getUpdated() { | |
} | ||
|
||
/** | ||
* @param updated | ||
* the updated to set | ||
* @param updated the updated to set | ||
*/ | ||
public void setUpdated(long updated) { | ||
this.updated = updated; | ||
|
@@ -184,8 +176,7 @@ public long getDeleted() { | |
} | ||
|
||
/** | ||
* @param deleted | ||
* the deleted to set | ||
* @param deleted the deleted to set | ||
*/ | ||
public void setDeleted(long deleted) { | ||
this.deleted = deleted; | ||
|
@@ -215,15 +206,15 @@ public String getLogMessage() { | |
|
||
StringBuilder sb = new StringBuilder(); | ||
switch (this.state) { | ||
case OPEN -> sb.append("TX is still open after "); | ||
case COMMITTED -> sb.append("TX was completed after "); | ||
case ROLLED_BACK -> sb.append("TX was rolled back after "); | ||
case FAILED -> sb.append("TX has failed after "); | ||
default -> { | ||
sb.append("TX is in unhandled state "); | ||
sb.append(this.state); | ||
sb.append(" after "); | ||
} | ||
case OPEN -> sb.append("TX is still open after "); | ||
case COMMITTED -> sb.append("TX was completed after "); | ||
case ROLLED_BACK -> sb.append("TX was rolled back after "); | ||
case FAILED -> sb.append("TX has failed after "); | ||
default -> { | ||
sb.append("TX is in unhandled state "); | ||
sb.append(this.state); | ||
sb.append(" after "); | ||
} | ||
} | ||
|
||
sb.append(StringHelper.formatNanoDuration(this.txDuration)); | ||
|
Oops, something went wrong.