Execution and observability
The shared mechanics — discovery, annotation attributes, classloading, how a plugin gets into the distribution — are on the plugin types overview.
Extension point
An extension point is a hook: Hop announces that something happened, and every plugin listening for that announcement gets called. There are about a hundred named points, from HopGuiStart through PipelinePrepareExecution and TransformBeforeStart to PipelineCompleted, and the Hop codebase itself uses them heavily.
- Annotation
-
@ExtensionPoint - Implement
-
IExtensionPoint<T> - Plugin type
-
ExtensionPointPluginType, idEXTENSION_POINT - Examples
-
over a hundred in the codebase;
engine/src/main/java/org/apache/hop/lineage/xpis a compact set
@ExtensionPoint(
id = "LineageHubPipelineCompletedXp",
extensionPointId = "PipelineCompleted",
description = "Emits lineage at pipeline completion")
public class LineageHubPipelineCompletedXp
implements IExtensionPoint<IPipelineEngine<PipelineMeta>> {
@Override
public void callExtensionPoint(
ILogChannel log, IVariables variables, IPipelineEngine<PipelineMeta> pipeline) { ... }
} Two ids, and they are not the same thing:
id-
the plugin’s own id, unique among extension points.
extensionPointId-
which hook to listen to. The names are the constants of the
HopExtensionPointenum inorg.apache.hop.core.extension, which is also the list of what is available. Anything can fire an extension point, so a plugin may define and announce its own.
The generic parameter is the object Hop hands over, and it decides where your plugin will and will not work:
| Bind to the interface, not the implementation. An extension point declared as |
Extension points run inline, on the thread that fired them. Anything slow belongs on a queue, not in callExtensionPoint.
Logging
A logging plugin participates in the lifecycle of the logging subsystem. It is initialised very early — HopClientEnvironment.init() loads logging plugins immediately after the registry is filled, before anything else — which is what makes it the right place to attach an external logging framework or a log store.
- Annotation
-
@LoggingPlugin - Implement
-
ILoggingPlugin - Plugin type
-
LoggingPluginType, idLOGGING
The interface is just init() and dispose(); everything else is done by registering your own listeners with Hop’s logging registry from init().
There are no implementations in the distribution today, so there is no in-tree example to copy. For routing log lines somewhere else, an extension point on the logging-related hooks, or an execution information location, is usually the easier route.
Execution information location
An execution information location is where Hop stores what happened during a run: the execution itself, its state, its logging text, its metrics, and any sampled data. This is what the Hop GUI execution perspective and Hop Server read back.
- Annotation
-
@ExecutionInfoLocationPlugin - Implement
-
IExecutionInfoLocation - Plugin type
-
ExecutionInfoLocationPluginType, idEXECUTION_INFO_LOCATIONS - Examples
-
engine/src/main/java/org/apache/hop/execution/local(files),…/remote(another Hop Server),…/caching,plugins/misc/execution-database(a relational database)
The interface has two halves. The writing half — registerExecution, updateExecutionState, registerData — is called by the engines while a pipeline or workflow runs. The reading half — getExecution, getExecutionState, findExecutions, findChildIds, getExecutionData — is called by the UI and the server. Implement both, including the parent/child lookups, or drill-down in the execution perspective will not work.
The settings live in an Execution Information Location metadata object, so the plugin’s fields carry @HopMetadataProperty and @GuiWidgetElement annotations, exactly like a variable resolver.
Locations are written to on every state update of every component. Buffering is normal — unBuffer(executionId) and clearCaches() exist for that reason — and the caching implementations in the engine are the examples to follow.
Execution data sampler
A sampler decides which rows are captured while a pipeline runs, so they can be shown afterwards. The built-ins are first rows, last rows, random rows and basic data profiling.
- Annotation
-
@ExecutionDataSamplerPlugin - Implement
-
IExecutionDataSampler<Store> - Plugin type
-
ExecutionDataSamplerPluginType, idEXECUTION_DATA_SAMPLER_LOCATIONS - Examples
-
engine/src/main/java/org/apache/hop/execution/sampler/plugins
Two methods do the work:
createSamplerStore(ExecutionDataSamplerMeta)-
creates the store this sampler accumulates into, one per transform copy and stream
sampleRow(store, streamType, rowMeta, row)-
called for every row on that stream
|
|
Samplers are selected in the pipeline run configuration, and their stores are written to the execution information location.
Lineage sink
A lineage sink is where Hop’s lineage events are delivered — a catalogue, a broker, a file. Hop ships an OpenLineage sink.
- Annotation
-
@LineageSinkPlugin - Implement
-
ILineageSink - Plugin type
-
LineageSinkPluginType, idLINEAGE_SINKS - Example
-
plugins/tech/openlineage - Details
accept(List<LineageEvent>) receives batches from the lineage hub, with optional init(…) and shutdown() around it. The hub dispatches asynchronously, so a slow sink slows down lineage delivery, not the pipeline.
Hop Server servlet
A server plugin is an HTTP endpoint on Hop Server. Everything the server exposes — status, execution, sniffing, the export of pipelines — is one of these.
- Annotation
-
@HopServerServlet - Implement
-
IHopServerPlugin, in practice by extendingBaseHttpServletorBaseHopServerPlugin - Plugin type
-
HopServerPluginType, idHOP_SERVER_SERVLET - Examples
-
engine/src/main/java/org/apache/hop/www
@HopServerServlet(id = "pipelineStatus", name = "Get the status of a pipeline")
public class GetPipelineStatusServlet extends BaseHttpServlet implements IHopServerPlugin { ... } getContextPath() is the path the servlet is mounted on, and setup(PipelineMap, WorkflowMap) hands over the server’s registries of running pipelines and workflows.
| A servlet plugin is an addition to the attack surface of Hop Server. Authentication is handled by the server, not by the servlet, but everything else — what the endpoint exposes, what it accepts, and what it does with it — is on the plugin. See SECURITY.md and the threat model it links before adding one. |