1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 2002, 2014 Oracle and/or its affiliates.  All rights reserved.
5  *
6  */
7 
8 package com.sleepycat.je.rep;
9 
10 import static com.sleepycat.je.rep.impl.node.FeederManagerStatDefinition.N_FEEDERS_CREATED;
11 import static com.sleepycat.je.rep.impl.node.FeederManagerStatDefinition.N_FEEDERS_SHUTDOWN;
12 import static com.sleepycat.je.rep.impl.node.FeederManagerStatDefinition.N_MAX_REPLICA_LAG;
13 import static com.sleepycat.je.rep.impl.node.FeederManagerStatDefinition.N_MAX_REPLICA_LAG_NAME;
14 import static com.sleepycat.je.rep.impl.node.ReplayStatDefinition.LATEST_COMMIT_LAG_MS;
15 import static com.sleepycat.je.rep.impl.node.ReplayStatDefinition.MAX_COMMIT_PROCESSING_NANOS;
16 import static com.sleepycat.je.rep.impl.node.ReplayStatDefinition.MIN_COMMIT_PROCESSING_NANOS;
17 import static com.sleepycat.je.rep.impl.node.ReplayStatDefinition.N_ABORTS;
18 import static com.sleepycat.je.rep.impl.node.ReplayStatDefinition.N_COMMITS;
19 import static com.sleepycat.je.rep.impl.node.ReplayStatDefinition.N_COMMIT_ACKS;
20 import static com.sleepycat.je.rep.impl.node.ReplayStatDefinition.N_COMMIT_NO_SYNCS;
21 import static com.sleepycat.je.rep.impl.node.ReplayStatDefinition.N_COMMIT_SYNCS;
22 import static com.sleepycat.je.rep.impl.node.ReplayStatDefinition.N_COMMIT_WRITE_NO_SYNCS;
23 import static com.sleepycat.je.rep.impl.node.ReplayStatDefinition.N_ELAPSED_TXN_TIME;
24 import static com.sleepycat.je.rep.impl.node.ReplayStatDefinition.N_GROUP_COMMITS;
25 import static com.sleepycat.je.rep.impl.node.ReplayStatDefinition.N_GROUP_COMMIT_MAX_EXCEEDED;
26 import static com.sleepycat.je.rep.impl.node.ReplayStatDefinition.N_GROUP_COMMIT_TIMEOUTS;
27 import static com.sleepycat.je.rep.impl.node.ReplayStatDefinition.N_GROUP_COMMIT_TXNS;
28 import static com.sleepycat.je.rep.impl.node.ReplayStatDefinition.N_LNS;
29 import static com.sleepycat.je.rep.impl.node.ReplayStatDefinition.N_NAME_LNS;
30 import static com.sleepycat.je.rep.impl.node.ReplayStatDefinition.TOTAL_COMMIT_LAG_MS;
31 import static com.sleepycat.je.rep.impl.node.ReplayStatDefinition.TOTAL_COMMIT_PROCESSING_NANOS;
32 import static com.sleepycat.je.rep.impl.node.ReplicaStatDefinition.N_LAG_CONSISTENCY_WAITS;
33 import static com.sleepycat.je.rep.impl.node.ReplicaStatDefinition.N_LAG_CONSISTENCY_WAIT_MS;
34 import static com.sleepycat.je.rep.impl.node.ReplicaStatDefinition.N_VLSN_CONSISTENCY_WAITS;
35 import static com.sleepycat.je.rep.impl.node.ReplicaStatDefinition.N_VLSN_CONSISTENCY_WAIT_MS;
36 import static com.sleepycat.je.rep.stream.FeederTxnStatDefinition.ACK_WAIT_MS;
37 import static com.sleepycat.je.rep.stream.FeederTxnStatDefinition.TOTAL_TXN_MS;
38 import static com.sleepycat.je.rep.stream.FeederTxnStatDefinition.TXNS_ACKED;
39 import static com.sleepycat.je.rep.stream.FeederTxnStatDefinition.TXNS_NOT_ACKED;
40 import static com.sleepycat.je.rep.utilint.BinaryProtocolStatDefinition.BYTES_READ_RATE;
41 import static com.sleepycat.je.rep.utilint.BinaryProtocolStatDefinition.BYTES_WRITE_RATE;
42 import static com.sleepycat.je.rep.utilint.BinaryProtocolStatDefinition.MESSAGE_READ_RATE;
43 import static com.sleepycat.je.rep.utilint.BinaryProtocolStatDefinition.MESSAGE_WRITE_RATE;
44 import static com.sleepycat.je.rep.utilint.BinaryProtocolStatDefinition.N_BYTES_READ;
45 import static com.sleepycat.je.rep.utilint.BinaryProtocolStatDefinition.N_BYTES_WRITTEN;
46 import static com.sleepycat.je.rep.utilint.BinaryProtocolStatDefinition.N_ENTRIES_WRITTEN_OLD_VERSION;
47 import static com.sleepycat.je.rep.utilint.BinaryProtocolStatDefinition.N_MESSAGES_BATCHED;
48 import static com.sleepycat.je.rep.utilint.BinaryProtocolStatDefinition.N_MESSAGES_READ;
49 import static com.sleepycat.je.rep.utilint.BinaryProtocolStatDefinition.N_MESSAGES_WRITTEN;
50 import static com.sleepycat.je.rep.utilint.BinaryProtocolStatDefinition.N_MESSAGE_BATCHES;
51 import static com.sleepycat.je.rep.utilint.BinaryProtocolStatDefinition.N_READ_NANOS;
52 import static com.sleepycat.je.rep.utilint.BinaryProtocolStatDefinition.N_WRITE_NANOS;
53 
54 import java.io.Serializable;
55 import java.util.Arrays;
56 import java.util.Collection;
57 import java.util.HashMap;
58 import java.util.Map;
59 
60 import com.sleepycat.je.Durability.ReplicaAckPolicy;
61 import com.sleepycat.je.Environment;
62 import com.sleepycat.je.EnvironmentFailureException;
63 import com.sleepycat.je.StatsConfig;
64 import com.sleepycat.je.Transaction;
65 import com.sleepycat.je.TransactionConfig;
66 import com.sleepycat.je.rep.impl.RepImpl;
67 import com.sleepycat.je.rep.impl.node.FeederManager;
68 import com.sleepycat.je.rep.impl.node.FeederManagerStatDefinition;
69 import com.sleepycat.je.rep.impl.node.RepNode;
70 import com.sleepycat.je.rep.impl.node.ReplayStatDefinition;
71 import com.sleepycat.je.rep.impl.node.Replica;
72 import com.sleepycat.je.rep.impl.node.ReplicaStatDefinition;
73 import com.sleepycat.je.rep.stream.FeederTxnStatDefinition;
74 import com.sleepycat.je.rep.utilint.BinaryProtocolStatDefinition;
75 import com.sleepycat.je.rep.vlsn.VLSNIndexStatDefinition;
76 import com.sleepycat.je.utilint.IntegralLongAvgStat;
77 import com.sleepycat.je.utilint.StatDefinition;
78 import com.sleepycat.je.utilint.StatGroup;
79 
80 /**
81  * Statistics for a replicated environment.
82  * <p>
83  * The statistics are logically grouped into four categories. Viewing the
84  * statistics through {@link ReplicatedEnvironmentStats#toString()} displays
85  * the values in these categories, as does viewing the stats through the {@link
86  * <a href="{@docRoot}/../jconsole/JConsole-plugin.html">RepJEMonitor
87  * mbean</a>}.  Viewing the stats with {@link
88  * ReplicatedEnvironmentStats#toStringVerbose()} will provide more detailed
89  * descriptions of the stats and stat categories.
90  * <p>
91  * The current categories are:
92  * <ul>
93  *  <li><b>FeederManager</b>: A feed is the {@link <a
94  * href="{@docRoot}/../ReplicationGuide/introduction.html#replicationstreams">replication
95  * stream</a>} between a master and replica. The current number of feeders
96  * gives a sense of the connectivity of the replication group.
97  *  </li>
98  *  <li><b>BinaryProtocol</b>: These statistics center on the network traffic
99  *   engendered by the replication stream, and provide a sense of the network
100  *   bandwidth seen by the replication group.
101  *  </li>
102  *  <li><b>Replay</b>: The act of receiving and applying the replication stream
103  *  at the Replica node is called Replay. These stats give a sense of how much
104  *  load the replica node is experiencing when processing the traffic from the
105  *  replication group.
106  *  </li>
107  *  <li><b>ConsistencyTracker</b>: The tracker is invoked when consistency
108  *  policies are used at a replica node. This provides a measure of delays
109  *  experienced by read requests at a replica, in order to conform with the
110  *  consistency specified by the application.
111  *  </li>
112  * </ul>
113  *
114  * @see <a href="{@docRoot}/../jconsole/JConsole-plugin.html">Viewing
115  * Statistics with JConsole</a>
116  */
117 public class ReplicatedEnvironmentStats implements Serializable {
118     private static final long serialVersionUID = 1L;
119 
120     /**
121      * The "impossible" return value used by stats accessors to indicate the
122      * statistic is not available in this instance of
123      * ReplicatedEnvironmentStats, because it represents an earlier
124      * de-serialized instance in which this statistic was unavailable.
125      */
126     private static final int VALUE_UNAVAILABLE = -1;
127 
128     private StatGroup feederManagerStats;
129     private StatGroup feederTxnStats;
130     private StatGroup replayStats;
131     private StatGroup trackerStats;
132     private StatGroup protocolStats;
133     private StatGroup vlsnIndexStats;
134 
135     private final Map<String, String> tipsMap = new HashMap<String, String>();
136 
ReplicatedEnvironmentStats(RepImpl repImpl, StatsConfig config)137     ReplicatedEnvironmentStats(RepImpl repImpl, StatsConfig config) {
138         final RepNode repNode = repImpl.getRepNode();
139         final FeederManager feederManager = repNode.feederManager();
140 
141         feederManagerStats = feederManager.getFeederManagerStats(config);
142         feederTxnStats = repNode.getFeederTxns().getStats(config);
143 
144         final Replica replica = repNode.getReplica();
145         replayStats = replica.getReplayStats(config);
146         trackerStats = replica.getTrackerStats(config);
147         protocolStats = feederManager.getProtocolStats(config);
148         vlsnIndexStats = repImpl.getVLSNIndex().getStats(config);
149 
150         protocolStats.addAll(replica.getProtocolStats(config));
151         addMessageRateStats();
152         addBytesRateStats();
153     }
154 
155     /**
156      * @hidden
157      * Internal use only.
158      */
ReplicatedEnvironmentStats()159     public ReplicatedEnvironmentStats() {
160     }
161 
162     /**
163      * @hidden
164      * Internal use only.
165      */
getStatGroups()166     public Collection<StatGroup> getStatGroups() {
167         return (feederTxnStats != null) ?
168             Arrays.asList(feederManagerStats,
169                           feederTxnStats,
170                           replayStats,
171                           trackerStats,
172                           protocolStats,
173                           vlsnIndexStats) :
174             Arrays.asList(feederManagerStats,
175                           replayStats,
176                           trackerStats,
177                           protocolStats,
178                           vlsnIndexStats);
179     }
180 
181     /**
182      * @hidden
183      * Internal use only.
184      */
getStatGroupsMap()185     public Map<String, StatGroup> getStatGroupsMap() {
186         HashMap<String, StatGroup> statmap = new HashMap<String, StatGroup>();
187         statmap.put(feederManagerStats.getName(), feederManagerStats);
188         statmap.put(replayStats.getName(), replayStats);
189         statmap.put(trackerStats.getName(), trackerStats);
190         statmap.put(protocolStats.getName(), protocolStats);
191         statmap.put(vlsnIndexStats.getName(), vlsnIndexStats);
192         if (feederTxnStats != null) {
193             statmap.put(feederTxnStats.getName(), feederTxnStats);
194         }
195         return statmap;
196     }
197 
198     /**
199      * @hidden
200      * Internal use only.
201      */
setStatGroup(StatGroup sg)202     public void setStatGroup(StatGroup sg) {
203 
204         if (sg.getName().equals(FeederManagerStatDefinition.GROUP_NAME)) {
205             feederManagerStats = sg;
206         } else if (sg.getName().equals(ReplayStatDefinition.GROUP_NAME)) {
207             replayStats = sg;
208         } else if (sg.getName().equals(ReplicaStatDefinition.GROUP_NAME)) {
209             trackerStats = sg;
210         } else if (sg.getName().equals
211                        (BinaryProtocolStatDefinition.GROUP_NAME)) {
212             protocolStats = sg;
213         } else if (sg.getName().equals(VLSNIndexStatDefinition.GROUP_NAME)) {
214            vlsnIndexStats = sg;
215         } else if (sg.getName().equals(FeederTxnStatDefinition.GROUP_NAME)) {
216             feederTxnStats = sg;
217         } else {
218             throw EnvironmentFailureException.unexpectedState
219                 ("Internal error stat context is not registered");
220         }
221     }
222 
223     /**
224      * @hidden
225      * Internal use only
226      *
227      * For JConsole plugin support.
228      */
getStatGroupTitles()229     public static String[] getStatGroupTitles() {
230         return new String[] {
231             FeederManagerStatDefinition.GROUP_NAME,
232             FeederTxnStatDefinition.GROUP_NAME,
233             BinaryProtocolStatDefinition.GROUP_NAME,
234             ReplayStatDefinition.GROUP_NAME,
235             ReplicaStatDefinition.GROUP_NAME,
236             VLSNIndexStatDefinition.GROUP_NAME};
237     }
238 
addMessageRateStats()239     private void addMessageRateStats() {
240         long numerator;
241         long denominator;
242 
243         numerator = (protocolStats.getLongStat(N_MESSAGES_READ) == null) ?
244                      0 : protocolStats.getLongStat(N_MESSAGES_READ).get();
245         denominator = (protocolStats.getLongStat(N_READ_NANOS) == null) ?
246                 0 : protocolStats.getLongStat(N_READ_NANOS).get();
247         @SuppressWarnings("unused")
248         IntegralLongAvgStat msgReadRate =
249             new IntegralLongAvgStat
250                 (protocolStats,
251                  MESSAGE_READ_RATE,
252                  numerator,
253                  denominator,
254                  1000000000);
255 
256         numerator = (protocolStats.getLongStat(N_MESSAGES_WRITTEN) == null) ?
257                 0 : protocolStats.getLongStat(N_MESSAGES_WRITTEN).get();
258         denominator = (protocolStats.getLongStat(N_WRITE_NANOS) == null) ?
259            0 : protocolStats.getLongStat(N_WRITE_NANOS).get();
260         @SuppressWarnings("unused")
261         IntegralLongAvgStat msgWriteRate =
262             new IntegralLongAvgStat
263                 (protocolStats,
264                  MESSAGE_WRITE_RATE,
265                  numerator,
266                  denominator,
267                  1000000000);
268     }
269 
addBytesRateStats()270     private void addBytesRateStats() {
271         long numerator;
272         long denominator;
273 
274         numerator = (protocolStats.getLongStat(N_BYTES_READ) == null) ?
275                      0 : protocolStats.getLongStat(N_BYTES_READ).get();
276         denominator = (protocolStats.getLongStat(N_READ_NANOS) == null) ?
277                 0 : protocolStats.getLongStat(N_READ_NANOS).get();
278         @SuppressWarnings("unused")
279         IntegralLongAvgStat bytesReadRate =
280             new IntegralLongAvgStat
281                 (protocolStats,
282                  BYTES_READ_RATE,
283                  numerator,
284                  denominator,
285                  1000000000);
286 
287         numerator = (protocolStats.getLongStat(N_BYTES_WRITTEN) == null) ?
288                 0 : protocolStats.getLongStat(N_BYTES_WRITTEN).get();
289         denominator = (protocolStats.getLongStat(N_WRITE_NANOS) == null) ?
290            0 : protocolStats.getLongStat(N_WRITE_NANOS).get();
291         @SuppressWarnings("unused")
292         IntegralLongAvgStat bytesWriteRate =
293             new IntegralLongAvgStat
294                 (protocolStats,
295                  BYTES_WRITE_RATE,
296                  numerator,
297                  denominator,
298                  1000000000);
299     }
300 
301     /* Feeder Stats. */
302 
303     /**
304      * The number of Feeder threads since this node was started. A Master
305      * supplies the Replication Stream to a Replica via a Feeder thread. The
306      * Feeder thread is created when a Replica connects to the node and is
307      * shutdown when the connection is terminated.
308      */
getNFeedersCreated()309     public int getNFeedersCreated() {
310         return feederManagerStats.getInt(N_FEEDERS_CREATED);
311     }
312 
313     /**
314      * The number of Feeder threads that were shut down, either because this
315      * node, or the Replica terminated the connection.
316      *
317      * @see #getNFeedersCreated()
318      */
getNFeedersShutdown()319     public int getNFeedersShutdown() {
320         return feederManagerStats.getInt(N_FEEDERS_SHUTDOWN);
321     }
322 
323     /**
324      * The lag (in VLSNs) associated with the replica that's farthest behind in
325      * replaying the replication stream.
326      */
getNMaxReplicaLag()327     public long getNMaxReplicaLag() {
328         return feederManagerStats.getLong(N_MAX_REPLICA_LAG);
329     }
330 
331     /**
332      * The name of the replica that's farthest behind in replaying the
333      * replication stream.
334      */
getNMaxReplicaLagName()335     public String getNMaxReplicaLagName() {
336         return feederManagerStats.getString(N_MAX_REPLICA_LAG_NAME);
337     }
338 
339     /* Master transaction commit acknowledgment statistics. */
340 
341     /**
342      * The number of transactions that were successfully acknowledged based
343      * upon the {@link ReplicaAckPolicy} policy associated with the
344      * transaction commit.
345      */
getNTxnsAcked()346     public long getNTxnsAcked() {
347         return (feederTxnStats == null) ?
348                VALUE_UNAVAILABLE :
349                feederTxnStats.getAtomicLong(TXNS_ACKED);
350     }
351 
352     /**
353      * The number of transactions that were not acknowledged as required by the
354      * {@link ReplicaAckPolicy} policy associated with the transaction commit.
355      * These transactions resulted in {@link InsufficientReplicasException} or
356      * {@link InsufficientAcksException}.
357      */
getNTxnsNotAcked()358     public long getNTxnsNotAcked() {
359         return (feederTxnStats == null) ?
360                VALUE_UNAVAILABLE :
361                feederTxnStats.getAtomicLong(TXNS_NOT_ACKED);
362     }
363 
364     /**
365      * The total time in milliseconds spent in replicated transactions. This
366      * represents the time from the start of the transaction until its
367      * successful commit and acknowledgment. It includes the time spent
368      * waiting for transaction commit acknowledgments, as determined by
369      * {@link #getAckWaitMs()}.
370      */
getTotalTxnMs()371     public long getTotalTxnMs() {
372         return (feederTxnStats == null) ?
373                 VALUE_UNAVAILABLE :
374                 feederTxnStats.getAtomicLong(TOTAL_TXN_MS);
375     }
376 
377     /**
378      * The total time in milliseconds that the master spent waiting for the
379      * {@link ReplicaAckPolicy} to be satisfied during successful transaction
380      * commits.
381      *
382      * @see #getTotalTxnMs()
383      */
getAckWaitMs()384     public long getAckWaitMs() {
385         return (feederTxnStats == null) ?
386                 VALUE_UNAVAILABLE :
387                 feederTxnStats.getAtomicLong(ACK_WAIT_MS);
388     }
389 
390     /* Replay Stats. */
391 
392     /**
393      * The number of commit log records that were replayed by this node when
394      * it was a Replica. There is one commit record record for each actual
395      * commit on the Master.
396      */
getNReplayCommits()397     public long getNReplayCommits() {
398         return replayStats.getLong(N_COMMITS);
399     }
400 
401     /**
402      * The number of commit log records that needed to be acknowledged to the
403      * Master by this node when it was a Replica. The rate of change of this
404      * statistic, will show a strong correlation with that of
405      * <code>NReplayCommits</code> statistic, if the <code>Durability</code>
406      * policy used by transactions on the master calls for transaction commit
407      * acknowledgments and the Replica is current with respect to the Master.
408      */
getNReplayCommitAcks()409     public long getNReplayCommitAcks() {
410         return replayStats.getLong(N_COMMIT_ACKS);
411     }
412 
413     /**
414      * The number of commitSync() calls executed when satisfying transaction
415      * commit acknowledgment requests from the Master.
416      */
getNReplayCommitSyncs()417     public long getNReplayCommitSyncs() {
418         return replayStats.getLong(N_COMMIT_SYNCS);
419     }
420 
421     /**
422      * The number of commitNoSync() calls executed when satisfying transaction
423      * commit acknowledgment requests from the Master.
424      */
getNReplayCommitNoSyncs()425     public long getNReplayCommitNoSyncs() {
426         return replayStats.getLong(N_COMMIT_NO_SYNCS);
427     }
428 
429     /**
430      * The number of commitNoSync() calls executed when satisfying transaction
431      * commit acknowledgment requests from the Master.
432      */
getNReplayCommitWriteNoSyncs()433     public long getNReplayCommitWriteNoSyncs() {
434         return replayStats.getLong(N_COMMIT_WRITE_NO_SYNCS);
435     }
436 
437     /**
438      * The number of abort records which were replayed while the node was in
439      * the Replica state.
440      */
getNReplayAborts()441     public long getNReplayAborts() {
442         return replayStats.getLong(N_ABORTS);
443     }
444 
445     /**
446      * The number of NameLN records which were replayed while the node was in
447      * the Replica state.
448      */
getNReplayNameLNs()449     public long getNReplayNameLNs() {
450         return replayStats.getLong(N_NAME_LNS);
451     }
452 
453     /**
454      * The number of data records (creation, update, deletion) which were
455      * replayed while the node was in the Replica state.
456      */
getNReplayLNs()457     public long getNReplayLNs() {
458         return replayStats.getLong(N_LNS);
459     }
460 
461     /**
462      * The total elapsed time in milliseconds spent replaying committed and
463      * aborted transactions.
464      */
getReplayElapsedTxnTime()465     public long getReplayElapsedTxnTime() {
466         return replayStats.getLong(N_ELAPSED_TXN_TIME);
467     }
468 
469     /**
470      * The number of group commits that were initiated due to the
471      * {@link ReplicationConfig#REPLICA_GROUP_COMMIT_INTERVAL group timeout
472      * interval} being exceeded.
473      *
474      * @since 5.0.76
475      */
getNReplayGroupCommitTimeouts()476     public long getNReplayGroupCommitTimeouts() {
477         return replayStats.getLong(N_GROUP_COMMIT_TIMEOUTS);
478     }
479 
480     /**
481      * The number of group commits that were initiated due the
482      * {@link ReplicationConfig#REPLICA_MAX_GROUP_COMMIT max group size} being
483      * exceeded.
484      *
485      * @since 5.0.76
486      */
getNReplayGroupCommitMaxExceeded()487      public long getNReplayGroupCommitMaxExceeded() {
488          return replayStats.getLong(N_GROUP_COMMIT_MAX_EXCEEDED);
489      }
490 
491     /**
492      * The number of replay transaction commits that were part of a group
493      * commit operation.
494      *
495      * @since 5.0.76
496      */
getNReplayGroupCommitTxns()497      public long getNReplayGroupCommitTxns() {
498          return replayStats.getLong(N_GROUP_COMMIT_TXNS);
499      }
500 
501      /**
502       * The number of group commit operations.
503       *
504       * @since 5.0.76
505       */
getNReplayGroupCommits()506      public long getNReplayGroupCommits() {
507          return replayStats.getLong(N_GROUP_COMMITS);
508      }
509 
510     /**
511      * The minimum time taken to replay a transaction commit operation.
512      */
getReplayMinCommitProcessingNanos()513     public long getReplayMinCommitProcessingNanos() {
514         return replayStats.getLong(MIN_COMMIT_PROCESSING_NANOS);
515     }
516 
517     /**
518      * The maximum time taken to replay a transaction commit operation.
519      */
getReplayMaxCommitProcessingNanos()520     public long getReplayMaxCommitProcessingNanos() {
521         return replayStats.getLong(MAX_COMMIT_PROCESSING_NANOS);
522     }
523 
524     /**
525      * The total time spent to replay all commit operations.
526      */
getReplayTotalCommitProcessingNanos()527     public long getReplayTotalCommitProcessingNanos() {
528         return replayStats.getLong(TOTAL_COMMIT_PROCESSING_NANOS);
529     }
530 
531     /**
532      * @hidden
533      * TODO: Make visible after experimenting with this new stat
534      *
535      * The sum of time periods, measured in milliseconds, between when update
536      * operations commit on the master and then subsequently commit on the
537      * replica.  Divide this value by the total number of commit operations,
538      * available by calling {@link #getNReplayCommits}, to find the average
539      * commit lag for a single operation.
540      *
541      * <p>Note that each lag is computed on the replica by comparing the time
542      * of the master commit, as measured by the master, and time on the replica
543      * when it commits locally.  As a result, the return value will be affected
544      * by any clock skew between the master and the replica.
545      */
getReplayTotalCommitLagMs()546     public long getReplayTotalCommitLagMs() {
547         return replayStats.getLong(TOTAL_COMMIT_LAG_MS);
548     }
549 
550     /**
551      * @hidden
552      * TODO: Make visible after experimenting with this new stat
553      *
554      * The time in milliseconds between when the latest update operation
555      * committed on the master and then subsequently committed on the replica.
556      *
557      * <p>Note that the lag is computed on the replica by comparing the time of
558      * the master commit, as measured by the master, and time on the replica
559      * when it commits locally.  As a result, the return value will be affected
560      * by any clock skew between the master and the replica.
561      */
getReplayLatestCommitLagMs()562     public long getReplayLatestCommitLagMs() {
563         return replayStats.getLong(LATEST_COMMIT_LAG_MS);
564     }
565 
566     /* Protocol Stats. */
567 
568     /**
569      * The number of bytes of Replication Stream read over the network. It does
570      * not include the TCP/IP overhead.
571      * <p>
572      * If the node has served as both a Replica and Master since it was first
573      * started, the number represents the sum total of all Feeder related
574      * network activity, as well as Replica network activity.
575      */
getNProtocolBytesRead()576     public long getNProtocolBytesRead() {
577         return protocolStats.getLong(N_BYTES_READ);
578     }
579 
580     /**
581      * The number of Replication Stream messages read over the network.
582      * <p>
583      * If the node has served as both a Replica and Master since it was first
584      * started, the number represents the sum total of all Feeder related
585      * network activity, as well as Replica network activity.
586      */
getNProtocolMessagesRead()587     public long getNProtocolMessagesRead() {
588         return protocolStats.getLong(N_MESSAGES_READ);
589     }
590 
591     /**
592      * The number of Replication Stream bytes written over the network.
593      * <p>
594      * If the node has served as both a Replica and Master since it was first
595      * started, the number represents the sum total of all Feeder related
596      * network activity, as well as Replica network activity.
597      */
getNProtocolBytesWritten()598     public long getNProtocolBytesWritten() {
599         return protocolStats.getLong(N_BYTES_WRITTEN);
600     }
601 
602     /**
603      * The number of Replication Stream messages that were written as part
604      * of a message batch instead of being written  individually.
605      *
606      * It represents a subset of the messages returned by
607      * {@link #getNProtocolMessagesWritten()}
608      *
609      * @see #getNProtocolMessageBatches
610      *
611      * @since 6.2.7
612      */
getNProtocolMessagesBatched()613     public long getNProtocolMessagesBatched() {
614         return protocolStats.getLong(N_MESSAGES_BATCHED);
615     }
616 
617     /**
618      * The number of Replication Stream message batches written to the network.
619      *
620      * @see #getNProtocolMessagesBatched
621      *
622      * @since 6.2.7
623      */
getNProtocolMessageBatches()624     public long getNProtocolMessageBatches() {
625         return protocolStats.getLong(N_MESSAGE_BATCHES);
626     }
627 
628     /**
629      * The total number of Replication Stream messages written over the
630      * network.
631      * <p>
632      * If the node has served as both a Replica and Master since it was first
633      * started, the number represents the sum total of all Feeder related
634      * network activity, as well as Replica network activity.
635      */
getNProtocolMessagesWritten()636     public long getNProtocolMessagesWritten() {
637         return protocolStats.getLong(N_MESSAGES_WRITTEN);
638     }
639 
640     /**
641      * The number of nanoseconds spent reading from the network channel.
642      * <p>
643      * If the node has served as both a Replica and Master since it was first
644      * started, the number represents the sum total of all Feeder related
645      * network activity, as well as Replica network activity.
646      */
getProtocolReadNanos()647     public long getProtocolReadNanos() {
648         return protocolStats.getLong(N_READ_NANOS);
649     }
650 
651     /**
652      * The number of nanoseconds spent writing to the network channel.
653      * <p>
654      * If the node has served as both a Replica and Master since it was first
655      * started, the number represents the sum total of all Feeder related
656      * network activity, as well as Replica network activity.
657      */
getProtocolWriteNanos()658     public long getProtocolWriteNanos() {
659         return protocolStats.getLong(N_WRITE_NANOS);
660     }
661 
662     /**
663      * Incoming replication message throughput, in terms of messages received
664      * from the replication network channels per second.
665      * <p> If the node has served as both a Replica and Master since
666      * it was first started, the number represents the message reading rate
667      * over all Feeder related network activity, as well as Replica network
668      * activity.
669      */
getProtocolMessageReadRate()670     public long getProtocolMessageReadRate() {
671         IntegralLongAvgStat rstat =
672             protocolStats.getIntegralLongAvgStat(MESSAGE_READ_RATE);
673         return (rstat != null) ? rstat.get().longValue() : 0;
674     }
675 
676     /**
677      * Outgoing message throughput, in terms of message written to the
678      * replication network channels per second.
679      * <p>
680      * If the node has served as both a Replica and Master since it was first
681      * started, the number represents the message writing rate over all Feeder
682      * related network activity, as well as Replica network activity.
683      */
getProtocolMessageWriteRate()684     public long getProtocolMessageWriteRate() {
685         IntegralLongAvgStat rstat =
686             protocolStats.getIntegralLongAvgStat(MESSAGE_WRITE_RATE);
687         return (rstat != null) ? rstat.get().longValue() : 0;
688     }
689 
690     /**
691      * Bytes read throughput, in terms of bytes received from the replication
692      * network channels per second.
693      * <p>
694      * If the node has served as both a Replica and Master since it was first
695      * started, the number represents the bytes reading rate over all Feeder
696      * related network activity, as well as Replica network activity.
697      */
getProtocolBytesReadRate()698     public long getProtocolBytesReadRate() {
699         IntegralLongAvgStat rstat =
700             protocolStats.getIntegralLongAvgStat(BYTES_READ_RATE);
701         return (rstat != null) ? rstat.get().longValue() : 0;
702     }
703 
704     /**
705      * Bytes written throughput, in terms of bytes written to the replication
706      * network channels per second.
707      * <p>
708      * If the node has served as both a Replica and Master since it was first
709      * started, the number represents the bytes writing rate over all Feeder
710      * related network activity, as well as Replica network activity.
711      */
getProtocolBytesWriteRate()712     public long getProtocolBytesWriteRate() {
713         IntegralLongAvgStat rstat =
714             protocolStats.getIntegralLongAvgStat(BYTES_WRITE_RATE);
715         return (rstat != null) ? rstat.get().longValue() : 0;
716     }
717 
718     /**
719      * Returns the number of messages containing log entries that were written
720      * to the replication stream using the previous log format to support
721      * replication to a replica running an earlier version during an upgrade.
722      */
getNProtocolEntriesWrittenOldVersion()723     public long getNProtocolEntriesWrittenOldVersion() {
724         return protocolStats.getLong(N_ENTRIES_WRITTEN_OLD_VERSION);
725     }
726 
727     /* ConsistencyTracker Stats. */
728 
729     /**
730      * The number of times a Replica held back a
731      * {@link Environment#beginTransaction(Transaction,TransactionConfig)}
732      * operation to satisfy the {@link TimeConsistencyPolicy}.
733      */
getTrackerLagConsistencyWaits()734     public long getTrackerLagConsistencyWaits() {
735         return trackerStats.getLong(N_LAG_CONSISTENCY_WAITS);
736     }
737 
738     /**
739      * The total time (in msec) for which a Replica held back a
740      * {@link Environment#beginTransaction(Transaction,TransactionConfig)}
741      * operation to satisfy the {@link TimeConsistencyPolicy}.
742      */
getTrackerLagConsistencyWaitMs()743     public long getTrackerLagConsistencyWaitMs() {
744         return trackerStats.getLong(N_LAG_CONSISTENCY_WAIT_MS);
745     }
746 
747     /**
748      * The number of times a Replica held back a
749      * {@link Environment#beginTransaction(Transaction,TransactionConfig)}
750      * operation to satisfy the {@link CommitPointConsistencyPolicy}.
751      */
getTrackerVLSNConsistencyWaits()752     public long getTrackerVLSNConsistencyWaits() {
753         return trackerStats.getLong(N_VLSN_CONSISTENCY_WAITS);
754     }
755 
756     /**
757      * The total time (in msec) for which a Replica held back a
758      * {@link Environment#beginTransaction(Transaction,TransactionConfig)}
759      * operation to satisfy the {@link CommitPointConsistencyPolicy}.
760      */
getTrackerVLSNConsistencyWaitMs()761     public long getTrackerVLSNConsistencyWaitMs() {
762         return trackerStats.getLong(N_VLSN_CONSISTENCY_WAIT_MS);
763     }
764 
765     /**
766      * Returns a string representation of the statistics.
767      */
768     @Override
toString()769     public String toString() {
770         StringBuilder sb = new StringBuilder();
771 
772         for (StatGroup group : getStatGroups()) {
773             sb.append(group.toString());
774         }
775 
776         return sb.toString();
777     }
778 
toStringVerbose()779     public String toStringVerbose() {
780         StringBuilder sb = new StringBuilder();
781 
782         for (StatGroup group : getStatGroups()) {
783             sb.append(group.toStringVerbose());
784         }
785 
786         return sb.toString();
787     }
788 
getTips()789     public Map<String, String> getTips() {
790         /* Add FeederManager stats definition. */
791 
792         for (StatGroup group : getStatGroups()) {
793             tipsMap.put(group.getName(), group.getDescription());
794             for (StatDefinition def : group.getStats().keySet()) {
795                 tipsMap.put(def.getName(), def.getDescription());
796             }
797         }
798 
799         return tipsMap;
800     }
801 }
802