package com.chickling.kmanager.jmx; import java.util.List; import java.util.Optional; import javax.management.Attribute; import javax.management.AttributeList; import javax.management.MBeanServerConnection; import javax.management.MalformedObjectNameException; import javax.management.ObjectName; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author Hulva Luva.H * @since 2017-07-11 * */ public class KafkaMetrics { private static Logger LOG = LoggerFactory.getLogger(KafkaMetrics.class); // kafka.network:type=RequestMetrics,name=RequestsPerSec,request={Produce|FetchConsumer|FetchFollower} // java.lang public static final String OPRATING_SYSTEM = "java.lang:type=OperatingSystem"; public static final String RUNTIME = "java.lang:type=Runtime"; // kafka.cluster public static final String IN_SYNC_REPLICAS_COUNT = "kafka.cluster:type=Partition,name=InSyncReplicasCount,topic={},partition={}"; public static final String REPLICAS_COUNT = "kafka.cluster:type=Partition,name=ReplicasCount,topic={},partition={}"; public static final String UNDER_REPLICATED = "kafka.cluster:type=Partition,name=UnderReplicated,topic={},partition={}"; // kafka.controller public static final String LEADER_ELECTION_RATE_AND_TIME_MS = "kafka.controller:type=ControllerStats,name=LeaderElectionRateAndTimeMs"; public static final String UNCLEAN_LEADER_ELECTIONS_PER_SEC = "kafka.controller:type=ControllerStats,name=UncleanLeaderElectionsPerSec"; public static final String ACTIVE_CONTROLLER_COUNT = "kafka.controller:type=KafkaController,name=ActiveControllerCount"; public static final String OFFLINE_PARTITIONS_COUNT = "kafka.controller:type=KafkaController,name=OfflinePartitionsCount"; public static final String PREFERED_REPLICA_IMBALANCE = "kafka.controller:type=KafkaController,name=PreferredReplicaImbalanceCount"; // kafka.log public static final String LOG_END_OFFSET = "kafka.log:type=Log,name=LogEndOffset,topic={},partition={}"; public static final String LOG_START_OFFSET = "kafka.log:type=Log,name=LogStartOffset,topic={},partition={}"; public static final String LOG_SEGMENTS_NUM = "kafka.log:type=Log,name=NumLogSegments,topic={},partition={}"; public static final String LOG_SIZE = "kafka.log:type=Log,name=Size,topic={},partition={}"; public static final String CLEANER_RECOPY_PERCENT = "kafka.log:type=LogCleaner,name=cleaner-recopy-percent"; public static final String MAX_BUFFER_UTILIZATION_PERCENT = "kafka.log:type=LogCleaner,name=max-buffer-utilization-percent"; public static final String MAX_CLEAN_TIME_SECS = "kafka.log:type=LogCleaner,name=max-clean-time-secs"; public static final String MAX_DIRTY_PERCENT = "kafka.log:type=LogCleanerManager,name=max-dirty-percent"; public static final String TIME_SINCE_LAST_RUN_CLEANER_MS = "kafka.log:type=LogCleanerManager,name=time-since-last-run-ms"; // kafka.network public static final String PROCESSOR_IDLEPERCENT = "kafka.network:type=Processor,name=IdlePercent,networkProcessor={}"; public static final String REQUEST_QUEUE_SIZE = "kafka.network:type=RequestChannel,name=RequestQueueSize"; public static final String RESPONSE_QUEUE_SIZE = "kafka.network:type=RequestChannel,name=ResponseQueueSize"; public static final String RESPONSE_QUEUE_SIZE_OF_PROCESSOR = "kafka.network:type=RequestChannel,name=ResponseQueueSize,processor={}"; public static final String REQUEST_METRICS = "kafka.network:type=RequestMetrics,name={},request= {}"; public static final String REQUEST_METRICS_NAMES[] = {"LocalTimeMs", "RemoteTimeMs", "RequestQueueTimeMs", "RequestQueueTimeMs", "RequestsPerSec", "ResponseQueueTimeMs", "ResponseSendTimeMs", "ThrottleTimeMs", "TotalTimeMs"}; public static final String REQUEST_METRICS_REQUESTS[] = {"ApiVersions", "ControlledShutdown", "CreateTopics", "DeleteTopics", "DescribeGroups", "Fetch", "FetchConsumer", "FetchFollower", "GroupCoordinator", "Heartbeat", "JoinGroup", "LeaderAndIsr", "LeaveGroup", "ListGroups", "Metadata", "OffsetCommit", "OffsetFetch", "Offsets", "Produce", "SaslHandshake", "StopReplica", "SyncGroup", "UpdateMetadata"}; public static final String NETWORK_PROCESSOR_AVG_IDLE_PERCENT = "kafka.network:type=SocketServer,name=NetworkProcessorAvgIdlePercent"; // kafka.server public static final String BROKER_BYTES_IN_PER_SEC = "kafka.server:type=BrokerTopicMetrics,name=BytesInPerSec"; public static final String TOPIC_BYTES_IN_PER_SEC = "kafka.server:type=BrokerTopicMetrics,name=BytesInPerSec,topic={}"; public static final String BROKER_BYTES_OUT_PER_SEC = "kafka.server:type=BrokerTopicMetrics,name=BytesOutPerSec"; public static final String TOPIC_BYTES_OUT_PER_SEC = "kafka.server:type=BrokerTopicMetrics,name=BytesOutPerSec,topic={}"; public static final String BROKER_BYTES_REJECTERD_PER_SEC = "kafka.server:type=BrokerTopicMetrics,name=BytesRejectedPerSec"; public static final String TOPIC_BYTES_REJECTERD_PER_SEC = "kafka.server:type=BrokerTopicMetrics,name=BytesRejectedPerSec,topic={}"; public static final String BROKER_FAILED_FETCH_REQUESTS_PER_SEC = "kafka.server:type=BrokerTopicMetrics,name=FailedFetchRequestsPerSec"; public static final String TOPIC_FAILED_FETCH_REQUESTS_PER_SEC = "kafka.server:type=BrokerTopicMetrics,name=FailedFetchRequestsPerSec,topic={}"; public static final String BROKER_FAILED_PRODUCE_REQUESTS_PER_SEC = "kafka.server:type=BrokerTopicMetrics,name=FailedProduceRequestsPerSec"; public static final String TOPIC_FAILED_PRODUCE_REQUESTS_PER_SEC = "kafka.server:type=BrokerTopicMetrics,name=FailedProduceRequestsPerSec,topic={}"; public static final String BROKER_MESSAGES_IN_PER_SEC = "kafka.server:type=BrokerTopicMetrics,name=MessagesInPerSec"; public static final String TOPIC_MESSAGES_IN_PER_SEC = "kafka.server:type=BrokerTopicMetrics,name=MessagesInPerSec,topic={}"; public static final String TOTAL_FETCH_REQUESTS_PER_SEC = "kafka.server:type=BrokerTopicMetrics,name=TotalFetchRequestsPerSec"; public static final String TOTAL_PRODUCE_REQUESTS_PER_SEC = "kafka.server:type=BrokerTopicMetrics,name=TotalProduceRequestsPerSec"; public static final String CONSUMER_EXPIRES_PER_SEC = "kafka.server:type=DelayedFetchMetrics,name=ExpiresPerSec,fetcherType=consumer"; public static final String FOLLOWER_EXPIRES_PER_SEC = "kafka.server:type=DelayedFetchMetrics,name=ExpiresPerSec,fetcherType=follower"; public static final String DELAYED_OPERATIONS_FETCH_NUM = "kafka.server:type=DelayedOperationPurgatory,name=NumDelayedOperations,delayedOperation=Fetch"; public static final String DELAYED_OPERATIONS_HEARTBEAT_NUM = "kafka.server:type=DelayedOperationPurgatory,name=NumDelayedOperations,delayedOperation=Heartbeat"; public static final String DELAYED_OPERATIONS_PRODUCE_NUM = "kafka.server:type=DelayedOperationPurgatory,name=NumDelayedOperations,delayedOperation=Produce"; public static final String DELAYED_OPERATIONS_REBALANCE_NUM = "kafka.server:type=DelayedOperationPurgatory,name=NumDelayedOperations,delayedOperation=Rebalance"; public static final String DELAYED_OPERATIONS_TOPIC_NUM = "kafka.server:type=DelayedOperationPurgatory,name=NumDelayedOperations,delayedOperation=topic"; public static final String DELAYED_OPERATIONS_FETCH_PURGATORY_SIZE = "kafka.server:type=DelayedOperationPurgatory,name=PurgatorySize,delayedOperation=Fetch"; public static final String DELAYED_OPERATIONS_HEARTBEAT_PURGATORY_SIZE = "kafka.server:type=DelayedOperationPurgatory,name=PurgatorySize,delayedOperation=Heartbeat"; public static final String DELAYED_OPERATIONS_PRODUCE_PURGATORY_SIZE = "kafka.server:type=DelayedOperationPurgatory,name=PurgatorySize,delayedOperation=Produce"; public static final String DELAYED_OPERATIONS_REBALANCE_PURGATORY_SIZE = "kafka.server:type=DelayedOperationPurgatory,name=PurgatorySize,delayedOperation=Rebalance"; public static final String DELAYED_OPERATIONS_TOPIC_PURGATORY_SIZE = "kafka.server:type=DelayedOperationPurgatory,name=PurgatorySize,delayedOperation=topic"; public static final String FETCH_DELAY_QUEUE_SIZE = "kafka.server:type=Fetch"; public static final String PRODUCE_DELAY_QUEUE_SIZE = "kafka.server:type=Produce"; public static final String CONSUMER_LAG = "kafka.server:type=FetcherLagMetrics,name=ConsumerLag,clientId={},topic={},partition={}"; public static final String FETCHER_STATS_BYTES_PER_SEC = "kafka.server:type=FetcherStats,name=BytesPerSec,clientId={},brokerHost={},brokerPort={}"; public static final String FETCHER_STATS_REQUESTS_PER_SEC = "kafka.server:type=FetcherStats,name=RequestsPerSec,clientId={},brokerHost={},brokerPort={}"; public static final String REQUEST_HANDLER_AVG_IDLE_PERCENT = "kafka.server:type=KafkaRequestHandlerPool,name=RequestHandlerAvgIdlePercent"; public static final String BROKER_STATE = "kafka.server:type=KafkaServer,name=BrokerState"; public static final String CLUSTER_ID = "kafka.server:type=KafkaServer,name=ClusterId"; public static final String LEADER_REPLICATION = "kafka.server:type=LeaderReplication"; public static final String REPLICA_MAX_LAG = "kafka.server:type=ReplicaFetcherManager,name=MaxLag,clientId=Replica"; public static final String REPLICA_MIN_FETCH_RATE = "kafka.server:type=ReplicaFetcherManager,name=MinFetchRate,clientId=Replica"; public static final String REPLICA_ISR_EXPANDS_PER_SEC = "kafka.server:type=ReplicaManager,name=IsrExpandsPerSec"; public static final String REPLICA_ISR_SHRINKS_PER_SEC = "kafka.server:type=ReplicaManager,name=IsrShrinksPerSec"; public static final String REPLICA_LEADER_COUNT = "kafka.server:type=ReplicaManager,name=LeaderCount"; public static final String REPLICA_PARTITION_COUNT = "kafka.server:type=ReplicaManager,name=PartitionCount"; public static final String REPLICA_UNDERREPLICATED_PARTITIONS = "kafka.server:type=ReplicaManager,name=UnderReplicatedPartitions"; // kafka.server:type=SessionExpireListener public static final String ZK_AUTHFAILURES_PER_SEC = "kafka.server:type=SessionExpireListener,name=ZooKeeperAuthFailuresPerSec"; public static final String ZK_DISCONNECTS_PER_SEC = "kafka.server:type=SessionExpireListener,name=ZooKeeperDisconnectsPerSec"; public static final String ZK_EXPIRES_PER_SEC = "kafka.server:type=SessionExpireListener,name=ZooKeeperExpiresPerSec"; public static final String ZK_RO_CONNECTS_PER_SEC = "kafka.server:type=SessionExpireListener,name=ZooKeeperReadOnlyConnectsPerSec"; public static final String ZK_SASL_AUTHS_PER_SEC = "kafka.server:type=SessionExpireListener,name=ZooKeeperSaslAuthenticationsPerSec"; public static final String ZK_SYNC_CONNECTIONS_PER_SEC = "kafka.server:type=SessionExpireListener,name=ZooKeeperSyncConnectsPerSec"; // app-info public static final String APP_INFO = "kafka.server:type=app-info,id=0"; public static final String REPLICA_FETCHER_METRICS = "kafka.server:type=replica-fetcher-metrics,broker-id={},fetcher-id={}"; public static final String SOCKET_SERVER_METRICS = "kafka.server:type=socket-server-metrics,networkProcessor={}"; public MeterMetric getItem(MBeanServerConnection mbsc, Optional<String> topicName, String metricName){ return getBrokerTopicMetrics(mbsc, metricName, topicName); } public MeterMetric getBytesInPerSec(MBeanServerConnection mbsc, Optional<String> topicName) { return getBrokerTopicMetrics(mbsc, "BytesInPerSec", topicName); } public MeterMetric getBytesOutPerSec(MBeanServerConnection mbsc, Optional<String> topicName) { return getBrokerTopicMetrics(mbsc, "BytesOutPerSec", topicName); } public MeterMetric getBytesRejectedPerSec(MBeanServerConnection mbsc, Optional<String> topicName) { return getBrokerTopicMetrics(mbsc, "BytesRejectedPerSec", topicName); } public MeterMetric getFailedFetchRequestsPerSec(MBeanServerConnection mbsc, Optional<String> topicName) { return getBrokerTopicMetrics(mbsc, "FailedFetchRequestsPerSec", topicName); } public MeterMetric getFailedProduceRequestsPerSec(MBeanServerConnection mbsc, Optional<String> topicName) { return getBrokerTopicMetrics(mbsc, "FailedProduceRequestsPerSec", topicName); } public MeterMetric getMessagesInPerSec(MBeanServerConnection mbsc, Optional<String> topicName) { return getBrokerTopicMetrics(mbsc, "MessagesInPerSec", topicName); } private MeterMetric getBrokerTopicMetrics(MBeanServerConnection mbsc, String metricName, Optional<String> topicName) { return getMeterMetric(mbsc, getObjectName(metricName, topicName)); } private MeterMetric getMeterMetric(MBeanServerConnection mbsc, ObjectName objectName) { String[] attributes = {"Count", "MeanRate", "OneMinuteRate", "FiveMinuteRate", "FifteenMinuteRate"}; AttributeList attributeList = null; try { attributeList = mbsc.getAttributes(objectName, attributes); } catch (Exception e) { LOG.warn("getMeterMetric failed! " + e.getMessage()); return new MeterMetric(0L, 0D, 0D, 0D, 0D); } return new MeterMetric(getLongValue(attributeList, attributes[0]), getDoubleValue(attributeList, attributes[1]), getDoubleValue(attributeList, attributes[2]), getDoubleValue(attributeList, attributes[3]), getDoubleValue(attributeList, attributes[4])); } private ObjectName getObjectName(String metricName, Optional<String> topicName) { ObjectName objectName = null; try { if (topicName.isPresent()) { objectName = new ObjectName("kafka.server:type=BrokerTopicMetrics,name=" + metricName + ",topic=" + topicName.get()); } else { objectName = new ObjectName("kafka.server:type=BrokerTopicMetrics,name=" + metricName); } } catch (MalformedObjectNameException e) { LOG.error("Get ObjectName error! " + e.getMessage()); } return objectName; } private Double getDoubleValue(AttributeList attributes, String name) { List<Attribute> _attributes = attributes.asList(); for (Attribute attr : _attributes) { if (attr.getName().equalsIgnoreCase(name)) { return (Double) attr.getValue(); } } return 0D; } private Long getLongValue(AttributeList attributes, String name) { List<Attribute> _attributes = attributes.asList(); for (Attribute attr : _attributes) { if (attr.getName().equalsIgnoreCase(name)) { return (Long) attr.getValue(); } } return 0L; } }