55
66package io .opentelemetry .contrib .jmxscraper ;
77
8- import io .opentelemetry .api .GlobalOpenTelemetry ;
98import io .opentelemetry .api .OpenTelemetry ;
9+ import io .opentelemetry .api .common .AttributeKey ;
10+ import io .opentelemetry .api .common .Attributes ;
1011import io .opentelemetry .contrib .jmxscraper .config .JmxScraperConfig ;
1112import io .opentelemetry .contrib .jmxscraper .config .PropertiesCustomizer ;
1213import io .opentelemetry .contrib .jmxscraper .config .PropertiesSupplier ;
1314import io .opentelemetry .instrumentation .jmx .engine .JmxMetricInsight ;
1415import io .opentelemetry .instrumentation .jmx .engine .MetricConfiguration ;
1516import io .opentelemetry .instrumentation .jmx .yaml .RuleParser ;
16- import io .opentelemetry .sdk .OpenTelemetrySdk ;
1717import io .opentelemetry .sdk .autoconfigure .AutoConfiguredOpenTelemetrySdk ;
1818import io .opentelemetry .sdk .autoconfigure .spi .ConfigurationException ;
19+ import io .opentelemetry .sdk .resources .Resource ;
1920import java .io .DataInputStream ;
2021import java .io .IOException ;
2122import java .io .InputStream ;
2728import java .util .Collections ;
2829import java .util .List ;
2930import java .util .Map ;
30- import java .util .Optional ;
3131import java .util .Properties ;
32+ import java .util .UUID ;
3233import java .util .concurrent .atomic .AtomicBoolean ;
3334import java .util .logging .Level ;
3435import java .util .logging .Logger ;
3536import javax .management .MBeanServerConnection ;
37+ import javax .management .ObjectName ;
3638import javax .management .remote .JMXConnector ;
3739
3840public class JmxScraper {
41+
42+ private static final AttributeKey <String > SERVICE_INSTANCE_ID =
43+ AttributeKey .stringKey ("service.instance.id" );
44+
3945 private static final Logger logger = Logger .getLogger (JmxScraper .class .getName ());
4046 private static final String CONFIG_ARG = "-config" ;
4147 private static final String TEST_ARG = "-test" ;
@@ -65,30 +71,35 @@ public static void main(String[] args) {
6571 propagateToSystemProperties (argsConfig );
6672
6773 PropertiesCustomizer configCustomizer = new PropertiesCustomizer ();
68- JmxScraperConfig scraperConfig = configCustomizer .getScraperConfig ();
69-
70- long exportSeconds = scraperConfig .getSamplingInterval ().toMillis () / 1000 ;
71- logger .log (Level .INFO , "metrics export interval (seconds) = " + exportSeconds );
7274
73- JmxConnectorBuilder connectorBuilder =
74- JmxConnectorBuilder .createNew (scraperConfig .getServiceUrl ());
75+ // auto-configure SDK
76+ OpenTelemetry openTelemetry =
77+ AutoConfiguredOpenTelemetrySdk .builder ()
78+ .addPropertiesSupplier (new PropertiesSupplier (argsConfig ))
79+ .addPropertiesCustomizer (configCustomizer )
80+ // we rely on the config customizer to be executed first to get effective config
81+ .addResourceCustomizer (
82+ (resource , configProperties ) -> {
83+ UUID instanceId =
84+ getRemoteServiceInstanceId (configCustomizer .getConnectorBuilder ());
85+ if (resource .getAttribute (SERVICE_INSTANCE_ID ) != null || instanceId == null ) {
86+ return resource ;
87+ }
88+ logger .log (Level .INFO , "remote service instance ID: " + instanceId );
89+ return resource .merge (
90+ Resource .create (Attributes .of (SERVICE_INSTANCE_ID , instanceId .toString ())));
91+ })
92+ .build ()
93+ .getOpenTelemetrySdk ();
7594
76- Optional .ofNullable (scraperConfig .getUsername ()).ifPresent (connectorBuilder ::withUser );
77- Optional .ofNullable (scraperConfig .getPassword ()).ifPresent (connectorBuilder ::withPassword );
78-
79- if (scraperConfig .isRegistrySsl ()) {
80- connectorBuilder .withSslRegistry ();
81- }
95+ // scraper configuration and connector builder are built using effective SDK configuration
96+ // thus we have to get it after the SDK is built
97+ JmxScraperConfig scraperConfig = configCustomizer .getScraperConfig ();
98+ JmxConnectorBuilder connectorBuilder = configCustomizer .getConnectorBuilder ();
8299
83100 if (testMode ) {
84101 System .exit (testConnection (connectorBuilder ) ? 0 : 1 );
85102 } else {
86- // auto-configure SDK
87- OpenTelemetry openTelemetry = AutoConfiguredOpenTelemetrySdk .builder ()
88- .addPropertiesSupplier (new PropertiesSupplier (argsConfig ))
89- .addPropertiesCustomizer (configCustomizer )
90- .build ()
91- .getOpenTelemetrySdk ();
92103 JmxMetricInsight jmxInsight =
93104 JmxMetricInsight .createService (
94105 openTelemetry , scraperConfig .getSamplingInterval ().toMillis ());
@@ -116,7 +127,6 @@ public static void main(String[] args) {
116127
117128 private static boolean testConnection (JmxConnectorBuilder connectorBuilder ) {
118129 try (JMXConnector connector = connectorBuilder .build ()) {
119-
120130 MBeanServerConnection connection = connector .getMBeanServerConnection ();
121131 Integer mbeanCount = connection .getMBeanCount ();
122132 if (mbeanCount > 0 ) {
@@ -132,6 +142,30 @@ private static boolean testConnection(JmxConnectorBuilder connectorBuilder) {
132142 }
133143 }
134144
145+ // TODO : test on local JVM and call it more than once for stability
146+ static UUID getRemoteServiceInstanceId (JmxConnectorBuilder connectorBuilder ) {
147+ try (JMXConnector jmxConnector = connectorBuilder .build ()) {
148+ MBeanServerConnection connection = jmxConnector .getMBeanServerConnection ();
149+
150+ StringBuilder id = new StringBuilder ();
151+ try {
152+ ObjectName objectName = new ObjectName ("java.lang:type=Runtime" );
153+ for (String attribute : Arrays .asList ("StartTime" , "Pid" , "Name" )) {
154+ Object value = connection .getAttribute (objectName , attribute );
155+ if (id .length () > 0 ) {
156+ id .append ("," );
157+ }
158+ id .append (value );
159+ }
160+ return UUID .nameUUIDFromBytes (id .toString ().getBytes ());
161+ } catch (Exception e ) {
162+ throw new RuntimeException (e );
163+ }
164+ } catch (IOException e ) {
165+ return null ;
166+ }
167+ }
168+
135169 // package private for testing
136170 static void propagateToSystemProperties (Properties properties ) {
137171 for (Map .Entry <Object , Object > entry : properties .entrySet ()) {
0 commit comments