-
-
Notifications
You must be signed in to change notification settings - Fork 435
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
159 additions
and
108 deletions.
There are no files selected for viewing
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
105 changes: 105 additions & 0 deletions
105
sentry/src/main/java/io/sentry/DefaultTransactionPerformanceCollector.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,105 @@ | ||
package io.sentry; | ||
|
||
import io.sentry.util.Objects; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Timer; | ||
import java.util.TimerTask; | ||
import java.util.concurrent.ConcurrentHashMap; | ||
import java.util.concurrent.atomic.AtomicBoolean; | ||
import org.jetbrains.annotations.ApiStatus; | ||
import org.jetbrains.annotations.NotNull; | ||
import org.jetbrains.annotations.Nullable; | ||
|
||
@ApiStatus.Internal | ||
public final class DefaultTransactionPerformanceCollector | ||
implements TransactionPerformanceCollector { | ||
private static final long TRANSACTION_COLLECTION_INTERVAL_MILLIS = 100; | ||
private static final long TRANSACTION_COLLECTION_TIMEOUT_MILLIS = 30000; | ||
private final @NotNull Object timerLock = new Object(); | ||
private volatile @Nullable Timer timer = null; | ||
private final @NotNull Map<String, PerformanceCollectionData> performanceDataMap = | ||
new ConcurrentHashMap<>(); | ||
private final @NotNull List<ICollector> collectors; | ||
private final @NotNull SentryOptions options; | ||
private final @NotNull AtomicBoolean isStarted = new AtomicBoolean(false); | ||
|
||
public DefaultTransactionPerformanceCollector(final @NotNull SentryOptions options) { | ||
this.options = Objects.requireNonNull(options, "The options object is required."); | ||
this.collectors = options.getCollectors(); | ||
} | ||
|
||
@Override | ||
@SuppressWarnings("FutureReturnValueIgnored") | ||
public void start(final @NotNull ITransaction transaction) { | ||
if (collectors.isEmpty()) { | ||
options | ||
.getLogger() | ||
.log( | ||
SentryLevel.INFO, | ||
"No collector found. Performance stats will not be captured during transactions."); | ||
return; | ||
} | ||
|
||
if (!performanceDataMap.containsKey(transaction.getEventId().toString())) { | ||
performanceDataMap.put(transaction.getEventId().toString(), new PerformanceCollectionData()); | ||
options | ||
.getExecutorService() | ||
.schedule( | ||
() -> { | ||
PerformanceCollectionData data = stop(transaction); | ||
if (data != null) { | ||
performanceDataMap.put(transaction.getEventId().toString(), data); | ||
} | ||
}, | ||
TRANSACTION_COLLECTION_TIMEOUT_MILLIS); | ||
} | ||
if (!isStarted.getAndSet(true)) { | ||
synchronized (timerLock) { | ||
for (ICollector collector : collectors) { | ||
collector.setup(); | ||
} | ||
if (timer == null) { | ||
timer = new Timer(true); | ||
} | ||
// We schedule the timer to start after a delay, so we let some time pass between setup() | ||
// and collect() calls. | ||
// This way ICollectors that collect average stats based on time intervals, like | ||
// AndroidCpuCollector, can have an actual time interval to evaluate. | ||
timer.scheduleAtFixedRate( | ||
new TimerTask() { | ||
@Override | ||
public void run() { | ||
synchronized (timerLock) { | ||
for (ICollector collector : collectors) { | ||
collector.collect(performanceDataMap.values()); | ||
} | ||
// We commit data after calling all collectors. | ||
// This way we avoid issues caused by having multiple cpu or memory collectors. | ||
for (PerformanceCollectionData data : performanceDataMap.values()) { | ||
data.commitData(); | ||
} | ||
} | ||
} | ||
}, | ||
TRANSACTION_COLLECTION_INTERVAL_MILLIS, | ||
TRANSACTION_COLLECTION_INTERVAL_MILLIS); | ||
} | ||
} | ||
} | ||
|
||
@Override | ||
public @Nullable PerformanceCollectionData stop(final @NotNull ITransaction transaction) { | ||
synchronized (timerLock) { | ||
PerformanceCollectionData data = | ||
performanceDataMap.remove(transaction.getEventId().toString()); | ||
if (performanceDataMap.isEmpty() && isStarted.getAndSet(false)) { | ||
if (timer != null) { | ||
timer.cancel(); | ||
timer = null; | ||
} | ||
} | ||
return data; | ||
} | ||
} | ||
} |
24 changes: 24 additions & 0 deletions
24
sentry/src/main/java/io/sentry/NoOpTransactionPerformanceCollector.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,24 @@ | ||
package io.sentry; | ||
|
||
import org.jetbrains.annotations.NotNull; | ||
import org.jetbrains.annotations.Nullable; | ||
|
||
public final class NoOpTransactionPerformanceCollector implements TransactionPerformanceCollector { | ||
|
||
private static final NoOpTransactionPerformanceCollector instance = | ||
new NoOpTransactionPerformanceCollector(); | ||
|
||
public static NoOpTransactionPerformanceCollector getInstance() { | ||
return instance; | ||
} | ||
|
||
private NoOpTransactionPerformanceCollector() {} | ||
|
||
@Override | ||
public void start(@NotNull ITransaction transaction) {} | ||
|
||
@Override | ||
public @Nullable PerformanceCollectionData stop(@NotNull ITransaction transaction) { | ||
return null; | ||
} | ||
} |
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
98 changes: 4 additions & 94 deletions
98
sentry/src/main/java/io/sentry/TransactionPerformanceCollector.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 |
---|---|---|
@@ -1,102 +1,12 @@ | ||
package io.sentry; | ||
|
||
import io.sentry.util.Objects; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Timer; | ||
import java.util.TimerTask; | ||
import java.util.concurrent.ConcurrentHashMap; | ||
import java.util.concurrent.atomic.AtomicBoolean; | ||
import org.jetbrains.annotations.ApiStatus; | ||
import org.jetbrains.annotations.NotNull; | ||
import org.jetbrains.annotations.Nullable; | ||
|
||
@ApiStatus.Internal | ||
public final class TransactionPerformanceCollector { | ||
private static final long TRANSACTION_COLLECTION_INTERVAL_MILLIS = 100; | ||
private static final long TRANSACTION_COLLECTION_TIMEOUT_MILLIS = 30000; | ||
private final @NotNull Object timerLock = new Object(); | ||
private volatile @Nullable Timer timer = null; | ||
private final @NotNull Map<String, PerformanceCollectionData> performanceDataMap = | ||
new ConcurrentHashMap<>(); | ||
private final @NotNull List<ICollector> collectors; | ||
private final @NotNull SentryOptions options; | ||
private final @NotNull AtomicBoolean isStarted = new AtomicBoolean(false); | ||
public interface TransactionPerformanceCollector { | ||
|
||
public TransactionPerformanceCollector(final @NotNull SentryOptions options) { | ||
this.options = Objects.requireNonNull(options, "The options object is required."); | ||
this.collectors = options.getCollectors(); | ||
} | ||
void start(@NotNull ITransaction transaction); | ||
|
||
@SuppressWarnings("FutureReturnValueIgnored") | ||
public void start(final @NotNull ITransaction transaction) { | ||
if (collectors.isEmpty()) { | ||
options | ||
.getLogger() | ||
.log( | ||
SentryLevel.INFO, | ||
"No collector found. Performance stats will not be captured during transactions."); | ||
return; | ||
} | ||
|
||
if (!performanceDataMap.containsKey(transaction.getEventId().toString())) { | ||
performanceDataMap.put(transaction.getEventId().toString(), new PerformanceCollectionData()); | ||
options | ||
.getExecutorService() | ||
.schedule( | ||
() -> { | ||
PerformanceCollectionData data = stop(transaction); | ||
if (data != null) { | ||
performanceDataMap.put(transaction.getEventId().toString(), data); | ||
} | ||
}, | ||
TRANSACTION_COLLECTION_TIMEOUT_MILLIS); | ||
} | ||
if (!isStarted.getAndSet(true)) { | ||
synchronized (timerLock) { | ||
for (ICollector collector : collectors) { | ||
collector.setup(); | ||
} | ||
if (timer == null) { | ||
timer = new Timer(true); | ||
} | ||
// We schedule the timer to start after a delay, so we let some time pass between setup() | ||
// and collect() calls. | ||
// This way ICollectors that collect average stats based on time intervals, like | ||
// AndroidCpuCollector, can have an actual time interval to evaluate. | ||
timer.scheduleAtFixedRate( | ||
new TimerTask() { | ||
@Override | ||
public void run() { | ||
synchronized (timerLock) { | ||
for (ICollector collector : collectors) { | ||
collector.collect(performanceDataMap.values()); | ||
} | ||
// We commit data after calling all collectors. | ||
// This way we avoid issues caused by having multiple cpu or memory collectors. | ||
for (PerformanceCollectionData data : performanceDataMap.values()) { | ||
data.commitData(); | ||
} | ||
} | ||
} | ||
}, | ||
TRANSACTION_COLLECTION_INTERVAL_MILLIS, | ||
TRANSACTION_COLLECTION_INTERVAL_MILLIS); | ||
} | ||
} | ||
} | ||
|
||
public @Nullable PerformanceCollectionData stop(final @NotNull ITransaction transaction) { | ||
synchronized (timerLock) { | ||
PerformanceCollectionData data = | ||
performanceDataMap.remove(transaction.getEventId().toString()); | ||
if (performanceDataMap.isEmpty() && isStarted.getAndSet(false)) { | ||
if (timer != null) { | ||
timer.cancel(); | ||
timer = null; | ||
} | ||
} | ||
return data; | ||
} | ||
} | ||
@Nullable | ||
PerformanceCollectionData stop(@NotNull ITransaction transaction); | ||
} |
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