apache/hadoop · error · MetricsException
Hybrid metrics: registry required.
Error message
Hybrid metrics: registry required.
What it means
MetricsSourceBuilder.build() supports 'hybrid' sources: objects that implement MetricsSource but also carry @Metric-annotated members. Those members are wired through a MetricsRegistry field on the class; if @Metric members exist but no MetricsRegistry field does, build() throws MetricsException('Hybrid metrics: registry required.').
Source
Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/metrics2/lib/MetricsSourceBuilder.java:79
MetricsSourceBuilder(Object source, MutableMetricsFactory factory) {
this.source = checkNotNull(source, "source");
this.factory = checkNotNull(factory, "mutable metrics factory");
Class<?> cls = source.getClass();
registry = initRegistry(source);
for (Field field : ReflectionUtils.getDeclaredFieldsIncludingInherited(cls)) {
add(source, field);
}
for (Method method : ReflectionUtils.getDeclaredMethodsIncludingInherited(cls)) {
add(source, method);
}
}
public MetricsSource build() {
if (source instanceof MetricsSource) {
if (hasAtMetric && !hasRegistry) {
throw new MetricsException("Hybrid metrics: registry required.");
}
return (MetricsSource) source;
}
else if (!hasAtMetric) {
throw new MetricsException("No valid @Metric annotation found.");
}
return new MetricsSource() {
@Override
public void getMetrics(MetricsCollector builder, boolean all) {
registry.snapshot(builder.addRecord(registry.info()), all);
}
};
}
public MetricsInfo info() {
return info;
}
View on GitHub (pinned to 2add963021)
Solutions
- Add a MetricsRegistry field (private final MetricsRegistry registry = new MetricsRegistry(...)) and snapshot it inside getMetrics
- Drop the @Metric annotations if getMetrics is fully custom
- Move the annotated members into a separate registry-based class and register that instead
Example fix
// before
class MySource implements MetricsSource {
@Metric public MutableGaugeLong size;
public void getMetrics(MetricsCollector c, boolean all) { /* custom */ }
}
// after
class MySource implements MetricsSource {
private final MetricsRegistry registry = new MetricsRegistry("MySource");
@Metric public MutableGaugeLong size;
public void getMetrics(MetricsCollector c, boolean all) {
registry.snapshot(c.addRecord(registry.info()), all);
}
} Defensive patterns
Strategy: validation
Validate before calling
static void assertHybridSourceValid(Class<?> cls) {
boolean hasMetric = Arrays.stream(cls.getDeclaredFields())
.anyMatch(f -> f.isAnnotationPresent(Metric.class));
boolean hasRegistry = Arrays.stream(cls.getDeclaredFields())
.anyMatch(f -> MetricsRegistry.class.isAssignableFrom(f.getType()));
if (MetricsSource.class.isAssignableFrom(cls) && hasMetric && !hasRegistry) {
throw new IllegalStateException("hybrid metrics source needs a MetricsRegistry field");
}
} Prevention
- Whenever you add @Metric members to a MetricsSource implementation, add a MetricsRegistry field and snapshot it in getMetrics
- Run assertHybridSourceValid in a unit test for every metrics class
- Keep custom getMetrics classes free of @Metric unless you wire the registry
When it happens
Trigger: A class implements MetricsSource (custom getMetrics) and declares @Metric-annotated fields or methods, but has no MetricsRegistry field for the builder to populate and snapshot.
Common situations: Evolving a hand-written source by adding @Metric convenience members; merging a registry-based metrics class into an existing MetricsSource implementation.
Related errors
- No valid @Metric annotation found.
- Unsupported counter type: {}
- Unsupported gauge type: {}
- Unsupported tag type: {}
- Error setting field {} annotated with {}
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/429138b6703f8c31.
Report an issue: GitHub.