-
-
Notifications
You must be signed in to change notification settings - Fork 52
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
239 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"skip_files": [ | ||
"lib/decorators.ex" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
if Code.ensure_loaded?(Decorator.Define) do | ||
defmodule Spandex.Decorators do | ||
@moduledoc """ | ||
Provides a way of annotating functions to be traced. | ||
Span function decorators take an optional argument which is the attributes to update the span with. One of those attributes can be the `:tracer` in case you want to override the default tracer (e.g., in case you want to use multiple tracers). | ||
IMPORTANT If you define multiple clauses for a function, you'll have to decorate all of the ones you want to span. | ||
Note: Decorators don't magically do everything. It often makes a lot of sense to use `Tracer.update_span` from within your function to add details that are only available inside that same function. | ||
defmodule Foo do | ||
use Spandex.Decorators | ||
@decorate trace() | ||
def bar(a) do | ||
a * 2 | ||
end | ||
@decorate trace(service: "ecto", type: "sql") | ||
def databaz(a) do | ||
a * 3 | ||
end | ||
end | ||
""" | ||
|
||
@tracer Application.get_env(:spandex, :decorators)[:tracer] | ||
|
||
use Decorator.Define, span: 0, span: 1, trace: 0, trace: 1 | ||
|
||
def trace(body, context) do | ||
trace([], body, context) | ||
end | ||
|
||
def trace(attributes, body, context) do | ||
name = Keyword.get(attributes, :name, default_name(context)) | ||
tracer = Keyword.get(attributes, :tracer, @tracer) | ||
attributes = Keyword.delete(attributes, :tracer) | ||
|
||
quote do | ||
require unquote(tracer) | ||
|
||
unquote(tracer).trace unquote(name), unquote(attributes) do | ||
unquote(body) | ||
end | ||
end | ||
end | ||
|
||
def span(body, context) do | ||
span([], body, context) | ||
end | ||
|
||
def span(attributes, body, context) do | ||
name = Keyword.get(attributes, :name, default_name(context)) | ||
tracer = Keyword.get(attributes, :tracer, @tracer) | ||
|
||
attributes = | ||
attributes | ||
|> Keyword.delete(:tracer) | ||
|> Keyword.put_new(:resource, name) | ||
|
||
quote do | ||
require unquote(tracer) | ||
|
||
unquote(tracer).span unquote(name), unquote(attributes) do | ||
unquote(body) | ||
end | ||
end | ||
end | ||
|
||
defp default_name(%{module: module, name: function, arity: arity}) do | ||
module = | ||
module | ||
|> Atom.to_string() | ||
|> String.trim_leading("Elixir.") | ||
|
||
"#{module}.#{function}/#{arity}" | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
defmodule Spandex.DecoratorsTest do | ||
use ExUnit.Case, async: true | ||
|
||
alias Spandex.Test.Support.Decorated | ||
alias Spandex.Test.Support.OtherTracer | ||
alias Spandex.Test.Support.Tracer | ||
alias Spandex.Test.Util | ||
|
||
test "creates trace when decorating function with trace annotation" do | ||
Decorated.test_trace() | ||
|
||
assert Util.find_span("decorated_trace") != nil | ||
end | ||
|
||
test "creates trace named after module name, function name and arity when nameless" do | ||
Decorated.test_nameless_trace() | ||
|
||
assert Util.find_span("Spandex.Test.Support.Decorated.test_nameless_trace/0") != nil | ||
end | ||
|
||
test "creates span when decorating function with span annotation" do | ||
Tracer.start_trace("my_trace") | ||
Decorated.test_span() | ||
Tracer.finish_trace() | ||
|
||
assert Util.find_span("decorated_span") != nil | ||
end | ||
|
||
test "creates span named after module name, function name and arity when nameless" do | ||
Tracer.start_trace("my_trace") | ||
Decorated.test_nameless_span() | ||
Tracer.finish_trace() | ||
|
||
assert Util.find_span("Spandex.Test.Support.Decorated.test_nameless_span/0") != nil | ||
end | ||
|
||
test "uses another tracer when overriding it via the tracer option" do | ||
OtherTracer.start_trace("my_trace") | ||
Decorated.test_other_tracer() | ||
OtherTracer.finish_trace() | ||
|
||
assert Util.find_span("Spandex.Test.Support.Decorated.test_other_tracer/0") != nil | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
defmodule Spandex.Test.Support.Decorated do | ||
@moduledoc """ | ||
Simple module to test span and trace decorators (`Spandex.Decorators`) | ||
""" | ||
|
||
use Spandex.Decorators | ||
alias Spandex.Test.Support.OtherTracer | ||
|
||
@decorate trace(name: "decorated_trace") | ||
def test_trace, do: :trace | ||
|
||
@decorate trace() | ||
def test_nameless_trace, do: :nameless_trace | ||
|
||
@decorate span(name: "decorated_span") | ||
def test_span, do: :span | ||
|
||
@decorate span() | ||
def test_nameless_span, do: :nameless_span | ||
|
||
@decorate span(tracer: OtherTracer) | ||
def test_other_tracer, do: :other_tracer | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
defmodule Spandex.Test.Support.OtherTracer do | ||
@moduledoc false | ||
use Spandex.Tracer, otp_app: :spandex | ||
end |