Event sinks are responsible for receiving and optionally modifying event data.
Event sink factories are responsible for handling event types during parsing.
Interface for Flight Recorder parser extensions.
Handles loading of parser extension factories using Java Service Loader.
A descriptor of a value field for use in
To create a new parser extension you start by implementing the
IParserExtension interface. This
is a (normally stateless) factory class that can create implementations of
IEventSinkFactory. For each
loading of a Flight Recording exactly one instance of IEventSinkFactory will be created for each
implementation of IParserExtension that is passed to the loader.
Parser extensions are loaded using the Java ServiceLoader framework. To register an
implementation, add its fully qualified class name to a resource file named
org/openjdk/jmc/flightrecorder/parser/IParserExtension that should be included in the
same jar file as the implementation.
The actual reading of the Flight Recording is then split into multiple threads that read
different parts of the recording. For every event type that is encountered a call to
IEventSinkFactory.create is made to get an
IEventSink instance. For every event of
IEventSink.addEvent is called with the actual event values. Note that the IEventSinkFactory
instance will be shared by all read threads so the create method must be thread safe. However,
each thread will have its own IEventSink instance for every event that it has found. This means
that there will most probably be multiple instances of IEventSink for the same event type, each
one owned by a separate read thread.
When all events have been read and passed through the sinks (all read threads are finished), a
IEventSinkFactory.flush will be made. This allows the factory to create any additional events
that it may need to create.
IParserExtension.getEventSinkFactory method takes another IEventSinkFactory instance as an
argument. This subfactory is the next factory to pass event types and events to. This allows for
creating a chain of extensions that modify the events in different ways. The last factory in this
chain is an internal implementation that takes care of the events for use in the Mission Control.
Basically, for every call to
IEventSinkfactory.create you will get the metadata for an
event type. Inspect this metadata and call the
create method of the subfactory with the
metadata, either modified or unmodified. This will give you an IEventSink instance that you can
return immediately if you don't want to do anything with this event, or use in your own
IEventSink implementation. If you want to create additional "synthetic" event types based on this
type, then you can call
create on the subfactory multiple times.
For every call to
IEventSink.addEvent you will get the event values. You can look at
these values and do whatever you want with them. Examples are generating additional attributes
and calculating statistics. Once you have your new values you call
addEvent on the
correct sink from the subfactory. Note that the arguments to the
addEvent call (the event
values) must match the attributes specified when the IEventSink was created with the
If you want to create events like statistics that should be created after all other events have
been read, then you can use the
method. Create a sink for your new event type when you get the
create call for the type
that you want to calculate statistics for. Collect data during
addEvent calls and when
you get the
flush call, add the statistics events by calling
addEvent on the
statistics event sink.
Copyright © 2018. All rights reserved.