New - Support distribution.solarwinds config node with per-key merging - #549
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds support for reading SolarWinds agent configuration from a new top-level distribution.solarwinds node in sdk-config.yaml, with per-key merging against the existing instrumentation/development.java.solarwinds node (distribution takes precedence per key). The resolution logic is centralized in a new SolarwindsConfigResolver, and both the agent bootstrap/customization path and shared config customizer are updated to use it; additionally, logging output is enhanced to include thread name and a flaky JDBC test is stabilized.
Changes:
- Introduce
SolarwindsConfigResolverto resolve and mergedistribution.solarwinds+instrumentation/development.java.solarwinds. - Update
DeclarativeLoaderandSharedConfigCustomizerProviderto use the centralized resolver. - Update example/smoke YAML configs, enhance internal log formatting, and stabilize JDBC instrumentation tests.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| smoke-tests/sdk-config.yaml | Moves shared SolarWinds settings into distribution.solarwinds for smoke tests. |
| sdk-config.yaml | Adds distribution.solarwinds to the root example config and adds placeholder sections. |
| libs/shared/src/test/java/com/solarwinds/opentelemetry/extensions/config/provider/SharedConfigCustomizerProviderTest.java | Adds coverage for reading/precedence/merge behavior across distribution + instrumentation nodes. |
| libs/shared/src/main/java/com/solarwinds/opentelemetry/extensions/config/SolarwindsConfigResolver.java | New centralized resolver implementing per-key merge semantics. |
| libs/shared/src/main/java/com/solarwinds/opentelemetry/extensions/config/provider/SharedConfigCustomizerProvider.java | Switches to centralized resolver instead of hard-coded instrumentation-node traversal. |
| libs/logging/src/main/java/com/solarwinds/joboe/logging/Logger.java | Updates log label formatting to include thread name. |
| libs/core/src/main/java/com/solarwinds/joboe/core/rpc/RpcClient.java | Minor refactor to a method reference for async init submission. |
| instrumentation/jdbc/javaagent/src/test/java/com/solarwinds/opentelemetry/instrumentation/JdbcInstrumentationTest.java | Stabilizes test by reusing container and asserting via span polling instead of exact trace structure. |
| custom/src/test/java/com/solarwinds/opentelemetry/extensions/config/DeclarativeLoaderTest.java | Updates tests to match new declarative customization integration and distribution-node support. |
| custom/src/main/java/com/solarwinds/opentelemetry/extensions/config/DeclarativeLoader.java | Switches to DeclarativeConfigurationCustomizerProvider and resolves SolarWinds config via the new resolver. |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
jerrytfleung
left a comment
There was a problem hiding this comment.
LGTM. Just left a question about the merge logic.
|
|
||
| @Override | ||
| public ComponentLoader getComponentLoader() { | ||
| return primary.getComponentLoader(); |
There was a problem hiding this comment.
Is it true that primary and fallback have the same ComponentLoader such that we don't need to consider the fallback one while merging?
There was a problem hiding this comment.
Yes. They belong to the same class loader.
Summary
The agent can now read its configuration from the top-level
distribution.solarwindsnode insdk-config.yaml, making it usable in multi-language deployments where shared settings live outsidethe Java-specific
instrumentation/development.java.solarwindsnode. When both nodes are present,their keys are merged:
distributionwins for any key it defines, and theinstrumentationnodefills in the rest. The resolution logic is centralized in a new
SolarwindsConfigResolverclassconsumed by both
DeclarativeLoaderandSharedConfigCustomizerProvider. A flaky JDBCinstrumentation test is also fixed in this branch.
Changes
DeclarativeLoader— new integration pointDeclarativeLoaderpreviously implementedBeforeAgentListenerand obtained its config viaExtendedOpenTelemetry.getInstrumentationConfig("solarwinds"), which only ever resolved theinstrumentation/development.java.solarwindsnode. It now implementsDeclarativeConfigurationCustomizerProviderand registers a model customizer, which gives it directaccess to the full config tree and lets it resolve both nodes before the SDK is fully initialized.
SolarwindsConfigResolver— centralized resolution with mergingBoth
DeclarativeLoaderandSharedConfigCustomizerProviderpreviously duplicated the nodetraversal logic (
getStructured("distribution")…). The newSolarwindsConfigResolverclass inlibs/sharedis the single place that knows how to locate and combine the two nodes.Resolution rules:
distribution.solarwindspresent → use it directly.instrumentation/development.java.solarwindspresent → use it directly.MergedConfigPropertiesview that resolves each key fromdistributionfirst and falls back to
instrumentationfor keys not defined there.null(callers wrap this inObjects.requireNonNull).MergedConfigPropertiesis a private inner class that implementsDeclarativeConfigPropertiesbydelegating every getter to the primary node and falling back to the secondary node when the primary
returns
null.getPropertyKeys()returns the union of both nodes' key sets. An empty node(present but no keys) is honored — it defers every key to the other node rather than blocking it.
sdk-config.yamlupdatesShared settings (
agent.serviceKey,agent.collector,agent.logging) are moved frominstrumentation/development.java.solarwindsinto the newdistribution.solarwindsblock in boththe root and smoke-test config files, reflecting the intended multi-language sharing model. Empty
stubs for
tracer_provider.processors,meter_provider.readers, andlogger_provider.processorsare added for discoverability.
Thread name in APM log lines
The internal logger format now includes
[thread-name]between the log level and the message,making it easier to correlate agent-internal log output with application thread activity.
Flaky JDBC test fix
JdbcInstrumentationTestwas flaky because:leak into subsequent assertions.
waitAndAssertTraces, which pinned the exact number and grouping of traces,while the JDBC driver emits a variable number of setup statements on connection open.
The fix makes the container a static field (started once for the class) and calls
testing.clearData()after the connection is opened to discard driver-setup spans before the codeunder test runs. Assertions are rewritten to poll
testing.spans()with Awaitility and check onlythat a
rootINTERNALspan carryingsw.query_tagwas exported, without constraining the rest ofthe trace structure.
Test services data