
com.undefinedlabs.scope.statistics.Statistics Maven / Gradle / Ivy
package com.undefinedlabs.scope.statistics;
import com.undefinedlabs.scope.Span;
import com.undefinedlabs.scope.SpanContext;
import com.undefinedlabs.scope.context.SharedContextMap;
import com.undefinedlabs.scope.jdk.Supplier;
import com.undefinedlabs.scope.logger.ScopeLogger;
import com.undefinedlabs.scope.logger.ScopeLoggerLevel;
import com.undefinedlabs.scope.logger.ScopeLoggerResolver;
import com.undefinedlabs.scope.reporter.internal.remote.model.ScopeSpan;
import com.undefinedlabs.scope.settings.ScopeSettings;
import com.undefinedlabs.scope.settings.ScopeSettingsResolver;
import com.undefinedlabs.scope.utils.ThreadUtils;
import com.undefinedlabs.scope.utils.baggage.BaggageKeys;
import com.undefinedlabs.scope.utils.baggage.BaggageValues;
import com.undefinedlabs.scope.utils.tag.TagKeys;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
public enum Statistics {
INSTANCE;
private static final ScopeLogger LOGGER = ScopeLoggerResolver.INSTANCE.get();
private final boolean traceEnabled =
ScopeLoggerLevel.TRACE.equals(
ScopeSettingsResolver.INSTANCE.get().getSetting(ScopeSettings.SCOPE_LOGGER_LEVEL));
private final Map> conflictFilepathsByClassName = new HashMap<>();
private final AtomicInteger runnerCachedTestCount = new AtomicInteger();
private final List runnerCachedTest = new ArrayList<>();
private final List coverageNotDetectedExecutableLines = new ArrayList<>();
private final Map> coverageSessionChannelMismatch = new HashMap<>();
private final Map> coverageNullOnMap = new HashMap<>();
private final AtomicInteger startedCoverageSessions = new AtomicInteger();
private final AtomicInteger finishedCoverageSessions = new AtomicInteger();
private final Map startedCoverageSessionsStats =
new HashMap<>();
private final List finishedCoverageSessionsStats = new ArrayList<>();
private final Map reportedCoverageLackOfSessionsPerThread =
new HashMap<>();
private final AtomicInteger reportedCoveragePayloadOnSessionClosed = new AtomicInteger();
private final List reportedCoveragePayloadOnSessionClosedPayloads = new ArrayList<>();
private final AtomicInteger reportedCoverageLackOfSession = new AtomicInteger();
private final AtomicInteger reportedCoverageNoneSessionStarted = new AtomicInteger();
private final AtomicInteger startedSpansAsTest = new AtomicInteger();
private final AtomicInteger finishedSpansAsTest = new AtomicInteger();
private final AtomicInteger startedSpans = new AtomicInteger();
private final AtomicInteger finishedSpans = new AtomicInteger();
private final AtomicInteger reportedSpans = new AtomicInteger();
private final AtomicInteger reportedSpansOnTime = new AtomicInteger();
private final AtomicInteger totalSentSpans = new AtomicInteger();
private final AtomicInteger successSentSpans = new AtomicInteger();
private final AtomicInteger failedSentSpans = new AtomicInteger();
private final AtomicInteger submittedSendTasks = new AtomicInteger();
private final AtomicInteger executedSendTasks = new AtomicInteger();
private boolean processEndSentSuccess;
private String branch;
private boolean runnerActivation;
private String logPathFile;
private boolean coverageActivation;
private long startScopeExecution;
private long durationScopeExecution;
private float throughputSubmittedSendTasks;
private float throughputExecutedSendTasks;
private int flushInterval;
private int maxBufferSizeSpans;
private int maxBufferSizeEvents;
private int senderThreadsNum;
private long senderCloseTimeoutMs;
private final Map notFinishedSpans = new HashMap<>();
private final Map reportedAfterOutOfTime = new HashMap<>();
private final Map trackedStartedAfterOutOfTime = new HashMap<>();
private final Map trackedFinishedAfterOutOfTime = new HashMap<>();
private final Object lock = new Object();
public void registerSourceCodeConflict(
final Map> conflictFilepathsByClassName) {
this.conflictFilepathsByClassName.putAll(conflictFilepathsByClassName);
}
public void registerSuccessSentProcessEnd() {
synchronized (lock) {
processEndSentSuccess = true;
}
}
public void registerBranch(final String branch) {
this.branch = branch;
}
public void registerRunnerCachedTest(
final String platform, final String testSuite, final String testName) {
runnerCachedTestCount.addAndGet(1);
synchronized (runnerCachedTest) {
runnerCachedTest.add(platform + "#" + testSuite + "#" + testName);
}
}
public void registerRunnerActivation(final boolean runnerActivation) {
this.runnerActivation = runnerActivation;
}
public void registerLogPathFile(final String logPathFile) {
this.logPathFile = logPathFile;
}
public void registerCoveragePayloadOnSessionClosed(final String payload) {
reportedCoveragePayloadOnSessionClosed.addAndGet(1);
if (traceEnabled) {
synchronized (reportedCoveragePayloadOnSessionClosedPayloads) {
reportedCoveragePayloadOnSessionClosedPayloads.add(payload);
}
}
}
public void registerCoverageNotDetectedExecutableLines(final String className) {
if (traceEnabled) {
coverageNotDetectedExecutableLines.add(className);
}
}
private void registerInThreadMap(
final Map> threadMap,
final Thread thread,
final Supplier valueSupplier) {
if (traceEnabled) {
synchronized (threadMap) {
final String threadId = ThreadUtils.getUniqueId(thread);
final String value = valueSupplier.get();
final Set valueStore = threadMap.get(threadId);
if (valueStore == null) {
final Set newValueStore = new HashSet<>();
newValueStore.add(value);
threadMap.put(threadId, newValueStore);
} else {
threadMap.get(threadId).add(value);
}
}
}
}
public void registerCoverageSessionChannelMismatch(
final Thread thread,
final String activeSessionIdTls,
final String activeSessionIdOnChannelRegistration) {
if (traceEnabled) {
registerInThreadMap(
coverageSessionChannelMismatch,
thread,
new Supplier() {
@Override
public String get() {
return "TLS ["
+ activeSessionIdTls
+ "] != ChannelReg ["
+ activeSessionIdOnChannelRegistration
+ "]";
}
});
}
}
public void registerCoverageNullOnMap(final Thread thread, final SharedContextMap map) {
if (traceEnabled) {
registerInThreadMap(
coverageNullOnMap,
thread,
new Supplier() {
@Override
public String get() {
return map.getId();
}
});
}
}
public void registerCoverageStartSession(final String sessionId, final Thread thread) {
startedCoverageSessions.addAndGet(1);
if (traceEnabled) {
synchronized (startedCoverageSessionsStats) {
startedCoverageSessionsStats.put(
sessionId, new CoverageSessionStatistics(sessionId, ThreadUtils.getUniqueId(thread)));
}
}
}
public void registerCoverageEndSession(final String sessionId) {
finishedCoverageSessions.addAndGet(1);
if (traceEnabled) {
synchronized (startedCoverageSessionsStats) {
final CoverageSessionStatistics coverageStatistics =
startedCoverageSessionsStats.remove(sessionId);
if (coverageStatistics != null) {
finishedCoverageSessionsStats.add(coverageStatistics);
}
}
}
}
public void registerCoverageActivation(final boolean coverageActivation) {
this.coverageActivation = coverageActivation;
}
public void registerCoverageOutOfSession(final Thread thread) {
if (traceEnabled) {
synchronized (startedCoverageSessionsStats) {
if (startedCoverageSessionsStats.size() > 0) {
final AtomicInteger reportedLackCoverage =
reportedCoverageLackOfSessionsPerThread.get(ThreadUtils.getUniqueId(thread));
if (reportedLackCoverage == null) {
reportedCoverageLackOfSessionsPerThread.put(
ThreadUtils.getUniqueId(thread), new AtomicInteger(1));
} else {
reportedLackCoverage.addAndGet(1);
}
reportedCoverageLackOfSession.addAndGet(1);
} else {
reportedCoverageNoneSessionStarted.addAndGet(1);
}
}
}
}
public void registerCoverageOnSession(final String sessionId, final Thread thread) {
if (traceEnabled) {
synchronized (startedCoverageSessionsStats) {
final CoverageSessionStatistics coverageSessionStatistics =
startedCoverageSessionsStats.get(sessionId);
if (coverageSessionStatistics == null) {
LOGGER.warn("--- Coverage Session Statistics of '" + sessionId + "' is null. " + thread);
} else {
coverageSessionStatistics.registerCoverageOnSession(ThreadUtils.getUniqueId(thread));
}
}
}
}
public void registerTrackStartedSpanOutOfTime(final Span span) {
synchronized (lock) {
trackedStartedAfterOutOfTime.put(span.context().toString(), span.getOperationName());
}
}
public void registerTrackFinishedSpanOutOfTime(final Span span) {
synchronized (lock) {
trackedFinishedAfterOutOfTime.put(span.context().toString(), span.getOperationName());
}
}
public void registerReportedSpanOnTime(final Span span) {
if (!(span instanceof Span)) {
return;
}
reportedSpansOnTime.addAndGet(1);
reportedSpans.addAndGet(1);
}
public void registerReportedOutOfTime(final String context, final ScopeSpan scopeSpan) {
synchronized (lock) {
reportedAfterOutOfTime.put(context, scopeSpan);
}
reportedSpans.addAndGet(1);
}
public void registerStartedTestSpan(final io.opentracing.Span span) {
if (!(span instanceof Span)) {
return;
}
startedSpansAsTest.addAndGet(1);
}
public void registerFinishedTestSpan(final io.opentracing.Span span) {
if (!(span instanceof Span)) {
return;
}
finishedSpansAsTest.addAndGet(1);
}
public void registerStartedSpan(final io.opentracing.Span span) {
if (!(span instanceof Span)) {
return;
}
startedSpans.addAndGet(1);
synchronized (lock) {
notFinishedSpans.put(span.context().toString(), (Span) span);
}
}
public void registerFinishedSpan(final io.opentracing.Span span) {
if (!(span instanceof Span)) {
return;
}
finishedSpans.addAndGet(1);
synchronized (lock) {
notFinishedSpans.remove(span.context().toString());
}
}
public void registerSuccessSentSpans(final List scopeSpans) {
successSentSpans.addAndGet(scopeSpans.size());
totalSentSpans.addAndGet(scopeSpans.size());
}
public void registerFailedSentSpans(final List scopeSpans) {
failedSentSpans.addAndGet(scopeSpans.size());
totalSentSpans.addAndGet(scopeSpans.size());
}
public void registerSendTaskPlanned() {
submittedSendTasks.addAndGet(1);
}
public void registerSendTaskExecuted() {
executedSendTasks.addAndGet(1);
}
public void registerStartScopeExecution() {
startScopeExecution = System.currentTimeMillis();
}
public void registerFinishScopeExecution() {
durationScopeExecution = System.currentTimeMillis() - startScopeExecution;
throughputSubmittedSendTasks =
(float) submittedSendTasks.get() / ((float) durationScopeExecution / 1000);
throughputExecutedSendTasks =
(float) executedSendTasks.get() / ((float) durationScopeExecution / 1000);
}
public void registerHealthCheckInterval(final int flushInterval) {
this.flushInterval = flushInterval;
}
public void registerMaxBufferSizeSpans(final int maxBufferSizeSpans) {
this.maxBufferSizeSpans = maxBufferSizeSpans;
}
public void registerMaxBufferSizeEvents(final int maxBufferSizeEvents) {
this.maxBufferSizeEvents = maxBufferSizeEvents;
}
public void registerSenderThreadsNum(final int senderThreadsNum) {
this.senderThreadsNum = senderThreadsNum;
}
public void registerSenderCloseTimeoutMs(final long senderCloseTimeoutMs) {
this.senderCloseTimeoutMs = senderCloseTimeoutMs;
}
public String getReport() {
synchronized (lock) {
final Collection notFinishedSpans = this.notFinishedSpans.values();
final StringBuilder sb = new StringBuilder();
sb.append("\n-- Statistics --");
sb.append("\n---- Source Code Filepath conflicts: ")
.append(conflictFilepathsByClassName.size());
if (traceEnabled && conflictFilepathsByClassName.size() > 0) {
for (final Map.Entry> entry : conflictFilepathsByClassName.entrySet()) {
sb.append("\n-------- ").append(entry.getKey());
for (final String conflict : entry.getValue()) {
sb.append("\n------------ ").append(conflict);
}
}
}
sb.append("\n---- Reporter Buffer Size Spans: ").append(maxBufferSizeSpans).append(" spans.");
sb.append("\n---- Reporter Buffer Size Events: ")
.append(maxBufferSizeEvents)
.append(" events.");
sb.append("\n---- Reporter Flush Interval: ").append(flushInterval).append(" ms.");
sb.append("\n---- Sender Threads Num: ").append(senderThreadsNum).append(" threads.");
sb.append("\n---- Sender Close Timeout: ").append(senderCloseTimeoutMs).append(" ms.");
sb.append("\n---- Runner [branch: ")
.append(branch)
.append("]: ")
.append((runnerActivation ? "enabled" : "disabled"));
if (runnerActivation) {
sb.append("\n-------- Total Cached Tests: ").append(runnerCachedTestCount.get());
for (final String cachedTest : runnerCachedTest) {
sb.append("\n----------- ").append(cachedTest);
}
}
sb.append("\n---- Coverage: ").append((coverageActivation ? "enabled" : "disabled"));
if (coverageActivation) {
sb.append("\n---- Total Coverage Sessions Started: ").append(startedCoverageSessions);
sb.append("\n---- Total Coverage Sessions Finished: ").append(finishedCoverageSessions);
if (traceEnabled) {
sb.append("\n---- Total Coverage Payloads On Session Closed: ")
.append(reportedCoveragePayloadOnSessionClosed);
for (final String payload : reportedCoveragePayloadOnSessionClosedPayloads) {
sb.append("\n-------- ").append(payload);
}
for (final CoverageSessionStatistics coverageSessionStatistics :
finishedCoverageSessionsStats) {
sb.append("\n-------- ")
.append("Coverage Session Id: ")
.append(coverageSessionStatistics.getSessionId())
.append(".");
sb.append("\n----------- ")
.append("Coverage Payloads: ")
.append(coverageSessionStatistics.getRegisteredCoverageOnSession())
.append(".");
sb.append("\n----------- ").append("Coverage Session on Threads:");
for (final String threadDesc : coverageSessionStatistics.getThreadsDescriptions()) {
sb.append("\n-------------- ").append(threadDesc);
}
}
sb.append("\n---- Total Coverage Sessions Not Finished: ")
.append(startedCoverageSessionsStats.size());
for (final CoverageSessionStatistics coverageSessionStatistics :
startedCoverageSessionsStats.values()) {
sb.append("\n-------- ")
.append("Coverage Session Id: ")
.append(coverageSessionStatistics.getSessionId())
.append(".");
sb.append("\n----------- ")
.append("Coverage Payloads: ")
.append(coverageSessionStatistics.getRegisteredCoverageOnSession())
.append(".");
sb.append("\n----------- ").append("Coverage Session on Threads:");
for (final String threadDesc : coverageSessionStatistics.getThreadsDescriptions()) {
sb.append("\n-------------- ").append(threadDesc);
}
}
sb.append("\n---- Coverage Orphan - Required Session: ")
.append(reportedCoverageLackOfSession)
.append(" payloads");
for (final Map.Entry entry :
reportedCoverageLackOfSessionsPerThread.entrySet()) {
sb.append("\n-------- ")
.append(entry.getKey())
.append(": ")
.append(entry.getValue())
.append(" payloads");
}
sb.append("\n---- Coverage Orphan - Not Required Session: ")
.append(reportedCoverageNoneSessionStarted)
.append(" payloads.");
sb.append("\n---- Coverage Not Detected Exec Lines:");
for (final String classname : coverageNotDetectedExecutableLines) {
sb.append("\n-------- ").append(classname);
}
if (coverageSessionChannelMismatch.size() > 0) {
sb.append("\n---- Coverage Session Mismatch (TLS vs Channel)");
for (final Map.Entry> entry :
coverageSessionChannelMismatch.entrySet()) {
sb.append("\n-------- ").append(entry.getKey());
for (final String message : entry.getValue()) {
sb.append("\n------------ ").append(message);
}
}
}
}
}
sb.append("\n---- LogPath File: ").append(logPathFile);
sb.append("\n---- Process End Sent: ").append(processEndSentSuccess);
sb.append("\n---- Total Duration: ").append(durationScopeExecution).append(" ms.");
sb.append("\n---- Test Spans Started: ").append(startedSpansAsTest.get());
sb.append("\n---- Test Spans Finished: ").append(finishedSpansAsTest.get());
sb.append("\n---- Total Spans Started: ").append(startedSpans.get());
sb.append("\n---- Total Spans Finished: ").append(finishedSpans.get());
sb.append("\n---- Total Spans Reported: ").append(reportedSpans.get());
sb.append("\n---- Total Spans Reported (On Time): ").append(reportedSpansOnTime.get());
sb.append("\n---- Total Spans Reported (Out Of Time): ")
.append(reportedAfterOutOfTime.size());
if (reportedAfterOutOfTime.size() > 0) {
for (final Map.Entry entry : reportedAfterOutOfTime.entrySet()) {
sb.append("\n-------- [")
.append(entry.getKey())
.append("] operation=")
.append(entry.getValue().getOperation());
}
}
sb.append("\n---- Total Started Spans tracked (Out Of Time): ")
.append(trackedStartedAfterOutOfTime.size());
if (trackedStartedAfterOutOfTime.size() > 0) {
for (final Map.Entry entry : trackedStartedAfterOutOfTime.entrySet()) {
sb.append("\n-------- [")
.append(entry.getKey())
.append("] operation=")
.append(entry.getValue());
}
}
sb.append("\n---- Total Finished Spans tracked (Out Of Time): ")
.append(trackedFinishedAfterOutOfTime.size());
if (trackedFinishedAfterOutOfTime.size() > 0) {
for (final Map.Entry entry : trackedFinishedAfterOutOfTime.entrySet()) {
sb.append("\n-------- [")
.append(entry.getKey())
.append("] operation=")
.append(entry.getValue());
}
}
sb.append("\n---- Total Send Tasks Submitted: ").append(submittedSendTasks.get());
sb.append("\n---- Total Send Tasks Executed: ").append(executedSendTasks.get());
sb.append("\n---- Throughput Send Tasks Submitted: ")
.append(throughputSubmittedSendTasks)
.append(" tasks/sec");
sb.append("\n---- Throughput Send Tasks Executed: ")
.append(throughputExecutedSendTasks)
.append(" tasks/sec");
sb.append("\n---- Total Spans Sent: ").append(totalSentSpans.get());
sb.append("\n---- Total Spans Sent Success: ").append(successSentSpans.get());
sb.append("\n---- Total Spans Sent Failed: ").append(failedSentSpans.get());
sb.append("\n---- Total Spans Not Finished: ").append(notFinishedSpans.size());
int i = 1;
for (final Span span : notFinishedSpans) {
final String traceKind = span.getBaggageItem(BaggageKeys.TRACE_KIND);
final String parentId = ((SpanContext) span.context()).toParentSpanId();
final boolean isTestSpan =
parentId == null && BaggageValues.TRACE_KIND_TEST.equals(traceKind);
sb.append("\n" + i + "-------- ")
.append(span.getOperationName())
.append(", ")
.append("IsTestSpan: ")
.append(isTestSpan)
.append(", ")
.append(span.getTags().get(TagKeys.Test.TEST_SUITE))
.append("#")
.append(span.getTags().get(TagKeys.Test.TEST_NAME))
.append(" [")
.append(span.context())
.append("]");
i += 1;
}
return sb.toString();
}
}
protected void cleanUp() {
synchronized (lock) {
processEndSentSuccess = false;
coverageActivation = false;
runnerActivation = false;
startedSpansAsTest.set(0);
finishedSpansAsTest.set(0);
startedSpans.set(0);
finishedSpans.set(0);
successSentSpans.set(0);
failedSentSpans.set(0);
totalSentSpans.set(0);
submittedSendTasks.set(0);
executedSendTasks.set(0);
reportedSpans.set(0);
reportedSpansOnTime.set(0);
startScopeExecution = 0L;
reportedCoveragePayloadOnSessionClosed.set(0);
durationScopeExecution = 0L;
throughputSubmittedSendTasks = 0.0F;
throughputExecutedSendTasks = 0.0F;
flushInterval = 0;
maxBufferSizeSpans = 0;
maxBufferSizeEvents = 0;
senderThreadsNum = 0;
senderCloseTimeoutMs = 0;
reportedAfterOutOfTime.clear();
notFinishedSpans.clear();
runnerCachedTest.clear();
runnerCachedTestCount.set(0);
trackedStartedAfterOutOfTime.clear();
trackedFinishedAfterOutOfTime.clear();
conflictFilepathsByClassName.clear();
reportedCoveragePayloadOnSessionClosedPayloads.clear();
}
}
protected AtomicInteger getStartedSpansAsTest() {
return startedSpansAsTest;
}
protected AtomicInteger getFinishedSpansAsTest() {
return finishedSpansAsTest;
}
protected AtomicInteger getStartedSpans() {
return startedSpans;
}
protected AtomicInteger getFinishedSpans() {
return finishedSpans;
}
protected Map getNotFinishedSpans() {
return notFinishedSpans;
}
public AtomicInteger getFailedSentSpans() {
return failedSentSpans;
}
public AtomicInteger getTotalSentSpans() {
return totalSentSpans;
}
public AtomicInteger getSuccessSentSpans() {
return successSentSpans;
}
public Integer getNotFinishedSpansNum() {
return getNotFinishedSpans().keySet().size();
}
public String getLogPathFile() {
return logPathFile;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy