Since its announcement by AWS Lambda, Golang has become a great alternative to the already existing runtimes. In addition to its rapid growth among the community, now Golang preserves this growth also in the serverless world. In the fight against the villain of the serverless applications, cold-starts; Golang seems to perform better than the other compiled languages available in AWS Lambda. When we also consider the advantages of being a type-safe language, we see the popularity of the Golang is not surprising.
The Go agent of Thundra set off with the basic support for AWS Lambda, showing some metrics and invocation details about your Golang Lambda functions in Thundra web console. Now we are moving to the second stage with the new version of our Go agent and announcing OpenTracing compatibility! With this new version of the Go agent, it is now possible to manually instrument your Golang Lambda functions using the OpenTracing interface!
What is OpenTracing?
Tracing let us know what is happening insides of our processes. With the rise of microservices, the number of processes has increased so much that tracing those processes have become more complex. OpenTracing has come into existence with these issues in mind under the guidance of Cloud Native Computing Foundation. OpenTracing basically provides a set of interfaces and concepts that work across many languages to let us trace the requests throughout the distributed systems.
It is very probable that we have a system consisting of different parts where each part may possibly use different languages and libraries. This languages and libraries have different solutions for instrumentation. That makes the hard job of tracing our applications even harder. OpenTracing emerges at this point and solves the problem by providing a standard for tracing. This standard allows us to trace and observe what is happening inside the processes that make up our system, using the set of language-agnostic concepts that OpenTracing provides us.
OpenTracing compatibility for Thundra Go Agent!
Since OpenTracing is a mere set of interfaces and concepts, someone else should implement these interfaces to make use of OpenTracing at its full potential. Just like we did it for Python, Node.js, and Java; Thundra now provides OpenTracing capability for our Go agent!
Let’s see the capabilities of the new version of Thundra’s Go agent! We will use a demo Lambda function which basically takes a JPEG image link, a width value, and a height value from the event. Then, our Lambda function downloads the image given in the link, resizes the image to the given width and height values. Lastly, our demo Lambda function uploads the resized image to S3 and returns the public link to be used to access the resized image. Let’s add Thundra to this demo function and trace what is happening inside step by step.
- Install thundra
go get -u -d github.com/thundra-io/thundra-lambda-agent-go
or use dep to install:
dep ensure -add github.com/thundra-io/thundra-lambda-agent-go
- Wrapping handler
The first step is wrapping the main Lambda handler that you normally give as an argument to the `lambda.Start`. Instead of giving your main Lambda handler directly, just wrap your handler with `thundra.Wrap` method.
Once you wrap your handler, you can now see the invocations of your Lambda function in Thundra Web console.
Even by just wrapping your method with Thundra already gives you lots of information related to your Lambda function and creates a root span representing your main Lambda handler. However, to fully benefit from OpenTracing capabilities of Thundra; we should be able to create multiple spans. Having multiple spans in our trace would give us a better overview of what is happening inside our function.
- Starting/finishing spans
Wrapping your Lambda handler with `thundra.Wrap` was the first step. Now let’s see how we can create, start and finish spans.
There are a couple of points to note here. The first thing we did here is that we are passing a context as an argument for each function that we want to create a span. Then we are creating a span in the first lines of the functions using the `opentracing.StartSpanFromContext` method which accepts a context as the first parameter and an operation name as the second parameter. In order to finish this span at the end of the function, we are also using the defer statement with the `span.Finish()` function call. However, this is not necessary of course. You can perfectly finish a span wherever you want. Basically, spans will only measure the time between their start and finish, and most of the time you want to measure a function as a whole. That’s why using defer statement to finish spans is a good choice.
Let’s deploy and invoke our function and see what is happening in Thundra console.
That is a much better trace comparing to the first version of our trace where we only had a root span representing all the things happening inside our function. Now we have different spans representing each function separately and giving the execution time of the corresponding function. Let’s continue what else we can do to make this trace more useful.
- Adding logs to the spans
Now, let’s add some logs that would help us to understand more about what is happening throughout our Lambda function. Basically, Thundra provides a logger which you can use to log events happening inside your function and afterward these logs will be available in the Thundra web console. Sounds great, let’s do it!
Here we have modified our main handler function and add some Info logs and Error logs using Thundra. Whenever we download the image, resize the image or upload image to S3, we will see the corresponding logs in the Thundra web console. Also, we have added an Error log for the cases where our handler is given a non-positive width or height value. Let’s try both cases. First, invoke our Lamda function with a proper event value containing non-positive width and height values in the event, then with an event containing negative width value.
First event with proper width and height values
Second event with a negative width value
When we invoke our Lambda function using the first event, the trace we see in Thundra web console is looking very similar to the trace where we first create multiple spans. However, the difference is that this time we have logs that we added in our Lambda handler. To see the logs let’s switch to the LOGS tab in the console.
Here we have the info logs we logged using `thundra.Logger`. You can see the corresponding packages, functions and even the line numbers along with the log messages. Great! Let’s try one more time using the event that contains negative width value.
This time we have a different trace. We don’t have the `resizeImg` span that we do have before. Seems like this time our Lambda function just downloaded the image from the link provided in the event. Then, upload the downloaded image to the S3. Let’s also have a look at the LOGS tab to see if there is something different.
As you can see, this time we don’t have the log saying that image is resized. Instead, we have an error log that we have logged using `thundra.Logger` which is saying that width and height values should be positive.
If you have noticed, we have the logs in the Thundra console but we see all of them under the invocation logs tab. However, using slightly different methods of the `thundra.Logger`, we can see the logs also under their corresponding spans. Basically, Thundra logger also has another version of the logging methods which accepts a span as the first argument. Let’s modify our code one more time and add some debug and error logs inside the `downloadImg` function.
This time we didn’t log inside our main handler function but inside the `downloadImg` function. We have also used the `thundra.Logger` methods that accept a span as the first parameter. Let’s deploy this version of our function and invoke the Lambda one more time.
As you can see, this time we do not only have the logs under the LOGS tab but also inside the `downloadImg` span. That is much more informative since we do not have to switch between TRACE CHART and LOGS tabs. We can see the logs related to each span just by clicking the span and going to the Logs tab.
That was a quick introduction to the abilities of the Thundra’s new OpenTracing compatible Go agent. With OpenTracing compatibility is done, next step is the integrations for AWS SDK, Redis, HTTP, MySQL etc. for the Go agent! To continue getting more information about Thundra follow us on Twitter! Get your free account to try the new features!