Bryan Naegele fb6c3d2985
Conveniences for Tasks (#80)
* Conveniences for Tasks

* Finish Task module functions

* Complete Task and add Task.Supervisor

* Check if new funs added

* Remove with_ctx in favor of wrapping default

* Fix docs
2022-08-26 14:10:57 -06:00

473 lines
15 KiB
Elixir

defmodule OpentelemetryProcessPropagator.TaskTest do
use ExUnit.Case
alias OpentelemetryProcessPropagator.Task
require OpenTelemetry.Tracer, as: Tracer
require OpenTelemetry.Span
require Record
for {name, spec} <- Record.extract_all(from_lib: "opentelemetry/include/otel_span.hrl") do
Record.defrecord(name, spec)
end
for {name, spec} <- Record.extract_all(from_lib: "opentelemetry_api/include/opentelemetry.hrl") do
Record.defrecord(name, spec)
end
setup do
:application.stop(:opentelemetry)
:application.set_env(:opentelemetry, :tracer, :otel_tracer_default)
:application.set_env(:opentelemetry, :processors, [
{:otel_batch_processor, %{scheduled_delay_ms: 1}}
])
:application.start(:opentelemetry)
:otel_batch_processor.set_exporter(:otel_exporter_pid, self())
:ok
end
defmodule OtherAppModule do
def fun_with_span(value) do
Tracer.with_span "already traced fun", %{attributes: %{value: value}} do
value
end
end
end
describe "async_stream" do
test "async_stream/3" do
Tracer.with_span "parent span" do
Task.async_stream(["a", "b"], fn value ->
OtherAppModule.fun_with_span(value)
end)
|> Stream.run()
end
assert_receive {:span, span(name: "parent span", span_id: root_span_id, attributes: attrs)}
assert %{} = attributes(attrs)
assert_receive {:span, span(name: "already traced fun", parent_span_id: ^root_span_id, attributes: attrs)}
%{value: val1} = attributes(attrs)
assert_receive {:span, span(name: "already traced fun", parent_span_id: ^root_span_id, attributes: attrs)}
%{value: val2} = attributes(attrs)
assert ["a", "b"] == Enum.sort([val1, val2])
end
test "async_stream/5" do
Tracer.with_span "parent span" do
Task.async_stream(["a", "b"], __MODULE__, :stream_ctx_test_function, [
:async_stream
])
|> Stream.run()
end
assert_receive {:span, span(name: "parent span", span_id: root_span_id, attributes: attrs)}
assert %{} = attributes(attrs)
assert_receive {:span, span(name: "already traced fun", parent_span_id: ^root_span_id, attributes: attrs)}
%{value: val1} = attributes(attrs)
assert_receive {:span, span(name: "already traced fun", parent_span_id: ^root_span_id, attributes: attrs)}
%{value: val2} = attributes(attrs)
assert ["a", "b"] == Enum.sort([val1, val2])
end
test "async_stream_with_span/5" do
Tracer.with_span "parent span" do
Task.async_stream_with_span(["a", "b"], "task span", %{attributes: %{a: 1}}, fn value ->
Tracer.set_attribute(:value, value)
value
end)
|> Stream.run()
end
assert_receive {:span, span(span_id: root_span_id, name: "parent span")}, 500
assert_receive {:span, span(parent_span_id: ^root_span_id, name: "task span", attributes: attrs)}, 500
assert %{value: val1, a: 1} = attributes(attrs)
assert_receive {:span, span(parent_span_id: ^root_span_id, name: "task span", attributes: attrs)}, 500
assert %{value: val2, a: 1} = attributes(attrs)
assert ["a", "b"] == Enum.sort([val1, val2])
end
test "async_stream_with_span/7" do
Tracer.with_span "parent span" do
Task.async_stream_with_span(
["a", "b"],
"task span",
%{attributes: %{a: 1}},
__MODULE__,
:stream_test_function,
[:async_stream_with_span]
)
|> Stream.run()
end
assert_receive {:span, span(span_id: root_span_id, name: "parent span")}, 500
assert_receive {:span, span(parent_span_id: ^root_span_id, name: "task span", attributes: attrs)}, 500
assert %{value: val1, a: 1} = attributes(attrs)
assert_receive {:span, span(parent_span_id: ^root_span_id, name: "task span", attributes: attrs)}, 500
assert %{value: val2, a: 1} = attributes(attrs)
assert ["a", "b"] == Enum.sort([val1, val2])
end
test "async_stream_with_linked_span/5" do
Tracer.with_span "parent span" do
Task.async_stream_with_linked_span(["a", "b"], "task span", %{attributes: %{a: 1}}, fn value ->
Tracer.set_attribute(:value, value)
:ok
end)
|> Stream.run()
end
assert_receive {:span, span(name: "parent span")}, 500
assert_receive {:span, span(parent_span_id: :undefined, links: links, name: "task span", attributes: attrs)}, 500
assert %{value: val1, a: 1} = attributes(attrs)
assert [] != links
assert_receive {:span, span(parent_span_id: :undefined, links: links, name: "task span", attributes: attrs)}, 500
assert %{value: val2, a: 1} = attributes(attrs)
assert [] != links
assert ["a", "b"] == Enum.sort([val1, val2])
end
test "async_stream_with_linked_span/7" do
Tracer.with_span "parent span" do
Task.async_stream_with_linked_span(
["a", "b"],
"task span",
%{attributes: %{a: 1}},
__MODULE__,
:stream_test_function,
[:async_stream_with_linked_span]
)
|> Stream.run()
end
assert_receive {:span, span(name: "parent span")}, 500
assert_receive {:span, span(parent_span_id: :undefined, links: links, name: "task span", attributes: attrs)}, 500
assert %{a: 1, value: val1} = attributes(attrs)
assert [] != links
assert_receive {:span, span(parent_span_id: :undefined, links: links, name: "task span", attributes: attrs)}, 500
assert %{a: 1, value: val2} = attributes(attrs)
assert [] != links
assert ["a", "b"] == Enum.sort([val1, val2])
end
end
describe "async" do
test "async/1" do
Tracer.with_span "parent span", %{attributes: %{a: 1}} do
Task.async(fn ->
Tracer.set_attribute(:value, :async)
:ok
end)
|> Task.await()
end
assert_receive {:span, span(name: "parent span", attributes: attrs)}
assert %{a: 1, value: :async} == attributes(attrs)
end
test "async/3" do
Tracer.with_span "parent span", %{attributes: %{a: 1}} do
Task.async(__MODULE__, :ctx_test_function, [:async])
|> Task.await()
end
assert_receive {:span, span(name: "parent span", span_id: root_span_id, attributes: attrs)}
assert %{a: 1} == attributes(attrs)
assert_receive {:span, span(parent_span_id: ^root_span_id, name: "already traced fun", attributes: attrs)}
assert %{value: :async} == attributes(attrs)
end
test "async_with_span/3" do
Tracer.with_span "parent span" do
Task.async_with_span("task span", %{attributes: %{a: 1}}, fn ->
Tracer.set_attribute(:value, :async_with_span)
:ok
end)
|> Task.await()
end
assert_receive {:span, span(span_id: root_span_id, name: "parent span")}
assert_receive {:span, span(parent_span_id: ^root_span_id, name: "task span", attributes: attrs)}
assert %{a: 1, value: :async_with_span} == attributes(attrs)
end
test "async_with_span/5" do
Tracer.with_span "parent span" do
result =
Task.async_with_span("task span", %{attributes: %{a: 1}}, __MODULE__, :test_function, [:async_with_span])
|> Task.await()
assert :async_with_span == result
end
assert_receive {:span, span(span_id: root_span_id, name: "parent span")}
assert_receive {:span, span(parent_span_id: ^root_span_id, name: "task span", attributes: attrs)}
assert %{a: 1, value: :async_with_span} == attributes(attrs)
end
test "async_with_linked_span/3" do
Tracer.with_span "parent span" do
Task.async_with_linked_span("linked task span", %{attributes: %{a: 1}}, fn ->
Tracer.set_attribute(:value, :async_with_linked_span)
:ok
end)
|> Task.await()
end
assert_receive {:span, span(name: "parent span")}
assert_receive {:span,
span(parent_span_id: :undefined, links: links, attributes: attrs, name: "linked task span")}
assert %{a: 1, value: :async_with_linked_span} == attributes(attrs)
assert [] != links
end
test "async_with_linked_span/6" do
Tracer.with_span "parent span" do
result =
Task.async_with_linked_span("linked task span", %{attributes: %{a: 1}}, __MODULE__, :test_function, [
:async_with_linked_span
])
|> Task.await()
assert :async_with_linked_span == result
end
assert_receive {:span, span(name: "parent span")}
assert_receive {:span,
span(parent_span_id: :undefined, links: links, attributes: attrs, name: "linked task span")}
assert %{a: 1, value: :async_with_linked_span} == attributes(attrs)
assert [] != links
end
end
describe "start" do
test "start/3" do
Tracer.with_span "parent span", %{attributes: %{a: 1}} do
Task.start(fn ->
ctx_test_function(:start)
end)
end
assert_receive {:span, span(name: "parent span", span_id: root_span_id, attributes: attrs)}
assert %{a: 1} == attributes(attrs)
assert_receive {:span, span(name: "already traced fun", parent_span_id: ^root_span_id, attributes: attrs)}
assert %{value: :start} == attributes(attrs)
end
test "start/5" do
Tracer.with_span "parent span", %{attributes: %{a: 1}} do
Task.start(__MODULE__, :ctx_test_function, [:start])
end
assert_receive {:span, span(name: "parent span", span_id: root_span_id, attributes: attrs)}
assert %{a: 1} == attributes(attrs)
assert_receive {:span, span(name: "already traced fun", parent_span_id: ^root_span_id, attributes: attrs)}
assert %{value: :start} == attributes(attrs)
end
test "start_with_span/3" do
Tracer.with_span "parent span" do
Task.start_with_span("task span", %{attributes: %{a: 1}}, fn ->
Tracer.set_attribute(:value, :start_with_span)
:ok
end)
end
assert_receive {:span, span(span_id: root_span_id, name: "parent span")}
assert_receive {:span, span(parent_span_id: ^root_span_id, attributes: attrs, name: "task span")}
assert %{a: 1, value: :start_with_span} == attributes(attrs)
end
test "start_with_span/5" do
Tracer.with_span "parent span" do
Task.start_with_span("task span", %{attributes: %{a: 1}}, __MODULE__, :test_function, [:start_with_span])
end
assert_receive {:span, span(span_id: root_span_id, name: "parent span")}
assert_receive {:span, span(parent_span_id: ^root_span_id, name: "task span", attributes: attrs)}
assert %{a: 1, value: :start_with_span} == attributes(attrs)
end
test "start_with_linked_span" do
Tracer.with_span "parent span" do
Task.start_with_linked_span("linked task span", %{attributes: %{a: 1}}, fn ->
Tracer.set_attribute(:value, :start_with_linked_span)
:ok
end)
end
assert_receive {:span, span(name: "parent span")}
assert_receive {:span,
span(parent_span_id: :undefined, attributes: attrs, links: links, name: "linked task span")}
assert %{a: 1, value: :start_with_linked_span} == attributes(attrs)
assert [] != links
end
test "start_with_linked_span_mfa" do
Tracer.with_span "parent span" do
Task.start_with_linked_span("linked task span", %{attributes: %{a: 1}}, __MODULE__, :test_function, [
:start_with_linked_span
])
end
assert_receive {:span, span(name: "parent span")}
assert_receive {:span,
span(parent_span_id: :undefined, links: links, attributes: attrs, name: "linked task span")}
assert %{a: 1, value: :start_with_linked_span} == attributes(attrs)
assert [] != links
end
end
test "start_link" do
Tracer.with_span "parent span", %{attributes: %{a: 1}} do
Task.start_link(fn ->
ctx_test_function(:start_link)
:ok
end)
end
assert_receive {:span, span(name: "parent span", span_id: root_span_id, attributes: attrs)}
assert %{a: 1} == attributes(attrs)
assert_receive {:span, span(name: "already traced fun", parent_span_id: ^root_span_id, attributes: attrs)}
assert %{value: :start_link} == attributes(attrs)
end
test "start_link_mfa" do
Tracer.with_span "parent span", %{attributes: %{a: 1}} do
Task.start_link(__MODULE__, :ctx_test_function, [:start_link])
end
assert_receive {:span, span(name: "parent span", span_id: root_span_id, attributes: attrs)}
assert %{a: 1} == attributes(attrs)
assert_receive {:span, span(parent_span_id: ^root_span_id, attributes: attrs, name: "already traced fun")}
assert %{value: :start_link} == attributes(attrs)
end
test "start_link_with_span" do
Tracer.with_span "parent span" do
Task.start_link_with_span("task span", %{attributes: %{a: 1}}, fn ->
Tracer.set_attribute(:value, :start_link_with_span)
:ok
end)
end
assert_receive {:span, span(name: "parent span", span_id: root_span_id)}
assert_receive {:span, span(parent_span_id: ^root_span_id, attributes: attrs, name: "task span")}
assert %{a: 1, value: :start_link_with_span} == attributes(attrs)
end
test "start_link_with_span_mfa" do
Tracer.with_span "parent span" do
Task.start_link_with_span("task span", %{attributes: %{a: 1}}, __MODULE__, :test_function, [:start_link_with_span])
end
assert_receive {:span, span(name: "parent span", span_id: root_span_id)}
assert_receive {:span, span(parent_span_id: ^root_span_id, name: "task span", attributes: attrs)}
assert %{a: 1, value: :start_link_with_span} == attributes(attrs)
end
test "start_link_with_linked_span" do
Tracer.with_span "parent span" do
Task.start_link_with_linked_span("linked task span", %{attributes: %{a: 1}}, fn ->
Tracer.set_attribute(:value, :start_link_with_linked_span)
:ok
end)
end
assert_receive {:span, span(name: "parent span")}
assert_receive {:span, span(parent_span_id: :undefined, attributes: attrs, links: links, name: "linked task span")}
assert %{a: 1, value: :start_link_with_linked_span} == attributes(attrs)
assert [] != links
end
test "start_link_with_linked_span_mfa" do
Tracer.with_span "parent span" do
Task.start_link_with_linked_span("linked task span", %{attributes: %{a: 1}}, __MODULE__, :test_function, [
:start_link_with_linked_span
])
end
assert_receive {:span, span(name: "parent span")}
assert_receive {:span, span(parent_span_id: :undefined, links: links, attributes: attrs, name: "linked task span")}
assert %{a: 1, value: :start_link_with_linked_span} == attributes(attrs)
assert [] != links
end
def test_function(value) do
Tracer.set_attributes(%{value: value})
value
end
def ctx_test_function(value) do
OtherAppModule.fun_with_span(value)
end
def link_test_function(value) do
OtherAppModule.fun_with_span(value)
end
def stream_ctx_test_function(value, _args) do
OtherAppModule.fun_with_span(value)
end
def stream_test_function(value, _args) do
Tracer.set_attributes(%{value: value})
value
end
defp attributes({_, _, _, _, attributes}), do: attributes
end