Tracing
- Requirements
- Installation
- Getting started
- Enable Tracing
- Exporting traces
- End to end code
- Viewing your traces
- References
In this quickstart, we’ll glean insights from code segments and learn how to:
- Trace the code using OpenCensus Tracing
- Register and enable an exporter for a backend of our choice
- View traces on the backend of our choice
Requirements
- Erlang 20.0+ and rebar3 or Elixir 1.5+
- Zipkin as our choice of tracing backend: we are picking it because it is free, open source and easy to setup
For assistance setting up Zipkin, Click here for a guided codelab.
You can swap out any other exporter from the list of Erlang/Elixir exporters
Installation
OpenCensus Erlang comes with the Zipkin reporter so simply add the opencensus hex dependency to your project’s rebar.config or mix.exs:
{deps, [opencensus, opencensus_zipkin]}.defp deps() do
[
{:opencensus_elixir, "~> 0.2.0"},
{:opencensus_zipkin, "~> 0.1.0"}
]
endGetting Started
Unsure how to write and execute Erlang or Elixir code? Click here for an Erlang tutorial and here for an Elixir tutorial..
It would be nice if we could trace the following code, thus giving us observability in to how the code functions.
First, create a project named repl.
Next, put the following code inside of src/repl.erl:
-module(repl).
-export([run/0]).
run() ->
read_eval_process().
read_eval_process() ->
Line = io:get_line("> "),
Out = process_line(Line),
io:format("< ~s~n~n", [Out]),
read_eval_process().
process_line(Line) ->
string:uppercase(Line).defmodule Repl do
def run() do
read_eval_process()
end
defp read_eval_process() do
line = IO.gets("> ")
out = process_line(line)
IO.puts("< " <> out)
read_eval_process()
end
defp process_line(line) do
String.upcase(line)
end
endYou can run the code via rebar3 shell followed by repl:run(). or iex -S mix followed by Repl.run().
Enable Tracing
Include OpenCensus Application
Skip this section if you are using Elixir. In a mix project the dependencies are used as runtime dependencies unless specified to not be.
To enable tracing, we’ll include opencensus application in our project’s .app.src file so it is started as a dependency of our application. Your src/repl.app.src will looks like:
{application, repl,
[{description, "OpenCensus REPL example"},
{vsn, "0.1.0"},
{registered, []},
{applications,
[kernel,
stdlib,
opencensus
]},
{env,[]},
{modules, []},
]}.To start the applications when running the rebar3 shell for development you’ll add the following to rebar.config:
{shell, [{apps, [repl]},
{config, "config/sys.config"}]}.Instrumentation
We will be tracing the execution as it starts in read_eval_process/0, goes to read_line/0, and finally travels through process_line/1.
To accomplish this, we must create a span in each of the functions.
You can create a span with the ocp module’s function with_child_span/1 and finish with finish_span/0, with opencensus_elixir a macro with_child_span is provided as well:
When creating a new span with this way OpenCensus first checks if a parent Span already exists in the process dictionary. If it exists, a child span is created. Otherwise, a newly created span is inserted in to the process dictionary to become the parent Span.
Exporting traces
Import packages
To enable exporting of traces to Zipkin, we’ll need to set it as the reporter in sys.config:
[{opencensus, [{sampler, {oc_sampler_always, []}},
{reporters, [{oc_reporter_zipkin, []}]}]}
].use Mix.Config
config :opencensus,
sampler: {:oc_sampler_always, []},
reporters: [{:oc_reporter_zipkin, []}]Create Annotations
When looking at our traces on a backend (such as Stackdriver), we can add metadata to our traces to increase our post-mortem insight.
We’ll record the length of each requested string so that it is available to view when examining our traces. To accomplish this, we’ll annotate the function read_eval_process/0.
read_eval_process() ->
ocp:with_child_span("repl"),
Line = read_line(),
Annotation = oc_span:annotation( <<"Invoking process_line/1">>,
#{<<"len">> => length(Line),
<<"use">> => <<"repl">>}),
ocp:add_time_event(Annotation),
Out = process_line(Line),
io:format("< ~s~n~n", [Out]),
ocp:finish_span(),
read_eval_process(). import Opencensus.Trace
defp read_eval_process() do
with_child_span "repl" do
line = read_line()
annotation =
:oc_span.annotation("Invoking process_line/1", %{
"len" => String.length(line),
"use" => "repl"
})
:ocp.add_time_event(annotation)
out = process_line(line)
IO.puts("< " <> out)
read_eval_process()
end
endEnd to end code
Collectively our code will look this:
-module(repl).
-export([run/0]).
run() ->
read_eval_process().
read_eval_process() ->
ocp:with_child_span("repl"),
Line = read_line(),
Annotation = oc_span:annotation( <<"Invoking process_line/1">>,
#{<<"len">> => length(Line),
<<"use">> => <<"repl">>}),
ocp:add_time_event(Annotation),
Out = process_line(Line),
io:format("< ~s~n~n", [Out]),
ocp:finish_span(),
read_eval_process().
read_line() ->
ocp:with_child_span("read_line"),
try io:get_line("> ")
after
ocp:finish_span()
end.
process_line(Line) ->
ocp:with_child_span("process_line"),
try string:uppercase(Line)
after
ocp:finish_span()
end.defmodule Repl do
import Opencensus.Trace
def run() do
read_eval_process()
end
defp read_eval_process() do
with_child_span "repl" do
line = read_line()
annotation =
:oc_span.annotation("Invoking process_line/1", %{
"len" => String.length(line),
"use" => "repl"
})
:ocp.add_time_event(annotation)
out = process_line(line)
IO.puts("< " <> out)
read_eval_process()
end
end
defp read_line() do
with_child_span "read_line" do
IO.gets("> ")
end
end
defp process_line(line) do
with_child_span "process_line" do
String.upcase(line)
end
end
endRunning the code
Having already successfully started Zipkin as in Zipkin Codelab, we can now run our code by
rebar3 shell --sname repl@localhost
(repl@localhost)1> repl:run().iex --sname repl@localhost -S mix
iex(repl@localhost)1> Repl.run()Viewing your traces
With the above you should now be able to navigate to the Zipkin UI at http://localhost:9411 which will produce such a screenshot:

And on clicking on one of the traces, we should be able to see the annotation whose description Invoking process_line/1

whose annotation looks like

And on clicking on More info we should see

References
| Resource | URL |
|---|---|
| Zipkin project | https://zipkin.io/ |
| Erlang/Elixir exporters | Erlang/Elixir exporters |
| OpenCensus Erlang package | https://hexdocs.pm/opencensus/ |
| OpenCensus Elixir package | https://hexdocs.pm/opencensus_elixir/ |
| Setting up Zipkin | Zipkin Codelab |