1
1
package datadog .trace .bootstrap ;
2
2
3
+ import static java .util .Collections .emptyList ;
4
+ import static java .util .Collections .singletonList ;
5
+
3
6
import datadog .json .JsonWriter ;
4
7
import datadog .trace .bootstrap .environment .EnvironmentVariables ;
5
8
import de .thetaphi .forbiddenapis .SuppressForbidden ;
6
9
import java .io .Closeable ;
7
10
import java .io .OutputStream ;
8
11
import java .util .ArrayList ;
9
- import java .util .Collections ;
10
12
import java .util .LinkedHashMap ;
11
13
import java .util .List ;
12
14
import java .util .Map ;
@@ -51,14 +53,14 @@ public static BootstrapInitializationTelemetry createFromForwarderPath(String fo
51
53
*/
52
54
public abstract void onError (Throwable t );
53
55
56
+ public abstract void onError (String reasonCode );
57
+
54
58
/**
55
59
* Indicates an exception that occurred during the bootstrapping process that left initialization
56
60
* incomplete. Equivalent to calling {@link #onError(Throwable)} and {@link #markIncomplete()}
57
61
*/
58
62
public abstract void onFatalError (Throwable t );
59
63
60
- public abstract void onError (String reasonCode );
61
-
62
64
public abstract void markIncomplete ();
63
65
64
66
public abstract void finish ();
@@ -78,10 +80,10 @@ public void onAbort(String reasonCode) {}
78
80
public void onError (String reasonCode ) {}
79
81
80
82
@ Override
81
- public void onFatalError (Throwable t ) {}
83
+ public void onError (Throwable t ) {}
82
84
83
85
@ Override
84
- public void onError (Throwable t ) {}
86
+ public void onFatalError (Throwable t ) {}
85
87
86
88
@ Override
87
89
public void markIncomplete () {}
@@ -93,38 +95,31 @@ public void finish() {}
93
95
public static final class JsonBased extends BootstrapInitializationTelemetry {
94
96
private final JsonSender sender ;
95
97
96
- private final List <String > meta ;
97
- private final Map <String , List <String >> points ;
98
+ private final Telemetry telemetry ;
98
99
99
100
// one way false to true
100
101
private volatile boolean incomplete = false ;
101
- private volatile boolean error = false ;
102
102
103
103
JsonBased (JsonSender sender ) {
104
104
this .sender = sender ;
105
- this .meta = new ArrayList <>();
106
- this .points = new LinkedHashMap <>();
105
+ this .telemetry = new Telemetry ();
107
106
}
108
107
109
108
@ Override
110
109
public void initMetaInfo (String attr , String value ) {
111
- synchronized (this .meta ) {
112
- this .meta .add (attr );
113
- this .meta .add (value );
114
- }
110
+ telemetry .setMetadata (attr , value );
115
111
}
116
112
117
113
@ Override
118
114
public void onAbort (String reasonCode ) {
119
- onPoint ("library_entrypoint.abort" , "reason:" + reasonCode );
115
+ onPoint ("library_entrypoint.abort" , singletonList ( "reason:" + reasonCode ) );
120
116
markIncomplete ();
121
- setMetaInfo ("abort" , mapResultClass (reasonCode ), reasonCode );
117
+ setResultMeta ("abort" , mapResultClass (reasonCode ), reasonCode );
122
118
}
123
119
124
120
@ Override
125
121
public void onError (Throwable t ) {
126
- error = true ;
127
- setMetaInfo ("error" , "internal_error" , t .getMessage ());
122
+ setResultMeta ("error" , "internal_error" , t .getMessage ());
128
123
129
124
List <String > causes = new ArrayList <>();
130
125
@@ -145,6 +140,12 @@ public void onError(Throwable t) {
145
140
onPoint ("library_entrypoint.error" , causes );
146
141
}
147
142
143
+ @ Override
144
+ public void onError (String reasonCode ) {
145
+ onPoint ("library_entrypoint.error" , singletonList ("error_type:" + reasonCode ));
146
+ setResultMeta ("error" , mapResultClass (reasonCode ), reasonCode );
147
+ }
148
+
148
149
private int maxTags () {
149
150
String maxTags = EnvironmentVariables .get ("DD_TELEMETRY_FORWARDER_MAX_TAGS" );
150
151
@@ -165,14 +166,7 @@ public void onFatalError(Throwable t) {
165
166
markIncomplete ();
166
167
}
167
168
168
- @ Override
169
- public void onError (String reasonCode ) {
170
- error = true ;
171
- onPoint ("library_entrypoint.error" , "error_type:" + reasonCode );
172
- setMetaInfo ("error" , mapResultClass (reasonCode ), reasonCode );
173
- }
174
-
175
- private void setMetaInfo (String result , String resultClass , String resultReason ) {
169
+ private void setResultMeta (String result , String resultClass , String resultReason ) {
176
170
initMetaInfo ("result" , result );
177
171
initMetaInfo ("result_class" , resultClass );
178
172
initMetaInfo ("result_reason" , resultReason );
@@ -195,14 +189,8 @@ private String mapResultClass(String reasonCode) {
195
189
}
196
190
}
197
191
198
- private void onPoint (String name , String tag ) {
199
- onPoint (name , Collections .singletonList (tag ));
200
- }
201
-
202
192
private void onPoint (String name , List <String > tags ) {
203
- synchronized (this .points ) {
204
- this .points .put (name , tags );
205
- }
193
+ telemetry .addPoint (name , tags );
206
194
}
207
195
208
196
@ Override
@@ -212,51 +200,91 @@ public void markIncomplete() {
212
200
213
201
@ Override
214
202
public void finish () {
215
- if (!this .incomplete && !this .error ) {
216
- setMetaInfo ("success" , "success" , "Successfully configured ddtrace package" );
203
+ if (!this .incomplete ) {
204
+ onPoint ("library_entrypoint.complete" , emptyList ());
205
+ }
206
+
207
+ this .sender .send (telemetry );
208
+ }
209
+ }
210
+
211
+ public static class Telemetry {
212
+ private final Map <String , String > metadata ;
213
+ private final Map <String , List <String >> points ;
214
+
215
+ public Telemetry () {
216
+ metadata = new LinkedHashMap <>();
217
+ points = new LinkedHashMap <>();
218
+
219
+ setResults ("success" , "success" , "Successfully configured ddtrace package" );
220
+ }
221
+
222
+ public void setMetadata (String name , String value ) {
223
+ synchronized (metadata ) {
224
+ metadata .put (name , value );
217
225
}
226
+ }
218
227
228
+ public void setResults (String result , String resultClass , String resultReason ) {
229
+ synchronized (metadata ) {
230
+ metadata .put ("result" , result );
231
+ metadata .put ("result_class" , resultClass );
232
+ metadata .put ("result_reason" , resultReason );
233
+ }
234
+ }
235
+
236
+ public void addPoint (String name , List <String > tags ) {
237
+ synchronized (points ) {
238
+ points .put (name , tags );
239
+ }
240
+ }
241
+
242
+ @ Override
243
+ public String toString () {
219
244
try (JsonWriter writer = new JsonWriter ()) {
220
245
writer .beginObject ();
221
246
writer .name ("metadata" ).beginObject ();
222
- synchronized (this . meta ) {
223
- for (int i = 0 ; i + 1 < this . meta . size (); i = i + 2 ) {
224
- writer .name (this . meta . get ( i ));
225
- writer .value (this . meta . get ( i + 1 ));
247
+ synchronized (metadata ) {
248
+ for (Map . Entry < String , String > entry : metadata . entrySet () ) {
249
+ writer .name (entry . getKey ( ));
250
+ writer .value (entry . getValue ( ));
226
251
}
252
+
253
+ metadata .clear ();
227
254
}
228
255
writer .endObject ();
229
256
230
257
writer .name ("points" ).beginArray ();
231
- synchronized (this . points ) {
258
+ synchronized (points ) {
232
259
for (Map .Entry <String , List <String >> entry : points .entrySet ()) {
233
260
writer .beginObject ();
234
261
writer .name ("name" ).value (entry .getKey ());
235
- writer .name ("tags" ).beginArray ();
236
- for (String tag : entry .getValue ()) {
237
- writer .value (tag );
262
+ if (!entry .getValue ().isEmpty ()) {
263
+ writer .name ("tags" ).beginArray ();
264
+ for (String tag : entry .getValue ()) {
265
+ writer .value (tag );
266
+ }
267
+ writer .endArray ();
238
268
}
239
- writer .endArray ();
240
269
writer .endObject ();
241
270
}
242
- this .points .clear ();
243
- }
244
- if (!this .incomplete ) {
245
- writer .beginObject ().name ("name" ).value ("library_entrypoint.complete" ).endObject ();
271
+
272
+ points .clear ();
246
273
}
247
274
writer .endArray ();
248
275
writer .endObject ();
249
276
250
- this .sender .send (writer .toByteArray ());
251
- } catch (Throwable t ) {
252
- // Since this is the reporting mechanism, there's little recourse here
253
- // Decided to simply ignore - arguably might want to write to stderr
277
+ return writer .toString ();
254
278
}
255
279
}
256
280
}
257
281
282
+ /**
283
+ * Declare telemetry as {@code Object} to avoid issue with double class loading from different
284
+ * classloaders.
285
+ */
258
286
public interface JsonSender {
259
- void send (byte [] payload );
287
+ void send (Object telemetry );
260
288
}
261
289
262
290
public static final class ForwarderJsonSender implements JsonSender {
@@ -267,21 +295,21 @@ public static final class ForwarderJsonSender implements JsonSender {
267
295
}
268
296
269
297
@ Override
270
- public void send (byte [] payload ) {
271
- ForwarderJsonSenderThread t = new ForwarderJsonSenderThread (forwarderPath , payload );
298
+ public void send (Object telemetry ) {
299
+ ForwarderJsonSenderThread t = new ForwarderJsonSenderThread (forwarderPath , telemetry );
272
300
t .setDaemon (true );
273
301
t .start ();
274
302
}
275
303
}
276
304
277
305
public static final class ForwarderJsonSenderThread extends Thread {
278
306
private final String forwarderPath ;
279
- private final byte [] payload ;
307
+ private final Object telemetry ;
280
308
281
- public ForwarderJsonSenderThread (String forwarderPath , byte [] payload ) {
309
+ public ForwarderJsonSenderThread (String forwarderPath , Object telemetry ) {
282
310
super ("dd-forwarder-json-sender" );
283
311
this .forwarderPath = forwarderPath ;
284
- this .payload = payload ;
312
+ this .telemetry = telemetry ;
285
313
}
286
314
287
315
@ SuppressForbidden
@@ -291,6 +319,8 @@ public void run() {
291
319
292
320
// Run forwarder and mute tracing for subprocesses executed in by dd-java-agent.
293
321
try (final Closeable ignored = muteTracing ()) {
322
+ byte [] payload = telemetry .toString ().getBytes ();
323
+
294
324
Process process = builder .start ();
295
325
try (OutputStream out = process .getOutputStream ()) {
296
326
out .write (payload );
0 commit comments