Skip to content
This repository was archived by the owner on Dec 23, 2023. It is now read-only.

Commit ea590b8

Browse files
authored
Merge pull request #868 from HailongWen/app-engine-compatible-threadfactory
Use AppEngine compatible way to create threads. (fixes #707 and #777)
2 parents 2b46486 + 82f7125 commit ea590b8

File tree

2 files changed

+28
-16
lines changed

2 files changed

+28
-16
lines changed

impl_core/src/main/java/io/opencensus/implcore/internal/DaemonThreadFactory.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,19 @@
1616

1717
package io.opencensus.implcore.internal;
1818

19+
import com.google.common.util.concurrent.MoreExecutors;
1920
import java.util.concurrent.ThreadFactory;
2021
import java.util.concurrent.atomic.AtomicInteger;
2122

2223
/** A {@link ThreadFactory} implementation that starts all {@link Thread} as daemons. */
2324
public final class DaemonThreadFactory implements ThreadFactory {
25+
// AppEngine runtimes have constraints on threading and socket handling
26+
// that need to be accommodated.
27+
public static final boolean IS_RESTRICTED_APPENGINE =
28+
System.getProperty("com.google.appengine.runtime.environment") != null
29+
&& "1.7".equals(System.getProperty("java.specification.version"));
2430
private static final String DELIMITER = "-";
31+
private static final ThreadFactory threadFactory = MoreExecutors.platformThreadFactory();
2532
private final AtomicInteger threadIdGen = new AtomicInteger();
2633
private final String threadPrefix;
2734

@@ -36,8 +43,11 @@ public DaemonThreadFactory(String threadPrefix) {
3643

3744
@Override
3845
public Thread newThread(Runnable r) {
39-
Thread thread = new Thread(r, threadPrefix + threadIdGen.getAndIncrement());
40-
thread.setDaemon(true);
46+
Thread thread = threadFactory.newThread(r);
47+
if (!IS_RESTRICTED_APPENGINE) {
48+
thread.setName(threadPrefix + threadIdGen.getAndIncrement());
49+
thread.setDaemon(true);
50+
}
4151
return thread;
4252
}
4353
}

impl_core/src/main/java/io/opencensus/implcore/trace/export/SpanExporterImpl.java

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package io.opencensus.implcore.trace.export;
1818

1919
import com.google.common.annotations.VisibleForTesting;
20+
import io.opencensus.implcore.internal.DaemonThreadFactory;
2021
import io.opencensus.implcore.trace.SpanImpl;
2122
import io.opencensus.trace.export.ExportComponent;
2223
import io.opencensus.trace.export.SpanData;
@@ -35,7 +36,8 @@
3536
public final class SpanExporterImpl extends SpanExporter {
3637
private static final Logger logger = Logger.getLogger(ExportComponent.class.getName());
3738

38-
private final WorkerThread workerThread;
39+
private final Worker worker;
40+
private final Thread workerThread;
3941

4042
/**
4143
* Constructs a {@code SpanExporterImpl} that exports the {@link SpanData} asynchronously.
@@ -49,9 +51,8 @@ public final class SpanExporterImpl extends SpanExporter {
4951
*/
5052
static SpanExporterImpl create(int bufferSize, long scheduleDelayMillis) {
5153
// TODO(bdrutu): Consider to add a shutdown hook to not avoid dropping data.
52-
WorkerThread workerThread = new WorkerThread(bufferSize, scheduleDelayMillis);
53-
workerThread.start();
54-
return new SpanExporterImpl(workerThread);
54+
Worker worker = new Worker(bufferSize, scheduleDelayMillis);
55+
return new SpanExporterImpl(worker);
5556
}
5657

5758
/**
@@ -60,29 +61,32 @@ static SpanExporterImpl create(int bufferSize, long scheduleDelayMillis) {
6061
* @param span the {@code Span} to be added.
6162
*/
6263
public void addSpan(SpanImpl span) {
63-
workerThread.addSpan(span);
64+
worker.addSpan(span);
6465
}
6566

6667
@Override
6768
public void registerHandler(String name, Handler handler) {
68-
workerThread.registerHandler(name, handler);
69+
worker.registerHandler(name, handler);
6970
}
7071

7172
@Override
7273
public void unregisterHandler(String name) {
73-
workerThread.unregisterHandler(name);
74+
worker.unregisterHandler(name);
7475
}
7576

76-
private SpanExporterImpl(WorkerThread workerThread) {
77-
this.workerThread = workerThread;
77+
private SpanExporterImpl(Worker worker) {
78+
this.workerThread =
79+
new DaemonThreadFactory("ExportComponent.ServiceExporterThread").newThread(worker);
80+
this.workerThread.start();
81+
this.worker = worker;
7882
}
7983

8084
@VisibleForTesting
8185
Thread getServiceExporterThread() {
8286
return workerThread;
8387
}
8488

85-
// Worker thread that batches multiple span data and calls the registered services to export
89+
// Worker in a thread that batches multiple span data and calls the registered services to export
8690
// that data.
8791
//
8892
// The map of registered handlers is implemented using ConcurrentHashMap ensuring full
@@ -91,7 +95,7 @@ Thread getServiceExporterThread() {
9195
//
9296
// The list of batched data is protected by an explicit monitor object which ensures full
9397
// concurrency.
94-
private static final class WorkerThread extends Thread {
98+
private static final class Worker implements Runnable {
9599
private final Object monitor = new Object();
96100

97101
@GuardedBy("monitor")
@@ -140,12 +144,10 @@ private void onBatchExport(List<SpanData> spanDataList) {
140144

141145
// TODO: Decide whether to use a different class instead of LinkedList.
142146
@SuppressWarnings("JdkObsolete")
143-
private WorkerThread(int bufferSize, long scheduleDelayMillis) {
147+
private Worker(int bufferSize, long scheduleDelayMillis) {
144148
spans = new LinkedList<SpanImpl>();
145149
this.bufferSize = bufferSize;
146150
this.scheduleDelayMillis = scheduleDelayMillis;
147-
setDaemon(true);
148-
setName("ExportComponent.ServiceExporterThread");
149151
}
150152

151153
// Returns an unmodifiable list of all buffered spans data to ensure that any registered

0 commit comments

Comments
 (0)