Thundra APM
Search…
Deployment Integrations
Enrich Tracing in Go

Manual Instrumentation with Open Tracing

Thundra uses OpenTracing API to implement instrumentation. This allows you to manually instrument your code by following OpenTracing API instructions as Thundra’s agents are compliant with OpenTracing API.
To manually instrument your Go functions and see detailed spans, you will have to create span instances using the OpenTracing's StartSpan methods. OpenTracing API provides two different methods that you can use to start new spans in your function: opentracing.StartSpan and opentracing.StartSpanFromContext. We suggest using the opentracing.StartSpanFromContext method to create new spans by passing it a context, an operation name, and optional parameters. Refer to our section about using contexts to learn more.

You Don't Need to Create a Span for the Main Handler Function

Thundra automatically creates a root span representing the main Lambda handler function and finishes this root span when your Lambda function is done. Thus, you don't need to create a root span representing your handler function. Any other span you create in your main handler or in other functions will be the child of this root span.
The following code snippet shows an example usage of OpenTracing API to create new spans:
Creating a new span
1
// Pass a context parameter to the function
2
func sayHello(ctx context.Context, name string) {
3
// Create a new span to represent operations made in this function
4
span, _ := opentracing.StartSpanFromContext(ctx, "sayHello")
5
// Finish the span when function is done
6
defer span.Finish()
7
// Perform actual function logic
8
fmt.Printf("Hello, %s!\n", name)
9
}
Copied!

Using Contexts While Creating New Spans

Currently, Golang does not provide a local storage or a similar construct for threads. For this reason, OpenTracing API handles parent-child relations between spans using Golang's context objects.
Since Thundra creates a root span representing your main handler function, we strongly suggest you create your main handler function so that it accepts a context object as its first argument. This way, you will be able to access the root span that Thundra has created to represent your main handler function and use the passed context variable to create child spans from this root span.
The following code snippet shows how context objects can be used to create child spans:
Go
1
package main
2
3
import (
4
"context"
5
"time"
6
7
"github.com/aws/aws-lambda-go/lambda"
8
opentracing "github.com/opentracing/opentracing-go"
9
"github.com/thundra-io/thundra-lambda-agent-go/thundra"
10
)
11
12
// Your main lambda handler
13
func handler(ctx context.Context) (string, error) {
14
// Currently ctx object contains the root span that
15
// Thundra have created for you
16
17
// Sleep some amount, representing the operations
18
// that you make in your handler function before
19
// creating a new child span
20
time.Sleep(time.Millisecond * 100)
21
22
// Say you continue to make some operations in your
23
// main handler but this time create a childSpan
24
// to represent these operations.
25
aSpan, _ := opentracing.StartSpanFromContext(ctx, "childSpan-1")
26
time.Sleep(time.Millisecond * 100)
27
aSpan.Finish()
28
29
// Make a call to another function. Note that this function
30
// also accepts a context object. We are using this context
31
// object to carry the parent span information.
32
aFunction(ctx)
33
34
// Creating another span representing the another operations
35
// that we are doing inside the root span.
36
anotherSpan, _ := opentracing.StartSpanFromContext(ctx, "childSpan-3")
37
time.Sleep(time.Millisecond * 100)
38
anotherSpan.Finish()
39
40
// Say we have also some operations before our handler finishes
41
time.Sleep(time.Millisecond * 50)
42
43
return "Hello ƛ!", nil
44
}
45
46
func aFunction(ctx context.Context) {
47
span, _ := opentracing.StartSpanFromContext(ctx, "childSpan-2")
48
defer span.Finish()
49
50
time.Sleep(time.Millisecond * 100)
51
}
52
53
func main() {
54
// Wrap your lambda handler with Thundra
55
lambda.Start(thundra.Wrap(handler))
56
}
Copied!
The resulting trace chart that you will see in the Thundra web console for this function will be similar to the following image.
As you can see, there is the root span that Thundra automatically created while other spans are the child of the root span, as they should be.
Last modified 11mo ago