2727import com .google .devtools .cloudtrace .v1 .Trace ;
2828import com .google .devtools .cloudtrace .v1 .TraceSpan ;
2929import com .google .devtools .cloudtrace .v1 .Traces ;
30+ import io .opencensus .common .Duration ;
3031import io .opencensus .common .Function ;
3132import io .opencensus .common .Functions ;
3233import io .opencensus .common .Timestamp ;
34+ import io .opencensus .trace .Annotation ;
3335import io .opencensus .trace .AttributeValue ;
36+ import io .opencensus .trace .NetworkEvent ;
37+ import io .opencensus .trace .NetworkEvent .Type ;
3438import io .opencensus .trace .SpanContext ;
3539import io .opencensus .trace .SpanId ;
3640import io .opencensus .trace .TraceId ;
3741import io .opencensus .trace .export .SpanData ;
42+ import io .opencensus .trace .export .SpanData .TimedEvent ;
3843import io .opencensus .trace .export .SpanExporter ;
3944import java .io .IOException ;
4045import java .nio .ByteBuffer ;
@@ -51,6 +56,8 @@ final class StackdriverV1ExporterHandler extends SpanExporter.Handler {
5156
5257 private static final String STATUS_CODE = "g.co/status/code" ;
5358 private static final String STATUS_DESCRIPTION = "g.co/status/description" ;
59+ private static final String ANNOTATION_LABEL = "ANNOTATION-" ;
60+ private static final String NETWORK_EVENT_LABEL = "NETWORK-" ;
5461
5562 private final String projectId ;
5663 private final TraceServiceClient traceServiceClient ;
@@ -95,6 +102,22 @@ private Trace generateTrace(SpanData spanData) {
95102 spanBuilder .putLabels (label .getKey (), attributeValueToString (label .getValue ()));
96103 }
97104
105+ // Add Annotations as labels in the v1 API
106+ int seq = 0 ;
107+ for (TimedEvent <Annotation > annotation : spanData .getAnnotations ().getEvents ()) {
108+ spanBuilder .putLabels (
109+ ANNOTATION_LABEL + String .format ("%03d" , seq ++),
110+ renderAnnotation (annotation , spanData .getStartTimestamp ()));
111+ }
112+
113+ // Add NetworkEvents as labels in the v1 API
114+ seq = 0 ;
115+ for (TimedEvent <NetworkEvent > networkEvent : spanData .getNetworkEvents ().getEvents ()) {
116+ spanBuilder .putLabels (
117+ NETWORK_EVENT_LABEL + String .format ("%03d" , seq ++),
118+ renderNetworkEvents (networkEvent , spanData .getStartTimestamp ()));
119+ }
120+
98121 // Add Status as labels in the v1 API.
99122 spanBuilder .putLabels (STATUS_CODE , spanData .getStatus ().getCanonicalCode ().toString ());
100123 if (spanData .getStatus ().getDescription () != null ) {
@@ -132,6 +155,67 @@ private static TraceSpan.SpanKind toSpanKindProto(SpanData spanData) {
132155 return TraceSpan .SpanKind .SPAN_KIND_UNSPECIFIED ;
133156 }
134157
158+ private static String renderNetworkEvents (TimedEvent <NetworkEvent > timedEvent , Timestamp start ) {
159+ StringBuilder stringBuilder = new StringBuilder ();
160+ renderDelay (stringBuilder , timedEvent .getTimestamp ().subtractTimestamp (start ));
161+ NetworkEvent networkEvent = timedEvent .getEvent ();
162+ if (networkEvent .getType () == Type .RECV ) {
163+ stringBuilder .append ("Received" );
164+ } else if (networkEvent .getType () == Type .SENT ) {
165+ stringBuilder .append ("Sent" );
166+ } else {
167+ stringBuilder .append ("Unknown" );
168+ }
169+ stringBuilder .append (" message_id=" );
170+ stringBuilder .append (networkEvent .getMessageId ());
171+ stringBuilder .append (" uncompressed_size=" );
172+ stringBuilder .append (networkEvent .getUncompressedMessageSize ());
173+ stringBuilder .append (" compressed_size=" );
174+ stringBuilder .append (networkEvent .getCompressedMessageSize ());
175+ if (networkEvent .getKernelTimestamp () != null ) {
176+ stringBuilder .append (" kernel_timestamp=" );
177+ stringBuilder .append (networkEvent .getKernelTimestamp ().toString ());
178+ }
179+ return stringBuilder .toString ();
180+ }
181+
182+ private static String renderAnnotation (TimedEvent <Annotation > timedEvent , Timestamp start ) {
183+ StringBuilder stringBuilder = new StringBuilder ();
184+ renderDelay (stringBuilder , timedEvent .getTimestamp ().subtractTimestamp (start ));
185+ Annotation annotation = timedEvent .getEvent ();
186+ stringBuilder .append (annotation .getDescription ());
187+ if (!annotation .getAttributes ().isEmpty ()) {
188+ stringBuilder .append (" " );
189+ stringBuilder .append (renderAttributes (annotation .getAttributes ()));
190+ }
191+ return stringBuilder .toString ();
192+ }
193+
194+ private static void renderDelay (StringBuilder stringBuilder , Duration delay ) {
195+ long delayUs = delay .getSeconds () * 1000000 + delay .getNanos () / 1000 ;
196+ stringBuilder .append ("[@" );
197+ stringBuilder .append (delayUs );
198+ stringBuilder .append (" us] " );
199+ }
200+
201+ private static String renderAttributes (Map <String , AttributeValue > attributes ) {
202+ StringBuilder stringBuilder = new StringBuilder ();
203+ stringBuilder .append ("Attributes:{" );
204+ boolean first = true ;
205+ for (Map .Entry <String , AttributeValue > entry : attributes .entrySet ()) {
206+ if (first ) {
207+ first = false ;
208+ } else {
209+ stringBuilder .append (", " );
210+ }
211+ stringBuilder .append (entry .getKey ());
212+ stringBuilder .append ("=" );
213+ stringBuilder .append (attributeValueToString (entry .getValue ()));
214+ }
215+ stringBuilder .append ("}" );
216+ return stringBuilder .toString ();
217+ }
218+
135219 private static com .google .protobuf .Timestamp toTimestampProto (Timestamp timestamp ) {
136220 return com .google .protobuf .Timestamp .newBuilder ()
137221 .setSeconds (timestamp .getSeconds ())
0 commit comments