Skip to content

Commit 4e8128e

Browse files
authored
Optimizations for Filter/TelemetryClient startup (#650)
* optimized startup by limiting use of reflection and making some initialization async * removed some redundant catch clauses. documented new properties. removed debugging log messages
1 parent b4fe8b0 commit 4e8128e

File tree

13 files changed

+266
-137
lines changed

13 files changed

+266
-137
lines changed

core/src/main/java/com/microsoft/applicationinsights/internal/annotation/AnnotationPackageScanner.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,14 @@
3333
* Created by gupele on 3/15/2015.
3434
*/
3535
public final class AnnotationPackageScanner {
36+
private AnnotationPackageScanner(){}
3637
/**
3738
* The method will scan packages searching for classes that have the needed annotations.
3839
* @param annotationsToSearch The annotations we need.
3940
* @param packageToScan The packages to scan from, note that all sub packages will be scanned too.
4041
* @return A list of class names that are under the package we asked and that carry the needed annotations
4142
*/
42-
public List<String> scanForClassAnnotations(final Class<? extends Annotation>[] annotationsToSearch, String packageToScan) {
43+
public static List<String> scanForClassAnnotations(final Class<? extends Annotation>[] annotationsToSearch, String packageToScan) {
4344
final ArrayList<String> performanceModuleNames = new ArrayList<String>();
4445
AnnotationDetector.TypeReporter reporter = new AnnotationDetector.TypeReporter() {
4546
@Override

core/src/main/java/com/microsoft/applicationinsights/internal/channel/common/ApacheSender43.java

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,14 @@
2222
package com.microsoft.applicationinsights.internal.channel.common;
2323

2424
import java.io.IOException;
25+
import java.util.concurrent.ExecutorService;
26+
import java.util.concurrent.Executors;
27+
import java.util.concurrent.TimeUnit;
28+
import java.util.concurrent.atomic.AtomicReference;
2529

2630
import com.microsoft.applicationinsights.internal.logger.InternalLogger;
2731

32+
import com.microsoft.applicationinsights.internal.shutdown.SDKShutdownActivity;
2833
import org.apache.http.HttpResponse;
2934
import org.apache.http.client.HttpClient;
3035
import org.apache.http.client.config.RequestConfig;
@@ -39,22 +44,30 @@
3944
*/
4045
final class ApacheSender43 implements ApacheSender {
4146

42-
private final CloseableHttpClient httpClient;
43-
47+
private final AtomicReference<CloseableHttpClient> httpClientRef = new AtomicReference<>();
48+
private volatile boolean isClientInitialized = false;
49+
private final ExecutorService initializer = Executors.newSingleThreadExecutor();
4450
public ApacheSender43() {
45-
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
46-
cm.setMaxTotal(DEFAULT_MAX_TOTAL_CONNECTIONS);
47-
cm.setDefaultMaxPerRoute(DEFAULT_MAX_CONNECTIONS_PER_ROUTE);
51+
initializer.execute(new Runnable() {
52+
53+
@Override
54+
public void run() {
55+
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
56+
cm.setMaxTotal(DEFAULT_MAX_TOTAL_CONNECTIONS);
57+
cm.setDefaultMaxPerRoute(DEFAULT_MAX_CONNECTIONS_PER_ROUTE);
4858

49-
httpClient = HttpClients.custom()
50-
.setConnectionManager(cm)
51-
.useSystemProperties()
52-
.build();
53-
}
59+
httpClientRef.compareAndSet(null, HttpClients.custom()
60+
.setConnectionManager(cm)
61+
.useSystemProperties()
62+
.build());
63+
}
64+
});
65+
SDKShutdownActivity.INSTANCE.register(initializer);
66+
}
5467

5568
@Override
5669
public HttpResponse sendPostRequest(HttpPost post) throws IOException {
57-
return httpClient.execute(post);
70+
return getHttpClient().execute(post);
5871
}
5972

6073
@Override
@@ -71,15 +84,29 @@ public void dispose(HttpResponse response) {
7184
@Override
7285
public void close() {
7386
try {
74-
httpClient.close();
87+
((CloseableHttpClient)getHttpClient()).close();
7588
} catch (IOException e) {
7689
InternalLogger.INSTANCE.error("Failed to close http client, exception: %s", e.toString());
7790
}
7891
}
7992

8093
@Override
8194
public HttpClient getHttpClient() {
82-
return httpClient;
95+
if (!isClientInitialized) {
96+
synchronized (this) {
97+
if (!isClientInitialized) {
98+
while (httpClientRef.get() == null) {
99+
try {
100+
TimeUnit.MILLISECONDS.sleep(3);
101+
} catch (InterruptedException e){
102+
}
103+
}
104+
isClientInitialized = true;
105+
}
106+
}
107+
}
108+
109+
return httpClientRef.get();
83110
}
84111

85112
@Override

core/src/main/java/com/microsoft/applicationinsights/internal/channel/common/TransmitterImpl.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
package com.microsoft.applicationinsights.internal.channel.common;
2323

2424
import java.util.Collection;
25-
import java.util.concurrent.ScheduledThreadPoolExecutor;
25+
import java.util.concurrent.Executors;
26+
import java.util.concurrent.ScheduledExecutorService;
2627
import java.util.concurrent.Semaphore;
2728
import java.util.concurrent.TimeUnit;
2829
import java.util.concurrent.atomic.AtomicInteger;
@@ -120,7 +121,7 @@ public void run() {
120121

121122
private final TelemetrySerializer serializer;
122123

123-
private final ScheduledThreadPoolExecutor threadPool;
124+
private final ScheduledExecutorService threadPool;
124125

125126
private final TransmissionsLoader transmissionsLoader;
126127

@@ -138,8 +139,7 @@ public TransmitterImpl(TransmissionDispatcher transmissionDispatcher, TelemetryS
138139

139140
semaphore = new Semaphore(MAX_PENDING_SCHEDULE_REQUESTS);
140141

141-
threadPool = new ScheduledThreadPoolExecutor(2);
142-
threadPool.setThreadFactory(ThreadPoolUtils.createDaemonThreadFactory(TransmitterImpl.class, instanceId));
142+
threadPool = Executors.newScheduledThreadPool(2, ThreadPoolUtils.createDaemonThreadFactory(TransmitterImpl.class, instanceId));
143143

144144
this.transmissionsLoader = transmissionsLoader;
145145
this.transmissionsLoader.load(false);

core/src/main/java/com/microsoft/applicationinsights/internal/channel/samplingV2/FixedRateSamplingTelemetryProcessor.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,14 @@ public FixedRateSamplingTelemetryProcessor() {
7070
this.excludedTypes = new HashSet<Class>();
7171
try {
7272
this.allowedTypes = new HashMap<String, Class>() {{
73-
put(dependencyTelemetryName, Class.forName("com.microsoft.applicationinsights.telemetry.RemoteDependencyTelemetry"));
74-
put(eventTelemetryName, Class.forName("com.microsoft.applicationinsights.telemetry.EventTelemetry"));
75-
put(exceptionTelemetryName, Class.forName("com.microsoft.applicationinsights.telemetry.ExceptionTelemetry"));
76-
put(pageViewTelemetryName, Class.forName("com.microsoft.applicationinsights.telemetry.PageViewTelemetry"));
77-
put(requestTelemetryName, Class.forName("com.microsoft.applicationinsights.telemetry.RequestTelemetry"));
78-
put(traceTelemetryName, Class.forName("com.microsoft.applicationinsights.telemetry.TraceTelemetry"));
73+
put(dependencyTelemetryName, com.microsoft.applicationinsights.telemetry.RemoteDependencyTelemetry.class);
74+
put(eventTelemetryName, com.microsoft.applicationinsights.telemetry.EventTelemetry.class);
75+
put(exceptionTelemetryName, com.microsoft.applicationinsights.telemetry.ExceptionTelemetry.class);
76+
put(pageViewTelemetryName, com.microsoft.applicationinsights.telemetry.PageViewTelemetry.class);
77+
put(requestTelemetryName, com.microsoft.applicationinsights.telemetry.RequestTelemetry.class);
78+
put(traceTelemetryName, com.microsoft.applicationinsights.telemetry.TraceTelemetry.class);
7979
}};
80-
} catch (ClassNotFoundException e) {
80+
} catch (Exception e) {
8181
InternalLogger.INSTANCE.trace("Unable to locate telemetry classes. stack trace is %s", ExceptionUtils.getStackTrace(e));
8282
}
8383
}

core/src/main/java/com/microsoft/applicationinsights/internal/config/ReflectionUtils.java

Lines changed: 44 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.lang.reflect.InvocationTargetException;
2626
import java.lang.reflect.Method;
2727
import java.util.Collection;
28+
import java.util.HashMap;
2829
import java.util.List;
2930
import java.util.Map;
3031

@@ -38,6 +39,37 @@
3839
* Created by gupele on 8/7/2016.
3940
*/
4041
public final class ReflectionUtils {
42+
43+
private static final Map<String, Class<?>> builtInMap = new HashMap<>();
44+
45+
static {
46+
addClass(com.microsoft.applicationinsights.channel.concrete.inprocess.InProcessTelemetryChannel.class);
47+
addClass(com.microsoft.applicationinsights.internal.channel.stdout.StdOutChannel.class);
48+
49+
addClass(com.microsoft.applicationinsights.internal.heartbeat.HeartBeatModule.class);
50+
addClass(com.microsoft.applicationinsights.internal.perfcounter.JvmPerformanceCountersModule.class);
51+
addClass(com.microsoft.applicationinsights.internal.perfcounter.ProcessPerformanceCountersModule.class);
52+
53+
addClass(com.microsoft.applicationinsights.extensibility.initializer.SdkVersionContextInitializer.class);
54+
addClass(com.microsoft.applicationinsights.extensibility.initializer.DeviceInfoContextInitializer.class);
55+
56+
addClass(com.microsoft.applicationinsights.extensibility.initializer.TimestampPropertyInitializer.class);
57+
addClass(com.microsoft.applicationinsights.extensibility.initializer.SequencePropertyInitializer.class);
58+
addClass(com.microsoft.applicationinsights.extensibility.initializer.docker.DockerContextInitializer.class);
59+
60+
addClass(com.microsoft.applicationinsights.internal.processor.MetricTelemetryFilter.class);
61+
addClass(com.microsoft.applicationinsights.internal.processor.RequestTelemetryFilter.class);
62+
addClass(com.microsoft.applicationinsights.internal.channel.samplingV2.FixedRateSamplingTelemetryProcessor.class);
63+
addClass(com.microsoft.applicationinsights.internal.processor.SyntheticSourceFilter.class);
64+
addClass(com.microsoft.applicationinsights.internal.processor.PageViewTelemetryFilter.class);
65+
addClass(com.microsoft.applicationinsights.internal.processor.TelemetryEventFilter.class);
66+
addClass(com.microsoft.applicationinsights.internal.processor.TraceTelemetryFilter.class);
67+
}
68+
69+
static void addClass(Class<?> clazz) {
70+
builtInMap.put(clazz.getCanonicalName(), clazz);
71+
}
72+
4173
/**
4274
* Creates an instance from its name. We suppress Java compiler warnings for Generic casting
4375
*
@@ -56,18 +88,14 @@ public static <T> T createInstance(String className, Class<T> interfaceClass) {
5688
return null;
5789
}
5890

59-
Class<?> clazz = Class.forName(className).asSubclass(interfaceClass);
91+
Class<?> clazz = builtInMap.get(className);
92+
if (clazz == null) {
93+
clazz = Class.forName(className).asSubclass(interfaceClass);
94+
} else {
95+
clazz = clazz.asSubclass(interfaceClass);
96+
}
6097
T instance = (T)clazz.newInstance();
61-
6298
return instance;
63-
} catch (ClassCastException e) {
64-
InternalLogger.INSTANCE.error("Failed to create %s, Exception : %s", className, ExceptionUtils.getStackTrace(e));
65-
} catch (ClassNotFoundException e) {
66-
InternalLogger.INSTANCE.error("Failed to create %s, Exception : %s", className, ExceptionUtils.getStackTrace(e));
67-
} catch (InstantiationException e) {
68-
InternalLogger.INSTANCE.error("Failed to create %s, Exception : %s", className, ExceptionUtils.getStackTrace(e));
69-
} catch (IllegalAccessException e) {
70-
InternalLogger.INSTANCE.error("Failed to create %s, Exception : %s", className, ExceptionUtils.getStackTrace(e));
7199
} catch (Exception e) {
72100
InternalLogger.INSTANCE.error("Failed to create %s, Exception : %s", className, ExceptionUtils.getStackTrace(e));
73101
}
@@ -97,18 +125,15 @@ public static <T, A> T createInstance(String className, Class<T> interfaceClass
97125
return null;
98126
}
99127

100-
Class<?> clazz = Class.forName(className).asSubclass(interfaceClass);
128+
Class<?> clazz = builtInMap.get(className);
129+
if (clazz == null) {
130+
clazz = Class.forName(className).asSubclass(interfaceClass);
131+
} else {
132+
clazz = clazz.asSubclass(interfaceClass);
133+
}
101134
Constructor<?> clazzConstructor = clazz.getConstructor(argumentClass);
102135
T instance = (T)clazzConstructor.newInstance(argument);
103136
return instance;
104-
} catch (ClassCastException e) {
105-
InternalLogger.INSTANCE.error("Failed to create %s, Exception : %s", className, ExceptionUtils.getStackTrace(e));
106-
} catch (ClassNotFoundException e) {
107-
InternalLogger.INSTANCE.error("Failed to create %s, Exception : %s", className, ExceptionUtils.getStackTrace(e));
108-
} catch (InstantiationException e) {
109-
InternalLogger.INSTANCE.error("Failed to create %s, Exception : %s", className, ExceptionUtils.getStackTrace(e));
110-
} catch (IllegalAccessException e) {
111-
InternalLogger.INSTANCE.error("Failed to create %s, Exception : %s", className, ExceptionUtils.getStackTrace(e));
112137
} catch (Exception e) {
113138
InternalLogger.INSTANCE.error("Failed to create %s, Exception : %s", className, ExceptionUtils.getStackTrace(e));
114139
}

0 commit comments

Comments
 (0)