-
Notifications
You must be signed in to change notification settings - Fork 41
Adding upload statistics and alerts for both app binary uploads towards the CF API and OS uploads #1885
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Adding upload statistics and alerts for both app binary uploads towards the CF API and OS uploads #1885
Changes from all commits
f7777ca
20645c9
ce76772
f068192
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| package org.cloudfoundry.multiapps.controller.persistence.monitoring; | ||
|
|
||
| import jakarta.inject.Named; | ||
|
|
||
| import java.util.concurrent.atomic.AtomicLong; | ||
| import java.util.concurrent.atomic.LongAdder; | ||
|
|
||
| @Named | ||
| public class UploadDurationTracker { | ||
|
|
||
| private final UploadPathStatistics appBinaryStatistics = new UploadPathStatistics(); | ||
|
|
||
| private final UploadPathStatistics objectStoreStatistics = new UploadPathStatistics(); | ||
|
|
||
| public void recordAppBinaryUpload(long durationMillis, boolean timedOut) { | ||
| appBinaryStatistics.record(durationMillis, timedOut); | ||
| } | ||
|
|
||
| public void recordObjectStoreUpload(long durationMillis, boolean timedOut) { | ||
| objectStoreStatistics.record(durationMillis, timedOut); | ||
| } | ||
|
|
||
| public void recordAppBinaryUploadRejection() { | ||
| appBinaryStatistics.recordRejection(); | ||
| } | ||
|
|
||
| public UploadPathStatistics getAppBinaryStatistics() { | ||
| return this.appBinaryStatistics; | ||
| } | ||
|
|
||
| public UploadPathStatistics getObjectStoreStatistics() { | ||
| return this.objectStoreStatistics; | ||
| } | ||
|
|
||
| public static final class UploadPathStatistics { | ||
|
|
||
| private final LongAdder total = new LongAdder(); | ||
|
|
||
| private final LongAdder timeouts = new LongAdder(); | ||
|
|
||
| private final LongAdder sumDuration = new LongAdder(); | ||
|
|
||
| private final LongAdder rejections = new LongAdder(); | ||
|
|
||
| private final AtomicLong rejectionsInWindow = new AtomicLong(0); | ||
|
|
||
| private final AtomicLong maxDuration = new AtomicLong(0); | ||
|
|
||
| private final AtomicLong timeoutsInWindow = new AtomicLong(0); | ||
|
|
||
| public void record(long durationMillis, boolean timedOut) { | ||
|
Check warning on line 51 in multiapps-controller-persistence/src/main/java/org/cloudfoundry/multiapps/controller/persistence/monitoring/UploadDurationTracker.java
|
||
| long duration = Math.max(0, durationMillis); | ||
| total.increment(); | ||
|
|
||
| if (timedOut) { | ||
| timeouts.increment(); | ||
| timeoutsInWindow.incrementAndGet(); | ||
| } | ||
|
|
||
| sumDuration.add(duration); | ||
| maxDuration.accumulateAndGet(duration, Math::max); | ||
| } | ||
|
|
||
| public void recordRejection() { | ||
| rejections.increment(); | ||
| rejectionsInWindow.incrementAndGet(); | ||
| } | ||
|
|
||
| public long totalCount() { | ||
| return total.sum(); | ||
| } | ||
|
|
||
| public long timeoutCount() { | ||
| return timeouts.sum(); | ||
| } | ||
|
|
||
| public long maxDurationMs() { | ||
| return maxDuration.getAndSet(0); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why is this set to 0 after the value is read?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is on purpose as well, since Dynatrave is configured to poll each one minute which means that the poll happens at a random moment during these 60 seconds, which I would say that it is not fully correct, since a better way would be the way I have done it now - I am saving the maximum value per every 60 second poll and that is the value that dynatrace then displays on the charts. The idea is that in this one minute there might be a problematic deployment with lets say an abnormally high upload time and then after a couple of seconds there might be another totally normal one and the value would be overwritten and then if the Dynatrace poll is right after that - the chart would show that everything is totally alright. |
||
| } | ||
|
|
||
| public long sumDurationMs() { | ||
| return sumDuration.sum(); | ||
| } | ||
|
|
||
| public long timeoutsInWindow() { | ||
| return timeoutsInWindow.getAndSet(0); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same as the one above :D |
||
| } | ||
|
|
||
| public long rejectionCount() { | ||
| return rejections.sum(); | ||
| } | ||
|
|
||
| public long rejectionsInWindow() { | ||
| return rejectionsInWindow.getAndSet(0); | ||
| } | ||
|
|
||
| } | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| package org.cloudfoundry.multiapps.controller.persistence.monitoring; | ||
|
|
||
| import com.google.cloud.storage.StorageException; | ||
| import io.netty.handler.timeout.ReadTimeoutException; | ||
|
|
||
| import java.net.SocketTimeoutException; | ||
| import java.util.concurrent.TimeoutException; | ||
|
|
||
| public class UploadTimeoutMatcher { | ||
|
|
||
| private UploadTimeoutMatcher() { | ||
|
|
||
| } | ||
|
|
||
| public static boolean isUploadTimeoutException(Throwable throwable) { | ||
| if (throwable == null) { | ||
| return false; | ||
| } | ||
|
|
||
| Throwable cause = throwable.getCause(); | ||
| while (cause != null) { | ||
| if (cause instanceof SocketTimeoutException || cause instanceof TimeoutException || cause instanceof ReadTimeoutException || ( | ||
| cause instanceof StorageException | ||
|
Check warning on line 23 in multiapps-controller-persistence/src/main/java/org/cloudfoundry/multiapps/controller/persistence/monitoring/UploadTimeoutMatcher.java
|
||
| && ((StorageException) cause).getCode() == 504)) { | ||
| return true; | ||
| } | ||
| cause = cause.getCause(); | ||
| } | ||
| return false; | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This class which dynatrace uses for monitoring is only in memory - per instance and the values will be zero after restart of instance of DS, LSS. This is expected right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I made it like that on purpose so we are better able to see when and if an instance has any problems and also we do not have to think and be responsible about the persistence part of the whole thing, since Dynatrace automatically saves the information on the charts, even after if lets say there have been lots of restarts. We would only have to change the timeframe and we will be able to see if and which metric exactly has abnormal values.