Skip to content

PHOENIX-5215 Migrate from HTrace to OpenTelemetry tracing - #2586

Open
lfrancke wants to merge 14 commits into
apache:masterfrom
lfrancke:PHOENIX-5215-otel
Open

PHOENIX-5215 Migrate from HTrace to OpenTelemetry tracing#2586
lfrancke wants to merge 14 commits into
apache:masterfrom
lfrancke:PHOENIX-5215-otel

Conversation

@lfrancke

@lfranckelfrancke commented Jul 26, 2026

Copy link
Copy Markdown
Member

What changes were proposed in this pull request?

Important

This builds upon #2394 which has stalled for four months now. The four commits from @xavifeds8 are taken as is and later commits build on top of those four.

Removes Apache HTrace from Phoenix and replaces it with a thin OpenTelemetry facade, PhoenixTracing, adapted from HBase's TraceUtil (HBASE-22120).

Per the previous discussions on the mailing list and issue this doesn't depend on an opentelemetry SDK itself and instead relies on the one provided by HBase (2.5+).

HTrace as a direct dependency is banned going forward by maven-enforcer (we still get plenty of transitive ones in the 2.5 profile)

References

Yes, this has been a long time coming :)

Changes on top of #2394

Rebase onto master:

  • PhoenixMapReduceUtil.addPhoenixDependencyJars, added to master after PHOENIX-5215 Migrate from HTrace to OpenTelemetry tracing #2394 was written, still shipped htrace-core to YARN containers.
  • HTrace is banned going forward by maven-enforcer as direct dependencies only as the HBase 2.5 profile brings in Hadoop 3.2.4 which itself brings in htrace-core4 transitively, not much we can do about that

Correctness:

  • Pinned opentelemetry.version to 1.15.0. PHOENIX-5215 Migrate from HTrace to OpenTelemetry tracing #2394 used 1.49.0, but HBase 2.5.3, 2.5.10 and 2.6.1 ship 1.15.0 (2.5.14 and 2.6.3+ ship 1.49.0). Depending on the older version should be safer.
  • Stopped storing an OpenTelemetry Scope on PhoenixConnection and TracingIterator. A Scope restores a thread-local and must be closed on the thread that opened it, but a Connection is closed by an arbitrary thread (including the HA framework) and an iterator by whichever thread finishes with it.
  • Credited HBase's TraceUtil properly in the PhoenixTracing javadoc, and fixed javadoc placement on the deprecated tracing properties, which sat after @Deprecated and so was not javadoc at all.

Why are the changes needed?

Phoenix's tracing has been non-functional for years, so this removes a dead dependency (with vulnerabilities) and paves the way for a more modern OpenTelemetry pipeline integrated into the stuff HBase provides

Does this PR introduce any user-facing change?

Yes, though only to a feature that was already non-functional anyway (see above).

Removed: writing traces to an HBase table.PhoenixMetricsSink and TraceWriter are gone, so SYSTEM.TRACING_STATS is no longer written. The sink configuration in bin/hadoop-metrics2-phoenix.properties and bin/hadoop-metrics2-hbase.properties is retained but commented out, with a note pointing at the OpenTelemetry agent. SYSTEM.TRACING_STATS itself, the tracing webapp and bin/traceserver.py are untouched, that is the scope of #1721.

Changed: TRACE ON is now inert. The SQL grammar is untouched and the hook remains, so TRACE ON and TRACE OFF still parse and execute without error, but no Phoenix-side trace is started. Previously Phoenix owned a sampler and started its own root traces; under OpenTelemetry, sampling belongs to the SDK and the root span comes from whatever instrumented the caller. I decided to keep this PR to the removal of HTrace and replacing it with OTel. Making TRACE ON useful again can come in a follow-up.

Deprecated: Phoenix tracing properties.phoenix.trace.frequency, phoenix.trace.probability.threshold, phoenix.trace.enabled, phoenix.trace.batchSize, phoenix.trace.threadPoolSize, phoenix.trace.traceBufferSize and phoenix.trace.read.pagesize are marked @Deprecated and no longer read. I'd also be happy to just remove them. Opinions welcome. OpenTelemetry is configured through the agent, for example OTEL_EXPORTER_OTLP_ENDPOINT.

Unchanged: everything else. With no agent attached there is no behaviour change and no overhead.

How was this patch tested?

New PhoenixTracingIT covers the no-op path with no SDK present, TRACE ON / TRACE OFF round-tripping, and that no thread is left pinned to a stale Context after the connection closes.

Locally, against the HBase 2.6 profile:

  • Full build green across all 15 modules, including checkstyle, RAT, maven-enforcer and dependency analysis.
  • Unit tests green.
  • PhoenixTracingIT (3 tests) green
  • phoenix-pherf including its integration tests green.
  • mvn spotless:check clean across all modules.

Packaging, verified by inspecting the built artifacts.

Was this patch authored or co-authored using generative AI tooling?

Yes. Partially

Generated-by: Claude Opus 5 (Claude Code)

The four commits by @xavifeds8 are preserved unchanged from #2394, no idea about those. The commits above them carry Generated-by: and Co-authored-by: trailers individually, but even those are partially human authored. I've attempted this whole exercise already two or so years ago....and took some of what I had back then.

Per the ASF Generative Tooling Guidance: PhoenixTracing is adapted from HBase's TraceUtil, which is Apache-2.0 and therefore compatible, and this derivation is stated in the class javadoc.

xavifeds8and others added 7 commits July 25, 2026 22:28
…jars
Generated-by: Claude Opus 5 (Claude Code)
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…HBase
Generated-by: Claude Opus 5 (Claude Code)
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Generated-by: Claude Opus 5 (Claude Code)
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Generated-by: Claude Opus 5 (Claude Code)
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
@lfrancke
lfrancke marked this pull request as ready for review July 27, 2026 15:24
@lfrancke

Copy link
Copy Markdown
MemberAuthor

Yetus failed twice. The first one was real and I fixed the issues but the second one is no. I believe those test failures are unrelated and seem to happen on master as well.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Replaces Phoenix’s obsolete HTrace integration with an OpenTelemetry facade and updates tracing call sites, packaging, configuration, and tests.

Changes:

  • Removes HTrace dependencies, sinks, readers, utilities, and tests.
  • Adds PhoenixTracing and migrates client/server instrumentation to OpenTelemetry.
  • Updates shaded artifacts, runtime configuration, and tracing integration tests.

Reviewed changes

Copilot reviewed 48 out of 50 changed files in this pull request and generated 4 comments.

Show a summary per file
FileDescription
src/main/config/checkstyle/checker.xmlChanges static-import ordering.
pom.xmlManages OpenTelemetry and bans HTrace.
phoenix-server/pom.xmlPrevents OpenTelemetry shading.
phoenix-mapreduce-byo-shaded-hbase/pom.xmlRemoves HTrace shading exception.
phoenix-core/src/test/java/org/apache/phoenix/trace/TraceSpanReceiverTest.javaRemoves receiver tests.
phoenix-core/src/test/java/org/apache/phoenix/metrics/LoggingSink.javaRemoves tracing utility dependency.
phoenix-core/src/test/java/org/apache/phoenix/mapreduce/util/PhoenixMapReduceUtilTest.javaRemoves HTrace jar assertion.
phoenix-core/src/test/java/org/apache/hadoop/metrics2/lib/ExposedMetricsInfoImpl.javaRemoves obsolete test helper.
phoenix-core/src/test/java/org/apache/hadoop/metrics2/impl/ExposedMetricsRecordImpl.javaRemoves obsolete test helper.
phoenix-core/src/test/java/org/apache/hadoop/metrics2/impl/ExposedMetricCounterLong.javaRemoves obsolete test helper.
phoenix-core/src/it/java/org/apache/phoenix/trace/TracingTestUtil.javaRemoves legacy sink helper.
phoenix-core/src/it/java/org/apache/phoenix/trace/PhoenixTracingIT.javaTests no-SDK and TRACE behavior.
phoenix-core/src/it/java/org/apache/phoenix/trace/PhoenixTracingEndToEndIT.javaRemoves legacy tracing ITs.
phoenix-core/src/it/java/org/apache/phoenix/trace/PhoenixTagImpl.javaRemoves legacy metrics helper.
phoenix-core/src/it/java/org/apache/phoenix/trace/PhoenixTableMetricsWriterIT.javaRemoves table-writer ITs.
phoenix-core/src/it/java/org/apache/phoenix/trace/BaseTracingTestIT.javaRemoves HTrace test fixture.
phoenix-core/pom.xmlReplaces test HTrace dependency.
phoenix-core-server/src/main/java/org/apache/phoenix/mapreduce/util/PhoenixMapReduceUtil.javaStops shipping HTrace jars.
phoenix-core-server/src/main/java/org/apache/phoenix/index/PhoenixTransactionalIndexer.javaMigrates transactional index spans.
phoenix-core-server/src/main/java/org/apache/phoenix/hbase/index/LockManager.javaMigrates row-lock tracing.
phoenix-core-server/src/main/java/org/apache/phoenix/hbase/index/IndexRegionObserver.javaMigrates index observer spans.
phoenix-core-server/src/main/java/org/apache/phoenix/hbase/index/Indexer.javaMigrates indexer spans.
phoenix-core-server/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.javaRemoves HTrace initialization.
phoenix-core-server/src/main/java/org/apache/phoenix/coprocessor/BaseScannerRegionObserver.javaMigrates scanner span lifecycle.
phoenix-core-server/pom.xmlAdds provided OpenTelemetry APIs.
phoenix-core-client/src/main/java/org/apache/phoenix/trace/util/Tracing.javaRemoves HTrace facade.
phoenix-core-client/src/main/java/org/apache/phoenix/trace/util/NullSpan.javaRemoves HTrace no-op span.
phoenix-core-client/src/main/java/org/apache/phoenix/trace/util/ConfigurationAdapter.javaRemoves sampler configuration adapter.
phoenix-core-client/src/main/java/org/apache/phoenix/trace/TracingUtils.javaRemoves legacy tracing utilities.
phoenix-core-client/src/main/java/org/apache/phoenix/trace/TracingIterator.javaManages OpenTelemetry iterator spans.
phoenix-core-client/src/main/java/org/apache/phoenix/trace/TraceWriter.javaRemoves trace-table writer.
phoenix-core-client/src/main/java/org/apache/phoenix/trace/TraceSpanReceiver.javaRemoves HTrace receiver.
phoenix-core-client/src/main/java/org/apache/phoenix/trace/TraceReader.javaRemoves trace-table reader.
phoenix-core-client/src/main/java/org/apache/phoenix/trace/PhoenixTracing.javaAdds the OpenTelemetry facade.
phoenix-core-client/src/main/java/org/apache/phoenix/trace/PhoenixMetricsSink.javaRemoves legacy metrics sink.
phoenix-core-client/src/main/java/org/apache/phoenix/trace/MetricsInfoImpl.javaRemoves tracing metrics helper.
phoenix-core-client/src/main/java/org/apache/phoenix/query/QueryServicesOptions.javaDecouples default frequency from HTrace.
phoenix-core-client/src/main/java/org/apache/phoenix/query/QueryServices.javaDeprecates legacy tracing properties.
phoenix-core-client/src/main/java/org/apache/phoenix/jdbc/PhoenixStatement.javaTraces statement execution with OpenTelemetry.
phoenix-core-client/src/main/java/org/apache/phoenix/jdbc/PhoenixConnection.javaMigrates connection tracing state.
phoenix-core-client/src/main/java/org/apache/phoenix/iterate/SerialIterators.javaPropagates context to serial scans.
phoenix-core-client/src/main/java/org/apache/phoenix/iterate/ParallelIterators.javaPropagates context to parallel scans.
phoenix-core-client/src/main/java/org/apache/phoenix/execute/MutationState.javaMigrates mutation spans.
phoenix-core-client/src/main/java/org/apache/phoenix/execute/BaseQueryPlan.javaAdds query execution spans.
phoenix-core-client/src/main/java/org/apache/phoenix/compile/TraceQueryPlan.javaAdapts TRACE statements to OpenTelemetry.
phoenix-core-client/src/main/antlr3/PhoenixSQL.gUses the new TRACE option parser.
phoenix-core-client/pom.xmlAdds provided OpenTelemetry dependencies.
phoenix-client-parent/pom.xmlPrevents client-side OpenTelemetry shading.
bin/hadoop-metrics2-phoenix.propertiesRetires Phoenix trace sink configuration.
bin/hadoop-metrics2-hbase.propertiesRetires HBase trace sink configuration.
Suppressed comments (1)

phoenix-core-client/src/main/java/org/apache/phoenix/trace/PhoenixTracing.java:214

  • If action.get() throws synchronously, the exception escapes without recording the error or ending the newly created span. This leaves a live span that can never be exported. Handle synchronous RuntimeException/Error the same way as exceptional future completion.
 try (Scope ignored = span.makeCurrent()) {
CompletableFuture<T> future = action.get();
endSpan(future, span);
return future;
}

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment threadpom.xml
Comment on lines +1815 to +1820
<bannedDependencies>
<message>HTrace is retired, use OpenTelemetry via PhoenixTracing</message>
<searchTransitive>true</searchTransitive>
<excludes>
<exclude>org.apache.htrace:*</exclude>
</excludes>

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, that was my fault. I did not realize that Hadoop 3.2.4 still has HTrace. I've now changed the rule to only look for direct dependencies we add ourselves.

Comment on lines 1513 to +1514
Span child =
Tracing.child(span, "Writing mutationbatch for table: " + Bytes.toString(htableName));
PhoenixTracing.createSpan("phoenix.mutation.batch.write." + Bytes.toString(htableName));

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, good catch. This should be fixed now.

We didn't use the suggested finally because there is already a finally which runs on every retry iteration. Ending it there would kill the just created span immediately.

Comment on lines +1671 to 1677
} catch (RuntimeException e) {
// A RuntimeException here is a Phoenix bug, not a failed mutation. Rethrow it rather
// than wrapping it in a CommitException, which would report it as a server-side commit
// failure. Checked exceptions from hTable.batch() still fall through to the handler
// below. This is the pattern SpotBugs REC_CATCH_EXCEPTION asks for.
throw e;
} catch (Exception e) {

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was a decision I (human me, not AI) made. I don't know when/how this happened but anyway the existing code fails SpotBugs - maybe the rule was introduced after the code already existed? I don't know. But SpotBugs suggests exactly this pattern as a fix.

I can revert it but then we'll need a SpotBugs exclusion for that line. Personally I think it makes sense to keep this in but I'll let you decide.

Comment on lines +74 to +76
private static Span createSpan(String name, SpanKind kind) {
return getTracer().spanBuilder(name).setSpanKind(kind).startSpan();
}

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docs were wrong, that's true. But other than that this is a port from the HBase version.

Server side this makes no difference as HBase already creates a span, but client side it runs wherever and in those cases it does make sense to start something.

We've chosen to fix the javadoc instead of changing the behavior.

lfranckeand others added 6 commits August 16, 2026 09:34
Generated-by: Claude Opus 5 (Claude Code)
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Generated-by: Claude Opus 5 (Claude Code)
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Generated-by: Claude Opus 5 (Claude Code)
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Generated-by: Claude Opus 5 (Claude Code)
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Generated-by: Claude Opus 5 (Claude Code)
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Generated-by: Claude Opus 5 (Claude Code)
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
@lfrancke

lfrancke commented Aug 16, 2026

Copy link
Copy Markdown
MemberAuthor

@apurtell Thanks for kicking of the review.

I've addressed all comments but can't kick off a re-review myself.
There is one comment where I made a decision that could use another human pair of eyes. I'm fine reverting that as well.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@lfrancke@xavifeds8