001/*
002 * Copyright 2008-2018 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2015-2018 Ping Identity Corporation
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU General Public License (GPLv2 only)
010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011 * as published by the Free Software Foundation.
012 *
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016 * GNU General Public License for more details.
017 *
018 * You should have received a copy of the GNU General Public License
019 * along with this program; if not, see <http://www.gnu.org/licenses>.
020 */
021package com.unboundid.ldap.sdk.unboundidds.monitors;
022
023
024
025import java.util.Collections;
026import java.util.LinkedHashMap;
027import java.util.Map;
028
029import com.unboundid.ldap.sdk.Entry;
030import com.unboundid.util.NotMutable;
031import com.unboundid.util.ThreadSafety;
032import com.unboundid.util.ThreadSafetyLevel;
033
034import static com.unboundid.ldap.sdk.unboundidds.monitors.MonitorMessages.*;
035
036
037
038/**
039 * This class defines a monitor entry that provides information about the state
040 * of the UnboundID work queue.  This has replaced the traditional work queue as
041 * the default work queue implementation used by the Directory Server
042 * <BR>
043 * <BLOCKQUOTE>
044 *   <B>NOTE:</B>  This class, and other classes within the
045 *   {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
046 *   supported for use against Ping Identity, UnboundID, and Alcatel-Lucent 8661
047 *   server products.  These classes provide support for proprietary
048 *   functionality or for external specifications that are not considered stable
049 *   or mature enough to be guaranteed to work in an interoperable way with
050 *   other types of LDAP servers.
051 * </BLOCKQUOTE>
052 * <BR>
053 * The monitor information that it may make available includes:
054 * <UL>
055 *   <LI>The number of requests that were rejected because the work queue was
056 *       already at its maximum capacity.</LI>
057 *   <LI>The number of operations currently held in the work queue waiting to be
058 *       picked for processing by a worker thread.</LI>
059 *   <LI>The average number of operations held in the work queue since startup
060 *       as observed from periodic polling.</LI>
061 *   <LI>The maximum number of operations held in the work queue at any time
062 *       since startup as observed from periodic polling.</LI>
063 * </UL>
064 * The server should present at most one UnboundID work queue monitor entry.
065 * It can be retrieved using the
066 * {@link MonitorManager#getUnboundIDWorkQueueMonitorEntry} method.  This entry
067 * provides specific methods for accessing information about the state of
068 * the work queue (e.g., the
069 * {@link UnboundIDWorkQueueMonitorEntry#getCurrentSize} method may be used
070 * to retrieve the number of operations currently held in the work queue).
071 * Alternately, this information may be accessed using the generic API.  See the
072 * {@link MonitorManager} class documentation for an example that demonstrates
073 * the use of the generic API for accessing monitor data.
074 */
075@NotMutable()
076@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
077public final class UnboundIDWorkQueueMonitorEntry
078       extends MonitorEntry
079{
080  /**
081   * The structural object class used in LDAP statistics monitor entries.
082   */
083  static final String UNBOUNDID_WORK_QUEUE_MONITOR_OC =
084       "ds-unboundid-work-queue-monitor-entry";
085
086
087
088  /**
089   * The name of the attribute that contains the average worker thread percent
090   * busy.
091   */
092  private static final String ATTR_AVERAGE_QUEUE_TIME_MILLIS =
093       "average-operation-queue-time-millis";
094
095
096
097  /**
098   * The name of the attribute that contains the average worker thread percent
099   * busy.
100   */
101  private static final String ATTR_AVERAGE_PCT_BUSY =
102       "average-worker-thread-percent-busy";
103
104
105
106  /**
107   * The name of the attribute that contains the average observed work queue
108   * size.
109   */
110  private static final String ATTR_AVERAGE_SIZE = "average-queue-size";
111
112
113
114  /**
115   * The name of the attribute that contains the current work queue size.
116   */
117  private static final String ATTR_CURRENT_PCT_BUSY =
118       "current-worker-thread-percent-busy";
119
120
121
122  /**
123   * The name of the attribute that contains the current work queue size.
124   */
125  private static final String ATTR_CURRENT_SIZE = "current-queue-size";
126
127
128
129  /**
130   * The name of the attribute that contains the maximum observed work queue
131   * size.
132   */
133  private static final String ATTR_MAX_SIZE = "max-queue-size";
134
135
136
137  /**
138   * The name of the attribute that contains the maximum worker thread percent
139   * busy.
140   */
141  private static final String ATTR_MAX_PCT_BUSY =
142       "max-worker-thread-percent-busy";
143
144
145
146  /**
147   * The name of the attribute that contains the number of busy worker threads.
148   */
149  private static final String ATTR_NUM_BUSY_WORKER_THREADS =
150       "num-busy-worker-threads";
151
152
153
154  /**
155   * The name of the attribute that contains the number of worker threads.
156   */
157  private static final String ATTR_NUM_WORKER_THREADS = "num-worker-threads";
158
159
160
161  /**
162   * The name of the attribute that contains the average worker thread percent
163   * busy.
164   */
165  private static final String ATTR_RECENT_AVERAGE_SIZE =
166       "recent-average-queue-size";
167
168
169
170  /**
171   * The name of the attribute that contains the average worker thread percent
172   * busy.
173   */
174  private static final String ATTR_RECENT_QUEUE_TIME_MILLIS =
175       "recent-operation-queue-time-millis";
176
177
178
179  /**
180   * The name of the attribute that contains the recent worker thread percent
181   * busy.
182   */
183  private static final String ATTR_RECENT_PCT_BUSY =
184       "recent-worker-thread-percent-busy";
185
186
187
188  /**
189   * The name of the attribute that contains the total number of requests that
190   * have been rejected because the work queue was full.
191   */
192  private static final String ATTR_REQUESTS_REJECTED = "rejected-count";
193
194
195
196  /**
197   * The name of the attribute that contains the total number of requests that
198   * have were stolen from their primary queue by a worker thread associated
199   * with a different queue.
200   */
201  private static final String ATTR_REQUESTS_STOLEN = "stolen-count";
202
203
204
205  /**
206   * The name of the attribute that contains the current size of the work queue
207   * reserved for operations processed as part of administrative sessions.
208   */
209  private static final String ATTR_CURRENT_ADMIN_QUEUE_SIZE =
210       "current-administrative-session-queue-size";
211
212
213
214  /**
215   * The name of the attribute that contains the number of worker threads that
216   * are currently busy processing operations as part of an administrative
217   * session.
218   */
219  private static final String ATTR_MAX_ADMIN_SESSION_QUEUE_SIZE =
220       "max-administrative-session-queue-size";
221
222
223
224  /**
225   * The name of the attribute that contains the total number of worker threads
226   * reserved for processing operations that are part of an administrative
227   * session.
228   */
229  private static final String ATTR_NUM_ADMIN_WORKER_THREADS =
230       "num-administrative-session-worker-threads";
231
232
233
234  /**
235   * The name of the attribute that contains the number of worker threads that
236   * are currently busy processing operations as part of an administrative
237   * session.
238   */
239  private static final String ATTR_NUM_BUSY_ADMIN_WORKER_THREADS =
240       "num-busy-administrative-session-worker-threads";
241
242
243
244  /**
245   * The serial version UID for this serializable class.
246   */
247  private static final long serialVersionUID = -304216058351812232L;
248
249
250
251  // The average queue time in milliseconds.
252  private final Long averageQueueTimeMillis;
253
254  // The average worker thread percent busy.
255  private final Long averagePercentBusy;
256
257  // The average work queue size.
258  private final Long averageSize;
259
260  // The current administrative session work queue size.
261  private final Long currentAdminSize;
262
263  // The current work queue size.
264  private final Long currentSize;
265
266  // The current worker thread percent busy.
267  private final Long currentPercentBusy;
268
269  // The maximum administrative session work queue size.
270  private final Long maxAdminSize;
271
272  // The maximum worker thread percent busy.
273  private final Long maxPercentBusy;
274
275  // The maximum work queue size.
276  private final Long maxSize;
277
278  // The number of administrative session worker threads.
279  private final Long numAdminWorkerThreads;
280
281  // The number of busy worker threads.
282  private final Long numBusyWorkerThreads;
283
284  // The number of busy administrative session worker threads.
285  private final Long numBusyAdminWorkerThreads;
286
287  // The number of worker threads.
288  private final Long numWorkerThreads;
289
290  // The recent average work queue size.
291  private final Long recentAverageSize;
292
293  // The recent queue time in milliseconds.
294  private final Long recentQueueTimeMillis;
295
296  // The recent worker thread percent busy.
297  private final Long recentPercentBusy;
298
299  // The total number of requests rejected due to a full work queue.
300  private final Long requestsRejected;
301
302  // The total number of requests rejected due to a full work queue.
303  private final Long requestsStolen;
304
305
306
307  /**
308   * Creates a new UnboundID work queue monitor entry from the provided entry.
309   *
310   * @param  entry  The entry to be parsed as a traditional work queue monitor
311   *                entry.  It must not be {@code null}.
312   */
313  public UnboundIDWorkQueueMonitorEntry(final Entry entry)
314  {
315    super(entry);
316
317    averageSize               = getLong(ATTR_AVERAGE_SIZE);
318    currentSize               = getLong(ATTR_CURRENT_SIZE);
319    recentAverageSize         = getLong(ATTR_RECENT_AVERAGE_SIZE);
320    maxSize                   = getLong(ATTR_MAX_SIZE);
321    requestsRejected          = getLong(ATTR_REQUESTS_REJECTED);
322    requestsStolen            = getLong(ATTR_REQUESTS_STOLEN);
323    numBusyWorkerThreads      = getLong(ATTR_NUM_BUSY_WORKER_THREADS);
324    numWorkerThreads          = getLong(ATTR_NUM_WORKER_THREADS);
325    currentPercentBusy        = getLong(ATTR_CURRENT_PCT_BUSY);
326    averagePercentBusy        = getLong(ATTR_AVERAGE_PCT_BUSY);
327    recentPercentBusy         = getLong(ATTR_RECENT_PCT_BUSY);
328    maxPercentBusy            = getLong(ATTR_MAX_PCT_BUSY);
329    averageQueueTimeMillis    = getLong(ATTR_AVERAGE_QUEUE_TIME_MILLIS);
330    recentQueueTimeMillis     = getLong(ATTR_RECENT_QUEUE_TIME_MILLIS);
331    currentAdminSize          = getLong(ATTR_CURRENT_ADMIN_QUEUE_SIZE);
332    maxAdminSize              = getLong(ATTR_MAX_ADMIN_SESSION_QUEUE_SIZE);
333    numAdminWorkerThreads     = getLong(ATTR_NUM_ADMIN_WORKER_THREADS);
334    numBusyAdminWorkerThreads = getLong(ATTR_NUM_BUSY_ADMIN_WORKER_THREADS);
335  }
336
337
338
339  /**
340   * Retrieves the average number of operations observed in the work queue.
341   *
342   * @return  The average number of operations observed in the work queue, or
343   *          {@code null} if that information was not included in the monitor
344   *          entry.
345   */
346  public Long getAverageSize()
347  {
348    return averageSize;
349  }
350
351
352
353  /**
354   * Retrieves the average number of operations observed in the work queue over
355   * a recent interval.
356   *
357   * @return  The average number of operations observed in the work queue over a
358   *          recent interval, or {@code null} if that information was not
359   *          included in the monitor entry.
360   */
361  public Long getRecentAverageSize()
362  {
363    return recentAverageSize;
364  }
365
366
367
368  /**
369   * Retrieves the number of operations that are currently in the work queue
370   * waiting to be processed.
371   *
372   * @return  The number of operations that are currently in the work queue
373   *          waiting to be processed, or {@code null} if that information was
374   *          not included in the monitor entry.
375   */
376  public Long getCurrentSize()
377  {
378    return currentSize;
379  }
380
381
382
383  /**
384   * Retrieves the maximum number of operations observed in the work queue at
385   * any given time.
386   *
387   * @return  The total number of operations observed in the work queue at any
388   *          given time, or {@code null} if that information was not included
389   *          in the monitor entry.
390   */
391  public Long getMaxSize()
392  {
393    return maxSize;
394  }
395
396
397
398  /**
399   * Retrieves the total number of operation requests that were rejected because
400   * the work queue was at its maximum capacity.
401   *
402   * @return  The total number of operation requests rejected because the work
403   *          queue was at its maximum capacity, or {@code null} if that
404   *          information was not included in the monitor entry.
405   */
406  public Long getRequestsRejectedDueToQueueFull()
407  {
408    return requestsRejected;
409  }
410
411
412
413  /**
414   * Retrieves the total number of operation requests that have been stolen from
415   * their primary queue by a worker thread associated with a different queue.
416   *
417   * @return  The total number of operation requests that have been stolen from
418   *          their primary queue by a worker thread associated with a different
419   *          queue, or {@code null} if that information was not included in the
420   *          monitor entry.
421   */
422  public Long getRequestsStolen()
423  {
424    return requestsStolen;
425  }
426
427
428
429  /**
430   * Retrieves the number of worker threads configured for the work queue.
431   *
432   * @return  The number of worker threads configured for the work queue, or
433   *          {@code null} if that information was not included in the monitor
434   *          entry.
435   */
436  public Long getNumWorkerThreads()
437  {
438    return numWorkerThreads;
439  }
440
441
442
443  /**
444   * Retrieves the number of worker threads that are currently busy processing
445   * an operation.
446   *
447   * @return  The number of worker threads that are currently busy processing an
448   *          operation, or {@code null} if that information was not included in
449   *          the monitor entry.
450   */
451  public Long getNumBusyWorkerThreads()
452  {
453    return numBusyWorkerThreads;
454  }
455
456
457
458  /**
459   * Retrieves the percentage of worker threads that are currently busy
460   * processing an operation.
461   *
462   * @return  The percentage of worker threads that are currently busy
463   *          processing an operation, or {@code null} if that information was
464   *          not included in the monitor entry.
465   */
466  public Long getCurrentWorkerThreadPercentBusy()
467  {
468    return currentPercentBusy;
469  }
470
471
472
473  /**
474   * Retrieves the average percentage of the time since startup that worker
475   * threads have spent busy processing operations.
476   *
477   * @return  The average percentage of the time since startup that worker
478   *          threads have spent busy processing operations, or {@code null} if
479   *          that information was not included in the monitor entry.
480   */
481  public Long getAverageWorkerThreadPercentBusy()
482  {
483    return averagePercentBusy;
484  }
485
486
487
488  /**
489   * Retrieves the percentage of the time over a recent interval that worker
490   * threads have spent busy processing operations.
491   *
492   * @return  The percentage of the time over a recent interval that worker
493   *          threads have spent busy processing operations, or {@code null} if
494   *          that information was not included in the monitor entry.
495   */
496  public Long getRecentWorkerThreadPercentBusy()
497  {
498    return recentPercentBusy;
499  }
500
501
502
503  /**
504   * Retrieves the maximum percentage of the time over any interval that worker
505   * threads have spent busy processing operations.
506   *
507   * @return  The maximum percentage of the time over any interval that worker
508   *          threads have spent busy processing operations, or {@code null} if
509   *          that information was not included in the monitor entry.
510   */
511  public Long getMaxWorkerThreadPercentBusy()
512  {
513    return maxPercentBusy;
514  }
515
516
517
518  /**
519   * Retrieves the average length of time in milliseconds that operations have
520   * been required to wait on the work queue before being picked up by a worker
521   * thread.
522   *
523   * @return  The average length of time in milliseconds that operations have
524   *          been required to wait on the work queue, or {@code null} if that
525   *          information was not included in the monitor entry.
526   */
527  public Long getAverageOperationQueueTimeMillis()
528  {
529    return averageQueueTimeMillis;
530  }
531
532
533
534  /**
535   * Retrieves the average length of time in milliseconds that
536   * recently-processed operations have been required to wait on the work queue
537   * before being picked up by a worker thread.
538   *
539   * @return  The average length of time in milliseconds that recently-processed
540   *          operations have been required to wait on the work queue, or
541   *          {@code null} if that information was not included in the monitor
542   *          entry.
543   */
544  public Long getRecentOperationQueueTimeMillis()
545  {
546    return recentQueueTimeMillis;
547  }
548
549
550
551  /**
552   * Retrieves the number of operations that are currently waiting to be
553   * processed in the portion of the work queue reserved for operations that are
554   * part of an administrative session.
555   *
556   * @return  The number of operations that are currently waiting to be
557   *          processed in the portion of the work queue reserved for operations
558   *          that are part of an administrative session, or {@code null} if
559   *          that information was not included in the monitor entry.
560   */
561  public Long getCurrentAdministrativeSessionQueueSize()
562  {
563    return currentAdminSize;
564  }
565
566
567
568  /**
569   * Retrieves the maximum number of operations observed in the dedicated
570   * administrative session queue at any given time.
571   *
572   * @return  The total number of operations observed in the dedicated
573   *          administrative session queue at any given time, or {@code null} if
574   *          that information was not included in the monitor entry.
575   */
576  public Long getMaxAdministrativeSessionQueueSize()
577  {
578    return maxAdminSize;
579  }
580
581
582
583  /**
584   * Retrieves the number of worker threads that have been reserved for
585   * processing operations that are part of an administrative session.
586   *
587   * @return  The number of worker threads that have been reserved for
588   *          processing operations that are part of an administrative session,
589   *          or {@code null} if that information was not included in the
590   *          monitor entry.
591   */
592  public Long getNumAdministrativeSessionWorkerThreads()
593  {
594    return numAdminWorkerThreads;
595  }
596
597
598
599  /**
600   * Retrieves the number of worker threads that are currently busy processing
601   * an operation which is part of an administrative session.
602   *
603   * @return  The number of worker threads that are currently busy processing an
604   *          operation which is part of an administrative session, or
605   *          {@code null} if that information was not included in the monitor
606   *          entry.
607   */
608  public Long getNumBusyAdministrativeSessionWorkerThreads()
609  {
610    return numBusyAdminWorkerThreads;
611  }
612
613
614
615  /**
616   * {@inheritDoc}
617   */
618  @Override()
619  public String getMonitorDisplayName()
620  {
621    return INFO_UNBOUNDID_WORK_QUEUE_MONITOR_DISPNAME.get();
622  }
623
624
625
626  /**
627   * {@inheritDoc}
628   */
629  @Override()
630  public String getMonitorDescription()
631  {
632    return INFO_UNBOUNDID_WORK_QUEUE_MONITOR_DESC.get();
633  }
634
635
636
637  /**
638   * {@inheritDoc}
639   */
640  @Override()
641  public Map<String,MonitorAttribute> getMonitorAttributes()
642  {
643    final LinkedHashMap<String,MonitorAttribute> attrs =
644         new LinkedHashMap<String,MonitorAttribute>();
645
646    if (requestsRejected != null)
647    {
648      addMonitorAttribute(attrs,
649           ATTR_REQUESTS_REJECTED,
650           INFO_UNBOUNDID_WORK_QUEUE_DISPNAME_REQUESTS_REJECTED.get(),
651           INFO_UNBOUNDID_WORK_QUEUE_DESC_REQUESTS_REJECTED.get(),
652           requestsRejected);
653    }
654
655    if (requestsStolen != null)
656    {
657      addMonitorAttribute(attrs,
658           ATTR_REQUESTS_STOLEN,
659           INFO_UNBOUNDID_WORK_QUEUE_DISPNAME_REQUESTS_STOLEN.get(),
660           INFO_UNBOUNDID_WORK_QUEUE_DESC_REQUESTS_STOLEN.get(),
661           requestsStolen);
662    }
663
664    if (currentSize != null)
665    {
666      addMonitorAttribute(attrs,
667           ATTR_CURRENT_SIZE,
668           INFO_UNBOUNDID_WORK_QUEUE_DISPNAME_CURRENT_SIZE.get(),
669           INFO_UNBOUNDID_WORK_QUEUE_DESC_CURRENT_SIZE.get(),
670           currentSize);
671    }
672
673    if (recentAverageSize != null)
674    {
675      addMonitorAttribute(attrs,
676           ATTR_RECENT_AVERAGE_SIZE,
677           INFO_UNBOUNDID_WORK_QUEUE_DISPNAME_RECENT_AVERAGE_SIZE.get(),
678           INFO_UNBOUNDID_WORK_QUEUE_DESC_RECENT_AVERAGE_SIZE.get(),
679           recentAverageSize);
680    }
681
682    if (averageSize != null)
683    {
684      addMonitorAttribute(attrs,
685           ATTR_AVERAGE_SIZE,
686           INFO_UNBOUNDID_WORK_QUEUE_DISPNAME_AVERAGE_SIZE.get(),
687           INFO_UNBOUNDID_WORK_QUEUE_DESC_AVERAGE_SIZE.get(),
688           averageSize);
689    }
690
691    if (maxSize != null)
692    {
693      addMonitorAttribute(attrs,
694           ATTR_MAX_SIZE,
695           INFO_UNBOUNDID_WORK_QUEUE_DISPNAME_MAX_SIZE.get(),
696           INFO_UNBOUNDID_WORK_QUEUE_DESC_MAX_SIZE.get(),
697           maxSize);
698    }
699
700    if (numWorkerThreads != null)
701    {
702      addMonitorAttribute(attrs,
703           ATTR_NUM_WORKER_THREADS,
704           INFO_UNBOUNDID_WORK_QUEUE_DISPNAME_NUM_THREADS.get(),
705           INFO_UNBOUNDID_WORK_QUEUE_DESC_NUM_THREADS.get(),
706           numWorkerThreads);
707    }
708
709    if (numBusyWorkerThreads != null)
710    {
711      addMonitorAttribute(attrs,
712           ATTR_NUM_BUSY_WORKER_THREADS,
713           INFO_UNBOUNDID_WORK_QUEUE_DISPNAME_NUM_BUSY_THREADS.get(),
714           INFO_UNBOUNDID_WORK_QUEUE_DESC_NUM_BUSY_THREADS.get(),
715           numBusyWorkerThreads);
716    }
717
718    if (currentPercentBusy != null)
719    {
720      addMonitorAttribute(attrs,
721           ATTR_CURRENT_PCT_BUSY,
722           INFO_UNBOUNDID_WORK_QUEUE_DISPNAME_CURRENT_PCT_BUSY.get(),
723           INFO_UNBOUNDID_WORK_QUEUE_DESC_CURRENT_PCT_BUSY.get(),
724           currentPercentBusy);
725    }
726
727    if (averagePercentBusy != null)
728    {
729      addMonitorAttribute(attrs,
730           ATTR_AVERAGE_PCT_BUSY,
731           INFO_UNBOUNDID_WORK_QUEUE_DISPNAME_AVG_PCT_BUSY.get(),
732           INFO_UNBOUNDID_WORK_QUEUE_DESC_AVG_PCT_BUSY.get(),
733           averagePercentBusy);
734    }
735
736    if (recentPercentBusy != null)
737    {
738      addMonitorAttribute(attrs,
739           ATTR_RECENT_PCT_BUSY,
740           INFO_UNBOUNDID_WORK_QUEUE_DISPNAME_RECENT_PCT_BUSY.get(),
741           INFO_UNBOUNDID_WORK_QUEUE_DESC_RECENT_PCT_BUSY.get(),
742           recentPercentBusy);
743    }
744
745    if (maxPercentBusy != null)
746    {
747      addMonitorAttribute(attrs,
748           ATTR_MAX_PCT_BUSY,
749           INFO_UNBOUNDID_WORK_QUEUE_DISPNAME_MAX_PCT_BUSY.get(),
750           INFO_UNBOUNDID_WORK_QUEUE_DESC_MAX_PCT_BUSY.get(),
751           maxPercentBusy);
752    }
753
754    if (averageQueueTimeMillis != null)
755    {
756      addMonitorAttribute(attrs,
757           ATTR_AVERAGE_QUEUE_TIME_MILLIS,
758           INFO_UNBOUNDID_WORK_QUEUE_DISPNAME_AVG_QUEUE_TIME.get(),
759           INFO_UNBOUNDID_WORK_QUEUE_DESC_AVG_QUEUE_TIME.get(),
760           averageQueueTimeMillis);
761    }
762
763    if (recentQueueTimeMillis != null)
764    {
765      addMonitorAttribute(attrs,
766           ATTR_RECENT_QUEUE_TIME_MILLIS,
767           INFO_UNBOUNDID_WORK_QUEUE_DISPNAME_RECENT_QUEUE_TIME.get(),
768           INFO_UNBOUNDID_WORK_QUEUE_DESC_RECENT_QUEUE_TIME.get(),
769           recentQueueTimeMillis);
770    }
771
772    if (currentAdminSize != null)
773    {
774      addMonitorAttribute(attrs,
775           ATTR_CURRENT_ADMIN_QUEUE_SIZE,
776           INFO_UNBOUNDID_WORK_QUEUE_DISPNAME_CURRENT_ADMIN_QUEUE_SIZE.get(),
777           INFO_UNBOUNDID_WORK_QUEUE_DESC_CURRENT_ADMIN_QUEUE_SIZE.get(),
778           currentAdminSize);
779    }
780
781    if (maxAdminSize != null)
782    {
783      addMonitorAttribute(attrs,
784           ATTR_MAX_ADMIN_SESSION_QUEUE_SIZE,
785           INFO_UNBOUNDID_WORK_QUEUE_DISPNAME_MAX_ADMIN_QUEUE_SIZE.get(),
786           INFO_UNBOUNDID_WORK_QUEUE_DESC_MAX_ADMIN_QUEUE_SIZE.get(),
787           maxAdminSize);
788    }
789
790    if (numAdminWorkerThreads != null)
791    {
792      addMonitorAttribute(attrs,
793           ATTR_NUM_ADMIN_WORKER_THREADS,
794           INFO_UNBOUNDID_WORK_QUEUE_DISPNAME_NUM_ADMIN_THREADS.get(),
795           INFO_UNBOUNDID_WORK_QUEUE_DESC_NUM_ADMIN_THREADS.get(),
796           numAdminWorkerThreads);
797    }
798
799    if (numBusyAdminWorkerThreads != null)
800    {
801      addMonitorAttribute(attrs,
802           ATTR_NUM_BUSY_ADMIN_WORKER_THREADS,
803           INFO_UNBOUNDID_WORK_QUEUE_DISPNAME_NUM_BUSY_ADMIN_THREADS.get(),
804           INFO_UNBOUNDID_WORK_QUEUE_DESC_NUM_BUSY_ADMIN_THREADS.get(),
805           numBusyAdminWorkerThreads);
806    }
807
808    return Collections.unmodifiableMap(attrs);
809  }
810}