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"}
]
end
Getting 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
end
You 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
end
End 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
end
Running 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 |