@Override public void run() { try { for (Entry<String, ExportMeta> mapEntry : exportPathMap.entrySet()) { ExportMeta exportMeta = mapEntry.getValue(); // rotate as necessary synchronized (exportMeta) { MetricRegistryManager registryManager = exportMeta.registryManager; if (registryManager == null) { continue; } long oldLastRotatedTimestamp = registryManager.getLastRotatedTimestamp(); MetricRegistry currentMetricRegistry = registryManager.rotateAsNecessary(); MetricRegistry workingMetricRegistry = registryManager.get(); if (currentMetricRegistry != null && currentMetricRegistry != workingMetricRegistry) { if (exportMeta.dataPath != null) { try { // write out stats for old metric registry StringBuilder sb = new StringBuilder(); sb = exportMeta.metricsReporter.report( currentMetricRegistry, oldLastRotatedTimestamp, registryManager.getRotationInterval(), registryManager.getRotationTimeUnit(), sb); if (logger.isDebugEnabled()) { logger.debug( "Flushing to old data node after rotation: currentMetricRegistry={}; workingMetricRegistry={}; path={}; data={}", currentMetricRegistry, workingMetricRegistry, exportMeta.dataPath, sb.toString().replace("\n", "")); } zkClientUtil.updatePath( getContext().getZkClient(), getContext().getPathScheme(), exportMeta.dataPath, sb.toString().getBytes(UTF_8), getContext().getDefaultZkAclList(), CreateMode.PERSISTENT, -1); } catch (Exception e) { logger.error( "Could not export update metrics data after rotation: path=" + exportMeta.dataPath, e); } } // set to null to force creation of new node in ZK exportMeta.dataPath = null; } } } } catch (Exception e) { logger.error("Unexpected exception: " + e, e); } } // run
void scheduleExport( final String clusterId, final String serviceId, final String nodeId, final MetricRegistryManager registryManager, long updateInterval, TimeUnit updateIntervalTimeUnit) { final String key = exportPathMapKey(clusterId, serviceId, nodeId); synchronized (exportPathMap) { if (!exportPathMap.containsKey(key)) { exportPathMap.put(key, new ExportMeta(null, registryManager, null)); } else { logger.info("Metrics export already scheduled: {}", key); return; } } final ZkMetricsReporter reporter = ZkMetricsReporter.builder() .convertRatesTo(TimeUnit.SECONDS) .convertDurationsTo(TimeUnit.MILLISECONDS) .build(); // determine runnable interval long updateIntervalSeconds = updateIntervalTimeUnit.toSeconds(updateInterval); updateIntervalSeconds = Math.min( updateIntervalSeconds / 2, registryManager.getRotationTimeUnit().toSeconds(registryManager.getRotationInterval()) / 2); if (updateIntervalSeconds < 1) { updateIntervalSeconds = 1; } // get export metadata for this key final ExportMeta exportMeta = exportPathMap.get(key); if (exportMeta.future != null) { // cancel existing job if there is one exportMeta.future.cancel(false); } exportMeta.metricsReporter = reporter; // create future exportMeta.future = executorService.scheduleAtFixedRate( new Runnable() { @Override public void run() { // export to zk try { synchronized (exportMeta) { MetricRegistry currentMetricRegistry = registryManager.get(); // logger.trace("EXPORTING METRICS..."); StringBuilder sb = new StringBuilder(); sb = reporter.report( currentMetricRegistry, registryManager.getLastRotatedTimestamp(), registryManager.getRotationInterval(), registryManager.getRotationTimeUnit(), sb); // logger.trace("EXPORTING METRICS: clusterId={}; serviceId={}; data=\n{}", // clusterId, // serviceId, // sb); if (exportMeta.dataPath == null) { PathScheme pathScheme = getContext().getPathScheme(); String dataPathPrefix = pathScheme .getAbsolutePath( PathType.METRICS, pathScheme.joinTokens(clusterId, serviceId, nodeId)) .replace("\"", "'"); // update node and get new path exportMeta.dataPath = zkClientUtil.updatePath( getContext().getZkClient(), getContext().getPathScheme(), dataPathPrefix + "-", sb.toString().getBytes(UTF_8), getContext().getDefaultZkAclList(), CreateMode.PERSISTENT_SEQUENTIAL, -1); logger.debug("New data path: path={}", exportMeta.dataPath); // put in again to update data exportPathMap.put(key, exportMeta); } else { logger.debug("Updating data path: path={}", exportMeta.dataPath); // update node zkClientUtil.updatePath( getContext().getZkClient(), getContext().getPathScheme(), exportMeta.dataPath, sb.toString().getBytes(UTF_8), getContext().getDefaultZkAclList(), CreateMode.PERSISTENT, -1); } exportMeta.notifyAll(); } logger.debug("Updated metrics data: dataPath={}", exportMeta.dataPath); } catch (Exception e) { logger.error( "Could not export metrics data: clusterId=" + clusterId + "; serviceId=" + serviceId + "; nodeId=" + nodeId + "; dataPath=" + exportMeta.dataPath, e); } } }, 0, updateIntervalSeconds, TimeUnit.SECONDS); }