From 0f137525b5343508cfe777ef0d800da4fa69093c Mon Sep 17 00:00:00 2001 From: Damir Vandic Date: Thu, 24 Mar 2022 21:19:24 +0100 Subject: [PATCH] Make Ecto spans of preloads children of the parent span (#49) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🎉 --- .../opentelemetry_ecto/config/test.exs | 2 +- .../lib/opentelemetry_ecto.ex | 26 ++++++- instrumentation/opentelemetry_ecto/mix.exs | 3 +- instrumentation/opentelemetry_ecto/mix.lock | 26 ++++--- .../test_repo/migrations/1_setup_tables.exs | 5 ++ .../test/opentelemetry_ecto_test.exs | 75 ++++++++++++++++++- .../test/support/models/comment.ex | 8 ++ .../test/support/models/user.ex | 1 + 8 files changed, 129 insertions(+), 17 deletions(-) create mode 100644 instrumentation/opentelemetry_ecto/test/support/models/comment.ex diff --git a/instrumentation/opentelemetry_ecto/config/test.exs b/instrumentation/opentelemetry_ecto/config/test.exs index 5087377..7a781d0 100644 --- a/instrumentation/opentelemetry_ecto/config/test.exs +++ b/instrumentation/opentelemetry_ecto/config/test.exs @@ -11,4 +11,4 @@ config :opentelemetry_ecto, OpentelemetryEcto.TestRepo, pool: Ecto.Adapters.SQL.Sandbox config :opentelemetry, - processors: [{:otel_simple_processor, %{}}] + processors: [{:otel_batch_processor, %{scheduled_delay_ms: 1}}] diff --git a/instrumentation/opentelemetry_ecto/lib/opentelemetry_ecto.ex b/instrumentation/opentelemetry_ecto/lib/opentelemetry_ecto.ex index e40a1e2..d745ad4 100644 --- a/instrumentation/opentelemetry_ecto/lib/opentelemetry_ecto.ex +++ b/instrumentation/opentelemetry_ecto/lib/opentelemetry_ecto.ex @@ -1,6 +1,20 @@ defmodule OpentelemetryEcto do @moduledoc """ - Telemetry handler for creating OpenTelemetry Spans from Ecto query events. + Telemetry handler for creating OpenTelemetry Spans from Ecto query events. Any + relation preloads, which are executed in parallel in separate tasks, will be + linked to the span of the process that initiated the call. For example: + + Tracer.with_span "parent span" do + Repo.all(Query.from(User, preload: [:posts, :comments])) + end + + this will create a span called "parent span" with three child spans for each + query: users, posts, and comments. + + > #### Note {: .neutral} + > + > Due to limitations with how Ecto emits its telemetry, nested preloads are not + > represented as nested spans within a trace. """ require OpenTelemetry.Tracer @@ -88,6 +102,12 @@ defmodule OpentelemetryEcto do acc end) + parent_context = OpentelemetryProcessPropagator.fetch_parent_ctx(1, :"$callers") + + if parent_context != :undefined do + OpenTelemetry.Ctx.attach(parent_context) + end + s = OpenTelemetry.Tracer.start_span(span_name, %{ start_time: start_time, @@ -104,6 +124,10 @@ defmodule OpentelemetryEcto do end OpenTelemetry.Span.end_span(s) + + if parent_context != :undefined do + OpenTelemetry.Ctx.detach(parent_context) + end end defp format_error(%{__exception__: true} = exception) do diff --git a/instrumentation/opentelemetry_ecto/mix.exs b/instrumentation/opentelemetry_ecto/mix.exs index ec509ea..763b207 100644 --- a/instrumentation/opentelemetry_ecto/mix.exs +++ b/instrumentation/opentelemetry_ecto/mix.exs @@ -55,7 +55,8 @@ defmodule OpentelemetryEcto.MixProject do {:ex_doc, "~> 0.26.0", only: [:dev], runtime: false}, {:ecto_sql, ">= 3.0.0", only: [:dev, :test]}, {:postgrex, ">= 0.15.0", only: [:dev, :test]}, - {:dialyxir, "~> 1.1", only: [:dev, :test], runtime: false} + {:dialyxir, "~> 1.1", only: [:dev, :test], runtime: false}, + {:opentelemetry_process_propagator, "~> 0.1.0"} ] end end diff --git a/instrumentation/opentelemetry_ecto/mix.lock b/instrumentation/opentelemetry_ecto/mix.lock index bcacd8a..b01fb4d 100644 --- a/instrumentation/opentelemetry_ecto/mix.lock +++ b/instrumentation/opentelemetry_ecto/mix.lock @@ -3,27 +3,29 @@ "chatterbox": {:hex, :ts_chatterbox, "0.11.0", "b8f372c706023eb0de5bf2976764edb27c70fe67052c88c1f6a66b3a5626847f", [:rebar3], [{:hpack, "~>0.2.3", [hex: :hpack_erl, repo: "hexpm", optional: false]}], "hexpm", "722fe2bad52913ab7e87d849fc6370375f0c961ffb2f0b5e6d647c9170c382a6"}, "connection": {:hex, :connection, "1.1.0", "ff2a49c4b75b6fb3e674bfc5536451607270aac754ffd1bdfe175abe4a6d7a68", [:mix], [], "hexpm", "722c1eb0a418fbe91ba7bd59a47e28008a189d47e37e0e7bb85585a016b2869c"}, "ctx": {:hex, :ctx, "0.6.0", "8ff88b70e6400c4df90142e7f130625b82086077a45364a78d208ed3ed53c7fe", [:rebar3], [], "hexpm", "a14ed2d1b67723dbebbe423b28d7615eb0bdcba6ff28f2d1f1b0a7e1d4aa5fc2"}, - "db_connection": {:hex, :db_connection, "2.4.1", "6411f6e23f1a8b68a82fa3a36366d4881f21f47fc79a9efb8c615e62050219da", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ea36d226ec5999781a9a8ad64e5d8c4454ecedc7a4d643e4832bf08efca01f00"}, + "db_connection": {:hex, :db_connection, "2.4.2", "f92e79aff2375299a16bcb069a14ee8615c3414863a6fef93156aee8e86c2ff3", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "4fe53ca91b99f55ea249693a0229356a08f4d1a7931d8ffa79289b145fe83668"}, "decimal": {:hex, :decimal, "2.0.0", "a78296e617b0f5dd4c6caf57c714431347912ffb1d0842e998e9792b5642d697", [:mix], [], "hexpm", "34666e9c55dea81013e77d9d87370fe6cb6291d1ef32f46a1600230b1d44f577"}, "dialyxir": {:hex, :dialyxir, "1.1.0", "c5aab0d6e71e5522e77beff7ba9e08f8e02bad90dfbeffae60eaf0cb47e29488", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "07ea8e49c45f15264ebe6d5b93799d4dd56a44036cf42d0ad9c960bc266c0b9a"}, "earmark": {:hex, :earmark, "1.4.15", "2c7f924bf495ec1f65bd144b355d0949a05a254d0ec561740308a54946a67888", [:mix], [{:earmark_parser, ">= 1.4.13", [hex: :earmark_parser, repo: "hexpm", optional: false]}], "hexpm", "3b1209b85bc9f3586f370f7c363f6533788fb4e51db23aa79565875e7f9999ee"}, - "earmark_parser": {:hex, :earmark_parser, "1.4.18", "e1b2be73eb08a49fb032a0208bf647380682374a725dfb5b9e510def8397f6f2", [:mix], [], "hexpm", "114a0e85ec3cf9e04b811009e73c206394ffecfcc313e0b346de0d557774ee97"}, - "ecto": {:hex, :ecto, "3.7.1", "a20598862351b29f80f285b21ec5297da1181c0442687f9b8329f0445d228892", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d36e5b39fc479e654cffd4dbe1865d9716e4a9b6311faff799b6f90ab81b8638"}, - "ecto_sql": {:hex, :ecto_sql, "3.7.1", "8de624ef50b2a8540252d8c60506379fbbc2707be1606853df371cf53df5d053", [:mix], [{:db_connection, "~> 2.2", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.7.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.4.0 or ~> 0.5.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.15.0 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "2b42a32e2ce92f64aba5c88617891ab3b0ba34f3f3a503fa20009eae1a401c81"}, + "earmark_parser": {:hex, :earmark_parser, "1.4.23", "1d5f22a2802160fd454404fbf5e8f5d14cd8eb727c63701397b72d8c35267e69", [:mix], [], "hexpm", "2ec13bf14b2f4bbb4a15480970e295eede8bb01087fad6ceca27b724ab8e9d18"}, + "ecto": {:hex, :ecto, "3.7.2", "44c034f88e1980754983cc4400585970b4206841f6f3780967a65a9150ef09a8", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a600da5772d1c31abbf06f3e4a1ffb150e74ed3e2aa92ff3cee95901657a874e"}, + "ecto_sql": {:hex, :ecto_sql, "3.7.2", "55c60aa3a06168912abf145c6df38b0295c34118c3624cf7a6977cd6ce043081", [:mix], [{:db_connection, "~> 2.2", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.7.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.4.0 or ~> 0.5.0 or ~> 0.6.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.15.0 or ~> 0.16.0 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3c218ea62f305dcaef0b915fb56583195e7b91c91dcfb006ba1f669bfacbff2a"}, "erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"}, "ex_doc": {:hex, :ex_doc, "0.26.0", "1922164bac0b18b02f84d6f69cab1b93bc3e870e2ad18d5dacb50a9e06b542a3", [:mix], [{:earmark_parser, "~> 1.4.0", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "2775d66e494a9a48355db7867478ffd997864c61c65a47d31c4949459281c78d"}, "gproc": {:hex, :gproc, "0.8.0", "cea02c578589c61e5341fce149ea36ccef236cc2ecac8691fba408e7ea77ec2f", [:rebar3], [], "hexpm", "580adafa56463b75263ef5a5df4c86af321f68694e7786cb057fd805d1e2a7de"}, "grpcbox": {:hex, :grpcbox, "0.14.0", "3eb321bcd2275baf8b54cf381feb7b0559a50c02544de28fda039c7f2f9d1a7a", [:rebar3], [{:acceptor_pool, "~>1.0.0", [hex: :acceptor_pool, repo: "hexpm", optional: false]}, {:chatterbox, "~>0.11.0", [hex: :ts_chatterbox, repo: "hexpm", optional: false]}, {:ctx, "~>0.6.0", [hex: :ctx, repo: "hexpm", optional: false]}, {:gproc, "~>0.8.0", [hex: :gproc, repo: "hexpm", optional: false]}], "hexpm", "e24159b7b6d3f9869bbe528845c0125fed2259366ba908fd04a1f45fe81d0660"}, "hpack": {:hex, :hpack_erl, "0.2.3", "17670f83ff984ae6cd74b1c456edde906d27ff013740ee4d9efaa4f1bf999633", [:rebar3], [], "hexpm", "06f580167c4b8b8a6429040df36cc93bba6d571faeaec1b28816523379cbb23a"}, - "makeup": {:hex, :makeup, "1.0.5", "d5a830bc42c9800ce07dd97fa94669dfb93d3bf5fcf6ea7a0c67b2e0e4a7f26c", [:mix], [{:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cfa158c02d3f5c0c665d0af11512fed3fba0144cf1aadee0f2ce17747fba2ca9"}, - "makeup_elixir": {:hex, :makeup_elixir, "0.15.2", "dc72dfe17eb240552857465cc00cce390960d9a0c055c4ccd38b70629227e97c", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.1", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "fd23ae48d09b32eff49d4ced2b43c9f086d402ee4fd4fcb2d7fad97fa8823e75"}, + "makeup": {:hex, :makeup, "1.1.0", "6b67c8bc2882a6b6a445859952a602afc1a41c2e08379ca057c0f525366fc3ca", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "0a45ed501f4a8897f580eabf99a2e5234ea3e75a4373c8a52824f6e873be57a6"}, + "makeup_elixir": {:hex, :makeup_elixir, "0.16.0", "f8c570a0d33f8039513fbccaf7108c5d750f47d8defd44088371191b76492b0b", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "28b2cbdc13960a46ae9a8858c4bebdec3c9a6d7b4b9e7f4ed1502f8159f338e7"}, "makeup_erlang": {:hex, :makeup_erlang, "0.1.1", "3fcb7f09eb9d98dc4d208f49cc955a34218fc41ff6b84df7c75b3e6e533cc65f", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "174d0809e98a4ef0b3309256cbf97101c6ec01c4ab0b23e926a9e17df2077cbb"}, - "nimble_parsec": {:hex, :nimble_parsec, "1.2.0", "b44d75e2a6542dcb6acf5d71c32c74ca88960421b6874777f79153bbbbd7dccc", [:mix], [], "hexpm", "52b2871a7515a5ac49b00f214e4165a40724cf99798d8e4a65e4fd64ebd002c1"}, - "opentelemetry": {:hex, :opentelemetry, "1.0.0", "6e98f4a9230681b2e4c88d45783ce1c02d671ffc0b5ac0cba69a34a3f5ada8d8", [:rebar3], [{:opentelemetry_api, "~> 1.0.0", [hex: :opentelemetry_api, repo: "hexpm", optional: false]}], "hexpm", "08d8697740f70594d05067cb62a0a8845ff568b2d47e1f8c78c46708ab58a74f"}, - "opentelemetry_api": {:hex, :opentelemetry_api, "1.0.0", "6e501f750ead189f35aed07eb8023fa6655fca12f913a196102f67db4ed5172c", [:mix, :rebar3], [], "hexpm", "ac51520bde21fdea7f82cea9236ce4e88a21281c22bc23b0f1fa3b28b4352fcf"}, - "opentelemetry_exporter": {:hex, :opentelemetry_exporter, "1.0.0", "12fd928e72dec8108d40214a667e7a90026827d6268db678617c9e40ec3dc931", [:rebar3], [{:grpcbox, ">= 0.0.0", [hex: :grpcbox, repo: "hexpm", optional: false]}, {:opentelemetry, "~> 1.0", [hex: :opentelemetry, repo: "hexpm", optional: false]}, {:opentelemetry_api, "~> 1.0", [hex: :opentelemetry_api, repo: "hexpm", optional: false]}, {:tls_certificate_check, "~> 1.11", [hex: :tls_certificate_check, repo: "hexpm", optional: false]}], "hexpm", "e2d2377abfb823cc99c1b68b4ce31df1ff1ce63e0c7bdbee7a7527e2d825168d"}, - "postgrex": {:hex, :postgrex, "0.15.13", "7794e697481799aee8982688c261901de493eb64451feee6ea58207d7266d54a", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "3ffb76e1a97cfefe5c6a95632a27ffb67f28871c9741fb585f9d1c3cd2af70f1"}, + "nimble_parsec": {:hex, :nimble_parsec, "1.2.3", "244836e6e3f1200c7f30cb56733fd808744eca61fd182f731eac4af635cc6d0b", [:mix], [], "hexpm", "c8d789e39b9131acf7b99291e93dae60ab48ef14a7ee9d58c6964f59efb570b0"}, + "opentelemetry": {:hex, :opentelemetry, "1.0.2", "9ffa9ddcbec9356154681bc9d0a54bb20f0de0e8c6696ccc298b49633308782b", [:rebar3], [{:opentelemetry_api, "~> 1.0", [hex: :opentelemetry_api, repo: "hexpm", optional: false]}], "hexpm", "e774506333c8afd9133fee4ba69d06e6413ccad6ee76f10e59c3ec624009af23"}, + "opentelemetry_api": {:hex, :opentelemetry_api, "1.0.2", "91353ee40583b1d4f07d7b13ed62642abfec6aaa0d8a2114f07edafb2df781c5", [:mix, :rebar3], [], "hexpm", "2a8247f85c44216b883900067478d59955d11e58e5cfca7c884cd4f203ace3ac"}, + "opentelemetry_ecto": {:git, "https://github.com/bryannaegele/opentelemetry-erlang-contrib.git", "9730da9300cdd08138d3455deb270b06f3a440fa", [sparse: "propagators/opentelemetry_process_propagator", branch: "otel-process-walker"]}, + "opentelemetry_exporter": {:hex, :opentelemetry_exporter, "1.0.2", "19a102d1f04776399a915be27121852468318c27146e553faf28008e3e474972", [:rebar3], [{:grpcbox, ">= 0.0.0", [hex: :grpcbox, repo: "hexpm", optional: false]}, {:opentelemetry, "~> 1.0", [hex: :opentelemetry, repo: "hexpm", optional: false]}, {:opentelemetry_api, "~> 1.0", [hex: :opentelemetry_api, repo: "hexpm", optional: false]}, {:tls_certificate_check, "~> 1.11", [hex: :tls_certificate_check, repo: "hexpm", optional: false]}], "hexpm", "43de904dd7f482009bf1a40d591ab5ed25f603f1072a04a162e87f7f8c08dbb5"}, + "opentelemetry_process_propagator": {:hex, :opentelemetry_process_propagator, "0.1.1", "81ec6825971903486ee73be23230d06764df39ee11011e520f601aa2bb21c893", [:mix, :rebar3], [{:opentelemetry_api, "~> 1.0", [hex: :opentelemetry_api, repo: "hexpm", optional: false]}], "hexpm", "0572f26066bbb0457e22e169f966c0140a8f95237716c9c6ba4458d6dbaa724b"}, + "postgrex": {:hex, :postgrex, "0.16.2", "0f83198d0e73a36e8d716b90f45f3bde75b5eebf4ade4f43fa1f88c90a812f74", [:mix], [{:connection, "~> 1.1", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "a9ea589754d9d4d076121090662b7afe155b374897a6550eb288f11d755acfa0"}, "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"}, "telemetry": {:hex, :telemetry, "1.0.0", "0f453a102cdf13d506b7c0ab158324c337c41f1cc7548f0bc0e130bbf0ae9452", [:rebar3], [], "hexpm", "73bc09fa59b4a0284efb4624335583c528e07ec9ae76aca96ea0673850aec57a"}, - "tls_certificate_check": {:hex, :tls_certificate_check, "1.11.0", "609dcd503f31170f0799dac380eb0e086388cf918fc769aaa60ddd6bbf575218", [:rebar3], [{:ssl_verify_fun, "1.1.6", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm", "4ab962212ef7c87482619cb298e1fe06e047b57f0bd58cc417b3b299eb8d036e"}, + "tls_certificate_check": {:hex, :tls_certificate_check, "1.12.0", "417124799daad41d5ed13d5efc15becec5b7bb9854397f92492b2e25be7b41f6", [:rebar3], [{:ssl_verify_fun, "1.1.6", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm", "f65b090606f2503364727013ef9f70a1535a7f00a78a850b2e7ab238dda4adcb"}, } diff --git a/instrumentation/opentelemetry_ecto/priv/test_repo/migrations/1_setup_tables.exs b/instrumentation/opentelemetry_ecto/priv/test_repo/migrations/1_setup_tables.exs index dc435b4..02a8f87 100644 --- a/instrumentation/opentelemetry_ecto/priv/test_repo/migrations/1_setup_tables.exs +++ b/instrumentation/opentelemetry_ecto/priv/test_repo/migrations/1_setup_tables.exs @@ -10,5 +10,10 @@ defmodule OpentelemetryEcto.TestRepo.Migrations.SetupTables do add :body, :text add :user_id, references(:users) end + + create table(:comments) do + add :body, :text + add :user_id, references(:users) + end end end diff --git a/instrumentation/opentelemetry_ecto/test/opentelemetry_ecto_test.exs b/instrumentation/opentelemetry_ecto/test/opentelemetry_ecto_test.exs index 11be4f3..2068bcd 100644 --- a/instrumentation/opentelemetry_ecto/test/opentelemetry_ecto_test.exs +++ b/instrumentation/opentelemetry_ecto/test/opentelemetry_ecto_test.exs @@ -4,7 +4,10 @@ defmodule OpentelemetryEctoTest do require OpenTelemetry.Tracer alias OpentelemetryEcto.TestRepo, as: Repo - alias OpentelemetryEcto.TestModels.{User, Post} + alias OpentelemetryEcto.TestModels.{Comment, User, Post} + + require Ecto.Query, as: Query + require OpenTelemetry.Tracer, as: Tracer @event_name [:opentelemetry_ecto, :test_repo] @@ -15,7 +18,16 @@ defmodule OpentelemetryEctoTest do end setup do - :otel_simple_processor.set_exporter(:otel_exporter_pid, self()) + :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()) OpenTelemetry.Tracer.start_span("test") @@ -113,6 +125,65 @@ defmodule OpentelemetryEctoTest do assert message =~ "non_existant_field does not exist" end + test "preloads in sequence are tied to the parent span" do + user = Repo.insert!(%User{email: "opentelemetry@erlang.org"}) + Repo.insert!(%Post{body: "We got traced!", user: user}) + Repo.insert!(%Comment{body: "We got traced!", user: user}) + + attach_handler() + + Tracer.with_span "parent span" do + Repo.all(Query.from(User, preload: [:posts, :comments]), in_parallel: false) + end + + assert_receive {:span, span(span_id: root_span_id, name: "parent span")} + assert_receive {:span, span(parent_span_id: ^root_span_id, name: "opentelemetry_ecto.test_repo.query:users")} + assert_receive {:span, span(parent_span_id: ^root_span_id, name: "opentelemetry_ecto.test_repo.query:posts")} + assert_receive {:span, span(parent_span_id: ^root_span_id, name: "opentelemetry_ecto.test_repo.query:comments")} + end + + test "preloads in parallel are tied to the parent span" do + user = Repo.insert!(%User{email: "opentelemetry@erlang.org"}) + Repo.insert!(%Post{body: "We got traced!", user: user}) + Repo.insert!(%Comment{body: "We got traced!", user: user}) + + attach_handler() + + Tracer.with_span "parent span" do + Repo.all(Query.from(User, preload: [:posts, :comments])) + end + + assert_receive {:span, span(span_id: root_span_id, name: "parent span")} + assert_receive {:span, span(parent_span_id: ^root_span_id, name: "opentelemetry_ecto.test_repo.query:users")} + assert_receive {:span, span(parent_span_id: ^root_span_id, name: "opentelemetry_ecto.test_repo.query:posts")} + assert_receive {:span, span(parent_span_id: ^root_span_id, name: "opentelemetry_ecto.test_repo.query:comments")} + end + + test "nested query preloads are tied to the parent span" do + user = Repo.insert!(%User{email: "opentelemetry@erlang.org"}) + Repo.insert!(%Post{body: "We got traced!", user: user}) + Repo.insert!(%Comment{body: "We got traced!", user: user}) + + attach_handler() + + Tracer.with_span "parent span" do + users_query = from u in User, preload: [:posts, :comments] + comments_query = from c in Comment, preload: [user: ^users_query] + Repo.all(Query.from(User, preload: [:posts, comments: ^comments_query])) + end + + assert_receive {:span, span(span_id: root_span_id, name: "parent span")} + # root query + assert_receive {:span, span(parent_span_id: ^root_span_id, name: "opentelemetry_ecto.test_repo.query:users")} + # comments preload + assert_receive {:span, span(parent_span_id: ^root_span_id, name: "opentelemetry_ecto.test_repo.query:comments")} + # users preload + assert_receive {:span, span(parent_span_id: ^root_span_id, name: "opentelemetry_ecto.test_repo.query:users")} + # preloads of user + assert_receive {:span, span(parent_span_id: ^root_span_id, name: "opentelemetry_ecto.test_repo.query:posts")} + assert_receive {:span, span(parent_span_id: ^root_span_id, name: "opentelemetry_ecto.test_repo.query:comments")} + end + def attach_handler(config \\ []) do # For now setup the handler manually in each test handler = {__MODULE__, self()} diff --git a/instrumentation/opentelemetry_ecto/test/support/models/comment.ex b/instrumentation/opentelemetry_ecto/test/support/models/comment.ex new file mode 100644 index 0000000..19cdb13 --- /dev/null +++ b/instrumentation/opentelemetry_ecto/test/support/models/comment.ex @@ -0,0 +1,8 @@ +defmodule OpentelemetryEcto.TestModels.Comment do + use Ecto.Schema + + schema "comments" do + field(:body, :string) + belongs_to(:user, OpentelemetryEcto.TestModels.User) + end +end diff --git a/instrumentation/opentelemetry_ecto/test/support/models/user.ex b/instrumentation/opentelemetry_ecto/test/support/models/user.ex index 0ea5a2b..280ec8b 100644 --- a/instrumentation/opentelemetry_ecto/test/support/models/user.ex +++ b/instrumentation/opentelemetry_ecto/test/support/models/user.ex @@ -5,5 +5,6 @@ defmodule OpentelemetryEcto.TestModels.User do field(:email, :string) has_many(:posts, OpentelemetryEcto.TestModels.Post) + has_many(:comments, OpentelemetryEcto.TestModels.Comment) end end