Skip to content

Commit

Permalink
added Waiting in build queue
Browse files Browse the repository at this point in the history
  • Loading branch information
evernat committed Oct 13, 2019
1 parent 69fec17 commit efa4d03
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 1 deletion.
2 changes: 1 addition & 1 deletion pom.xml
Expand Up @@ -42,7 +42,7 @@
<dependency>
<groupId>net.bull.javamelody</groupId>
<artifactId>javamelody-core</artifactId>
<version>1.79.0</version>
<version>1.80.0-SNAPSHOT</version>
</dependency>
<!-- slf4j-api for Jenkins issue https://issues.jenkins-ci.org/browse/JENKINS-11293
NoClassDefFoundError: org.slf4j.ILoggerFactory on IBM J9 JVM,
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/net/bull/javamelody/NodesCollector.java
Expand Up @@ -165,6 +165,8 @@ public void collectWithoutErrorsNow() {
// note: this BUILD_QUEUE_LENGTH needs at least javamelody-core 1.35.0-SNAPSHOT
// including values for buildQueueLength in translations*.properties
JdbcWrapper.BUILD_QUEUE_LENGTH.set(queueLength);
final long waitingDurationsSum = WaitingDurationQueueListener.getWaitingDurationsSum();
JdbcWrapper.BUILD_QUEUE_WAITING_DURATIONS_SUM.set(waitingDurationsSum);

final List<JavaInformations> javaInformations = new ArrayList<>(
getLastJavaInformationsList().values());
Expand Down
@@ -0,0 +1,58 @@
/*
* Copyright 2008-2019 by Emeric Vernat
*
* This file is part of the Monitoring plugin.
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.bull.javamelody;

import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import hudson.Extension;
import hudson.model.Queue.LeftItem;
import hudson.model.Queue.WaitingItem;
import hudson.model.queue.QueueListener;

/**
* Listener d'entrée et de sortie de la file d'attente pour calculer un indicateur d'attente.

This comment has been minimized.

Copy link
@darxriggs

darxriggs Oct 14, 2019

I suggest to write the Javadoc in English.

This comment has been minimized.

Copy link
@evernat

evernat Oct 14, 2019

Author Contributor

@darxriggs
Yes, I should write the javadoc in English.
And I thought a second that you asked if this is using more and more memory over time.
I think it isn't, if onLeft is always called sometimes after onEnterWaiting and if id is the same between WaitingItem and LeftItem, like I suppose.
Let me know if you have a doubt. It would better be true.
At least it's true for a few tests I did.

This comment has been minimized.

Copy link
@darxriggs

darxriggs Oct 15, 2019

I removed my comment about the memory usage. Initially I overlooked the removal in onLeft().

* @author Emeric Vernat
*/
@Extension
public class WaitingDurationQueueListener extends QueueListener {
private static final ConcurrentMap<Long, Date> START_TIMES_BY_ID = new ConcurrentHashMap<>();

/** {@inheritDoc} */
@Override
public void onEnterWaiting(WaitingItem wi) {
START_TIMES_BY_ID.put(wi.getId(), new Date());

This comment has been minimized.

Copy link
@darxriggs

darxriggs Oct 15, 2019

What's the exact "waiting" duration that should be calculated in the listener? Have you considered using Item#getInQueueSince()? If there would for example be other slow QueueListeners, using new Date() here might be way off.

This comment has been minimized.

Copy link
@evernat

evernat Oct 15, 2019

Author Contributor

What's the exact "waiting" duration that should be calculated in the listener?

Good question. For an item in the queue, it should certainly be how long a user has been waiting (since the item entered the queue) before the item starts building (or is canceled). Then for all users, it is the sum of the durations for all the items in the queue. (An average is not good here.)

Have you considered using Item#getInQueueSince()?

Computing the sum of Item#getInQueueSince() would need to get the list of items in the queue but Queue#getBuildableItems() contains buildable and pendings items, while blocked ones are also a cause of user's waiting (https://javadoc.jenkins.io/hudson/model/Queue.html). By the way, in the Jenkins load statistics and in this plugin, the "queue length" metric is supposed to be for nodes provisioning, so it does not count the blocked items, while the "waiting" duration here is measured since entering the queue including blocked items.

If there would for example be other slow QueueListeners, using new Date() here might be way off.

Might be true yes. I will use new Date(waitingItem.getInQueueSince()) instead of new Date(). Thanks.

This comment has been minimized.

Copy link
@evernat

evernat Oct 15, 2019

Author Contributor

For reference, this metric was asked by a user and was supposed to be needed from the users' point of view: https://groups.google.com/forum/#!topic/javamelody/X954dFEbkyQ

}

/** {@inheritDoc} */
@Override
public void onLeft(LeftItem li) {
START_TIMES_BY_ID.remove(li.getId());
}

static long getWaitingDurationsSum() {
final long now = System.currentTimeMillis();
long sum = 0;
for (final Date date : START_TIMES_BY_ID.values()) {
// now can be a bit before date
sum += now - date.getTime();
}
return Math.max(sum, 0);
}
}

0 comments on commit efa4d03

Please sign in to comment.