| 
									
										
										
										
											2020-01-18 10:20:46 +00:00
										 |  |  | // Package trace provides an interface for distributed tracing | 
					
						
							|  |  |  | package trace | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"context" | 
					
						
							|  |  |  | 	"time" | 
					
						
							| 
									
										
										
										
											2020-02-12 11:57:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-04 21:40:43 +01:00
										 |  |  | 	"go-micro.dev/v5/metadata" | 
					
						
							|  |  |  | 	"go-micro.dev/v5/transport/headers" | 
					
						
							| 
									
										
										
										
											2022-10-20 13:00:50 +02:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var ( | 
					
						
							|  |  |  | 	// DefaultTracer is the default tracer. | 
					
						
							|  |  |  | 	DefaultTracer = NewTracer() | 
					
						
							| 
									
										
										
										
											2020-01-18 10:20:46 +00:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-30 16:27:07 +02:00
										 |  |  | // Tracer is an interface for distributed tracing. | 
					
						
							| 
									
										
										
										
											2020-01-29 15:45:11 +00:00
										 |  |  | type Tracer interface { | 
					
						
							| 
									
										
										
										
											2020-01-18 10:20:46 +00:00
										 |  |  | 	// Start a trace | 
					
						
							| 
									
										
										
										
											2020-01-24 21:44:48 +00:00
										 |  |  | 	Start(ctx context.Context, name string) (context.Context, *Span) | 
					
						
							| 
									
										
										
										
											2020-01-18 10:20:46 +00:00
										 |  |  | 	// Finish the trace | 
					
						
							|  |  |  | 	Finish(*Span) error | 
					
						
							|  |  |  | 	// Read the traces | 
					
						
							|  |  |  | 	Read(...ReadOption) ([]*Span, error) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-30 16:27:07 +02:00
										 |  |  | // SpanType describe the nature of the trace span. | 
					
						
							| 
									
										
										
										
											2020-02-12 11:57:17 +01:00
										 |  |  | type SpanType int | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const ( | 
					
						
							| 
									
										
										
										
											2022-09-30 16:27:07 +02:00
										 |  |  | 	// SpanTypeRequestInbound is a span created when serving a request. | 
					
						
							| 
									
										
										
										
											2020-02-12 11:57:17 +01:00
										 |  |  | 	SpanTypeRequestInbound SpanType = iota | 
					
						
							| 
									
										
										
										
											2022-09-30 16:27:07 +02:00
										 |  |  | 	// SpanTypeRequestOutbound is a span created when making a service call. | 
					
						
							| 
									
										
										
										
											2020-02-12 11:57:17 +01:00
										 |  |  | 	SpanTypeRequestOutbound | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-30 16:27:07 +02:00
										 |  |  | // Span is used to record an entry. | 
					
						
							| 
									
										
										
										
											2020-01-18 10:20:46 +00:00
										 |  |  | type Span struct { | 
					
						
							| 
									
										
										
										
											2023-04-26 00:16:34 +00:00
										 |  |  | 	// Start time | 
					
						
							|  |  |  | 	Started time.Time | 
					
						
							|  |  |  | 	// associated data | 
					
						
							|  |  |  | 	Metadata map[string]string | 
					
						
							| 
									
										
										
										
											2020-01-18 10:20:46 +00:00
										 |  |  | 	// Id of the trace | 
					
						
							|  |  |  | 	Trace string | 
					
						
							|  |  |  | 	// name of the span | 
					
						
							|  |  |  | 	Name string | 
					
						
							|  |  |  | 	// id of the span | 
					
						
							|  |  |  | 	Id string | 
					
						
							|  |  |  | 	// parent span id | 
					
						
							|  |  |  | 	Parent string | 
					
						
							| 
									
										
										
										
											2020-01-24 21:24:51 +00:00
										 |  |  | 	// Duration in nano seconds | 
					
						
							|  |  |  | 	Duration time.Duration | 
					
						
							| 
									
										
										
										
											2020-02-12 11:57:17 +01:00
										 |  |  | 	// Type | 
					
						
							|  |  |  | 	Type SpanType | 
					
						
							| 
									
										
										
										
											2020-01-18 10:20:46 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-30 16:27:07 +02:00
										 |  |  | // FromContext returns a span from context. | 
					
						
							| 
									
										
										
										
											2020-02-06 17:22:16 +00:00
										 |  |  | func FromContext(ctx context.Context) (traceID string, parentSpanID string, isFound bool) { | 
					
						
							| 
									
										
										
										
											2022-10-20 13:00:50 +02:00
										 |  |  | 	traceID, traceOk := metadata.Get(ctx, headers.TraceIDKey) | 
					
						
							|  |  |  | 	microID, microOk := metadata.Get(ctx, headers.ID) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-06 17:22:16 +00:00
										 |  |  | 	if !traceOk && !microOk { | 
					
						
							|  |  |  | 		isFound = false | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-10-20 13:00:50 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-06 17:22:16 +00:00
										 |  |  | 	if !traceOk { | 
					
						
							|  |  |  | 		traceID = microID | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-10-20 13:00:50 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	parentSpanID, ok := metadata.Get(ctx, headers.SpanID) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-06 17:22:16 +00:00
										 |  |  | 	return traceID, parentSpanID, ok | 
					
						
							| 
									
										
										
										
											2020-01-18 10:20:46 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-30 16:27:07 +02:00
										 |  |  | // ToContext saves the trace and span ids in the context. | 
					
						
							| 
									
										
										
										
											2020-02-06 17:22:16 +00:00
										 |  |  | func ToContext(ctx context.Context, traceID, parentSpanID string) context.Context { | 
					
						
							|  |  |  | 	return metadata.MergeContext(ctx, map[string]string{ | 
					
						
							| 
									
										
										
										
											2022-10-20 13:00:50 +02:00
										 |  |  | 		headers.TraceIDKey: traceID, | 
					
						
							|  |  |  | 		headers.SpanID:     parentSpanID, | 
					
						
							| 
									
										
										
										
											2020-02-06 17:22:16 +00:00
										 |  |  | 	}, true) | 
					
						
							| 
									
										
										
										
											2020-01-18 10:20:46 +00:00
										 |  |  | } |