{"record":{"id":"429138b6703f8c31","repo":"apache/hadoop","slug":"hybrid-metrics-registry-required","errorCode":null,"errorMessage":"Hybrid metrics: registry required.","messagePattern":"Hybrid metrics: registry required\\.","errorType":"exception","errorClass":"MetricsException","httpStatus":null,"severity":"error","filePath":"hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/metrics2/lib/MetricsSourceBuilder.java","lineNumber":79,"sourceCode":"\n  MetricsSourceBuilder(Object source, MutableMetricsFactory factory) {\n    this.source = checkNotNull(source, \"source\");\n    this.factory = checkNotNull(factory, \"mutable metrics factory\");\n    Class<?> cls = source.getClass();\n    registry = initRegistry(source);\n\n    for (Field field : ReflectionUtils.getDeclaredFieldsIncludingInherited(cls)) {\n      add(source, field);\n    }\n    for (Method method : ReflectionUtils.getDeclaredMethodsIncludingInherited(cls)) {\n      add(source, method);\n    }\n  }\n\n  public MetricsSource build() {\n    if (source instanceof MetricsSource) {\n      if (hasAtMetric && !hasRegistry) {\n        throw new MetricsException(\"Hybrid metrics: registry required.\");\n      }\n      return (MetricsSource) source;\n    }\n    else if (!hasAtMetric) {\n      throw new MetricsException(\"No valid @Metric annotation found.\");\n    }\n    return new MetricsSource() {\n      @Override\n      public void getMetrics(MetricsCollector builder, boolean all) {\n        registry.snapshot(builder.addRecord(registry.info()), all);\n      }\n    };\n  }\n\n  public MetricsInfo info() {\n    return info;\n  }\n","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/metrics2/lib/MetricsSourceBuilder.java#L61-L97","documentation":"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.').","triggerScenarios":"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.","commonSituations":"Evolving a hand-written source by adding @Metric convenience members; merging a registry-based metrics class into an existing MetricsSource implementation.","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"],"exampleFix":"// before\nclass MySource implements MetricsSource {\n  @Metric public MutableGaugeLong size;\n  public void getMetrics(MetricsCollector c, boolean all) { /* custom */ }\n}\n\n// after\nclass MySource implements MetricsSource {\n  private final MetricsRegistry registry = new MetricsRegistry(\"MySource\");\n  @Metric public MutableGaugeLong size;\n  public void getMetrics(MetricsCollector c, boolean all) {\n    registry.snapshot(c.addRecord(registry.info()), all);\n  }\n}","handlingStrategy":"validation","validationCode":"static void assertHybridSourceValid(Class<?> cls) {\n  boolean hasMetric = Arrays.stream(cls.getDeclaredFields())\n      .anyMatch(f -> f.isAnnotationPresent(Metric.class));\n  boolean hasRegistry = Arrays.stream(cls.getDeclaredFields())\n      .anyMatch(f -> MetricsRegistry.class.isAssignableFrom(f.getType()));\n  if (MetricsSource.class.isAssignableFrom(cls) && hasMetric && !hasRegistry) {\n    throw new IllegalStateException(\"hybrid metrics source needs a MetricsRegistry field\");\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["metrics2","hadoop","annotation","builder","hybrid-source"],"backgroundTag":"hybrid-metrics-registry-missing","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}