2020import java .lang .reflect .Method ;
2121import java .util .Objects ;
2222import java .util .logging .Logger ;
23+ import javax .annotation .Nullable ;
2324
2425/**
2526 * Utilities for interacting with incubating components ({@code
@@ -36,28 +37,12 @@ static AutoConfiguredOpenTelemetrySdk configureFromFile(
3637 Logger logger , String configurationFile , ComponentLoader componentLoader ) {
3738 logger .fine ("Autoconfiguring from configuration file: " + configurationFile );
3839 try (FileInputStream fis = new FileInputStream (configurationFile )) {
39- Class <?> declarativeConfiguration =
40+ Object model =
4041 Class .forName (
41- "io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfiguration" );
42- Method parse = declarativeConfiguration .getMethod ("parse" , InputStream .class );
43- Object model = parse .invoke (null , fis );
44- Class <?> openTelemetryConfiguration =
45- Class .forName (
46- "io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel" );
47- Method create =
48- declarativeConfiguration .getMethod (
49- "create" , openTelemetryConfiguration , ComponentLoader .class );
50- OpenTelemetrySdk sdk = (OpenTelemetrySdk ) create .invoke (null , model , componentLoader );
51- Class <?> sdkConfigProvider =
52- Class .forName ("io.opentelemetry.sdk.extension.incubator.fileconfig.SdkConfigProvider" );
53- Method createFileConfigProvider =
54- sdkConfigProvider .getMethod ("create" , openTelemetryConfiguration , ComponentLoader .class );
55- ConfigProvider configProvider =
56- (ConfigProvider ) createFileConfigProvider .invoke (null , model , componentLoader );
57- // Note: can't access file configuration resource without reflection so setting a dummy
58- // resource
59- return AutoConfiguredOpenTelemetrySdk .create (
60- sdk , Resource .getDefault (), null , configProvider );
42+ "io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfiguration" )
43+ .getMethod ("parse" , InputStream .class )
44+ .invoke (null , fis );
45+ return getOpenTelemetrySdk (model , componentLoader );
6146 } catch (FileNotFoundException e ) {
6247 throw new ConfigurationException ("Configuration file not found" , e );
6348 } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException e ) {
@@ -77,6 +62,63 @@ static AutoConfiguredOpenTelemetrySdk configureFromFile(
7762 }
7863 }
7964
65+ @ Nullable
66+ public static AutoConfiguredOpenTelemetrySdk configureFromSpi (ComponentLoader componentLoader ) {
67+ try {
68+ Class <?> providerClass =
69+ Class .forName (
70+ "io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationProvider" );
71+ Method getConfigurationModel = providerClass .getMethod ("getConfigurationModel" );
72+
73+ for (Object configProvider : componentLoader .load (providerClass )) {
74+ Object model = getConfigurationModel .invoke (configProvider );
75+ if (model != null ) {
76+ return getOpenTelemetrySdk (model , componentLoader );
77+ }
78+ }
79+ return null ;
80+ } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException e ) {
81+ throw new ConfigurationException (
82+ "Error configuring from SPI. Is opentelemetry-sdk-extension-incubator on the classpath?" ,
83+ e );
84+ } catch (InvocationTargetException e ) {
85+ Throwable cause = e .getCause ();
86+ if (cause instanceof DeclarativeConfigException ) {
87+ throw toConfigurationException ((DeclarativeConfigException ) cause );
88+ }
89+ throw new ConfigurationException ("Unexpected error configuring from SPI" , e );
90+ }
91+ }
92+
93+ private static AutoConfiguredOpenTelemetrySdk getOpenTelemetrySdk (
94+ Object model , ComponentLoader componentLoader )
95+ throws IllegalAccessException ,
96+ InvocationTargetException ,
97+ ClassNotFoundException ,
98+ NoSuchMethodException {
99+
100+ Class <?> openTelemetryConfiguration =
101+ Class .forName (
102+ "io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel" );
103+ Class <?> declarativeConfiguration =
104+ Class .forName (
105+ "io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfiguration" );
106+ Method create =
107+ declarativeConfiguration .getMethod (
108+ "create" , openTelemetryConfiguration , ComponentLoader .class );
109+
110+ OpenTelemetrySdk sdk = (OpenTelemetrySdk ) create .invoke (null , model , componentLoader );
111+ Class <?> sdkConfigProvider =
112+ Class .forName ("io.opentelemetry.sdk.extension.incubator.fileconfig.SdkConfigProvider" );
113+ Method createFileConfigProvider =
114+ sdkConfigProvider .getMethod ("create" , openTelemetryConfiguration , ComponentLoader .class );
115+ ConfigProvider configProvider =
116+ (ConfigProvider ) createFileConfigProvider .invoke (null , model , componentLoader );
117+ // Note: can't access file configuration resource without reflection so setting a dummy
118+ // resource
119+ return AutoConfiguredOpenTelemetrySdk .create (sdk , Resource .getDefault (), null , configProvider );
120+ }
121+
80122 private static ConfigurationException toConfigurationException (
81123 DeclarativeConfigException exception ) {
82124 String message = Objects .requireNonNull (exception .getMessage ());
0 commit comments