@Override public void disconnectSensors() { super.disconnectSensors(); if (jmxFeed != null) jmxFeed.stop(); if (jmxMxBeanFeed != null) jmxMxBeanFeed.stop(); if (jmxHelper != null) jmxHelper.terminate(); if (functionFeed != null) functionFeed.stop(); }
@SuppressWarnings({"unchecked", "rawtypes"}) @Override protected void connectSensors() { // "cassandra" isn't really a protocol, but okay for now setAttribute( DATASTORE_URL, "cassandra://" + getAttribute(HOSTNAME) + ":" + getAttribute(THRIFT_PORT)); super.connectSensors(); jmxHelper = new JmxHelper(this); boolean retrieveUsageMetrics = getConfig(RETRIEVE_USAGE_METRICS); jmxFeed = JmxFeed.builder() .entity(this) .period(3000, TimeUnit.MILLISECONDS) .helper(jmxHelper) .pollAttribute( new JmxAttributePollConfig<Boolean>(SERVICE_UP_JMX) .objectName(storageServiceMBean) .attributeName("Initialized") .onSuccess(Functions.forPredicate(Predicates.notNull())) .onException(Functions.constant(false)) .suppressDuplicates(true)) .pollAttribute( new JmxAttributePollConfig<Set<BigInteger>>(TOKENS) .objectName(storageServiceMBean) .attributeName("TokenToEndpointMap") .onSuccess( new Function<Object, Set<BigInteger>>() { @Override public Set<BigInteger> apply(@Nullable Object arg) { Map input = (Map) arg; if (input == null || input.isEmpty()) return null; // FIXME does not work on aws-ec2, uses RFC1918 address Predicate<String> self = Predicates.in( ImmutableList.of( getAttribute(HOSTNAME), getAttribute(ADDRESS), getAttribute(SUBNET_ADDRESS), getAttribute(SUBNET_HOSTNAME))); Set<String> tokens = Maps.filterValues(input, self).keySet(); Set<BigInteger> result = Sets.newLinkedHashSet(); for (String token : tokens) { result.add(new BigInteger(token)); } return result; } }) .onException(Functions.<Set<BigInteger>>constant(null)) .suppressDuplicates(true)) .pollAttribute( new JmxAttributePollConfig<BigInteger>(TOKEN) .objectName(storageServiceMBean) .attributeName("TokenToEndpointMap") .onSuccess( new Function<Object, BigInteger>() { @Override public BigInteger apply(@Nullable Object arg) { Map input = (Map) arg; // TODO remove duplication from setting TOKENS if (input == null || input.isEmpty()) return null; // FIXME does not work on aws-ec2, uses RFC1918 address Predicate<String> self = Predicates.in( ImmutableList.of( getAttribute(HOSTNAME), getAttribute(ADDRESS), getAttribute(SUBNET_ADDRESS), getAttribute(SUBNET_HOSTNAME))); Set<String> tokens = Maps.filterValues(input, self).keySet(); String token = Iterables.getFirst(tokens, null); return (token != null) ? new BigInteger(token) : null; } }) .onException(Functions.<BigInteger>constant(null)) .suppressDuplicates(true)) .pollOperation( new JmxOperationPollConfig<String>(DATACENTER_NAME) .period(60, TimeUnit.SECONDS) .objectName(snitchMBean) .operationName("getDatacenter") .operationParams(ImmutableList.of(getBroadcastAddress())) .onException(Functions.<String>constant(null)) .suppressDuplicates(true)) .pollOperation( new JmxOperationPollConfig<String>(RACK_NAME) .period(60, TimeUnit.SECONDS) .objectName(snitchMBean) .operationName("getRack") .operationParams(ImmutableList.of(getBroadcastAddress())) .onException(Functions.<String>constant(null)) .suppressDuplicates(true)) .pollAttribute( new JmxAttributePollConfig<Integer>(PEERS) .objectName(storageServiceMBean) .attributeName("TokenToEndpointMap") .onSuccess( new Function<Object, Integer>() { @Override public Integer apply(@Nullable Object arg) { Map input = (Map) arg; if (input == null || input.isEmpty()) return 0; return input.size(); } }) .onException(Functions.constant(-1))) .pollAttribute( new JmxAttributePollConfig<Integer>(LIVE_NODE_COUNT) .objectName(storageServiceMBean) .attributeName("LiveNodes") .onSuccess( new Function<Object, Integer>() { @Override public Integer apply(@Nullable Object arg) { List input = (List) arg; if (input == null || input.isEmpty()) return 0; return input.size(); } }) .onException(Functions.constant(-1))) .pollAttribute( new JmxAttributePollConfig<Integer>(READ_ACTIVE) .objectName(readStageMBean) .attributeName("ActiveCount") .onException(Functions.constant((Integer) null)) .enabled(retrieveUsageMetrics)) .pollAttribute( new JmxAttributePollConfig<Long>(READ_PENDING) .objectName(readStageMBean) .attributeName("PendingTasks") .onException(Functions.constant((Long) null)) .enabled(retrieveUsageMetrics)) .pollAttribute( new JmxAttributePollConfig<Long>(READ_COMPLETED) .objectName(readStageMBean) .attributeName("CompletedTasks") .onException(Functions.constant((Long) null)) .enabled(retrieveUsageMetrics)) .pollAttribute( new JmxAttributePollConfig<Integer>(WRITE_ACTIVE) .objectName(mutationStageMBean) .attributeName("ActiveCount") .onException(Functions.constant((Integer) null)) .enabled(retrieveUsageMetrics)) .pollAttribute( new JmxAttributePollConfig<Long>(WRITE_PENDING) .objectName(mutationStageMBean) .attributeName("PendingTasks") .onException(Functions.constant((Long) null)) .enabled(retrieveUsageMetrics)) .pollAttribute( new JmxAttributePollConfig<Long>(WRITE_COMPLETED) .objectName(mutationStageMBean) .attributeName("CompletedTasks") .onException(Functions.constant((Long) null)) .enabled(retrieveUsageMetrics)) .build(); functionFeed = FunctionFeed.builder() .entity(this) .period(3000, TimeUnit.MILLISECONDS) .poll( new FunctionPollConfig<Long, Long>(THRIFT_PORT_LATENCY) .onException(Functions.constant((Long) null)) .callable( new Callable<Long>() { public Long call() { try { long start = System.currentTimeMillis(); Socket s = new Socket(getAttribute(Attributes.HOSTNAME), getThriftPort()); s.close(); long latency = System.currentTimeMillis() - start; computeServiceUp(); return latency; } catch (Exception e) { if (log.isDebugEnabled()) log.debug("Cassandra thrift port poll failure: " + e); setAttribute(SERVICE_UP, false); return null; } } public void computeServiceUp() { // this will wait an additional poll period after thrift port is up, // as the caller will not have set yet, but that will help ensure it is // really healthy! setAttribute( SERVICE_UP, getAttribute(THRIFT_PORT_LATENCY) != null && getAttribute(THRIFT_PORT_LATENCY) >= 0 && Boolean.TRUE.equals(getAttribute(SERVICE_UP_JMX))); } }) .enabled(retrieveUsageMetrics)) .build(); jmxMxBeanFeed = JavaAppUtils.connectMXBeanSensors(this); }