1515import static io .opentelemetry .semconv .incubating .OsIncubatingAttributes .OS_TYPE ;
1616import static io .opentelemetry .semconv .incubating .OsIncubatingAttributes .OS_VERSION ;
1717
18- import com .fasterxml .jackson .core .JsonFactory ;
1918import com .fasterxml .jackson .core .JsonParser ;
2019import com .fasterxml .jackson .core .JsonToken ;
2120import io .opentelemetry .api .common .AttributeKey ;
2524import io .opentelemetry .sdk .resources .Resource ;
2625import io .opentelemetry .semconv .incubating .CloudIncubatingAttributes ;
2726import java .io .IOException ;
28- import java .net .MalformedURLException ;
29- import java .net .URL ;
30- import java .time .Duration ;
3127import java .util .HashMap ;
3228import java .util .Map ;
33- import java .util .Objects ;
3429import java .util .Optional ;
3530import java .util .function .BiConsumer ;
31+ import java .util .function .Function ;
3632import java .util .function .Supplier ;
3733import java .util .logging .Level ;
3834import java .util .logging .Logger ;
39- import okhttp3 .OkHttpClient ;
40- import okhttp3 .Request ;
41- import okhttp3 .Response ;
4235import org .jetbrains .annotations .NotNull ;
4336
4437public class AzureVmResourceProvider extends CloudResourceProvider {
4538
46- private static final Map <String , AttributeKey <String >> COMPUTE_MAPPING = new HashMap <>();
39+ static class Entry {
40+ final AttributeKey <String > key ;
41+ final Function <String , String > transform ;
4742
48- static {
49- COMPUTE_MAPPING .put ("location" , CLOUD_REGION );
50- COMPUTE_MAPPING .put ("resourceId" , CLOUD_RESOURCE_ID );
51- COMPUTE_MAPPING .put ("vmId" , HOST_ID );
52- COMPUTE_MAPPING .put ("name" , HOST_NAME );
53- COMPUTE_MAPPING .put ("vmSize" , HOST_TYPE );
54- COMPUTE_MAPPING .put ("osType" , OS_TYPE );
55- COMPUTE_MAPPING .put ("version" , OS_VERSION );
56- COMPUTE_MAPPING .put ("vmScaleSetName" , AttributeKey .stringKey ("azure.vm.scaleset.name" ));
57- COMPUTE_MAPPING .put ("sku" , AttributeKey .stringKey ("azure.vm.sku" ));
58- }
59-
60- private static final JsonFactory JSON_FACTORY = new JsonFactory ();
43+ Entry (AttributeKey <String > key ) {
44+ this (key , Function .identity ());
45+ }
6146
62- private static final Duration TIMEOUT = Duration .ofSeconds (1 );
47+ Entry (AttributeKey <String > key , Function <String , String > transform ) {
48+ this .key = key ;
49+ this .transform = transform ;
50+ }
51+ }
6352
64- private static final Logger logger = Logger .getLogger (AzureVmResourceProvider .class .getName ());
65- private static final URL METADATA_URL ;
53+ private static final Map <String , Entry > COMPUTE_MAPPING = new HashMap <>();
6654
6755 static {
68- try {
69- METADATA_URL = new URL ("http://169.254.169.254/metadata/instance?api-version=2021-02-01" );
70- } catch (MalformedURLException e ) {
71- throw new IllegalStateException (e );
72- }
56+ COMPUTE_MAPPING .put ("location" , new Entry (CLOUD_REGION ));
57+ COMPUTE_MAPPING .put ("resourceId" , new Entry (CLOUD_RESOURCE_ID ));
58+ COMPUTE_MAPPING .put ("vmId" , new Entry (HOST_ID ));
59+ COMPUTE_MAPPING .put ("name" , new Entry (HOST_NAME ));
60+ COMPUTE_MAPPING .put ("vmSize" , new Entry (HOST_TYPE ));
61+ COMPUTE_MAPPING .put ("osType" , new Entry (OS_TYPE ));
62+ COMPUTE_MAPPING .put ("version" , new Entry (OS_VERSION ));
63+ COMPUTE_MAPPING .put (
64+ "vmScaleSetName" , new Entry (AttributeKey .stringKey ("azure.vm.scaleset.name" )));
65+ COMPUTE_MAPPING .put ("sku" , new Entry (AttributeKey .stringKey ("azure.vm.sku" )));
7366 }
7467
68+ private static final Logger logger = Logger .getLogger (AzureVmResourceProvider .class .getName ());
69+
7570 private final Supplier <Optional <String >> client ;
7671
7772 // SPI
7873 public AzureVmResourceProvider () {
79- this (() -> fetchMetadata ( METADATA_URL ));
74+ this (AzureMetadataService . defaultClient ( ));
8075 }
8176
8277 // visible for testing
@@ -87,20 +82,26 @@ public AzureVmResourceProvider(Supplier<Optional<String>> client) {
8782 @ Override
8883 public int order () {
8984 // run after the fast cloud resource providers that only check environment variables
85+ // and after the AKS provider
9086 return 100 ;
9187 }
9288
9389 @ Override
9490 public Resource createResource (ConfigProperties config ) {
95- return client .get ().map (AzureVmResourceProvider ::parseMetadata ).orElse (Resource .empty ());
91+ return client
92+ .get ()
93+ .map (
94+ body ->
95+ parseMetadata (
96+ body , COMPUTE_MAPPING , CloudIncubatingAttributes .CloudPlatformValues .AZURE_VM ))
97+ .orElse (Resource .empty ());
9698 }
9799
98- private static Resource parseMetadata (String body ) {
99- AttributesBuilder builder =
100- azureAttributeBuilder (CloudIncubatingAttributes .CloudPlatformValues .AZURE_VM );
101- try (JsonParser parser = JSON_FACTORY .createParser (body )) {
100+ static Resource parseMetadata (String body , Map <String , Entry > computeMapping , String platform ) {
101+ AttributesBuilder builder = azureAttributeBuilder (platform );
102+ try (JsonParser parser = AzureMetadataService .JSON_FACTORY .createParser (body )) {
102103 parser .nextToken ();
103- parseResponse (parser , builder );
104+ parseResponse (parser , builder , computeMapping );
104105 } catch (IOException e ) {
105106 logger .log (Level .FINE , "Can't get Azure VM metadata" , e );
106107 }
@@ -115,7 +116,9 @@ static AttributesBuilder azureAttributeBuilder(String platform) {
115116 return builder ;
116117 }
117118
118- static void parseResponse (JsonParser parser , AttributesBuilder builder ) throws IOException {
119+ static void parseResponse (
120+ JsonParser parser , AttributesBuilder builder , Map <String , Entry > computeMapping )
121+ throws IOException {
119122 if (!parser .isExpectedStartObjectToken ()) {
120123 logger .log (Level .FINE , "Couldn't parse ECS metadata, invalid JSON" );
121124 return ;
@@ -126,7 +129,7 @@ static void parseResponse(JsonParser parser, AttributesBuilder builder) throws I
126129 (name , value ) -> {
127130 try {
128131 if (name .equals ("compute" )) {
129- consumeCompute (parser , builder );
132+ consumeCompute (parser , builder , computeMapping );
130133 } else {
131134 parser .skipChildren ();
132135 }
@@ -136,14 +139,15 @@ static void parseResponse(JsonParser parser, AttributesBuilder builder) throws I
136139 });
137140 }
138141
139- private static void consumeCompute (JsonParser parser , AttributesBuilder builder )
142+ private static void consumeCompute (
143+ JsonParser parser , AttributesBuilder builder , Map <String , Entry > computeMapping )
140144 throws IOException {
141145 consumeJson (
142146 parser ,
143147 (computeName , computeValue ) -> {
144- AttributeKey < String > key = COMPUTE_MAPPING .get (computeName );
145- if (key != null ) {
146- builder .put (key , computeValue );
148+ Entry entry = computeMapping .get (computeName );
149+ if (entry != null ) {
150+ builder .put (entry . key , entry . transform . apply ( computeValue ) );
147151 } else {
148152 try {
149153 parser .skipChildren ();
@@ -160,36 +164,4 @@ private static void consumeJson(JsonParser parser, BiConsumer<String, String> co
160164 consumer .accept (parser .currentName (), parser .nextTextValue ());
161165 }
162166 }
163-
164- // visible for testing
165- static Optional <String > fetchMetadata (URL url ) {
166- OkHttpClient client =
167- new OkHttpClient .Builder ()
168- .callTimeout (TIMEOUT )
169- .connectTimeout (TIMEOUT )
170- .readTimeout (TIMEOUT )
171- .build ();
172-
173- Request request = new Request .Builder ().url (url ).get ().addHeader ("Metadata" , "true" ).build ();
174-
175- try (Response response = client .newCall (request ).execute ()) {
176- int responseCode = response .code ();
177- if (responseCode != 200 ) {
178- logger .log (
179- Level .FINE ,
180- "Error response from "
181- + url
182- + " code ("
183- + responseCode
184- + ") text "
185- + response .message ());
186- return Optional .empty ();
187- }
188-
189- return Optional .of (Objects .requireNonNull (response .body ()).string ());
190- } catch (IOException e ) {
191- logger .log (Level .FINE , "Failed to fetch Azure VM metadata" , e );
192- return Optional .empty ();
193- }
194- }
195167}
0 commit comments