Please wait version 1.0.0 released.
If available in Hex, the package can be installed
by adding aws_ex_ray
to your list of dependencies in mix.exs
:
def application do
[
extra_applications: [
:logger,
:aws_ex_ray
# ...
],
mod {MyApp.Supervisor, []}
]
end
def deps do
[
{:aws_ex_ray, "~> 0.1.16"},
# add support libraries as you like
{:aws_ex_ray_plug, "~> 0.1"},
{:aws_ex_ray_ecto, "~> 0.1"},
{:aws_ex_ray_httpoison, "~> 0.1"},
{:aws_ex_ray_ex_aws, "~> 0.1"}
]
end
Documentation can be generated with ExDoc and published on HexDocs. Once published, the docs can be found at https://hexdocs.pm/aws_ex_ray.
Setup your AWS environment.
Run xray
daemon on an EC2 instance which you want your application run on.
https://docs.aws.amazon.com/xray/latest/devguide/xray-daemon.html
trace = Trace.new()
segment = AwsExRay.start_tracing(trace, "root_segment_name")
do_your_job()
AwsExRay.finish_tracing(segment)
def do_your_job() do
current_trace = AwsExRay.start_subsegment("subsegment-name")
do_some_work()
case current_trace do
{:ok, subsegment} ->
AwsExRay.finish_subsegment(subsegment)
{:error, :out_of_xray} -> :ok # you need to do nothing.
end
end
Following example doesn't work.
start_subsegment
returns always {:error, :out_of_xray}
.
Because the subsegment is not on the process which start tracing.
Pay attention when you use Task.Supervisor or GenServer.
segment = AwsExRay.start_tracing(trace, "root_segment_name")
Task.Supervisor.start_child(MyTaskSupervisor, fn ->
####################################################################
# this function is executed on different process as root-segment!!!
####################################################################
current_trace = AwsExRay.start_subsegment("subsegment-name")
do_some_work()
case current_trace do
{:ok, subsegment} ->
AwsExRay.finish_subsegment(subsegment)
{:error, :out_of_xray} -> :ok
end
end)
The solution.
Call AwsExRay.Process.keep_tracing(process_which_starts_tracing)
like following
segment = AwsExRay.start_tracing(trace, "root_segment_name")
tracing_pid = self()
Task.Supervisor.start_child(MyTaskSupervisor, fn ->
AwsExRay.Process.keep_tracing(tracing_pid)
current_trace = AwsExRay.start_subsegment("subsegment-name")
do_some_work()
case current_trace do
{:ok, subsegment} ->
AwsExRay.finish_subsegment(subsegment)
{:error, :out_of_xray} -> :ok
end
end)
[client] --> [1: front_server] --> [2: internal_api or job_worker]
You can tracking Trace including (2) not only (1). If (2) server is HTTP server. You can put X-Amzn-Trace-Id into your requests HTTP headers.
If you use AwsExRay.HTTPoison, it's easy. all you have to do is to set :traced
option.
options = [traced: true]
result = AwsExRay.HTTPoison.get(url, headers, options)
If you setup AwsExRay.Plug, it automatically takes over tracing.
defmodule MyInternalAPIRouter do
use Plug.Router
plug AwsExRay.Plug, name: "my-internal-api"
You can directory pass Trace value
case AwsExRay.start_subsegment("internal-api-request", namespace: :remote) do
{:error, :out_of_xray} ->
pass_job_in_some_way(%{
your_job_data: ...
})
{:ok, subsegment} ->
pass_job_in_some_way(%{
your_job_data: ...
trace_value: Subsegment.generate_trace_value(subsegment)
})
AwsExRay.finish_subsegment(subsegment)
end
And job worker side, it can take over the Trace
job = receive_job_in_some_way()
case AwsExRay.Trace.parse(job.trace_value) do
{:ok, trace}
AwsExRay.start_tracing(trace, "internal-job-name")
:ok
{:error, :not_found} ->
:ok
end
If you don't need to put detailed parameters into segment/subsegment, You can do like following
trace = Trace.new()
result = AwsExRay.trace(trace, "root_segment_name", fn ->
do_your_job()
end)
This is same as,
trace = Trace.new()
segment = AwsExRay.start_tracing(trace, "root_segment_name")
result = do_your_job()
AwsExRay.finish_tracing(segment)
result
This way supports just only annotations
trace = Trace.new()
result = AwsExRay.trace(trace, "root_segment_name", %{"MyAnnotationKey" => "MyAnnotationValue"}, fn ->
do_your_job()
end)
opts = [namespace: :none]
result = AwsExRay.subsegment("name", opts, fn trace_value ->
# trace_value is an empty string if this context is out of trace
do_your_job()
end)
This is same as,
current_trace = AwsExRay.start_subsegment("subsegment-name")
result = do_some_work()
case current_trace do
{:ok, subsegment} ->
AwsExRay.finish_subsegment(subsegment)
{:error, :out_of_xray} -> :ok # you need to do nothing.
end
result
This way supports just only annotations
opts = [namespace: :none]
result = AwsExRay.subsegment("name", %{"MyAnnotationKey" => "MyAnnotationValue"}, opts, fn ->
do_your_job()
end)
config :aws_ex_ray,
rules_module: AwsExRay.Rules.SamplingRate,
sampling_rate: 0.1,
default_annotation: %{foo: "bar"},
default_metadata: %{bar: "buz"}
key | default | description |
---|---|---|
rules_module | AwsExRay.Rules.SamplingRate | see below |
sampling_rate | 0.1 | set number between 0.0 - 1.0. recommended that set 0.0 for 'test' environment |
default_annotation | %{} | annotation parameters automatically put into segment/subsegment |
default_metadata | %{} | metadata parameters automatically put into segment/subsegment |
daemon_address | 127.0.0.1 | your xray daemon's host name. typically, you don't need to customize this. |
daemon_port | 2000 | your xray daemon's port. typically, you don't need to customize this. |
default_client_pool_size | 10 | number of UDP client which connects to xray daemon |
default_client_pool_overflow | 100 | overflow capacity size of UDP client |
default_store_monitor_pool_size | 10 | number of tracing-process-monitor |
There are different ways to configure how to decide which requests to
sample. The default rules_module
is
AwsExRay.Rules.SamplingRate
. It uses the sampling_rate
setting to
determine how many requests to sample. For example, if sampling_rate
is set to the default of 0.1
, every request has a 10% chance of
being sampled.
You can also set rules_module
to AwsExRay.Rules.OnlineRules
. With
this module, the sampling_rate
setting is ignored. Instead, it
fetches sampling rules from AWS X-Ray, as described here:
https://docs.aws.amazon.com/xray/latest/devguide/xray-console-sampling.html
Trace.new
expects a map with the following keys:
service_name
service_type
http_method
host
url_path
resource_arn
It compares the values in the map with the rules configured in AWS X-Ray. If a value is missing from the map, it matches only if the rule has a wildcard for that field.
The highest-priority rule that matches the values in the map is picked, and the sampling rate and reservoir size are used to determine whether the request should be sampled.
https://github.com/lyokato/aws_ex_ray_plug
In your router, set AwsExRay.Plug
.
defmodule MyPlugRouter do
use Plug.Router
plug AwsExRay.Plug, name: "my-xray", skip: [{:get, "/bar"}]
plug :match
plug :dispatch
get "/foo" do
conn
|> put_resp_content_type("application/json")
|> send_resp(200, Poison.encode!(%{body: "Hello, Foo"}))
end
get "/bar" do
conn
|> put_resp_content_type("application/json")
|> send_resp(200, Poison.encode!(%{body: "Hello, Bar"}))
end
end
Then automatically start tracing segment if the request is not included skip setting.
https://github.com/lyokato/aws_ex_ray_ecto
In your config file,
put AwsExRay.Ecto.Logger
into Ecto's :loggers
setting.
config :my_app, MyApp.EctoRepo,
adapter: Ecto.Adapters.MySQL,
hostname: "example.org",
port: "3306",
database: "my_db",
username: "foo",
password: "bar",
loggers: [Ecto.LogEntry, AwsExRay.Ecto.Logger]
Then automatically record subsegment if queries called on the tracing process.
https://github.com/lyokato/aws_ex_ray_httpoison
use AwsExRay.HTTPoison
instead of HTTPoison
result = AwsExRay.HTTPoison.get! "https://example.org/"
Then automatically record subsegment if HTTP request called on the tracing process.
https://github.com/lyokato/aws_ex_ray_ex_aws
In your config file,
put AwsExRay.ExAws.HTTPClient
to :http_client
setting.
config :ex_aws,
http_client: AwsExRay.ExAws.HTTPClient
Then automatically record subsegment if HTTP request toward AWS-Services called on the tracing process.
MIT-LICENSE
Lyo Kaot <lyo.kato at gmail.com>