When JxmSink object is instantiated, a reporter object is created.
private[spark] class JmxSink(val property: Properties, val registry: MetricRegistry,
securityMgr: SecurityManager) extends Sink {
val reporter: JmxReporter = JmxReporter.forRegistry(registry).build()
override def start() {
reporter.start()
}
override def stop() {
reporter.stop()
}
override def report() { }
}
The sequences of operations after val reporter: JmxReporter = JmxReporter.forRegistry(registry).build()
is called.
public static Builder forRegistry(MetricRegistry registry) {
return new Builder(registry);
}
private Builder(MetricRegistry registry) {
this.registry = registry;
this.rateUnit = TimeUnit.SECONDS;
this.durationUnit = TimeUnit.MILLISECONDS;
this.domain = "metrics";
this.objectNameFactory = new DefaultObjectNameFactory();
this.specificDurationUnits = Collections.emptyMap();
this.specificRateUnits = Collections.emptyMap();
}
/**
* Builds a {@link JmxReporter} with the given properties.
*
* @return a {@link JmxReporter}
*/
public JmxReporter build() {
final MetricTimeUnits timeUnits = new MetricTimeUnits(rateUnit, durationUnit, specificRateUnits, specificDurationUnits);
if (mBeanServer==null) {
mBeanServer = ManagementFactory.getPlatformMBeanServer();
}
return new JmxReporter(mBeanServer, domain, registry, filter, timeUnits, objectNameFactory);
}
then, the start method of MetricsSystem is called. sinks.foreach(_.start)
def start() {
require(!running, "Attempting to start a MetricsSystem that is already running")
running = true
StaticSources.allSources.foreach(registerSource)
registerSources()
registerSinks()
sinks.foreach(_.start)
}
then start() method of JmxSink is called.
override def start() {
reporter.start()
}
code of reporter.start()
:
public void start() {
registry.addListener(listener);
}
Code of addListener method of MetricRegisty class.
/**
* Adds a {@link MetricRegistryListener} to a collection of listeners that will be notified on
* metric creation. Listeners will be notified in the order in which they are added.
* <p/>
* <b>N.B.:</b> The listener will be notified of all existing metrics when it first registers.
*
* @param listener the listener that will be notified
*/
public void addListener(MetricRegistryListener listener) {
listeners.add(listener);
for (Map.Entry<String, Metric> entry : metrics.entrySet()) {
notifyListenerOfAddedMetric(listener, entry.getValue(), entry.getKey());
}
}
private void notifyListenerOfAddedMetric(MetricRegistryListener listener, Metric metric, String name) {
if (metric instanceof Gauge) {
listener.onGaugeAdded(name, (Gauge<?>) metric);
} else if (metric instanceof Counter) {
listener.onCounterAdded(name, (Counter) metric);
} else if (metric instanceof Histogram) {
listener.onHistogramAdded(name, (Histogram) metric);
} else if (metric instanceof Meter) {
listener.onMeterAdded(name, (Meter) metric);
} else if (metric instanceof Timer) {
listener.onTimerAdded(name, (Timer) metric);
} else {
throw new IllegalArgumentException("Unknown metric type: " + metric.getClass());
}
}
take onCounterAdded as an example. This method is a method of JmxListener which is a static class of JmxReportor.
@Override
public void onCounterAdded(String name, Counter counter) {
try {
if (filter.matches(name, counter)) {
final ObjectName objectName = createName("counters", name);
registerMBean(new JmxCounter(counter, objectName), objectName);
}
} catch (InstanceAlreadyExistsException e) {
LOGGER.debug("Unable to register counter", e);
} catch (JMException e) {
LOGGER.warn("Unable to register counter", e);
}
}
type=counters,this.name = metrics
private ObjectName createName(String type, String name) {
return objectNameFactory.createName(type, this.name, name);
}
objetNameFactory is object of DefaultObjectNameFactory, which implements ObjectNameFactory. objetNameFactory in instantiated at Builder.build() method.
public class DefaultObjectNameFactory implements ObjectNameFactory {
private static final Logger LOGGER = LoggerFactory.getLogger(JmxReporter.class);
@Override
public ObjectName createName(String type, String domain, String name) {
try {
ObjectName objectName = new ObjectName(domain, "name", name);
if (objectName.isPattern()) {
objectName = new ObjectName(domain, "name", ObjectName.quote(name));
}
return objectName;
} catch (MalformedObjectNameException e) {
try {
return new ObjectName(domain, "name", ObjectName.quote(name));
} catch (MalformedObjectNameException e1) {
LOGGER.warn("Unable to register {} {}", type, name, e1);
throw new RuntimeException(e1);
}
}
}
}
public interface ObjectNameFactory {
ObjectName createName(String type, String domain, String name);
}
JmxCounter
private static class JmxCounter extends AbstractBean implements JmxCounterMBean {
private final Counter metric;
private JmxCounter(Counter metric, ObjectName objectName) {
super(objectName);
this.metric = metric;
}
@Override
public long getCount() {
return metric.getCount();
}
}
Counter is a class in com.codahale.metrics package.