private void checkForest(Set<Sensor> sensors) { if (!sensors.add(this)) throw new IllegalArgumentException("Circular dependency in sensors: " + name() + " is its own parent."); for (Sensor parent : parents) parent.checkForest(sensors); }
public void close() { for (MetricName metricName : topLevelMetricNames) metrics.removeMetric(metricName); for (Sensor sensor : sensors) metrics.removeSensor(sensor.name()); } }
/** * Remove a sensor (if it exists), associated metrics and its children. * * @param name The name of the sensor to be removed */ public void removeSensor(String name) { Sensor sensor = sensors.get(name); if (sensor != null) { List<Sensor> childSensors = null; synchronized (sensor) { synchronized (this) { if (sensors.remove(name, sensor)) { for (KafkaMetric metric : sensor.metrics()) removeMetric(metric.metricName()); log.debug("Removed sensor with name {}", name); childSensors = childrenSensors.remove(sensor); for (final Sensor parent : sensor.parents()) { childrenSensors.getOrDefault(parent, emptyList()).remove(sensor); } } } } if (childSensors != null) { for (Sensor childSensor : childSensors) removeSensor(childSensor.name()); } } }
public void close(final Metrics metrics) { metrics.removeSensor(sensor.name()); metrics.removeMetric(metric.metricName()); }
/** * Verifies that concurrent sensor add, remove, updates and read don't result * in errors or deadlock. */ @Test public void testConcurrentReadUpdate() throws Exception { final Random random = new Random(); final Deque<Sensor> sensors = new ConcurrentLinkedDeque<>(); metrics = new Metrics(new MockTime(10)); SensorCreator sensorCreator = new SensorCreator(metrics); final AtomicBoolean alive = new AtomicBoolean(true); executorService = Executors.newSingleThreadExecutor(); executorService.submit(new ConcurrentMetricOperation(alive, "record", () -> sensors.forEach(sensor -> sensor.record(random.nextInt(10000))))); for (int i = 0; i < 10000; i++) { if (sensors.size() > 5) { Sensor sensor = random.nextBoolean() ? sensors.removeFirst() : sensors.removeLast(); metrics.removeSensor(sensor.name()); } StatType statType = StatType.forId(random.nextInt(StatType.values().length)); sensors.add(sensorCreator.createSensor(statType, i)); for (Sensor sensor : sensors) { for (KafkaMetric metric : sensor.metrics()) { assertNotNull("Invalid metric value", metric.metricValue()); } } } alive.set(false); }
public static void main(String[] args) { long iters = Long.parseLong(args[0]); Metrics metrics = new Metrics(); try { Sensor parent = metrics.sensor("parent"); Sensor child = metrics.sensor("child", parent); for (Sensor sensor : Arrays.asList(parent, child)) { sensor.add(metrics.metricName(sensor.name() + ".avg", "grp1"), new Avg()); sensor.add(metrics.metricName(sensor.name() + ".count", "grp1"), new Count()); sensor.add(metrics.metricName(sensor.name() + ".max", "grp1"), new Max()); sensor.add(new Percentiles(1024, 0.0, iters, BucketSizing.CONSTANT, new Percentile(metrics.metricName(sensor.name() + ".median", "grp1"), 50.0), new Percentile(metrics.metricName(sensor.name() + ".p_99", "grp1"), 99.0))); } long start = System.nanoTime(); for (int i = 0; i < iters; i++) parent.record(i); double ellapsed = (System.nanoTime() - start) / (double) iters; System.out.println(String.format("%.2f ns per metric recording.", ellapsed)); } finally { metrics.close(); } } }
if (sensors.size() > 10) { Sensor sensor = random.nextBoolean() ? sensors.removeFirst() : sensors.removeLast(); metrics.removeSensor(sensor.name());
/** * Deletes a sensor and its parents, if any */ @Override public void removeSensor(final Sensor sensor) { Objects.requireNonNull(sensor, "Sensor is null"); metrics.removeSensor(sensor.name()); final Sensor parent = parentSensors.get(sensor); if (parent != null) { metrics.removeSensor(parent.name()); } }
private void checkForest(Set<Sensor> sensors) { if (!sensors.add(this)) throw new IllegalArgumentException("Circular dependency in sensors: " + name() + " is its own parent."); for (int i = 0; i < parents.length; i++) parents[i].checkForest(sensors); }
/** * Get or create a sensor with the given unique name and zero or more parent sensors. All parent sensors will * receive every value recorded with this sensor. * * @param name The name of the sensor * @param config A default configuration to use for this sensor for metrics that don't have their own config * @param recordingLevel The recording level. * @param parents The parent sensors * @return The sensor that is created */ public synchronized Sensor sensor(String name, MetricConfig config, Sensor.RecordingLevel recordingLevel, Sensor... parents) { // We need to make sure that all sensor names are unique across all groups, so use the sensor prefix Sensor result = metrics.sensor(sensorPrefix + name, config, Long.MAX_VALUE, recordingLevel, parents); if (result != null) sensorNames.add(result.name()); return result; }