001/*
002 * Copyright 2009-2024 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright 2009-2024 Ping Identity Corporation
007 *
008 * Licensed under the Apache License, Version 2.0 (the "License");
009 * you may not use this file except in compliance with the License.
010 * You may obtain a copy of the License at
011 *
012 *    http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing, software
015 * distributed under the License is distributed on an "AS IS" BASIS,
016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017 * See the License for the specific language governing permissions and
018 * limitations under the License.
019 */
020/*
021 * Copyright (C) 2009-2024 Ping Identity Corporation
022 *
023 * This program is free software; you can redistribute it and/or modify
024 * it under the terms of the GNU General Public License (GPLv2 only)
025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
026 * as published by the Free Software Foundation.
027 *
028 * This program is distributed in the hope that it will be useful,
029 * but WITHOUT ANY WARRANTY; without even the implied warranty of
030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
031 * GNU General Public License for more details.
032 *
033 * You should have received a copy of the GNU General Public License
034 * along with this program; if not, see <http://www.gnu.org/licenses>.
035 */
036package com.unboundid.ldap.sdk;
037
038
039
040import java.io.Serializable;
041import java.text.DecimalFormat;
042import java.util.concurrent.atomic.AtomicLong;
043
044import com.unboundid.util.Mutable;
045import com.unboundid.util.NotNull;
046import com.unboundid.util.ThreadSafety;
047import com.unboundid.util.ThreadSafetyLevel;
048
049
050
051/**
052 * This class provides a data structure with information about operations
053 * performed on an associated LDAP connection.  Calls to update statistics
054 * maintained by this class are threadsafe, but attempts to access different
055 * statistics may not be consistent if other operations may be in progress on
056 * the connection.
057 * <BR><BR>
058 * The set of statistics maintained for connections:
059 * <UL>
060 *   <LI>The number of attempts made to establish the connection.</LI>
061 *   <LI>The number of times the connection has been closed.</LI>
062 *   <LI>The number of requests of each type that have been sent over the
063 *       connection.</LI>
064 *   <LI>The number of responses of each type that have been received over the
065 *       connection.</LI>
066 *   <LI>The average response time (in milliseconds or nanoseconds) for each
067 *       type of operation processed on the connection.</LI>
068 * </UL>
069 */
070@Mutable()
071@ThreadSafety(level=ThreadSafetyLevel.MOSTLY_THREADSAFE)
072public final class LDAPConnectionStatistics
073       implements Serializable
074{
075  /**
076   * The serial version UID for this serializable class.
077   */
078  private static final long serialVersionUID = -1096417617572481790L;
079
080
081
082  // The number of abandon requests sent over the associated connection.
083  @NotNull private final AtomicLong numAbandonRequests;
084
085  // The number of add requests sent over the associated connection.
086  @NotNull private final AtomicLong numAddRequests;
087
088  // The number of add responses received on the associated connection.
089  @NotNull private final AtomicLong numAddResponses;
090
091  // The number of bind requests sent over the associated connection.
092  @NotNull private final AtomicLong numBindRequests;
093
094  // The number of bind responses received on the associated connection.
095  @NotNull private final AtomicLong numBindResponses;
096
097  // The number of compare requests sent over the associated connection.
098  @NotNull private final AtomicLong numCompareRequests;
099
100  // The number of compare responses received on the associated connection.
101  @NotNull private final AtomicLong numCompareResponses;
102
103  // The number of times the associated connection has been connected to a
104  // server.
105  @NotNull private final AtomicLong numConnects;
106
107  // The number of delete requests sent over the associated connection.
108  @NotNull private final AtomicLong numDeleteRequests;
109
110  // The number of delete responses received on the associated connection.
111  @NotNull private final AtomicLong numDeleteResponses;
112
113  // The number of times the associated connection has been disconnected from a
114  // server.
115  @NotNull private final AtomicLong numDisconnects;
116
117  // The number of extended requests sent over the associated connection.
118  @NotNull private final AtomicLong numExtendedRequests;
119
120  // The number of extended responses received on the associated connection.
121  @NotNull private final AtomicLong numExtendedResponses;
122
123  // The number of modify requests sent over the associated connection.
124  @NotNull private final AtomicLong numModifyRequests;
125
126  // The number of modify responses received on the associated connection.
127  @NotNull private final AtomicLong numModifyResponses;
128
129  // The number of modify DN requests sent over the associated connection.
130  @NotNull private final AtomicLong numModifyDNRequests;
131
132  // The number of modify DN responses received on the associated connection.
133  @NotNull private final AtomicLong numModifyDNResponses;
134
135  // The number of search requests sent over the associated connection.
136  @NotNull private final AtomicLong numSearchRequests;
137
138  // The number of search result entry responses received on the associated
139  // connection.
140  @NotNull private final AtomicLong numSearchEntryResponses;
141
142  // The number of search result reference responses received on the associated
143  // connection.
144  @NotNull private final AtomicLong numSearchReferenceResponses;
145
146  // The number of search result done responses received on the associated
147  // connection.
148  @NotNull private final AtomicLong numSearchDoneResponses;
149
150  // The number of unbind requests sent over the associated connection.
151  @NotNull private final AtomicLong numUnbindRequests;
152
153  // The total length of time spent waiting for add responses.
154  @NotNull private final AtomicLong totalAddResponseTime;
155
156  // The total length of time spent waiting for bind responses.
157  @NotNull private final AtomicLong totalBindResponseTime;
158
159  // The total length of time spent waiting for compare responses.
160  @NotNull private final AtomicLong totalCompareResponseTime;
161
162  // The total length of time spent waiting for delete responses.
163  @NotNull private final AtomicLong totalDeleteResponseTime;
164
165  // The total length of time spent waiting for extended responses.
166  @NotNull private final AtomicLong totalExtendedResponseTime;
167
168  // The total length of time spent waiting for modify responses.
169  @NotNull private final AtomicLong totalModifyResponseTime;
170
171  // The total length of time spent waiting for modify DN responses.
172  @NotNull private final AtomicLong totalModifyDNResponseTime;
173
174  // The total length of time spent waiting for search done responses.
175  @NotNull private final AtomicLong totalSearchResponseTime;
176
177
178
179  /**
180   * Creates a new instance of this LDAP connection statistics object.  All of
181   * the counts will be initialized to zero.
182   */
183  public LDAPConnectionStatistics()
184  {
185    numAbandonRequests          = new AtomicLong(0L);
186    numAddRequests              = new AtomicLong(0L);
187    numAddResponses             = new AtomicLong(0L);
188    numBindRequests             = new AtomicLong(0L);
189    numBindResponses            = new AtomicLong(0L);
190    numCompareRequests          = new AtomicLong(0L);
191    numCompareResponses         = new AtomicLong(0L);
192    numConnects                 = new AtomicLong(0L);
193    numDeleteRequests           = new AtomicLong(0L);
194    numDeleteResponses          = new AtomicLong(0L);
195    numDisconnects              = new AtomicLong(0L);
196    numExtendedRequests         = new AtomicLong(0L);
197    numExtendedResponses        = new AtomicLong(0L);
198    numModifyRequests           = new AtomicLong(0L);
199    numModifyResponses          = new AtomicLong(0L);
200    numModifyDNRequests         = new AtomicLong(0L);
201    numModifyDNResponses        = new AtomicLong(0L);
202    numSearchRequests           = new AtomicLong(0L);
203    numSearchEntryResponses     = new AtomicLong(0L);
204    numSearchReferenceResponses = new AtomicLong(0L);
205    numSearchDoneResponses      = new AtomicLong(0L);
206    numUnbindRequests           = new AtomicLong(0L);
207    totalAddResponseTime        = new AtomicLong(0L);
208    totalBindResponseTime       = new AtomicLong(0L);
209    totalCompareResponseTime    = new AtomicLong(0L);
210    totalDeleteResponseTime     = new AtomicLong(0L);
211    totalExtendedResponseTime   = new AtomicLong(0L);
212    totalModifyResponseTime     = new AtomicLong(0L);
213    totalModifyDNResponseTime   = new AtomicLong(0L);
214    totalSearchResponseTime     = new AtomicLong(0L);
215  }
216
217
218
219  /**
220   * Resets all counters back to zero.
221   */
222  public void reset()
223  {
224    numAbandonRequests.set(0L);
225    numAddRequests.set(0L);
226    numAddResponses.set(0L);
227    numBindRequests.set(0L);
228    numBindResponses.set(0L);
229    numCompareRequests.set(0L);
230    numCompareResponses.set(0L);
231    numConnects.set(0L);
232    numDeleteRequests.set(0L);
233    numDeleteResponses.set(0L);
234    numDisconnects.set(0L);
235    numExtendedRequests.set(0L);
236    numExtendedResponses.set(0L);
237    numModifyRequests.set(0L);
238    numModifyResponses.set(0L);
239    numModifyDNRequests.set(0L);
240    numModifyDNResponses.set(0L);
241    numSearchRequests.set(0L);
242    numSearchEntryResponses.set(0L);
243    numSearchReferenceResponses.set(0L);
244    numSearchDoneResponses.set(0L);
245    numUnbindRequests.set(0L);
246    totalAddResponseTime.set(0L);
247    totalBindResponseTime.set(0L);
248    totalCompareResponseTime.set(0L);
249    totalDeleteResponseTime.set(0L);
250    totalExtendedResponseTime.set(0L);
251    totalModifyResponseTime.set(0L);
252    totalModifyDNResponseTime.set(0L);
253    totalSearchResponseTime.set(0L);
254  }
255
256
257
258  /**
259   * Retrieves the number of times an attempt has been made to establish the
260   * associated connection.
261   *
262   * @return  The number of times an attempt has been made to establish the
263   *          associated connection.
264   */
265  public long getNumConnects()
266  {
267    return numConnects.get();
268  }
269
270
271
272  /**
273   * Increments the number of times an attempt has been made to establish the
274   * associated connection.
275   */
276  void incrementNumConnects()
277  {
278    numConnects.incrementAndGet();
279  }
280
281
282
283  /**
284   * Retrieves the number of times the associated connection has been
285   * terminated.  Note that this may exceed the number of connection attempts
286   * because there may be cases in which an attempt is made to close a
287   * connection after it has already been closed or otherwise disconnected.
288   *
289   * @return  The number of times the associated connection has been terminated.
290   */
291  public long getNumDisconnects()
292  {
293    return numDisconnects.get();
294  }
295
296
297
298  /**
299   * Increments the number of times an attempt has been made to terminate the
300   * associated connection.
301   */
302  void incrementNumDisconnects()
303  {
304    numDisconnects.incrementAndGet();
305  }
306
307
308
309  /**
310   * Retrieves the number of abandon requests sent on the associated connection.
311   *
312   * @return  The number of abandon requests sent on the associated connection.
313   */
314  public long getNumAbandonRequests()
315  {
316    return numAbandonRequests.get();
317  }
318
319
320
321  /**
322   * Increments the number of abandon requests sent on the associated
323   * connection.
324   */
325  void incrementNumAbandonRequests()
326  {
327    numAbandonRequests.incrementAndGet();
328  }
329
330
331
332  /**
333   * Retrieves the number of add requests sent on the associated connection.
334   *
335   * @return  The number of add requests sent on the associated connection.
336   */
337  public long getNumAddRequests()
338  {
339    return numAddRequests.get();
340  }
341
342
343
344  /**
345   * Increments the number of add requests sent on the associated connection.
346   */
347  void incrementNumAddRequests()
348  {
349    numAddRequests.incrementAndGet();
350  }
351
352
353
354  /**
355   * Retrieves the number of add responses sent on the associated connection.
356   *
357   * @return  The number of add responses sent on the associated connection.
358   */
359  public long getNumAddResponses()
360  {
361    return numAddResponses.get();
362  }
363
364
365
366  /**
367   * Increments the number of add responses sent on the associated connection.
368   *
369   * @param  responseTime  The length of time in nanoseconds between sending
370   *                       the request and receiving the response.
371   */
372  void incrementNumAddResponses(final long responseTime)
373  {
374    numAddResponses.incrementAndGet();
375
376    if (responseTime > 0)
377    {
378      totalAddResponseTime.addAndGet(responseTime);
379    }
380  }
381
382
383
384  /**
385   * Retrieves the total response time in nanoseconds for all add operations
386   * processed on the associated connection.
387   *
388   * @return  The total response time in nanoseconds for all add operations
389   *          processed on the associated connection.
390   */
391  public long getTotalAddResponseTimeNanos()
392  {
393    return totalAddResponseTime.get();
394  }
395
396
397
398  /**
399   * Retrieves the total response time in milliseconds for all add operations
400   * processed on the associated connection.
401   *
402   * @return  The total response time in milliseconds for all add operations
403   *          processed on the associated connection.
404   */
405  public long getTotalAddResponseTimeMillis()
406  {
407    return Math.round(totalAddResponseTime.get() / 1_000_000.0d);
408  }
409
410
411
412  /**
413   * Retrieves the average response time in nanoseconds for all add operations
414   * processed on the associated connection.
415   *
416   * @return  The average response time in nanoseconds for all add operations
417   *          processed on the associated connection, or {@code Double.NaN} if
418   *          no add operations have yet been performed.
419   */
420  public double getAverageAddResponseTimeNanos()
421  {
422    final long totalTime  = totalAddResponseTime.get();
423    final long totalCount = numAddResponses.get();
424
425    if (totalTime > 0)
426    {
427      return (1.0d * totalTime / totalCount);
428    }
429    else
430    {
431      return Double.NaN;
432    }
433  }
434
435
436
437  /**
438   * Retrieves the average response time in milliseconds for all add operations
439   * processed on the associated connection.
440   *
441   * @return  The average response time in milliseconds for all add operations
442   *          processed on the associated connection, or {@code Double.NaN} if
443   *          no add operations have yet been performed.
444   */
445  public double getAverageAddResponseTimeMillis()
446  {
447    final long totalTime  = totalAddResponseTime.get();
448    final long totalCount = numAddResponses.get();
449
450    if (totalTime > 0)
451    {
452      return (totalTime / 1_000_000.0d / totalCount);
453    }
454    else
455    {
456      return Double.NaN;
457    }
458  }
459
460
461
462  /**
463   * Retrieves the number of bind requests sent on the associated connection.
464   *
465   * @return  The number of bind requests sent on the associated connection.
466   */
467  public long getNumBindRequests()
468  {
469    return numBindRequests.get();
470  }
471
472
473
474  /**
475   * Increments the number of bind requests sent on the associated connection.
476   */
477  void incrementNumBindRequests()
478  {
479    numBindRequests.incrementAndGet();
480  }
481
482
483
484  /**
485   * Retrieves the number of bind responses sent on the associated connection.
486   *
487   * @return  The number of bind responses sent on the associated connection.
488   */
489  public long getNumBindResponses()
490  {
491    return numBindResponses.get();
492  }
493
494
495
496  /**
497   * Increments the number of bind responses sent on the associated connection.
498   *
499   * @param  responseTime  The length of time in nanoseconds between sending
500   *                       the request and receiving the response.
501   */
502  void incrementNumBindResponses(final long responseTime)
503  {
504    numBindResponses.incrementAndGet();
505
506    if (responseTime > 0)
507    {
508      totalBindResponseTime.addAndGet(responseTime);
509    }
510  }
511
512
513
514  /**
515   * Retrieves the total response time in nanoseconds for all bind operations
516   * processed on the associated connection.
517   *
518   * @return  The total response time in nanoseconds for all bind operations
519   *          processed on the associated connection.
520   */
521  public long getTotalBindResponseTimeNanos()
522  {
523    return totalBindResponseTime.get();
524  }
525
526
527
528  /**
529   * Retrieves the total response time in milliseconds for all bind operations
530   * processed on the associated connection.
531   *
532   * @return  The total response time in milliseconds for all bind operations
533   *          processed on the associated connection.
534   */
535  public long getTotalBindResponseTimeMillis()
536  {
537    return Math.round(totalBindResponseTime.get() / 1_000_000.0d);
538  }
539
540
541
542  /**
543   * Retrieves the average response time in nanoseconds for all bind operations
544   * processed on the associated connection.
545   *
546   * @return  The average response time in nanoseconds for all bind operations
547   *          processed on the associated connection, or {@code Double.NaN} if
548   *          no bind operations have yet been performed.
549   */
550  public double getAverageBindResponseTimeNanos()
551  {
552    final long totalTime  = totalBindResponseTime.get();
553    final long totalCount = numBindResponses.get();
554
555    if (totalTime > 0)
556    {
557      return (1.0d * totalTime / totalCount);
558    }
559    else
560    {
561      return Double.NaN;
562    }
563  }
564
565
566
567  /**
568   * Retrieves the average response time in milliseconds for all bind operations
569   * processed on the associated connection.
570   *
571   * @return  The average response time in milliseconds for all bind operations
572   *          processed on the associated connection, or {@code Double.NaN} if
573   *          no bind operations have yet been performed.
574   */
575  public double getAverageBindResponseTimeMillis()
576  {
577    final long totalTime  = totalBindResponseTime.get();
578    final long totalCount = numBindResponses.get();
579
580    if (totalTime > 0)
581    {
582      return (totalTime / 1_000_000.0d / totalCount);
583    }
584    else
585    {
586      return Double.NaN;
587    }
588  }
589
590
591
592  /**
593   * Retrieves the number of compare requests sent on the associated connection.
594   *
595   * @return  The number of compare requests sent on the associated connection.
596   */
597  public long getNumCompareRequests()
598  {
599    return numCompareRequests.get();
600  }
601
602
603
604  /**
605   * Increments the number of compare requests sent on the associated
606   * connection.
607   */
608  void incrementNumCompareRequests()
609  {
610    numCompareRequests.incrementAndGet();
611  }
612
613
614
615  /**
616   * Retrieves the number of compare responses sent on the associated
617   * connection.
618   *
619   * @return  The number of compare responses sent on the associated connection.
620   */
621  public long getNumCompareResponses()
622  {
623    return numCompareResponses.get();
624  }
625
626
627
628  /**
629   * Increments the number of compare responses sent on the associated
630   * connection.
631   *
632   * @param  responseTime  The length of time in nanoseconds between sending
633   *                       the request and receiving the response.
634   */
635  void incrementNumCompareResponses(final long responseTime)
636  {
637    numCompareResponses.incrementAndGet();
638
639    if (responseTime > 0)
640    {
641      totalCompareResponseTime.addAndGet(responseTime);
642    }
643  }
644
645
646
647  /**
648   * Retrieves the total response time in nanoseconds for all compare
649   * operations processed on the associated connection.
650   *
651   * @return  The total response time in nanoseconds for all compare operations
652   *          processed on the associated connection.
653   */
654  public long getTotalCompareResponseTimeNanos()
655  {
656    return totalCompareResponseTime.get();
657  }
658
659
660
661  /**
662   * Retrieves the total response time in milliseconds for all compare
663   * operations processed on the associated connection.
664   *
665   * @return  The total response time in milliseconds for all compare operations
666   *          processed on the associated connection.
667   */
668  public long getTotalCompareResponseTimeMillis()
669  {
670    return Math.round(totalCompareResponseTime.get() / 1_000_000.0d);
671  }
672
673
674
675  /**
676   * Retrieves the average response time in nanoseconds for all compare
677   * operations processed on the associated connection.
678   *
679   * @return  The average response time in nanoseconds for all compare
680   *          operations processed on the associated connection, or
681   *          {@code Double.NaN} if no compare operations have yet been
682   *          performed.
683   */
684  public double getAverageCompareResponseTimeNanos()
685  {
686    final long totalTime  = totalCompareResponseTime.get();
687    final long totalCount = numCompareResponses.get();
688
689    if (totalTime > 0)
690    {
691      return (1.0d * totalTime / totalCount);
692    }
693    else
694    {
695      return Double.NaN;
696    }
697  }
698
699
700
701  /**
702   * Retrieves the average response time in milliseconds for all compare
703   * operations processed on the associated connection.
704   *
705   * @return  The average response time in milliseconds for all compare
706   *          operations processed on the associated connection, or
707   *          {@code Double.NaN} if no compare operations have yet been
708   *          performed.
709   */
710  public double getAverageCompareResponseTimeMillis()
711  {
712    final long totalTime  = totalCompareResponseTime.get();
713    final long totalCount = numCompareResponses.get();
714
715    if (totalTime > 0)
716    {
717      return (totalTime / 1_000_000.0d / totalCount);
718    }
719    else
720    {
721      return Double.NaN;
722    }
723  }
724
725
726
727  /**
728   * Retrieves the number of delete requests sent on the associated connection.
729   *
730   * @return  The number of delete requests sent on the associated connection.
731   */
732  public long getNumDeleteRequests()
733  {
734    return numDeleteRequests.get();
735  }
736
737
738
739  /**
740   * Increments the number of delete requests sent on the associated connection.
741   */
742  void incrementNumDeleteRequests()
743  {
744    numDeleteRequests.incrementAndGet();
745  }
746
747
748
749  /**
750   * Retrieves the number of delete responses sent on the associated connection.
751   *
752   * @return  The number of delete responses sent on the associated connection.
753   */
754  public long getNumDeleteResponses()
755  {
756    return numDeleteResponses.get();
757  }
758
759
760
761  /**
762   * Increments the number of delete responses sent on the associated
763   * connection.
764   *
765   * @param  responseTime  The length of time in nanoseconds between sending
766   *                       the request and receiving the response.
767   */
768  void incrementNumDeleteResponses(final long responseTime)
769  {
770    numDeleteResponses.incrementAndGet();
771
772    if (responseTime > 0)
773    {
774      totalDeleteResponseTime.addAndGet(responseTime);
775    }
776  }
777
778
779
780  /**
781   * Retrieves the total response time in nanoseconds for all delete
782   * operations processed on the associated connection.
783   *
784   * @return  The total response time in nanoseconds for all delete operations
785   *          processed on the associated connection.
786   */
787  public long getTotalDeleteResponseTimeNanos()
788  {
789    return totalDeleteResponseTime.get();
790  }
791
792
793
794  /**
795   * Retrieves the total response time in milliseconds for all delete
796   * operations processed on the associated connection.
797   *
798   * @return  The total response time in milliseconds for all delete operations
799   *          processed on the associated connection.
800   */
801  public long getTotalDeleteResponseTimeMillis()
802  {
803    return Math.round(totalDeleteResponseTime.get() / 1_000_000.0d);
804  }
805
806
807
808  /**
809   * Retrieves the average response time in nanoseconds for all delete
810   * operations processed on the associated connection.
811   *
812   * @return  The average response time in nanoseconds for all delete
813   *          operations processed on the associated connection, or
814   *          {@code Double.NaN} if no delete operations have yet been
815   *          performed.
816   */
817  public double getAverageDeleteResponseTimeNanos()
818  {
819    final long totalTime  = totalDeleteResponseTime.get();
820    final long totalCount = numDeleteResponses.get();
821
822    if (totalTime > 0)
823    {
824      return (1.0d * totalTime / totalCount);
825    }
826    else
827    {
828      return Double.NaN;
829    }
830  }
831
832
833
834  /**
835   * Retrieves the average response time in milliseconds for all delete
836   * operations processed on the associated connection.
837   *
838   * @return  The average response time in milliseconds for all delete
839   *          operations processed on the associated connection, or
840   *          {@code Double.NaN} if no delete operations have yet been
841   *          performed.
842   */
843  public double getAverageDeleteResponseTimeMillis()
844  {
845    final long totalTime  = totalDeleteResponseTime.get();
846    final long totalCount = numDeleteResponses.get();
847
848    if (totalTime > 0)
849    {
850      return (totalTime / 1_000_000.0d / totalCount);
851    }
852    else
853    {
854      return Double.NaN;
855    }
856  }
857
858
859
860  /**
861   * Retrieves the number of extended requests sent on the associated
862   * connection.
863   *
864   * @return  The number of extended requests sent on the associated connection.
865   */
866  public long getNumExtendedRequests()
867  {
868    return numExtendedRequests.get();
869  }
870
871
872
873  /**
874   * Increments the number of extended requests sent on the associated
875   * connection.
876   */
877  void incrementNumExtendedRequests()
878  {
879    numExtendedRequests.incrementAndGet();
880  }
881
882
883
884  /**
885   * Retrieves the number of extended responses sent on the associated
886   * connection.
887   *
888   * @return  The number of extended responses sent on the associated
889   *          connection.
890   */
891  public long getNumExtendedResponses()
892  {
893    return numExtendedResponses.get();
894  }
895
896
897
898  /**
899   * Increments the number of extended responses sent on the associated
900   * connection.
901   *
902   * @param  responseTime  The length of time in nanoseconds between sending
903   *                       the request and receiving the response.
904   */
905  void incrementNumExtendedResponses(final long responseTime)
906  {
907    numExtendedResponses.incrementAndGet();
908
909    if (responseTime > 0)
910    {
911      totalExtendedResponseTime.addAndGet(responseTime);
912    }
913  }
914
915
916
917  /**
918   * Retrieves the total response time in nanoseconds for all extended
919   * operations processed on the associated connection.
920   *
921   * @return  The total response time in nanoseconds for all extended
922   *          operations processed on the associated connection.
923   */
924  public long getTotalExtendedResponseTimeNanos()
925  {
926    return totalExtendedResponseTime.get();
927  }
928
929
930
931  /**
932   * Retrieves the total response time in milliseconds for all extended
933   * operations processed on the associated connection.
934   *
935   * @return  The total response time in milliseconds for all extended
936   *          operations processed on the associated connection.
937   */
938  public long getTotalExtendedResponseTimeMillis()
939  {
940    return Math.round(totalExtendedResponseTime.get() / 1_000_000.0d);
941  }
942
943
944
945  /**
946   * Retrieves the average response time in nanoseconds for all extended
947   * operations processed on the associated connection.
948   *
949   * @return  The average response time in nanoseconds for all extended
950   *          operations processed on the associated connection, or
951   *          {@code Double.NaN} if no extended operations have yet been
952   *          performed.
953   */
954  public double getAverageExtendedResponseTimeNanos()
955  {
956    final long totalTime  = totalExtendedResponseTime.get();
957    final long totalCount = numExtendedResponses.get();
958
959    if (totalTime > 0)
960    {
961      return (1.0d * totalTime / totalCount);
962    }
963    else
964    {
965      return Double.NaN;
966    }
967  }
968
969
970
971  /**
972   * Retrieves the average response time in milliseconds for all extended
973   * operations processed on the associated connection.
974   *
975   * @return  The average response time in milliseconds for all extended
976   *          operations processed on the associated connection, or
977   *          {@code Double.NaN} if no extended operations have yet been
978   *          performed.
979   */
980  public double getAverageExtendedResponseTimeMillis()
981  {
982    final long totalTime  = totalExtendedResponseTime.get();
983    final long totalCount = numExtendedResponses.get();
984
985    if (totalTime > 0)
986    {
987      return (totalTime / 1_000_000.0d / totalCount);
988    }
989    else
990    {
991      return Double.NaN;
992    }
993  }
994
995
996
997  /**
998   * Retrieves the number of modify requests sent on the associated connection.
999   *
1000   * @return  The number of modify requests sent on the associated connection.
1001   */
1002  public long getNumModifyRequests()
1003  {
1004    return numModifyRequests.get();
1005  }
1006
1007
1008
1009  /**
1010   * Increments the number of modify requests sent on the associated connection.
1011   */
1012  void incrementNumModifyRequests()
1013  {
1014    numModifyRequests.incrementAndGet();
1015  }
1016
1017
1018
1019  /**
1020   * Retrieves the number of modify responses sent on the associated connection.
1021   *
1022   * @return  The number of modify responses sent on the associated connection.
1023   */
1024  public long getNumModifyResponses()
1025  {
1026    return numModifyResponses.get();
1027  }
1028
1029
1030
1031  /**
1032   * Increments the number of modify responses sent on the associated
1033   * connection.
1034   *
1035   * @param  responseTime  The length of time in nanoseconds between sending
1036   *                       the request and receiving the response.
1037   */
1038  void incrementNumModifyResponses(final long responseTime)
1039  {
1040    numModifyResponses.incrementAndGet();
1041
1042    if (responseTime > 0)
1043    {
1044      totalModifyResponseTime.addAndGet(responseTime);
1045    }
1046  }
1047
1048
1049
1050  /**
1051   * Retrieves the total response time in nanoseconds for all modify
1052   * operations processed on the associated connection.
1053   *
1054   * @return  The total response time in nanoseconds for all modify operations
1055   *          processed on the associated connection.
1056   */
1057  public long getTotalModifyResponseTimeNanos()
1058  {
1059    return totalModifyResponseTime.get();
1060  }
1061
1062
1063
1064  /**
1065   * Retrieves the total response time in milliseconds for all modify
1066   * operations processed on the associated connection.
1067   *
1068   * @return  The total response time in milliseconds for all modify operations
1069   *          processed on the associated connection.
1070   */
1071  public long getTotalModifyResponseTimeMillis()
1072  {
1073    return Math.round(totalModifyResponseTime.get() / 1_000_000.0d);
1074  }
1075
1076
1077
1078  /**
1079   * Retrieves the average response time in nanoseconds for all modify
1080   * operations processed on the associated connection.
1081   *
1082   * @return  The average response time in nanoseconds for all modify
1083   *          operations processed on the associated connection, or
1084   *          {@code Double.NaN} if no modify operations have yet been
1085   *          performed.
1086   */
1087  public double getAverageModifyResponseTimeNanos()
1088  {
1089    final long totalTime  = totalModifyResponseTime.get();
1090    final long totalCount = numModifyResponses.get();
1091
1092    if (totalTime > 0)
1093    {
1094      return (1.0d * totalTime / totalCount);
1095    }
1096    else
1097    {
1098      return Double.NaN;
1099    }
1100  }
1101
1102
1103
1104  /**
1105   * Retrieves the average response time in milliseconds for all modify
1106   * operations processed on the associated connection.
1107   *
1108   * @return  The average response time in milliseconds for all modify
1109   *          operations processed on the associated connection, or
1110   *          {@code Double.NaN} if no modify operations have yet been
1111   *          performed.
1112   */
1113  public double getAverageModifyResponseTimeMillis()
1114  {
1115    final long totalTime  = totalModifyResponseTime.get();
1116    final long totalCount = numModifyResponses.get();
1117
1118    if (totalTime > 0)
1119    {
1120      return (totalTime / 1_000_000.0d / totalCount);
1121    }
1122    else
1123    {
1124      return Double.NaN;
1125    }
1126  }
1127
1128
1129
1130  /**
1131   * Retrieves the number of modify DN requests sent on the associated
1132   * connection.
1133   *
1134   * @return  The number of modify DN requests sent on the associated
1135   *          connection.
1136   */
1137  public long getNumModifyDNRequests()
1138  {
1139    return numModifyDNRequests.get();
1140  }
1141
1142
1143
1144  /**
1145   * Increments the number of modify DN requests sent on the associated
1146   * connection.
1147   */
1148  void incrementNumModifyDNRequests()
1149  {
1150    numModifyDNRequests.incrementAndGet();
1151  }
1152
1153
1154
1155  /**
1156   * Retrieves the number of modify DN responses sent on the associated
1157   * connection.
1158   *
1159   * @return  The number of modify DN responses sent on the associated
1160   *          connection.
1161   */
1162  public long getNumModifyDNResponses()
1163  {
1164    return numModifyDNResponses.get();
1165  }
1166
1167
1168
1169  /**
1170   * Increments the number of modify DN responses sent on the associated
1171   * connection.
1172   *
1173   * @param  responseTime  The length of time in nanoseconds between sending
1174   *                       the request and receiving the response.
1175   */
1176  void incrementNumModifyDNResponses(final long responseTime)
1177  {
1178    numModifyDNResponses.incrementAndGet();
1179
1180    if (responseTime > 0)
1181    {
1182      totalModifyDNResponseTime.addAndGet(responseTime);
1183    }
1184  }
1185
1186
1187
1188  /**
1189   * Retrieves the total response time in nanoseconds for all modify DN
1190   * operations processed on the associated connection.
1191   *
1192   * @return  The total response time in nanoseconds for all modify DN
1193   *          operations processed on the associated connection.
1194   */
1195  public long getTotalModifyDNResponseTimeNanos()
1196  {
1197    return totalModifyDNResponseTime.get();
1198  }
1199
1200
1201
1202  /**
1203   * Retrieves the total response time in milliseconds for all modify DN
1204   * operations processed on the associated connection.
1205   *
1206   * @return  The total response time in milliseconds for all modify DN
1207   *          operations processed on the associated connection.
1208   */
1209  public long getTotalModifyDNResponseTimeMillis()
1210  {
1211    return Math.round(totalModifyDNResponseTime.get() / 1_000_000.0d);
1212  }
1213
1214
1215
1216  /**
1217   * Retrieves the average response time in nanoseconds for all modify DN
1218   * operations processed on the associated connection.
1219   *
1220   * @return  The average response time in nanoseconds for all modify DN
1221   *          operations processed on the associated connection, or
1222   *          {@code Double.NaN} if no modify DN operations have yet been
1223   *          performed.
1224   */
1225  public double getAverageModifyDNResponseTimeNanos()
1226  {
1227    final long totalTime  = totalModifyDNResponseTime.get();
1228    final long totalCount = numModifyDNResponses.get();
1229
1230    if (totalTime > 0)
1231    {
1232      return (1.0d * totalTime / totalCount);
1233    }
1234    else
1235    {
1236      return Double.NaN;
1237    }
1238  }
1239
1240
1241
1242  /**
1243   * Retrieves the average response time in milliseconds for all modify DN
1244   * operations processed on the associated connection.
1245   *
1246   * @return  The average response time in milliseconds for all modify DN
1247   *          operations processed on the associated connection, or
1248   *          {@code Double.NaN} if no modify DN operations have yet been
1249   *          performed.
1250   */
1251  public double getAverageModifyDNResponseTimeMillis()
1252  {
1253    final long totalTime  = totalModifyDNResponseTime.get();
1254    final long totalCount = numModifyDNResponses.get();
1255
1256    if (totalTime > 0)
1257    {
1258      return (totalTime / 1_000_000.0d / totalCount);
1259    }
1260    else
1261    {
1262      return Double.NaN;
1263    }
1264  }
1265
1266
1267
1268  /**
1269   * Retrieves the number of search requests sent on the associated connection.
1270   *
1271   * @return  The number of search requests sent on the associated connection.
1272   */
1273  public long getNumSearchRequests()
1274  {
1275    return numSearchRequests.get();
1276  }
1277
1278
1279
1280  /**
1281   * Increments the number of search requests sent on the associated
1282   * connection.
1283   */
1284  void incrementNumSearchRequests()
1285  {
1286    numSearchRequests.incrementAndGet();
1287  }
1288
1289
1290
1291  /**
1292   * Retrieves the number of search result entry responses received on the
1293   * associated connection.
1294   *
1295   * @return  The number of search result entry responses received on the
1296   *          associated connection.
1297   */
1298  public long getNumSearchEntryResponses()
1299  {
1300    return numSearchEntryResponses.get();
1301  }
1302
1303
1304
1305  /**
1306   * Retrieves the number of search result reference responses received on the
1307   * associated connection.
1308   *
1309   * @return  The number of search result reference responses received on the
1310   *          associated connection.
1311   */
1312  public long getNumSearchReferenceResponses()
1313  {
1314    return numSearchReferenceResponses.get();
1315  }
1316
1317
1318
1319  /**
1320   * Retrieves the number of search result done responses received on the
1321   * associated connection.
1322   *
1323   * @return  The number of search result done responses received on the
1324   *          associated connection.
1325   */
1326  public long getNumSearchDoneResponses()
1327  {
1328    return numSearchDoneResponses.get();
1329  }
1330
1331
1332
1333  /**
1334   * Increments the number of search result done responses received on the
1335   * associated connection.
1336   *
1337   * @param  numEntries     The number of search result entries returned for the
1338   *                        search.
1339   * @param  numReferences  The number of search result references returned for
1340   *                        the search.
1341   * @param  responseTime   The length of time in nanoseconds between sending
1342   *                        the search request and receiving the search result
1343   *                        done response.
1344   */
1345  void incrementNumSearchResponses(final int numEntries,
1346                                   final int numReferences,
1347                                   final long responseTime)
1348  {
1349    numSearchEntryResponses.addAndGet(numEntries);
1350    numSearchReferenceResponses.addAndGet(numReferences);
1351    numSearchDoneResponses.incrementAndGet();
1352
1353    if (responseTime > 0)
1354    {
1355      totalSearchResponseTime.addAndGet(responseTime);
1356    }
1357  }
1358
1359
1360
1361  /**
1362   * Retrieves the total response time in nanoseconds for all search
1363   * operations processed on the associated connection.
1364   *
1365   * @return  The total response time in nanoseconds for all search operations
1366   *          processed on the associated connection.
1367   */
1368  public long getTotalSearchResponseTimeNanos()
1369  {
1370    return totalSearchResponseTime.get();
1371  }
1372
1373
1374
1375  /**
1376   * Retrieves the total response time in milliseconds for all search
1377   * operations processed on the associated connection.
1378   *
1379   * @return  The total response time in milliseconds for all search operations
1380   *          processed on the associated connection.
1381   */
1382  public long getTotalSearchResponseTimeMillis()
1383  {
1384    return Math.round(totalSearchResponseTime.get() / 1_000_000.0d);
1385  }
1386
1387
1388
1389  /**
1390   * Retrieves the average response time in nanoseconds for all search
1391   * operations processed on the associated connection.
1392   *
1393   * @return  The average response time in nanoseconds for all search
1394   *          operations processed on the associated connection, or
1395   *          {@code Double.NaN} if no compare operations have yet been
1396   *          performed.
1397   */
1398  public double getAverageSearchResponseTimeNanos()
1399  {
1400    final long totalTime  = totalSearchResponseTime.get();
1401    final long totalCount = numSearchDoneResponses.get();
1402
1403    if (totalTime > 0)
1404    {
1405      return (1.0d * totalTime / totalCount);
1406    }
1407    else
1408    {
1409      return Double.NaN;
1410    }
1411  }
1412
1413
1414
1415  /**
1416   * Retrieves the average response time in milliseconds for all search
1417   * operations processed on the associated connection.
1418   *
1419   * @return  The average response time in milliseconds for all search
1420   *          operations processed on the associated connection, or
1421   *          {@code Double.NaN} if no compare operations have yet been
1422   *          performed.
1423   */
1424  public double getAverageSearchResponseTimeMillis()
1425  {
1426    final long totalTime  = totalSearchResponseTime.get();
1427    final long totalCount = numSearchDoneResponses.get();
1428
1429    if (totalTime > 0)
1430    {
1431      return (totalTime / 1_000_000.0d / totalCount);
1432    }
1433    else
1434    {
1435      return Double.NaN;
1436    }
1437  }
1438
1439
1440
1441  /**
1442   * Retrieves the number of unbind requests sent on the associated connection.
1443   *
1444   * @return  The number of unbind requests sent on the associated connection.
1445   */
1446  public long getNumUnbindRequests()
1447  {
1448    return numUnbindRequests.get();
1449  }
1450
1451
1452
1453  /**
1454   * Increments the number of unbind requests sent on the associated
1455   * connection.
1456   */
1457  void incrementNumUnbindRequests()
1458  {
1459    numUnbindRequests.incrementAndGet();
1460  }
1461
1462
1463
1464  /**
1465   * Retrieves a string representation of this LDAP connection statistics
1466   * object.
1467   *
1468   * @return  A string representation of this LDAP connection statistics object.
1469   */
1470  @Override()
1471  @NotNull()
1472  public String toString()
1473  {
1474    final StringBuilder buffer = new StringBuilder();
1475    toString(buffer);
1476    return buffer.toString();
1477  }
1478
1479
1480
1481  /**
1482   * Appends a string representation of this LDAP connection statistics object
1483   * to the provided buffer.
1484   *
1485   * @param  buffer  The buffer to which the string representation should be
1486   *                 appended.
1487   */
1488  public void toString(@NotNull final StringBuilder buffer)
1489  {
1490    final long connects          = numConnects.get();
1491    final long disconnects       = numDisconnects.get();
1492    final long abandonRequests   = numAbandonRequests.get();
1493    final long addRequests       = numAddRequests.get();
1494    final long addResponses      = numAddResponses.get();
1495    final long addTimes          = totalAddResponseTime.get();
1496    final long bindRequests      = numBindRequests.get();
1497    final long bindResponses     = numBindResponses.get();
1498    final long bindTimes         = totalBindResponseTime.get();
1499    final long compareRequests   = numCompareRequests.get();
1500    final long compareResponses  = numCompareResponses.get();
1501    final long compareTimes      = totalCompareResponseTime.get();
1502    final long deleteRequests    = numDeleteRequests.get();
1503    final long deleteResponses   = numDeleteResponses.get();
1504    final long deleteTimes       = totalDeleteResponseTime.get();
1505    final long extendedRequests  = numExtendedRequests.get();
1506    final long extendedResponses = numExtendedResponses.get();
1507    final long extendedTimes     = totalExtendedResponseTime.get();
1508    final long modifyRequests    = numModifyRequests.get();
1509    final long modifyResponses   = numModifyResponses.get();
1510    final long modifyTimes       = totalModifyResponseTime.get();
1511    final long modifyDNRequests  = numModifyDNRequests.get();
1512    final long modifyDNResponses = numModifyDNResponses.get();
1513    final long modifyDNTimes     = totalModifyDNResponseTime.get();
1514    final long searchRequests    = numSearchRequests.get();
1515    final long searchEntries     = numSearchEntryResponses.get();
1516    final long searchReferences  = numSearchReferenceResponses.get();
1517    final long searchDone        = numSearchDoneResponses.get();
1518    final long searchTimes       = totalSearchResponseTime.get();
1519    final long unbindRequests    = numUnbindRequests.get();
1520
1521    final DecimalFormat f = new DecimalFormat("0.000");
1522
1523    buffer.append("LDAPConnectionStatistics(numConnects=");
1524    buffer.append(connects);
1525    buffer.append(", numDisconnects=");
1526    buffer.append(disconnects);
1527
1528    buffer.append(", numAbandonRequests=");
1529    buffer.append(abandonRequests);
1530
1531    buffer.append(", numAddRequests=");
1532    buffer.append(addRequests);
1533    buffer.append(", numAddResponses=");
1534    buffer.append(addResponses);
1535    buffer.append(", totalAddResponseTimeNanos=");
1536    buffer.append(addTimes);
1537    if (addTimes > 0L)
1538    {
1539      buffer.append(", averageAddResponseTimeNanos=");
1540      buffer.append(f.format(1.0d * addResponses / addTimes));
1541    }
1542
1543    buffer.append(", numBindRequests=");
1544    buffer.append(bindRequests);
1545    buffer.append(", numBindResponses=");
1546    buffer.append(bindResponses);
1547    buffer.append(", totalBindResponseTimeNanos=");
1548    buffer.append(bindTimes);
1549    if (bindTimes > 0L)
1550    {
1551      buffer.append(", averageBindResponseTimeNanos=");
1552      buffer.append(f.format(1.0d * bindResponses / bindTimes));
1553    }
1554
1555    buffer.append(", numCompareRequests=");
1556    buffer.append(compareRequests);
1557    buffer.append(", numCompareResponses=");
1558    buffer.append(compareResponses);
1559    buffer.append(", totalCompareResponseTimeNanos=");
1560    buffer.append(compareTimes);
1561    if (compareTimes > 0L)
1562    {
1563      buffer.append(", averageCompareResponseTimeNanos=");
1564      buffer.append(f.format(1.0d * compareResponses / compareTimes));
1565    }
1566
1567    buffer.append(", numDeleteRequests=");
1568    buffer.append(deleteRequests);
1569    buffer.append(", numDeleteResponses=");
1570    buffer.append(deleteResponses);
1571    buffer.append(", totalDeleteResponseTimeNanos=");
1572    buffer.append(deleteTimes);
1573    if (deleteTimes > 0L)
1574    {
1575      buffer.append(", averageDeleteResponseTimeNanos=");
1576      buffer.append(f.format(1.0d * deleteResponses / deleteTimes));
1577    }
1578
1579    buffer.append(", numExtendedRequests=");
1580    buffer.append(extendedRequests);
1581    buffer.append(", numExtendedResponses=");
1582    buffer.append(extendedResponses);
1583    buffer.append(", totalExtendedResponseTimeNanos=");
1584    buffer.append(extendedTimes);
1585    if (extendedTimes > 0L)
1586    {
1587      buffer.append(", averageExtendedResponseTimeNanos=");
1588      buffer.append(f.format(1.0d * extendedResponses / extendedTimes));
1589    }
1590
1591    buffer.append(", numModifyRequests=");
1592    buffer.append(modifyRequests);
1593    buffer.append(", numModifyResponses=");
1594    buffer.append(modifyResponses);
1595    buffer.append(", totalModifyResponseTimeNanos=");
1596    buffer.append(modifyTimes);
1597    if (modifyTimes > 0L)
1598    {
1599      buffer.append(", averageModifyResponseTimeNanos=");
1600      buffer.append(f.format(1.0d * modifyResponses / modifyTimes));
1601    }
1602
1603    buffer.append(", numModifyDNRequests=");
1604    buffer.append(modifyDNRequests);
1605    buffer.append(", numModifyDNResponses=");
1606    buffer.append(modifyDNResponses);
1607    buffer.append(", totalModifyDNResponseTimeNanos=");
1608    buffer.append(modifyDNTimes);
1609    if (modifyDNTimes > 0L)
1610    {
1611      buffer.append(", averageModifyDNResponseTimeNanos=");
1612      buffer.append(f.format(1.0d * modifyDNResponses / modifyDNTimes));
1613    }
1614
1615    buffer.append(", numSearchRequests=");
1616    buffer.append(searchRequests);
1617    buffer.append(", numSearchEntries=");
1618    buffer.append(searchEntries);
1619    buffer.append(", numSearchReferences=");
1620    buffer.append(searchReferences);
1621    buffer.append(", numSearchDone=");
1622    buffer.append(searchDone);
1623    buffer.append(", totalSearchResponseTimeNanos=");
1624    buffer.append(searchTimes);
1625    if (searchTimes > 0L)
1626    {
1627      buffer.append(", averageSearchResponseTimeNanos=");
1628      buffer.append(f.format(1.0d * searchDone / searchTimes));
1629    }
1630
1631    buffer.append(", numUnbindRequests=");
1632    buffer.append(unbindRequests);
1633
1634    buffer.append(')');
1635  }
1636}