All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.aeron.samples.StreamStat Maven / Gradle / Ivy

There is a newer version: 1.46.7
Show newest version
/*
 * Copyright 2014-2021 Real Logic Limited.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.aeron.samples;

import io.aeron.Aeron;
import org.agrona.concurrent.status.CountersReader;

import java.io.PrintStream;
import java.util.*;

import static io.aeron.driver.status.PublisherLimit.PUBLISHER_LIMIT_TYPE_ID;
import static io.aeron.driver.status.PublisherPos.PUBLISHER_POS_TYPE_ID;
import static io.aeron.driver.status.ReceiverPos.RECEIVER_POS_TYPE_ID;
import static io.aeron.driver.status.SenderLimit.SENDER_LIMIT_TYPE_ID;
import static io.aeron.driver.status.StreamCounter.*;

/**
 * Tool for taking a snapshot of Aeron streams and relevant position counters.
 * 

* Each stream managed by the {@link io.aeron.driver.MediaDriver} will be sampled and a line of text * output per stream with each of the position counters for that stream. *

* Each counter has the format: * {@code ::} */ public final class StreamStat { private static final Comparator LINES_COMPARATOR = Comparator.comparingLong(StreamCompositeKey::sessionId) .thenComparingInt(StreamCompositeKey::streamId) .thenComparing(StreamCompositeKey::channel); private final CountersReader counters; /** * Main method for launching the process. * * @param args passed to the process. */ public static void main(final String[] args) { final CountersReader counters = SamplesUtil.mapCounters(); final StreamStat streamStat = new StreamStat(counters); streamStat.print(System.out); } /** * Construct by using a {@link CountersReader} which can be obtained from {@link Aeron#countersReader()}. * * @param counters to read for tracking positions. */ public StreamStat(final CountersReader counters) { this.counters = counters; } /** * Take a snapshot of all the counters and group them by streams. * * @return a snapshot of all the counters and group them by streams. */ public Map> snapshot() { final Map> streams = new TreeMap<>(LINES_COMPARATOR); counters.forEach( (counterId, typeId, keyBuffer, label) -> { if ((typeId >= PUBLISHER_LIMIT_TYPE_ID && typeId <= RECEIVER_POS_TYPE_ID) || typeId == SENDER_LIMIT_TYPE_ID || typeId == PUBLISHER_POS_TYPE_ID) { final StreamCompositeKey key = new StreamCompositeKey( keyBuffer.getInt(SESSION_ID_OFFSET), keyBuffer.getInt(STREAM_ID_OFFSET), keyBuffer.getStringAscii(CHANNEL_OFFSET)); final StreamPosition position = new StreamPosition( keyBuffer.getLong(REGISTRATION_ID_OFFSET), counters.getCounterValue(counterId), typeId); streams.computeIfAbsent(key, (ignore) -> new ArrayList<>()).add(position); } }); return streams; } /** * Print a snapshot of the stream positions to a {@link PrintStream}. *

* Each stream will be printed on its own line. * * @param out to which the stream snapshot will be written. * @return the number of streams printed. */ public int print(final PrintStream out) { final Map> streams = snapshot(); final StringBuilder builder = new StringBuilder(); for (final Map.Entry> entry : streams.entrySet()) { builder.setLength(0); final StreamCompositeKey key = entry.getKey(); builder .append("sessionId=").append(key.sessionId()) .append(" streamId=").append(key.streamId()) .append(" channel=").append(key.channel()) .append(" :"); for (final StreamPosition streamPosition : entry.getValue()) { builder .append(' ') .append(labelName(streamPosition.typeId())) .append(':').append(streamPosition.id()) .append(':').append(streamPosition.value()); } out.println(builder); } return streams.size(); } /** * Composite key which identifies an Aeron stream of messages. */ public static final class StreamCompositeKey { private final int sessionId; private final int streamId; private final String channel; /** * Construct a new key representing a unique stream. * * @param sessionId to identify the stream. * @param streamId within a channel. * @param channel as a URI. */ public StreamCompositeKey(final int sessionId, final int streamId, final String channel) { Objects.requireNonNull(channel, "Channel cannot be null"); this.sessionId = sessionId; this.streamId = streamId; this.channel = channel; } /** * The session id of the stream. * * @return session id of the stream. */ public int sessionId() { return sessionId; } /** * The stream id within a channel. * * @return stream id within a channel. */ public int streamId() { return streamId; } /** * The channel as a URI. * * @return channel as a URI. */ public String channel() { return channel; } /** * {@inheritDoc} */ public boolean equals(final Object o) { if (this == o) { return true; } if (!(o instanceof StreamCompositeKey)) { return false; } final StreamCompositeKey that = (StreamCompositeKey)o; return this.sessionId == that.sessionId && this.streamId == that.streamId && this.channel.equals(that.channel); } /** * {@inheritDoc} */ public int hashCode() { int result = sessionId; result = 31 * result + streamId; result = 31 * result + channel.hashCode(); return result; } /** * {@inheritDoc} */ public String toString() { return "StreamCompositeKey{" + "sessionId=" + sessionId + ", streamId=" + streamId + ", channel='" + channel + '\'' + '}'; } } /** * Represents a position within a particular stream of messages. */ public static final class StreamPosition { private final long id; private final long value; private final int typeId; /** * Stream position representation. * * @param id of the registered entity. * @param value of the position. * @param typeId of the counter. */ public StreamPosition(final long id, final long value, final int typeId) { this.id = id; this.value = value; this.typeId = typeId; } /** * The identifier for the registered entity, such as publication or subscription, to which the counter relates. * * @return the identifier for the registered entity to which the counter relates. */ public long id() { return id; } /** * The value of the counter. * * @return the value of the counter. */ public long value() { return value; } /** * The type category of the counter for the stream position. * * @return the type category of the counter for the stream position. */ public int typeId() { return typeId; } /** * {@inheritDoc} */ public boolean equals(final Object o) { if (this == o) { return true; } if (!(o instanceof StreamPosition)) { return false; } final StreamPosition that = (StreamPosition)o; return this.id == that.id && this.value == that.value && this.typeId == that.typeId; } /** * {@inheritDoc} */ public int hashCode() { int result = (int)(id ^ (id >>> 32)); result = 31 * result + (int)(value ^ (value >>> 32)); result = 31 * result + typeId; return result; } /** * {@inheritDoc} */ public String toString() { return "StreamPosition{" + "id=" + id + ", value=" + value + ", typeId=" + typeId + '}'; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy