From ef99d6e2f3ec0160f2be81aefabad29ae0df6cd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Ro=C5=BCnawski?= Date: Fri, 6 Dec 2024 17:22:24 +0100 Subject: [PATCH] Add metrics --- ex_webrtc/CHANGELOG.md | 1 + .../test_videoroom/config/config.exs | 9 +- .../lib/test_videoroom/application.ex | 8 +- .../lib/test_videoroom/scraper.ex | 38 +++ .../integration_test/test_videoroom/mix.exs | 5 +- .../integration_test/test_videoroom/mix.lock | 18 +- .../test/integration/basic_test.exs | 53 ++++ .../integration/metrics_validator_test.exs | 204 ++++++++++++++ .../test/support/metrics_validator.ex | 127 +++++++++ .../lib/ex_webrtc/peer_connection_handler.ex | 49 +++- .../peer_connection_handler/metrics.ex | 264 ++++++++++++++++++ ex_webrtc/lib/metrics.ex | 11 +- ex_webrtc/mix.exs | 2 +- ex_webrtc/mix.lock | 14 +- examples/ex_webrtc_videoroom/mix.exs | 7 +- integration_test/mix.exs | 2 +- integration_test/mix.lock | 16 +- 17 files changed, 777 insertions(+), 51 deletions(-) create mode 100644 ex_webrtc/integration_test/test_videoroom/lib/test_videoroom/scraper.ex create mode 100644 ex_webrtc/integration_test/test_videoroom/test/integration/metrics_validator_test.exs create mode 100644 ex_webrtc/integration_test/test_videoroom/test/support/metrics_validator.ex create mode 100644 ex_webrtc/lib/ex_webrtc/peer_connection_handler/metrics.ex diff --git a/ex_webrtc/CHANGELOG.md b/ex_webrtc/CHANGELOG.md index 0a4b8a8f..dc6cb15c 100644 --- a/ex_webrtc/CHANGELOG.md +++ b/ex_webrtc/CHANGELOG.md @@ -16,3 +16,4 @@ * Fix simulcast tests [#22](https://github.com/fishjam-cloud/membrane_rtc_engine/pull/22) * Fix layer switching [#24](https://github.com/fishjam-cloud/membrane_rtc_engine/pull/24) * Allow for configuring ice servers [#25](https://github.com/fishjam-cloud/membrane_rtc_engine/pull/25) +* Add rtp metrics [#23](https://github.com/fishjam-cloud/membrane_rtc_engine/pull/23) diff --git a/ex_webrtc/integration_test/test_videoroom/config/config.exs b/ex_webrtc/integration_test/test_videoroom/config/config.exs index 290fadaf..43ab3147 100644 --- a/ex_webrtc/integration_test/test_videoroom/config/config.exs +++ b/ex_webrtc/integration_test/test_videoroom/config/config.exs @@ -33,11 +33,6 @@ config :logger, :console, format: "$time $metadata[$level] $message\n", metadata: [:request_id] -config :logger, - compile_time_purge_matching: [ - [level_lower_than: :info] - ] - config :logger, level: :info config :phoenix, :json_library, Jason @@ -45,4 +40,8 @@ config :phoenix, :json_library, Jason # The CI image is too old for the precompiled deps to work config :bundlex, :disable_precompiled_os_deps, apps: [:ex_libsrtp] +config :membrane_telemetry_metrics, enabled: true + +config :membrane_rtc_engine_ex_webrtc, get_stats_interval: 1_000 + import_config "#{config_env()}.exs" diff --git a/ex_webrtc/integration_test/test_videoroom/lib/test_videoroom/application.ex b/ex_webrtc/integration_test/test_videoroom/lib/test_videoroom/application.ex index 5bc3ac56..d1ef1ec4 100644 --- a/ex_webrtc/integration_test/test_videoroom/lib/test_videoroom/application.ex +++ b/ex_webrtc/integration_test/test_videoroom/lib/test_videoroom/application.ex @@ -7,7 +7,13 @@ defmodule TestVideoroom.Application do def start(_type, _args) do children = [ {Phoenix.PubSub, name: TestVideoroom.PubSub}, - TestVideoroomWeb.Endpoint + TestVideoroomWeb.Endpoint, + {Membrane.TelemetryMetrics.Reporter, + [ + metrics: Membrane.RTC.Engine.Endpoint.ExWebRTC.Metrics.metrics(), + name: ExWebrtcMetricsReporter + ]}, + TestVideoroom.MetricsScraper ] opts = [strategy: :one_for_one, name: TestVideoroom.Supervisor] diff --git a/ex_webrtc/integration_test/test_videoroom/lib/test_videoroom/scraper.ex b/ex_webrtc/integration_test/test_videoroom/lib/test_videoroom/scraper.ex new file mode 100644 index 00000000..845f460b --- /dev/null +++ b/ex_webrtc/integration_test/test_videoroom/lib/test_videoroom/scraper.ex @@ -0,0 +1,38 @@ +defmodule TestVideoroom.MetricsScraper do + @moduledoc false + + use GenServer, restart: :temporary + + alias Membrane.TelemetryMetrics.Reporter + + @scrape_interval 1_000 + + def start_link(_opts) do + GenServer.start_link(__MODULE__, @scrape_interval, name: __MODULE__) + end + + @impl true + def init(scrape_interval) do + send(self(), :scrape) + + {:ok, %{scrape_interval: scrape_interval, subscriptions: []}} + end + + @impl true + def handle_info(:scrape, state) do + report = Reporter.scrape(ExWebrtcMetricsReporter) + + Process.send_after(self(), :scrape, state.scrape_interval) + + Enum.each(state.subscriptions, &send(&1, {:metrics, report})) + + {:noreply, state} + end + + @impl true + def handle_info({:subscribe, pid}, state) do + Reporter.scrape_and_cleanup(ExWebrtcMetricsReporter) + state = update_in(state.subscriptions, &[pid | &1]) + {:noreply, state} + end +end diff --git a/ex_webrtc/integration_test/test_videoroom/mix.exs b/ex_webrtc/integration_test/test_videoroom/mix.exs index 5525a8e4..015740e6 100644 --- a/ex_webrtc/integration_test/test_videoroom/mix.exs +++ b/ex_webrtc/integration_test/test_videoroom/mix.exs @@ -31,13 +31,12 @@ defmodule TestVideoroom.MixProject do {:phoenix_html, "~> 3.0"}, {:phoenix_live_view, "~> 0.17"}, {:esbuild, "~> 0.4", runtime: Mix.env() == :dev}, - {:telemetry, "~> 1.0", override: true}, + {:telemetry, "~> 1.0"}, {:jason, "~> 1.2"}, {:plug_cowboy, "~> 2.5"}, {:cowlib, "~> 2.11", override: true}, - {:membrane_rtc_engine, path: rtc_engine_path(), override: true}, + {:membrane_rtc_engine, path: rtc_engine_path()}, {:membrane_rtc_engine_ex_webrtc, path: Path.join(rtc_engine_path(), "../ex_webrtc/")}, - {:ex_sdp, "~> 0.17.0", override: true}, {:stampede, github: "fishjam-dev/stampede-elixir"} ] end diff --git a/ex_webrtc/integration_test/test_videoroom/mix.lock b/ex_webrtc/integration_test/test_videoroom/mix.lock index 857f9b97..b45dba2a 100644 --- a/ex_webrtc/integration_test/test_videoroom/mix.lock +++ b/ex_webrtc/integration_test/test_videoroom/mix.lock @@ -2,25 +2,25 @@ "bimap": {:hex, :bimap, "1.3.0", "3ea4832e58dc83a9b5b407c6731e7bae87458aa618e6d11d8e12114a17afa4b3", [:mix], [], "hexpm", "bf5a2b078528465aa705f405a5c638becd63e41d280ada41e0f77e6d255a10b4"}, "bunch": {:hex, :bunch, "1.6.1", "5393d827a64d5f846092703441ea50e65bc09f37fd8e320878f13e63d410aec7", [:mix], [], "hexpm", "286cc3add551628b30605efbe2fca4e38cc1bea89bcd0a1a7226920b3364fe4a"}, "bunch_native": {:hex, :bunch_native, "0.5.0", "8ac1536789a597599c10b652e0b526d8833348c19e4739a0759a2bedfd924e63", [:mix], [{:bundlex, "~> 1.0", [hex: :bundlex, repo: "hexpm", optional: false]}], "hexpm", "24190c760e32b23b36edeb2dc4852515c7c5b3b8675b1a864e0715bdd1c8f80d"}, - "bundlex": {:hex, :bundlex, "1.5.3", "35d01e5bc0679510dd9a327936ffb518f63f47175c26a35e708cc29eaec0890b", [:mix], [{:bunch, "~> 1.0", [hex: :bunch, repo: "hexpm", optional: false]}, {:elixir_uuid, "~> 1.2", [hex: :elixir_uuid, repo: "hexpm", optional: false]}, {:qex, "~> 0.5", [hex: :qex, repo: "hexpm", optional: false]}, {:req, ">= 0.4.0", [hex: :req, repo: "hexpm", optional: false]}, {:zarex, "~> 1.0", [hex: :zarex, repo: "hexpm", optional: false]}], "hexpm", "debd0eac151b404f6216fc60222761dff049bf26f7d24d066c365317650cd118"}, - "castore": {:hex, :castore, "1.0.9", "5cc77474afadf02c7c017823f460a17daa7908e991b0cc917febc90e466a375c", [:mix], [], "hexpm", "5ea956504f1ba6f2b4eb707061d8e17870de2bee95fb59d512872c2ef06925e7"}, + "bundlex": {:hex, :bundlex, "1.5.4", "3726acd463f4d31894a59bbc177c17f3b574634a524212f13469f41c4834a1d9", [:mix], [{:bunch, "~> 1.0", [hex: :bunch, repo: "hexpm", optional: false]}, {:elixir_uuid, "~> 1.2", [hex: :elixir_uuid, repo: "hexpm", optional: false]}, {:qex, "~> 0.5", [hex: :qex, repo: "hexpm", optional: false]}, {:req, ">= 0.4.0", [hex: :req, repo: "hexpm", optional: false]}, {:zarex, "~> 1.0", [hex: :zarex, repo: "hexpm", optional: false]}], "hexpm", "e745726606a560275182a8ac1c8ebd5e11a659bb7460d8abf30f397e59b4c5d2"}, + "castore": {:hex, :castore, "1.0.10", "43bbeeac820f16c89f79721af1b3e092399b3a1ecc8df1a472738fd853574911", [:mix], [], "hexpm", "1b0b7ea14d889d9ea21202c43a4fa015eb913021cb535e8ed91946f4b77a8848"}, "coerce": {:hex, :coerce, "1.0.1", "211c27386315dc2894ac11bc1f413a0e38505d808153367bd5c6e75a4003d096", [:mix], [], "hexpm", "b44a691700f7a1a15b4b7e2ff1fa30bebd669929ac8aa43cffe9e2f8bf051cf1"}, "cowboy": {:hex, :cowboy, "2.12.0", "f276d521a1ff88b2b9b4c54d0e753da6c66dd7be6c9fca3d9418b561828a3731", [:make, :rebar3], [{:cowlib, "2.13.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "8a7abe6d183372ceb21caa2709bec928ab2b72e18a3911aa1771639bef82651e"}, "cowboy_telemetry": {:hex, :cowboy_telemetry, "0.4.0", "f239f68b588efa7707abce16a84d0d2acf3a0f50571f8bb7f56a15865aae820c", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7d98bac1ee4565d31b62d59f8823dfd8356a169e7fcbb83831b8a5397404c9de"}, "cowlib": {:hex, :cowlib, "2.13.0", "db8f7505d8332d98ef50a3ef34b34c1afddec7506e4ee4dd4a3a266285d282ca", [:make, :rebar3], [], "hexpm", "e1e1284dc3fc030a64b1ad0d8382ae7e99da46c3246b815318a4b848873800a4"}, "crc": {:hex, :crc, "0.10.5", "ee12a7c056ac498ef2ea985ecdc9fa53c1bfb4e53a484d9f17ff94803707dfd8", [:mix, :rebar3], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "3e673b6495a9525c5c641585af1accba59a1eb33de697bedf341e247012c2c7f"}, - "elixir_make": {:hex, :elixir_make, "0.8.4", "4960a03ce79081dee8fe119d80ad372c4e7badb84c493cc75983f9d3bc8bde0f", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:certifi, "~> 2.0", [hex: :certifi, repo: "hexpm", optional: true]}], "hexpm", "6e7f1d619b5f61dfabd0a20aa268e575572b542ac31723293a4c1a567d5ef040"}, + "elixir_make": {:hex, :elixir_make, "0.9.0", "6484b3cd8c0cee58f09f05ecaf1a140a8c97670671a6a0e7ab4dc326c3109726", [:mix], [], "hexpm", "db23d4fd8b757462ad02f8aa73431a426fe6671c80b200d9710caf3d1dd0ffdb"}, "elixir_uuid": {:hex, :elixir_uuid, "1.2.1", "dce506597acb7e6b0daeaff52ff6a9043f5919a4c3315abb4143f0b00378c097", [:mix], [], "hexpm", "f7eba2ea6c3555cea09706492716b0d87397b88946e6380898c2889d68585752"}, "esbuild": {:hex, :esbuild, "0.8.1", "0cbf919f0eccb136d2eeef0df49c4acf55336de864e63594adcea3814f3edf41", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "25fc876a67c13cb0a776e7b5d7974851556baeda2085296c14ab48555ea7560f"}, "ex_dtls": {:hex, :ex_dtls, "0.16.0", "3ae38025ccc77f6db573e2e391602fa9bbc02253c137d8d2d59469a66cbe806b", [:mix], [{:bundlex, "~> 1.5.3", [hex: :bundlex, repo: "hexpm", optional: false]}, {:unifex, "~> 1.0", [hex: :unifex, repo: "hexpm", optional: false]}], "hexpm", "2a4e30d74c6ddf95cc5b796423293c06a0da295454c3823819808ff031b4b361"}, - "ex_ice": {:hex, :ex_ice, "0.8.3", "b3a56d8cc44555705dc33ce0942d0ce3fe9fa3132a1f1bfe79b4c5b91ed1562b", [:mix], [{:elixir_uuid, "~> 1.0", [hex: :elixir_uuid, repo: "hexpm", optional: false]}, {:ex_stun, "~> 0.2.0", [hex: :ex_stun, repo: "hexpm", optional: false]}, {:ex_turn, "~> 0.1.0", [hex: :ex_turn, repo: "hexpm", optional: false]}], "hexpm", "ffc17fa8f1bfb6e744eeb7e1009f3dd2e37dfd745ec808c66faeafb93ab0e036"}, + "ex_ice": {:hex, :ex_ice, "0.9.0", "d1a7e31b9cc52faf668f001f870344d3f9094955bafb6af62d84b7b4c2dd6b36", [:mix], [{:elixir_uuid, "~> 1.0", [hex: :elixir_uuid, repo: "hexpm", optional: false]}, {:ex_stun, "~> 0.2.0", [hex: :ex_stun, repo: "hexpm", optional: false]}, {:ex_turn, "~> 0.2.0", [hex: :ex_turn, repo: "hexpm", optional: false]}], "hexpm", "8f256faeb9cc5409d2177e68918198c7ef64372a729c8e1590699546554419aa"}, "ex_libsrtp": {:hex, :ex_libsrtp, "0.7.2", "211bd89c08026943ce71f3e2c0231795b99cee748808ed3ae7b97cd8d2450b6b", [:mix], [{:bunch, "~> 1.6", [hex: :bunch, repo: "hexpm", optional: false]}, {:bundlex, "~> 1.3", [hex: :bundlex, repo: "hexpm", optional: false]}, {:membrane_precompiled_dependency_provider, "~> 0.1.0", [hex: :membrane_precompiled_dependency_provider, repo: "hexpm", optional: false]}, {:unifex, "~> 1.1", [hex: :unifex, repo: "hexpm", optional: false]}], "hexpm", "2e20645d0d739a4ecdcf8d4810a0c198120c8a2f617f2b75b2e2e704d59f492a"}, "ex_rtcp": {:hex, :ex_rtcp, "0.4.0", "f9e515462a9581798ff6413583a25174cfd2101c94a2ebee871cca7639886f0a", [:mix], [], "hexpm", "28956602cf210d692fcdaf3f60ca49681634e1deb28ace41246aee61ee22dc3b"}, "ex_rtp": {:hex, :ex_rtp, "0.4.0", "1f1b5c1440a904706011e3afbb41741f5da309ce251cb986690ce9fd82636658", [:mix], [], "hexpm", "0f72d80d5953a62057270040f0f1ee6f955c08eeae82ac659c038001d7d5a790"}, - "ex_sdp": {:hex, :ex_sdp, "0.17.0", "4c50e7814f01f149c0ccf258fba8428f8567dffecf1c416ec3f6aaaac607a161", [:mix], [{:bunch, "~> 1.3", [hex: :bunch, repo: "hexpm", optional: false]}, {:elixir_uuid, "~> 1.2", [hex: :elixir_uuid, repo: "hexpm", optional: false]}], "hexpm", "c7fe0625902be2a835b5fe6834a189f7db7639d2625c8e9d8b3564e6d704145f"}, + "ex_sdp": {:hex, :ex_sdp, "1.1.0", "a93d72d00704efd83f7e144e4ca9822ca4aea5b5d851353d092de40e1ad0ecdc", [:mix], [{:bunch, "~> 1.3", [hex: :bunch, repo: "hexpm", optional: false]}, {:elixir_uuid, "~> 1.2", [hex: :elixir_uuid, repo: "hexpm", optional: false]}], "hexpm", "f5c033abcda958a9b090210f9429f24b74b003c28c24175c58a033a5205a1cfe"}, "ex_stun": {:hex, :ex_stun, "0.2.0", "feb1fc7db0356406655b2a617805e6c712b93308c8ea2bf0ba1197b1f0866deb", [:mix], [], "hexpm", "1e01ba8290082ccbf37acaa5190d1f69b51edd6de2026a8d6d51368b29d115d0"}, - "ex_turn": {:hex, :ex_turn, "0.1.0", "177405aadf3d754567d0d37cf881a83f9cacf8f45314d188633b04c4a9e7c1ec", [:mix], [{:ex_stun, "~> 0.2.0", [hex: :ex_stun, repo: "hexpm", optional: false]}], "hexpm", "d677737fb7d45274d5dac19fe3c26b9038b6effbc0a6b3e7417bccc76b6d1cd3"}, - "ex_webrtc": {:hex, :ex_webrtc, "0.6.1", "684134caccc1bb12402d3501c33d98f97ac83ff17e4d9d1c88a53983bad95187", [:mix], [{:crc, "~> 0.10", [hex: :crc, repo: "hexpm", optional: false]}, {:ex_dtls, "~> 0.16.0", [hex: :ex_dtls, repo: "hexpm", optional: false]}, {:ex_ice, "~> 0.8.3", [hex: :ex_ice, repo: "hexpm", optional: false]}, {:ex_libsrtp, "~> 0.7.1", [hex: :ex_libsrtp, repo: "hexpm", optional: false]}, {:ex_rtcp, "~> 0.4.0", [hex: :ex_rtcp, repo: "hexpm", optional: false]}, {:ex_rtp, "~> 0.4.0", [hex: :ex_rtp, repo: "hexpm", optional: false]}, {:ex_sctp, "0.1.0", [hex: :ex_sctp, repo: "hexpm", optional: true]}, {:ex_sdp, "~> 1.0", [hex: :ex_sdp, repo: "hexpm", optional: false]}], "hexpm", "2c989778d687c69a3da6c5a7c0c3d5bf9d4193012b25eefce77fdb06abb0dc4d"}, + "ex_turn": {:hex, :ex_turn, "0.2.0", "4e1f9b089e9a5ee44928d12370cc9ea7a89b84b2f6256832de65271212eb80de", [:mix], [{:ex_stun, "~> 0.2.0", [hex: :ex_stun, repo: "hexpm", optional: false]}], "hexpm", "08e884f0af2c4a147e3f8cd4ffe33e3452a256389f0956e55a8c4d75bf0e74cd"}, + "ex_webrtc": {:git, "https://github.com/elixir-webrtc/ex_webrtc.git", "a7a7f2975149e8da1fb1392eb842dec204fac2ba", []}, "finch": {:hex, :finch, "0.19.0", "c644641491ea854fc5c1bbaef36bfc764e3f08e7185e1f084e35e0672241b76d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.6.2 or ~> 1.7", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 1.1", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "fc5324ce209125d1e2fa0fcd2634601c52a787aff1cd33ee833664a5af4ea2b6"}, "fishjam_protos": {:git, "https://github.com/fishjam-cloud/protos.git", "0bcb420955d0441a355c49be0a492d9b827fbbe8", [sparse: "fishjam_protos"]}, "gun": {:hex, :gun, "1.3.3", "cf8b51beb36c22b9c8df1921e3f2bc4d2b1f68b49ad4fbc64e91875aa14e16b4", [:rebar3], [{:cowlib, "~> 2.7.0", [hex: :cowlib, repo: "hexpm", optional: false]}], "hexpm", "3106ce167f9c9723f849e4fb54ea4a4d814e3996ae243a1c828b256e749041e0"}, @@ -57,12 +57,12 @@ "ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"}, "ratio": {:hex, :ratio, "4.0.1", "3044166f2fc6890aa53d3aef0c336f84b2bebb889dc57d5f95cc540daa1912f8", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:numbers, "~> 5.2.0", [hex: :numbers, repo: "hexpm", optional: false]}], "hexpm", "c60cbb3ccdff9ffa56e7d6d1654b5c70d9f90f4d753ab3a43a6bf40855b881ce"}, "recase": {:hex, :recase, "0.8.0", "ec9500abee5d493d41e3cbfd7d51a4e10957a164570be0c805d5c6661b8cdbae", [:mix], [], "hexpm", "0d4b67b81e7897af77552bd1e6d6148717a4b45ec5c7b014a48b0ba9a28946b5"}, - "req": {:hex, :req, "0.5.6", "8fe1eead4a085510fe3d51ad854ca8f20a622aae46e97b302f499dfb84f726ac", [:mix], [{:brotli, "~> 0.3.1", [hex: :brotli, repo: "hexpm", optional: true]}, {:ezstd, "~> 1.0", [hex: :ezstd, repo: "hexpm", optional: true]}, {:finch, "~> 0.17", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 2.0.6 or ~> 2.1", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 1.0", [hex: :nimble_csv, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "cfaa8e720945d46654853de39d368f40362c2641c4b2153c886418914b372185"}, + "req": {:hex, :req, "0.5.8", "50d8d65279d6e343a5e46980ac2a70e97136182950833a1968b371e753f6a662", [:mix], [{:brotli, "~> 0.3.1", [hex: :brotli, repo: "hexpm", optional: true]}, {:ezstd, "~> 1.0", [hex: :ezstd, repo: "hexpm", optional: true]}, {:finch, "~> 0.17", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 2.0.6 or ~> 2.1", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 1.0", [hex: :nimble_csv, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "d7fc5898a566477e174f26887821a3c5082b243885520ee4b45555f5d53f40ef"}, "shmex": {:hex, :shmex, "0.5.1", "81dd209093416bf6608e66882cb7e676089307448a1afd4fc906c1f7e5b94cf4", [:mix], [{:bunch_native, "~> 0.5.0", [hex: :bunch_native, repo: "hexpm", optional: false]}, {:bundlex, "~> 1.0", [hex: :bundlex, repo: "hexpm", optional: false]}], "hexpm", "c29f8286891252f64c4e1dac40b217d960f7d58def597c4e606ff8fbe71ceb80"}, "stampede": {:git, "https://github.com/fishjam-dev/stampede-elixir.git", "3ef10d521c6ffb77725dfc4526299e8284fe0234", []}, "statistics": {:hex, :statistics, "0.6.3", "7fb182e7c1cab2980e392c7efef7ce326539f081f9defda4099550e9c2c7cb0f", [:mix], [], "hexpm", "a43d87726d240205e9ef47f29650a6e3132b4e4061e05512f32fa8120784a8e0"}, "telemetry": {:hex, :telemetry, "1.3.0", "fedebbae410d715cf8e7062c96a1ef32ec22e764197f70cda73d82778d61e7a2", [:rebar3], [], "hexpm", "7015fc8919dbe63764f4b4b87a95b7c0996bd539e0d499be6ec9d7f3875b79e6"}, "telemetry_metrics": {:hex, :telemetry_metrics, "0.6.2", "2caabe9344ec17eafe5403304771c3539f3b6e2f7fb6a6f602558c825d0d0bfb", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9b43db0dc33863930b9ef9d27137e78974756f5f198cae18409970ed6fa5b561"}, - "unifex": {:hex, :unifex, "1.2.0", "90d1ec5e6d788350e07e474f7bd8b0ee866d6606beb9ca4e20dbb26328712a84", [:mix], [{:bunch, "~> 1.0", [hex: :bunch, repo: "hexpm", optional: false]}, {:bundlex, "~> 1.4", [hex: :bundlex, repo: "hexpm", optional: false]}, {:shmex, "~> 0.5.0", [hex: :shmex, repo: "hexpm", optional: false]}], "hexpm", "7a8395aabc3ba6cff04bbe5b995de7f899a38eb57f189e49927d6b8b6ccb6883"}, + "unifex": {:hex, :unifex, "1.2.1", "6841c170a6e16509fac30b19e4e0a19937c33155a59088b50c15fc2c36251b6b", [:mix], [{:bunch, "~> 1.0", [hex: :bunch, repo: "hexpm", optional: false]}, {:bundlex, "~> 1.4", [hex: :bundlex, repo: "hexpm", optional: false]}, {:shmex, "~> 0.5.0", [hex: :shmex, repo: "hexpm", optional: false]}], "hexpm", "8c9d2e3c48df031e9995dd16865bab3df402c0295ba3a31f38274bb5314c7d37"}, "zarex": {:hex, :zarex, "1.0.5", "58239e3ee5d75f343262bb4df5cf466555a1c689f920e5d3651a9333972f7c7e", [:mix], [], "hexpm", "9fb72ef0567c2b2742f5119a1ba8a24a2fabb21b8d09820aefbf3e592fa9a46a"}, } diff --git a/ex_webrtc/integration_test/test_videoroom/test/integration/basic_test.exs b/ex_webrtc/integration_test/test_videoroom/test/integration/basic_test.exs index 2e9c5a46..2344bf7f 100644 --- a/ex_webrtc/integration_test/test_videoroom/test/integration/basic_test.exs +++ b/ex_webrtc/integration_test/test_videoroom/test/integration/basic_test.exs @@ -3,6 +3,8 @@ defmodule TestVideoroom.Integration.BasicTest do import TestVideoroom.Integration.Utils + alias TestVideoroom.MetricsValidator + @room_url "http://localhost:4001" # in miliseconds @@ -175,6 +177,48 @@ defmodule TestVideoroom.Integration.BasicTest do end end + @tag timeout: 30_000 + test "telemetry events are published" do + assert is_number(Application.fetch_env!(:membrane_rtc_engine_ex_webrtc, :get_stats_interval)) + browsers_number = 2 + + report_count = 15 + + pid = self() + receiver = Process.spawn(fn -> receive_stats(browsers_number, pid) end, [:link]) + + :ok = Process.send(TestVideoroom.MetricsScraper, {:subscribe, pid}, []) + + mustang_options = %{ + target_url: @room_url, + warmup_time: @warmup, + start_button: @start_with_all, + actions: [wait: report_count * 1_000], + receiver: receiver, + id: -1 + } + + for browser <- 0..(browsers_number - 1), into: [] do + mustang_options = %{mustang_options | id: browser} + + Task.async(fn -> + Stampede.start({TestMustang, mustang_options}, @browser_options) + end) + end + |> Task.await_many(:infinity) + + all_reports = receive_reports() + valid_reports = Enum.drop_while(all_reports, &(MetricsValidator.validate_report(&1) != :ok)) + + results = Enum.map(all_reports, &MetricsValidator.validate_report(&1)) + error_msg = "Too many reports failed. Results: #{inspect(results)}" + assert length(valid_reports) >= report_count - 3, error_msg + + Enum.each(valid_reports, fn report -> + assert :ok == MetricsValidator.validate_report(report) + end) + end + defp count_playing_streams(streams, kind) do streams |> Enum.filter(fn @@ -183,4 +227,13 @@ defmodule TestVideoroom.Integration.BasicTest do end) |> Enum.count() end + + defp receive_reports(reports \\ []) do + receive do + {:metrics, report} -> + receive_reports([report | reports]) + after + 0 -> Enum.reverse(reports) + end + end end diff --git a/ex_webrtc/integration_test/test_videoroom/test/integration/metrics_validator_test.exs b/ex_webrtc/integration_test/test_videoroom/test/integration/metrics_validator_test.exs new file mode 100644 index 00000000..65a0e0cc --- /dev/null +++ b/ex_webrtc/integration_test/test_videoroom/test/integration/metrics_validator_test.exs @@ -0,0 +1,204 @@ +defmodule TestVideoroom.MetricsValidatorTest do + use ExUnit.Case + + alias TestVideoroom.MetricsValidator + + @valid_report %{ + :"inbound-rtp.frames" => 711, + :"inbound-rtp.keyframes" => 6, + {:endpoint_id, "880b05c2-26ec-4570-bdb0-b3135cfb0f51"} => %{ + :"endpoint.metadata" => nil, + {:candidate_id, 14_026_748_491_453_184_096_451_935_712} => %{ + "remote_candidate.port": 57451, + "remote_candidate.candidate_type": :host, + "remote_candidate.address": {64769, 20937, 50361, 10743, 6191, 60062, 61488, 28880}, + "remote_candidate.protocol": :udp + }, + {:candidate_id, 32_868_965_248_888_745_976_920_688_227} => %{ + "remote_candidate.port": 52079, + "remote_candidate.candidate_type": :host, + "remote_candidate.address": {192, 168, 83, 211}, + "remote_candidate.protocol": :udp + }, + {:candidate_id, 45_401_189_091_481_423_807_557_611_453} => %{ + "remote_candidate.port": 64199, + "remote_candidate.candidate_type": :host, + "remote_candidate.address": {64868, 26973, 45153, 21239, 4306, 27448, 49169, 9579}, + "remote_candidate.protocol": :udp + }, + {:track_id, 17_624_400_963_682_007_360_158_917_538} => %{ + "outbound-rtp.bytes_sent_total": 18123, + "outbound-rtp.packets_sent_total": 869, + "outbound-rtp.bytes_sent": 38763, + "outbound-rtp.packets_sent": 861, + "outbound-rtp.nack_count": 0, + "outbound-rtp.pli_count": 0, + "outbound-rtp.markers_sent": 1, + "outbound-rtp.retransmitted_packets_sent": 0, + "outbound-rtp.retransmitted_bytes_sent": 0 + }, + {:track_id, 19_661_563_003_324_897_918_202_467_222} => %{ + "inbound-rtp.bytes_received_total": 32470, + "inbound-rtp.packets_received_total": 869, + "inbound-rtp.bytes_received": 49754, + "inbound-rtp.packets_received": 861, + "inbound-rtp.nack_count": 0, + "inbound-rtp.pli_count": 0, + "inbound-rtp.markers_received": 1, + "inbound-rtp.codec": "opus" + }, + {:track_id, 40_536_105_556_528_381_230_985_426_570} => %{ + "inbound-rtp.bytes_received_total": 627_866, + "inbound-rtp.packets_received_total": 711, + "inbound-rtp.bytes_received": 630_870, + "inbound-rtp.packets_received": 700, + "inbound-rtp.nack_count": 0, + "inbound-rtp.pli_count": 0, + "inbound-rtp.markers_received": 354, + "inbound-rtp.codec": "VP8" + }, + {:track_id, 45_142_545_509_899_998_558_361_891_913} => %{ + "outbound-rtp.bytes_sent_total": 613_269, + "outbound-rtp.packets_sent_total": 700, + "outbound-rtp.bytes_sent": 621_353, + "outbound-rtp.packets_sent": 691, + "outbound-rtp.nack_count": 0, + "outbound-rtp.pli_count": 0, + "outbound-rtp.markers_sent": 342, + "outbound-rtp.retransmitted_packets_sent": 0, + "outbound-rtp.retransmitted_bytes_sent": 0 + }, + {:track_id, "880b05c2-26ec-4570-bdb0-b3135cfb0f51:975ea58f-d4f9-4883-bf0b-d65c0518f427:h"} => + %{ + "track.metadata": %{"kind" => "audio", "peer" => "someone"} + }, + {:track_id, "880b05c2-26ec-4570-bdb0-b3135cfb0f51:da2a5f8b-ce90-4a56-960f-6a9b516842f2:h"} => + %{ + "track.metadata": %{"kind" => "video", "peer" => "someone"} + } + }, + {:endpoint_id, "9f360310-3c39-4c06-8e56-4b03c219203f"} => %{ + :"endpoint.metadata" => nil, + {:candidate_id, 4_316_758_042_763_144_371_620_902_461} => %{ + "remote_candidate.port": 61619, + "remote_candidate.candidate_type": :host, + "remote_candidate.address": {64769, 20937, 50361, 10743, 6191, 60062, 61488, 28880}, + "remote_candidate.protocol": :udp + }, + {:candidate_id, 12_838_722_509_836_369_313_583_058_448} => %{ + "remote_candidate.port": 57870, + "remote_candidate.candidate_type": :host, + "remote_candidate.address": {64868, 26973, 45153, 21239, 4306, 27448, 49169, 9579}, + "remote_candidate.protocol": :udp + }, + {:candidate_id, 42_097_866_262_092_454_953_939_447_754} => %{ + "remote_candidate.port": 63088, + "remote_candidate.candidate_type": :host, + "remote_candidate.address": {192, 168, 83, 211}, + "remote_candidate.protocol": :udp + }, + {:track_id, 14_421_130_449_273_850_722_417_999_534} => %{ + "inbound-rtp.bytes_received_total": 18123, + "inbound-rtp.packets_received_total": 869, + "inbound-rtp.bytes_received": 35471, + "inbound-rtp.packets_received": 861, + "inbound-rtp.nack_count": 0, + "inbound-rtp.pli_count": 0, + "inbound-rtp.markers_received": 1, + "inbound-rtp.codec": "opus" + }, + {:track_id, 21_544_248_585_878_222_070_106_624_216} => %{ + "inbound-rtp.bytes_received_total": 629_237, + "inbound-rtp.packets_received_total": 718, + "inbound-rtp.bytes_received": 635_165, + "inbound-rtp.packets_received": 709, + "inbound-rtp.nack_count": 0, + "inbound-rtp.pli_count": 0, + "inbound-rtp.markers_received": 360, + "inbound-rtp.codec": "VP8" + }, + {:track_id, 32_580_941_273_413_257_887_365_770_913} => %{ + "outbound-rtp.bytes_sent_total": 615_802, + "outbound-rtp.packets_sent_total": 699, + "outbound-rtp.bytes_sent": 621_210, + "outbound-rtp.packets_sent": 688, + "outbound-rtp.nack_count": 0, + "outbound-rtp.pli_count": 0, + "outbound-rtp.markers_sent": 342, + "outbound-rtp.retransmitted_packets_sent": 0, + "outbound-rtp.retransmitted_bytes_sent": 0 + }, + {:track_id, 55_846_976_219_512_124_544_222_914_403} => %{ + "outbound-rtp.bytes_sent_total": 32470, + "outbound-rtp.packets_sent_total": 869, + "outbound-rtp.bytes_sent": 53110, + "outbound-rtp.packets_sent": 861, + "outbound-rtp.nack_count": 0, + "outbound-rtp.pli_count": 0, + "outbound-rtp.markers_sent": 1, + "outbound-rtp.retransmitted_packets_sent": 0, + "outbound-rtp.retransmitted_bytes_sent": 0 + }, + {:track_id, "9f360310-3c39-4c06-8e56-4b03c219203f:c4239011-91d8-42ca-9f9b-21362a3e4d04:h"} => + %{ + "track.metadata": %{"kind" => "video", "peer" => "someone"} + }, + {:track_id, "9f360310-3c39-4c06-8e56-4b03c219203f:c8948440-c09c-4ef5-bbbb-60323b83c6e0:h"} => + %{ + "track.metadata": %{"kind" => "audio", "peer" => "someone"} + } + }, + {:track_id, "880b05c2-26ec-4570-bdb0-b3135cfb0f51:975ea58f-d4f9-4883-bf0b-d65c0518f427"} => %{ + "outbound-rtp.variant": :high, + "outbound-rtp.variant-reason": :set_bandwidth_allocation + }, + {:track_id, "880b05c2-26ec-4570-bdb0-b3135cfb0f51:da2a5f8b-ce90-4a56-960f-6a9b516842f2"} => %{ + "outbound-rtp.variant": :high, + "outbound-rtp.variant-reason": :set_bandwidth_allocation + }, + {:track_id, "9f360310-3c39-4c06-8e56-4b03c219203f:c4239011-91d8-42ca-9f9b-21362a3e4d04"} => %{ + "outbound-rtp.variant": :high, + "outbound-rtp.variant-reason": :set_bandwidth_allocation + }, + {:track_id, "9f360310-3c39-4c06-8e56-4b03c219203f:c8948440-c09c-4ef5-bbbb-60323b83c6e0"} => %{ + "outbound-rtp.variant": :high, + "outbound-rtp.variant-reason": :set_bandwidth_allocation + } + } + + test "Validates correct report" do + assert :ok == MetricsValidator.validate_report(@valid_report) + end + + test "Invalidates incorrect reports" do + report = + Map.update!( + @valid_report, + {:endpoint_id, "9f360310-3c39-4c06-8e56-4b03c219203f"}, + &Map.delete(&1, :"endpoint.metadata") + ) + + assert {:error, _reason} = MetricsValidator.validate_report(report) + + report = + Map.update!( + @valid_report, + {:endpoint_id, "9f360310-3c39-4c06-8e56-4b03c219203f"}, + &Map.delete(&1, {:track_id, 14_421_130_449_273_850_722_417_999_534}) + ) + + assert {:error, _reason} = MetricsValidator.validate_report(report) + + report = + update_in( + @valid_report, + [ + {:endpoint_id, "9f360310-3c39-4c06-8e56-4b03c219203f"}, + {:track_id, 21_544_248_585_878_222_070_106_624_216} + ], + &Map.delete(&1, :"inbound-rtp.bytes_received_total") + ) + + assert {:error, _reason} = MetricsValidator.validate_report(report) + end +end diff --git a/ex_webrtc/integration_test/test_videoroom/test/support/metrics_validator.ex b/ex_webrtc/integration_test/test_videoroom/test/support/metrics_validator.ex new file mode 100644 index 00000000..8128e97d --- /dev/null +++ b/ex_webrtc/integration_test/test_videoroom/test/support/metrics_validator.ex @@ -0,0 +1,127 @@ +defmodule TestVideoroom.MetricsValidator do + @spec validate_report(map()) :: :ok | {:error, String.t()} + def validate_report(report) do + endpoint_metrics = find_entries(report, :endpoint_id) + + with 2 <- length(endpoint_metrics) do + Enum.reduce_while(endpoint_metrics, :ok, &validate_endpoint_metrics/2) + else + _length -> + {:error, + "Found #{length(endpoint_metrics)} when there should be exactly 2 :endpoint_id entries in #{inspect(report)}"} + end + end + + defp validate_endpoint_metrics(metrics, _acc) do + with true <- Map.has_key?(metrics, :"endpoint.metadata"), + :ok <- metrics |> find_entries(:candidate_id) |> validate_candidates(), + :ok <- metrics |> find_entries(:track_id) |> validate_tracks() do + {:cont, :ok} + else + false -> {:halt, {:error, "No :\"endpoint.metadata\" key in endpoint metrics"}} + {:error, reason} -> {:halt, {:error, "#{reason} in #{inspect(metrics)}"}} + end + end + + defp validate_candidates(candidates) do + with true <- length(candidates) >= 1, + :ok <- Enum.reduce_while(candidates, :ok, &validate_candidate/2) do + :ok + else + false -> + {:error, "Found #{length(candidates)} when there should be at least 1 remote candidate"} + + {:error, _reason} = error -> + error + end + end + + defp validate_candidate( + %{ + "remote_candidate.port": port, + "remote_candidate.candidate_type": type, + "remote_candidate.address": address, + "remote_candidate.protocol": protocol + } = candidate, + _acc + ) do + if is_number(port) and type in [:host, :srflx, :prflx] and is_tuple(address) and + protocol in [:udp, :tcp] do + {:cont, :ok} + else + {:halt, {:error, "Invalid candidate #{inspect(candidate)}"}} + end + end + + defp validate_candidate(candidate, _acc), + do: {:halt, {:error, "Invalid candidate #{inspect(candidate)}"}} + + defp validate_tracks(tracks) do + with true <- length(tracks) == 6, + :ok <- Enum.reduce_while(tracks, :ok, &validate_track/2) do + :ok + else + false -> {:error, "Found #{length(tracks)} when there should be exactly 6 track entries"} + {:error, _reason} = error -> error + end + end + + defp validate_track( + %{ + "outbound-rtp.bytes_sent_total": bytes_total, + "outbound-rtp.packets_sent_total": packets_total, + "outbound-rtp.bytes_sent": bytes_sent, + "outbound-rtp.packets_sent": packets_sent, + "outbound-rtp.nack_count": nack_count, + "outbound-rtp.pli_count": pli_count, + "outbound-rtp.markers_sent": markers_sent, + "outbound-rtp.retransmitted_packets_sent": retransmitted_packets, + "outbound-rtp.retransmitted_bytes_sent": retransmitted_bytes + } = track, + _acc + ) do + if bytes_total > 0 and packets_total > 0 and + bytes_sent > 0 and packets_sent > 0 and is_number(nack_count) and is_number(pli_count) and + is_number(markers_sent) and is_number(retransmitted_bytes) and + is_number(retransmitted_packets) do + {:cont, :ok} + else + {:halt, {:error, "Invalid outbound track #{inspect(track)}"}} + end + end + + defp validate_track( + %{ + "inbound-rtp.bytes_received_total": bytes_total, + "inbound-rtp.packets_received_total": packets_total, + "inbound-rtp.bytes_received": bytes_received, + "inbound-rtp.packets_received": packets_received, + "inbound-rtp.nack_count": nack_count, + "inbound-rtp.pli_count": pli_count, + "inbound-rtp.markers_received": markers_received, + "inbound-rtp.codec": codec + } = track, + _acc + ) do + if bytes_total > 0 and packets_total > 0 and bytes_received > 0 and packets_received > 0 and + is_number(nack_count) and is_number(pli_count) and is_number(markers_received) and + codec in ["VP8", "H264", "opus"] do + {:cont, :ok} + else + {:halt, {:error, "Invalid inbound track #{inspect(track)}"}} + end + end + + defp validate_track(%{"track.metadata": _metadata}, _acc), do: {:cont, :ok} + + defp validate_track(track, _acc), do: {:halt, {:error, "Invalid track #{inspect(track)}"}} + + defp find_entries(entries, name) do + entries + |> Enum.filter(fn + {{^name, _id}, _v} -> true + _entry -> false + end) + |> Enum.map(fn {_k, v} -> v end) + end +end diff --git a/ex_webrtc/lib/ex_webrtc/peer_connection_handler.ex b/ex_webrtc/lib/ex_webrtc/peer_connection_handler.ex index d5720fd1..9f1766e8 100644 --- a/ex_webrtc/lib/ex_webrtc/peer_connection_handler.ex +++ b/ex_webrtc/lib/ex_webrtc/peer_connection_handler.ex @@ -6,6 +6,7 @@ defmodule Membrane.RTC.Engine.Endpoint.ExWebRTC.PeerConnectionHandler do alias Membrane.Buffer alias Membrane.RTC.Engine.Endpoint.ExWebRTC, as: EndpointExWebRTC + alias Membrane.RTC.Engine.Endpoint.ExWebRTC.PeerConnectionHandler.Metrics alias Membrane.RTC.Engine.Track alias ExWebRTC.{MediaStreamTrack, PeerConnection, RTPReceiver, RTPTransceiver} @@ -17,6 +18,11 @@ defmodule Membrane.RTC.Engine.Endpoint.ExWebRTC.PeerConnectionHandler do video_codecs: [ spec: [EndpointExWebRTC.video_codec()] | nil, description: "Allowed video codecs" + ], + telemetry_label: [ + spec: Membrane.TelemetryMetrics.label(), + default: [], + description: "Label passed to Membrane.TelemetryMetrics functions" ] def_input_pad :input, @@ -55,6 +61,8 @@ defmodule Membrane.RTC.Engine.Endpoint.ExWebRTC.PeerConnectionHandler do @impl true def handle_init(_ctx, opts) do + Metrics.register_events(opts.telemetry_label) + %{endpoint_id: endpoint_id} = opts video_codecs = @@ -94,9 +102,16 @@ defmodule Membrane.RTC.Engine.Endpoint.ExWebRTC.PeerConnectionHandler do # maps webrtc_track_id to InboundTrack inbound_tracks: %{}, mid_to_track_id: %{}, - track_id_to_metadata: %{} + track_id_to_metadata: %{}, + telemetry_label: opts.telemetry_label, + get_stats_interval: + Application.get_env(:membrane_rtc_engine_ex_webrtc, :get_stats_interval), + peer_connection_signaling_state: nil } + if not is_nil(state.get_stats_interval), + do: Process.send_after(self(), :get_stats, state.get_stats_interval) + {[], state} end @@ -106,7 +121,10 @@ defmodule Membrane.RTC.Engine.Endpoint.ExWebRTC.PeerConnectionHandler do end @impl true - def handle_pad_added(_pad, _ctx, state) do + def handle_pad_added(Pad.ref(:input, track_id), _ctx, state) do + if not is_map_key(state.outbound_tracks, track_id), + do: Membrane.Logger.error("Receiving new unknown track: #{track_id}") + {[], state} end @@ -140,13 +158,14 @@ defmodule Membrane.RTC.Engine.Endpoint.ExWebRTC.PeerConnectionHandler do end) :ok = PeerConnection.send_rtp(state.pc, webrtc_track_id, packet) + Metrics.emit_outbound_packet_event(packet, webrtc_track_id, state.telemetry_label) {[], state} end @impl true def handle_buffer(Pad.ref(:input, track_id), _buffer, _ctx, state) do - Membrane.Logger.warning("Received buffer from unknown track #{track_id}") + Membrane.Logger.debug("Received buffer from unknown track #{track_id}") {[], state} end @@ -245,6 +264,17 @@ defmodule Membrane.RTC.Engine.Endpoint.ExWebRTC.PeerConnectionHandler do handle_webrtc_msg(msg, ctx, state) end + @impl true + def handle_info(:get_stats, _ctx, state) do + state.pc + |> PeerConnection.get_stats() + |> Metrics.emit_from_rtc_stats(state.telemetry_label) + + Process.send_after(self(), :get_stats, state.get_stats_interval) + + {[], state} + end + defp handle_webrtc_msg({:ice_candidate, candidate}, _ctx, state) do msg = {:candidate, candidate} {[notify_parent: msg], state} @@ -256,6 +286,7 @@ defmodule Membrane.RTC.Engine.Endpoint.ExWebRTC.PeerConnectionHandler do end defp handle_webrtc_msg({:rtp, webrtc_track_id, rid, packet}, ctx, state) do + Metrics.emit_inbound_packet_event(packet, webrtc_track_id, rid, state.telemetry_label) variant = EndpointExWebRTC.to_track_variant(rid) actions = @@ -290,8 +321,14 @@ defmodule Membrane.RTC.Engine.Endpoint.ExWebRTC.PeerConnectionHandler do {actions, state} end - defp handle_webrtc_msg({:signaling_state_change, :stable}, _ctx, state) do - {[notify_parent: :negotiation_done], state} + defp handle_webrtc_msg({:signaling_state_change, new_state}, _ctx, state) do + actions = + case {state.peer_connection_signaling_state, new_state} do + {:have_remote_offer, :stable} -> [notify_parent: :negotiation_done] + _other -> [] + end + + {actions, %{state | peer_connection_signaling_state: new_state}} end defp handle_webrtc_msg({:rtcp, packets}, _ctx, state) do @@ -428,7 +465,7 @@ defmodule Membrane.RTC.Engine.Endpoint.ExWebRTC.PeerConnectionHandler do transceiver.receiver.track.id == track.id end) - Membrane.Logger.info("new track #{track.id}, #{track.kind}") + Membrane.Logger.info("new track #{inspect(track)}") if is_nil(transceiver) do transceivers = PeerConnection.get_transceivers(pc) diff --git a/ex_webrtc/lib/ex_webrtc/peer_connection_handler/metrics.ex b/ex_webrtc/lib/ex_webrtc/peer_connection_handler/metrics.ex new file mode 100644 index 00000000..3cdd4425 --- /dev/null +++ b/ex_webrtc/lib/ex_webrtc/peer_connection_handler/metrics.ex @@ -0,0 +1,264 @@ +defmodule Membrane.RTC.Engine.Endpoint.ExWebRTC.PeerConnectionHandler.Metrics do + @moduledoc false + # Defines metrics and events for stats received from the PeerConnection + + require Membrane.TelemetryMetrics + + alias ExWebRTC.MediaStreamTrack + + alias Membrane.RTC.Engine.Endpoint + alias Membrane.TelemetryMetrics + + @type rtc_stats_report :: %{required(atom() | integer()) => map()} + + @inbound_rtp_event [Endpoint.ExWebRTC, :rtp, :inbound] + @packet_received_event [Endpoint.ExWebRTC, :rtp, :inbound, :packet] + + @outbound_rtp_event [Endpoint.ExWebRTC, :rtp, :outbound] + @packet_sent_event [Endpoint.ExWebRTC, :rtp, :outbound, :packet] + + @remote_candidate_event [Endpoint.ExWebRTC, :candidate, :remote] + + @spec metrics() :: [Telemetry.Metrics.t()] + def metrics() do + inbound_metrics() ++ outbound_metrics() ++ remote_candidate() + end + + defp inbound_metrics() do + [ + Telemetry.Metrics.sum( + "inbound-rtp.bytes_received_total", + event_name: @packet_received_event, + measurement: :bytes + ), + Telemetry.Metrics.counter( + "inbound-rtp.packets_received_total", + event_name: @packet_received_event + ), + Telemetry.Metrics.last_value( + "inbound-rtp.bytes_received", + event_name: @inbound_rtp_event, + measurement: :bytes_received + ), + Telemetry.Metrics.last_value( + "inbound-rtp.packets_received", + event_name: @inbound_rtp_event, + measurement: :packets_received + ), + Telemetry.Metrics.last_value( + "inbound-rtp.nack_count", + event_name: @inbound_rtp_event, + measurement: :nack_count + ), + Telemetry.Metrics.last_value( + "inbound-rtp.pli_count", + event_name: @inbound_rtp_event, + measurement: :pli_count + ), + Telemetry.Metrics.last_value( + "inbound-rtp.markers_received", + event_name: @inbound_rtp_event, + measurement: :markers_received + ), + Telemetry.Metrics.last_value( + "inbound-rtp.codec", + event_name: @inbound_rtp_event, + measurement: :codec + ) + ] + end + + defp outbound_metrics() do + [ + Telemetry.Metrics.sum( + "outbound-rtp.bytes_sent_total", + event_name: @packet_sent_event, + measurement: :bytes + ), + Telemetry.Metrics.counter( + "outbound-rtp.packets_sent_total", + event_name: @packet_sent_event + ), + Telemetry.Metrics.last_value( + "outbound-rtp.bytes_sent", + event_name: @outbound_rtp_event, + measurement: :bytes_sent + ), + Telemetry.Metrics.last_value( + "outbound-rtp.packets_sent", + event_name: @outbound_rtp_event, + measurement: :packets_sent + ), + Telemetry.Metrics.last_value( + "outbound-rtp.nack_count", + event_name: @outbound_rtp_event, + measurement: :nack_count + ), + Telemetry.Metrics.last_value( + "outbound-rtp.pli_count", + event_name: @outbound_rtp_event, + measurement: :pli_count + ), + Telemetry.Metrics.last_value( + "outbound-rtp.markers_sent", + event_name: @outbound_rtp_event, + measurement: :markers_sent + ), + Telemetry.Metrics.last_value( + "outbound-rtp.codec", + event_name: @outbound_rtp_event, + measurement: :codec + ), + Telemetry.Metrics.last_value( + "outbound-rtp.retransmitted_packets_sent", + event_name: @outbound_rtp_event, + measurement: :retransmitted_packets_sent + ), + Telemetry.Metrics.last_value( + "outbound-rtp.retransmitted_bytes_sent", + event_name: @outbound_rtp_event, + measurement: :retransmitted_bytes_sent + ) + ] + end + + defp remote_candidate() do + [ + Telemetry.Metrics.last_value( + "remote_candidate.port", + event_name: @remote_candidate_event, + measurement: :port + ), + Telemetry.Metrics.last_value( + "remote_candidate.candidate_type", + event_name: @remote_candidate_event, + measurement: :candidate_type + ), + Telemetry.Metrics.last_value( + "remote_candidate.address", + event_name: @remote_candidate_event, + measurement: :address + ), + Telemetry.Metrics.last_value( + "remote_candidate.protocol", + event_name: @remote_candidate_event, + measurement: :protocol + ) + ] + end + + @spec emit_inbound_packet_event( + ExRTP.Packet.t(), + MediaStreamTrack.id(), + MediaStreamTrack.rid() | nil, + TelemetryMetrics.label() + ) :: :ok + def emit_inbound_packet_event(packet, webrtc_track_id, rid, telemetry_label) do + track_label = + if is_nil(rid) do + [track_id: webrtc_track_id] + else + [track_id: "#{webrtc_track_id}:#{rid}"] + end + + telemetry_label = telemetry_label ++ track_label + + TelemetryMetrics.execute( + @packet_received_event, + %{bytes: byte_size(packet.payload)}, + %{}, + telemetry_label + ) + + :ok + end + + @spec emit_outbound_packet_event( + ExRTP.Packet.t(), + MediaStreamTrack.id(), + TelemetryMetrics.label() + ) :: :ok + def emit_outbound_packet_event(packet, webrtc_track_id, telemetry_label) do + telemetry_label = telemetry_label ++ [track_id: webrtc_track_id] + + TelemetryMetrics.execute( + @packet_sent_event, + %{bytes: byte_size(packet.payload)}, + %{}, + telemetry_label + ) + + :ok + end + + @spec register_events(TelemetryMetrics.label()) :: :ok + def register_events(telemetry_label) do + Enum.each( + [ + @inbound_rtp_event, + @packet_received_event, + @outbound_rtp_event, + @packet_sent_event + ], + &TelemetryMetrics.register(&1, telemetry_label) + ) + + :ok + end + + @spec emit_from_rtc_stats(rtc_stats_report(), TelemetryMetrics.label()) :: :ok + def emit_from_rtc_stats(metrics, telemetry_label) do + Enum.each(metrics, fn {_id, entry} -> handle_entry(entry, telemetry_label) end) + end + + defp handle_entry(%{type: :inbound_rtp} = entry, telemetry_label) do + telemetry_label = telemetry_label ++ [track_id: entry[:track_identifier]] + + TelemetryMetrics.execute( + @inbound_rtp_event, + Map.take(entry, [ + :packets_received, + :bytes_received, + :nack_count, + :pli_count, + :markers_received, + :codec + ]), + %{}, + telemetry_label + ) + end + + defp handle_entry(%{type: :outbound_rtp} = entry, telemetry_label) do + telemetry_label = telemetry_label ++ [track_id: entry[:track_identifier]] + + TelemetryMetrics.execute( + @outbound_rtp_event, + Map.take(entry, [ + :packets_sent, + :bytes_sent, + :nack_count, + :pli_count, + :markers_sent, + :codec, + :retransmitted_packets_sent, + :retransmitted_bytes_sent + ]), + %{}, + telemetry_label + ) + end + + defp handle_entry(%{type: :remote_candidate} = entry, telemetry_label) do + telemetry_label = telemetry_label ++ [candidate_id: entry.id] + + TelemetryMetrics.execute( + @remote_candidate_event, + entry, + %{}, + telemetry_label + ) + end + + defp handle_entry(_entry, _label), do: :ok +end diff --git a/ex_webrtc/lib/metrics.ex b/ex_webrtc/lib/metrics.ex index 0394b87a..45a91f1e 100644 --- a/ex_webrtc/lib/metrics.ex +++ b/ex_webrtc/lib/metrics.ex @@ -11,17 +11,18 @@ defmodule Membrane.RTC.Engine.Endpoint.ExWebRTC.Metrics do require Membrane.TelemetryMetrics - alias Membrane.RTC.Engine.Endpoint.ExWebRTC.TrackReceiver + alias Membrane.RTC.Engine.Endpoint + alias Membrane.RTC.Engine.Endpoint.ExWebRTC.{PeerConnectionHandler, TrackReceiver} alias Membrane.RTC.Engine.Track alias Membrane.RTP.PayloadFormatResolver - @rtp_packet_arrival_event [Membrane.RTC.Engine.Endpoint.ExWebRTC, :RTP, :packet, :arrival] - @variant_switched_event [Membrane.RTC.Engine.Endpoint.ExWebRTC, :RTP, :variant, :switched] - @paddings_sent_event [Membrane.RTC.Engine.Endpoint.ExWebRTC, :RTP, :paddings, :sent] + @rtp_packet_arrival_event [Endpoint.ExWebRTC, :RTP, :packet, :arrival] + @variant_switched_event [Endpoint.ExWebRTC, :RTP, :variant, :switched] + @paddings_sent_event [Endpoint.ExWebRTC, :RTP, :paddings, :sent] @spec metrics() :: [Telemetry.Metrics.t()] def metrics() do - endpoint_metrics() + endpoint_metrics() ++ PeerConnectionHandler.Metrics.metrics() end defp endpoint_metrics() do diff --git a/ex_webrtc/mix.exs b/ex_webrtc/mix.exs index f354ebe3..b2668f3f 100644 --- a/ex_webrtc/mix.exs +++ b/ex_webrtc/mix.exs @@ -50,7 +50,7 @@ defmodule Membrane.RTC.Engine.Endpoint.ExWebRTC.MixProject do [ {:membrane_rtc_engine, path: "../engine"}, {:membrane_core, "~> 1.1.2"}, - {:ex_webrtc, "~> 0.6.1"}, + {:ex_webrtc, github: "elixir-webrtc/ex_webrtc"}, {:membrane_rtp_plugin, "~> 0.29.0"}, {:membrane_rtp_format, "~> 0.8.0"}, {:membrane_rtp_vp8_plugin, "~> 0.9.0"}, diff --git a/ex_webrtc/mix.lock b/ex_webrtc/mix.lock index 665bd827..35ff28a8 100644 --- a/ex_webrtc/mix.lock +++ b/ex_webrtc/mix.lock @@ -2,7 +2,7 @@ "bimap": {:hex, :bimap, "1.3.0", "3ea4832e58dc83a9b5b407c6731e7bae87458aa618e6d11d8e12114a17afa4b3", [:mix], [], "hexpm", "bf5a2b078528465aa705f405a5c638becd63e41d280ada41e0f77e6d255a10b4"}, "bunch": {:hex, :bunch, "1.6.1", "5393d827a64d5f846092703441ea50e65bc09f37fd8e320878f13e63d410aec7", [:mix], [], "hexpm", "286cc3add551628b30605efbe2fca4e38cc1bea89bcd0a1a7226920b3364fe4a"}, "bunch_native": {:hex, :bunch_native, "0.5.0", "8ac1536789a597599c10b652e0b526d8833348c19e4739a0759a2bedfd924e63", [:mix], [{:bundlex, "~> 1.0", [hex: :bundlex, repo: "hexpm", optional: false]}], "hexpm", "24190c760e32b23b36edeb2dc4852515c7c5b3b8675b1a864e0715bdd1c8f80d"}, - "bundlex": {:hex, :bundlex, "1.5.3", "35d01e5bc0679510dd9a327936ffb518f63f47175c26a35e708cc29eaec0890b", [:mix], [{:bunch, "~> 1.0", [hex: :bunch, repo: "hexpm", optional: false]}, {:elixir_uuid, "~> 1.2", [hex: :elixir_uuid, repo: "hexpm", optional: false]}, {:qex, "~> 0.5", [hex: :qex, repo: "hexpm", optional: false]}, {:req, ">= 0.4.0", [hex: :req, repo: "hexpm", optional: false]}, {:zarex, "~> 1.0", [hex: :zarex, repo: "hexpm", optional: false]}], "hexpm", "debd0eac151b404f6216fc60222761dff049bf26f7d24d066c365317650cd118"}, + "bundlex": {:hex, :bundlex, "1.5.4", "3726acd463f4d31894a59bbc177c17f3b574634a524212f13469f41c4834a1d9", [:mix], [{:bunch, "~> 1.0", [hex: :bunch, repo: "hexpm", optional: false]}, {:elixir_uuid, "~> 1.2", [hex: :elixir_uuid, repo: "hexpm", optional: false]}, {:qex, "~> 0.5", [hex: :qex, repo: "hexpm", optional: false]}, {:req, ">= 0.4.0", [hex: :req, repo: "hexpm", optional: false]}, {:zarex, "~> 1.0", [hex: :zarex, repo: "hexpm", optional: false]}], "hexpm", "e745726606a560275182a8ac1c8ebd5e11a659bb7460d8abf30f397e59b4c5d2"}, "bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"}, "certifi": {:hex, :certifi, "2.12.0", "2d1cca2ec95f59643862af91f001478c9863c2ac9cb6e2f89780bfd8de987329", [:rebar3], [], "hexpm", "ee68d85df22e554040cdb4be100f33873ac6051387baf6a8f6ce82272340ff1c"}, "coerce": {:hex, :coerce, "1.0.1", "211c27386315dc2894ac11bc1f413a0e38505d808153367bd5c6e75a4003d096", [:mix], [], "hexpm", "b44a691700f7a1a15b4b7e2ff1fa30bebd669929ac8aa43cffe9e2f8bf051cf1"}, @@ -10,19 +10,19 @@ "credo": {:hex, :credo, "1.7.8", "9722ba1681e973025908d542ec3d95db5f9c549251ba5b028e251ad8c24ab8c5", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "cb9e87cc64f152f3ed1c6e325e7b894dea8f5ef2e41123bd864e3cd5ceb44968"}, "dialyxir": {:hex, :dialyxir, "1.4.4", "fb3ce8741edeaea59c9ae84d5cec75da00fa89fe401c72d6e047d11a61f65f70", [:mix], [{:erlex, ">= 0.2.7", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "cd6111e8017ccd563e65621a4d9a4a1c5cd333df30cebc7face8029cacb4eff6"}, "earmark_parser": {:hex, :earmark_parser, "1.4.41", "ab34711c9dc6212dda44fcd20ecb87ac3f3fce6f0ca2f28d4a00e4154f8cd599", [:mix], [], "hexpm", "a81a04c7e34b6617c2792e291b5a2e57ab316365c2644ddc553bb9ed863ebefa"}, - "elixir_make": {:hex, :elixir_make, "0.8.4", "4960a03ce79081dee8fe119d80ad372c4e7badb84c493cc75983f9d3bc8bde0f", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:certifi, "~> 2.0", [hex: :certifi, repo: "hexpm", optional: true]}], "hexpm", "6e7f1d619b5f61dfabd0a20aa268e575572b542ac31723293a4c1a567d5ef040"}, + "elixir_make": {:hex, :elixir_make, "0.9.0", "6484b3cd8c0cee58f09f05ecaf1a140a8c97670671a6a0e7ab4dc326c3109726", [:mix], [], "hexpm", "db23d4fd8b757462ad02f8aa73431a426fe6671c80b200d9710caf3d1dd0ffdb"}, "elixir_uuid": {:hex, :elixir_uuid, "1.2.1", "dce506597acb7e6b0daeaff52ff6a9043f5919a4c3315abb4143f0b00378c097", [:mix], [], "hexpm", "f7eba2ea6c3555cea09706492716b0d87397b88946e6380898c2889d68585752"}, "erlex": {:hex, :erlex, "0.2.7", "810e8725f96ab74d17aac676e748627a07bc87eb950d2b83acd29dc047a30595", [:mix], [], "hexpm", "3ed95f79d1a844c3f6bf0cea61e0d5612a42ce56da9c03f01df538685365efb0"}, "ex_doc": {:hex, :ex_doc, "0.34.2", "13eedf3844ccdce25cfd837b99bea9ad92c4e511233199440488d217c92571e8", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "5ce5f16b41208a50106afed3de6a2ed34f4acfd65715b82a0b84b49d995f95c1"}, "ex_dtls": {:hex, :ex_dtls, "0.16.0", "3ae38025ccc77f6db573e2e391602fa9bbc02253c137d8d2d59469a66cbe806b", [:mix], [{:bundlex, "~> 1.5.3", [hex: :bundlex, repo: "hexpm", optional: false]}, {:unifex, "~> 1.0", [hex: :unifex, repo: "hexpm", optional: false]}], "hexpm", "2a4e30d74c6ddf95cc5b796423293c06a0da295454c3823819808ff031b4b361"}, - "ex_ice": {:hex, :ex_ice, "0.8.3", "b3a56d8cc44555705dc33ce0942d0ce3fe9fa3132a1f1bfe79b4c5b91ed1562b", [:mix], [{:elixir_uuid, "~> 1.0", [hex: :elixir_uuid, repo: "hexpm", optional: false]}, {:ex_stun, "~> 0.2.0", [hex: :ex_stun, repo: "hexpm", optional: false]}, {:ex_turn, "~> 0.1.0", [hex: :ex_turn, repo: "hexpm", optional: false]}], "hexpm", "ffc17fa8f1bfb6e744eeb7e1009f3dd2e37dfd745ec808c66faeafb93ab0e036"}, + "ex_ice": {:hex, :ex_ice, "0.9.0", "d1a7e31b9cc52faf668f001f870344d3f9094955bafb6af62d84b7b4c2dd6b36", [:mix], [{:elixir_uuid, "~> 1.0", [hex: :elixir_uuid, repo: "hexpm", optional: false]}, {:ex_stun, "~> 0.2.0", [hex: :ex_stun, repo: "hexpm", optional: false]}, {:ex_turn, "~> 0.2.0", [hex: :ex_turn, repo: "hexpm", optional: false]}], "hexpm", "8f256faeb9cc5409d2177e68918198c7ef64372a729c8e1590699546554419aa"}, "ex_libsrtp": {:hex, :ex_libsrtp, "0.7.2", "211bd89c08026943ce71f3e2c0231795b99cee748808ed3ae7b97cd8d2450b6b", [:mix], [{:bunch, "~> 1.6", [hex: :bunch, repo: "hexpm", optional: false]}, {:bundlex, "~> 1.3", [hex: :bundlex, repo: "hexpm", optional: false]}, {:membrane_precompiled_dependency_provider, "~> 0.1.0", [hex: :membrane_precompiled_dependency_provider, repo: "hexpm", optional: false]}, {:unifex, "~> 1.1", [hex: :unifex, repo: "hexpm", optional: false]}], "hexpm", "2e20645d0d739a4ecdcf8d4810a0c198120c8a2f617f2b75b2e2e704d59f492a"}, "ex_rtcp": {:hex, :ex_rtcp, "0.4.0", "f9e515462a9581798ff6413583a25174cfd2101c94a2ebee871cca7639886f0a", [:mix], [], "hexpm", "28956602cf210d692fcdaf3f60ca49681634e1deb28ace41246aee61ee22dc3b"}, "ex_rtp": {:hex, :ex_rtp, "0.4.0", "1f1b5c1440a904706011e3afbb41741f5da309ce251cb986690ce9fd82636658", [:mix], [], "hexpm", "0f72d80d5953a62057270040f0f1ee6f955c08eeae82ac659c038001d7d5a790"}, "ex_sdp": {:hex, :ex_sdp, "1.1.0", "a93d72d00704efd83f7e144e4ca9822ca4aea5b5d851353d092de40e1ad0ecdc", [:mix], [{:bunch, "~> 1.3", [hex: :bunch, repo: "hexpm", optional: false]}, {:elixir_uuid, "~> 1.2", [hex: :elixir_uuid, repo: "hexpm", optional: false]}], "hexpm", "f5c033abcda958a9b090210f9429f24b74b003c28c24175c58a033a5205a1cfe"}, "ex_stun": {:hex, :ex_stun, "0.2.0", "feb1fc7db0356406655b2a617805e6c712b93308c8ea2bf0ba1197b1f0866deb", [:mix], [], "hexpm", "1e01ba8290082ccbf37acaa5190d1f69b51edd6de2026a8d6d51368b29d115d0"}, - "ex_turn": {:hex, :ex_turn, "0.1.0", "177405aadf3d754567d0d37cf881a83f9cacf8f45314d188633b04c4a9e7c1ec", [:mix], [{:ex_stun, "~> 0.2.0", [hex: :ex_stun, repo: "hexpm", optional: false]}], "hexpm", "d677737fb7d45274d5dac19fe3c26b9038b6effbc0a6b3e7417bccc76b6d1cd3"}, - "ex_webrtc": {:hex, :ex_webrtc, "0.6.2", "2f51d4cb2217637d0134857c74611dc08e99d180dc782489435eb6cde3973270", [:mix], [{:crc, "~> 0.10", [hex: :crc, repo: "hexpm", optional: false]}, {:ex_dtls, "~> 0.16.0", [hex: :ex_dtls, repo: "hexpm", optional: false]}, {:ex_ice, "~> 0.8.3", [hex: :ex_ice, repo: "hexpm", optional: false]}, {:ex_libsrtp, "~> 0.7.1", [hex: :ex_libsrtp, repo: "hexpm", optional: false]}, {:ex_rtcp, "~> 0.4.0", [hex: :ex_rtcp, repo: "hexpm", optional: false]}, {:ex_rtp, "~> 0.4.0", [hex: :ex_rtp, repo: "hexpm", optional: false]}, {:ex_sctp, "0.1.0", [hex: :ex_sctp, repo: "hexpm", optional: true]}, {:ex_sdp, "~> 1.0", [hex: :ex_sdp, repo: "hexpm", optional: false]}], "hexpm", "9dd839285d0761776bb67acbe3131f73772d7ed6f5a2a7b44d586a31a4df2309"}, + "ex_turn": {:hex, :ex_turn, "0.2.0", "4e1f9b089e9a5ee44928d12370cc9ea7a89b84b2f6256832de65271212eb80de", [:mix], [{:ex_stun, "~> 0.2.0", [hex: :ex_stun, repo: "hexpm", optional: false]}], "hexpm", "08e884f0af2c4a147e3f8cd4ffe33e3452a256389f0956e55a8c4d75bf0e74cd"}, + "ex_webrtc": {:git, "https://github.com/elixir-webrtc/ex_webrtc.git", "a7a7f2975149e8da1fb1392eb842dec204fac2ba", []}, "excoveralls": {:hex, :excoveralls, "0.16.1", "0bd42ed05c7d2f4d180331a20113ec537be509da31fed5c8f7047ce59ee5a7c5", [:mix], [{:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "dae763468e2008cf7075a64cb1249c97cb4bc71e236c5c2b5e5cdf1cfa2bf138"}, "file_system": {:hex, :file_system, "1.0.1", "79e8ceaddb0416f8b8cd02a0127bdbababe7bf4a23d2a395b983c1f8b3f73edd", [:mix], [], "hexpm", "4414d1f38863ddf9120720cd976fce5bdde8e91d8283353f0e31850fa89feb9e"}, "finch": {:hex, :finch, "0.19.0", "c644641491ea854fc5c1bbaef36bfc764e3f08e7185e1f084e35e0672241b76d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.6.2 or ~> 1.7", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 1.1", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "fc5324ce209125d1e2fa0fcd2634601c52a787aff1cd33ee833664a5af4ea2b6"}, @@ -57,13 +57,13 @@ "protobuf": {:hex, :protobuf, "0.13.0", "7a9d9aeb039f68a81717eb2efd6928fdf44f03d2c0dfdcedc7b560f5f5aae93d", [:mix], [{:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "21092a223e3c6c144c1a291ab082a7ead32821ba77073b72c68515aa51fef570"}, "qex": {:hex, :qex, "0.5.1", "0d82c0f008551d24fffb99d97f8299afcb8ea9cf99582b770bd004ed5af63fd6", [:mix], [], "hexpm", "935a39fdaf2445834b95951456559e9dc2063d0a055742c558a99987b38d6bab"}, "ratio": {:hex, :ratio, "4.0.1", "3044166f2fc6890aa53d3aef0c336f84b2bebb889dc57d5f95cc540daa1912f8", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:numbers, "~> 5.2.0", [hex: :numbers, repo: "hexpm", optional: false]}], "hexpm", "c60cbb3ccdff9ffa56e7d6d1654b5c70d9f90f4d753ab3a43a6bf40855b881ce"}, - "req": {:hex, :req, "0.5.6", "8fe1eead4a085510fe3d51ad854ca8f20a622aae46e97b302f499dfb84f726ac", [:mix], [{:brotli, "~> 0.3.1", [hex: :brotli, repo: "hexpm", optional: true]}, {:ezstd, "~> 1.0", [hex: :ezstd, repo: "hexpm", optional: true]}, {:finch, "~> 0.17", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 2.0.6 or ~> 2.1", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 1.0", [hex: :nimble_csv, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "cfaa8e720945d46654853de39d368f40362c2641c4b2153c886418914b372185"}, + "req": {:hex, :req, "0.5.8", "50d8d65279d6e343a5e46980ac2a70e97136182950833a1968b371e753f6a662", [:mix], [{:brotli, "~> 0.3.1", [hex: :brotli, repo: "hexpm", optional: true]}, {:ezstd, "~> 1.0", [hex: :ezstd, repo: "hexpm", optional: true]}, {:finch, "~> 0.17", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 2.0.6 or ~> 2.1", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 1.0", [hex: :nimble_csv, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "d7fc5898a566477e174f26887821a3c5082b243885520ee4b45555f5d53f40ef"}, "shmex": {:hex, :shmex, "0.5.1", "81dd209093416bf6608e66882cb7e676089307448a1afd4fc906c1f7e5b94cf4", [:mix], [{:bunch_native, "~> 0.5.0", [hex: :bunch_native, repo: "hexpm", optional: false]}, {:bundlex, "~> 1.0", [hex: :bundlex, repo: "hexpm", optional: false]}], "hexpm", "c29f8286891252f64c4e1dac40b217d960f7d58def597c4e606ff8fbe71ceb80"}, "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"}, "statistics": {:hex, :statistics, "0.6.3", "7fb182e7c1cab2980e392c7efef7ce326539f081f9defda4099550e9c2c7cb0f", [:mix], [], "hexpm", "a43d87726d240205e9ef47f29650a6e3132b4e4061e05512f32fa8120784a8e0"}, "telemetry": {:hex, :telemetry, "1.3.0", "fedebbae410d715cf8e7062c96a1ef32ec22e764197f70cda73d82778d61e7a2", [:rebar3], [], "hexpm", "7015fc8919dbe63764f4b4b87a95b7c0996bd539e0d499be6ec9d7f3875b79e6"}, "telemetry_metrics": {:hex, :telemetry_metrics, "1.0.0", "29f5f84991ca98b8eb02fc208b2e6de7c95f8bb2294ef244a176675adc7775df", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "f23713b3847286a534e005126d4c959ebcca68ae9582118ce436b521d1d47d5d"}, "unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"}, - "unifex": {:hex, :unifex, "1.2.0", "90d1ec5e6d788350e07e474f7bd8b0ee866d6606beb9ca4e20dbb26328712a84", [:mix], [{:bunch, "~> 1.0", [hex: :bunch, repo: "hexpm", optional: false]}, {:bundlex, "~> 1.4", [hex: :bundlex, repo: "hexpm", optional: false]}, {:shmex, "~> 0.5.0", [hex: :shmex, repo: "hexpm", optional: false]}], "hexpm", "7a8395aabc3ba6cff04bbe5b995de7f899a38eb57f189e49927d6b8b6ccb6883"}, + "unifex": {:hex, :unifex, "1.2.1", "6841c170a6e16509fac30b19e4e0a19937c33155a59088b50c15fc2c36251b6b", [:mix], [{:bunch, "~> 1.0", [hex: :bunch, repo: "hexpm", optional: false]}, {:bundlex, "~> 1.4", [hex: :bundlex, repo: "hexpm", optional: false]}, {:shmex, "~> 0.5.0", [hex: :shmex, repo: "hexpm", optional: false]}], "hexpm", "8c9d2e3c48df031e9995dd16865bab3df402c0295ba3a31f38274bb5314c7d37"}, "zarex": {:hex, :zarex, "1.0.5", "58239e3ee5d75f343262bb4df5cf466555a1c689f920e5d3651a9333972f7c7e", [:mix], [], "hexpm", "9fb72ef0567c2b2742f5119a1ba8a24a2fabb21b8d09820aefbf3e592fa9a46a"}, } diff --git a/examples/ex_webrtc_videoroom/mix.exs b/examples/ex_webrtc_videoroom/mix.exs index ac2bc3bb..0028d783 100644 --- a/examples/ex_webrtc_videoroom/mix.exs +++ b/examples/ex_webrtc_videoroom/mix.exs @@ -29,15 +29,12 @@ defmodule VideoRoom.MixProject do {:poison, "~> 3.1"}, {:jason, "~> 1.2"}, {:phoenix_inline_svg, "~> 1.4"}, - {:telemetry, "~> 1.0.0", override: true}, + {:telemetry, "~> 1.0"}, {:esbuild, "~> 0.4", runtime: Mix.env() == :dev}, # rtc engine dependencies {:membrane_rtc_engine, path: "../../engine"}, - {:membrane_rtc_engine_ex_webrtc, path: "../../ex_webrtc"}, - - # Required for ex_webrtc - {:ex_sdp, "~> 0.17.0", override: true} + {:membrane_rtc_engine_ex_webrtc, path: "../../ex_webrtc"} ] end diff --git a/integration_test/mix.exs b/integration_test/mix.exs index b8fa10c2..28ed83a0 100644 --- a/integration_test/mix.exs +++ b/integration_test/mix.exs @@ -35,7 +35,7 @@ defmodule Membrane.RTC.Engine.Integration.MixProject do defp deps do [ # Engine deps - {:membrane_rtc_engine, path: "../engine", override: true}, + {:membrane_rtc_engine, path: "../engine"}, {:membrane_rtc_engine_hls, path: "../hls"}, {:membrane_rtc_engine_rtsp, path: "../rtsp"}, {:membrane_rtc_engine_file, path: "../file"}, diff --git a/integration_test/mix.lock b/integration_test/mix.lock index 30e73b09..d427ea82 100644 --- a/integration_test/mix.lock +++ b/integration_test/mix.lock @@ -2,27 +2,27 @@ "bimap": {:hex, :bimap, "1.3.0", "3ea4832e58dc83a9b5b407c6731e7bae87458aa618e6d11d8e12114a17afa4b3", [:mix], [], "hexpm", "bf5a2b078528465aa705f405a5c638becd63e41d280ada41e0f77e6d255a10b4"}, "bunch": {:hex, :bunch, "1.6.1", "5393d827a64d5f846092703441ea50e65bc09f37fd8e320878f13e63d410aec7", [:mix], [], "hexpm", "286cc3add551628b30605efbe2fca4e38cc1bea89bcd0a1a7226920b3364fe4a"}, "bunch_native": {:hex, :bunch_native, "0.5.0", "8ac1536789a597599c10b652e0b526d8833348c19e4739a0759a2bedfd924e63", [:mix], [{:bundlex, "~> 1.0", [hex: :bundlex, repo: "hexpm", optional: false]}], "hexpm", "24190c760e32b23b36edeb2dc4852515c7c5b3b8675b1a864e0715bdd1c8f80d"}, - "bundlex": {:hex, :bundlex, "1.5.3", "35d01e5bc0679510dd9a327936ffb518f63f47175c26a35e708cc29eaec0890b", [:mix], [{:bunch, "~> 1.0", [hex: :bunch, repo: "hexpm", optional: false]}, {:elixir_uuid, "~> 1.2", [hex: :elixir_uuid, repo: "hexpm", optional: false]}, {:qex, "~> 0.5", [hex: :qex, repo: "hexpm", optional: false]}, {:req, ">= 0.4.0", [hex: :req, repo: "hexpm", optional: false]}, {:zarex, "~> 1.0", [hex: :zarex, repo: "hexpm", optional: false]}], "hexpm", "debd0eac151b404f6216fc60222761dff049bf26f7d24d066c365317650cd118"}, + "bundlex": {:hex, :bundlex, "1.5.4", "3726acd463f4d31894a59bbc177c17f3b574634a524212f13469f41c4834a1d9", [:mix], [{:bunch, "~> 1.0", [hex: :bunch, repo: "hexpm", optional: false]}, {:elixir_uuid, "~> 1.2", [hex: :elixir_uuid, repo: "hexpm", optional: false]}, {:qex, "~> 0.5", [hex: :qex, repo: "hexpm", optional: false]}, {:req, ">= 0.4.0", [hex: :req, repo: "hexpm", optional: false]}, {:zarex, "~> 1.0", [hex: :zarex, repo: "hexpm", optional: false]}], "hexpm", "e745726606a560275182a8ac1c8ebd5e11a659bb7460d8abf30f397e59b4c5d2"}, "certifi": {:hex, :certifi, "2.12.0", "2d1cca2ec95f59643862af91f001478c9863c2ac9cb6e2f89780bfd8de987329", [:rebar3], [], "hexpm", "ee68d85df22e554040cdb4be100f33873ac6051387baf6a8f6ce82272340ff1c"}, "coerce": {:hex, :coerce, "1.0.1", "211c27386315dc2894ac11bc1f413a0e38505d808153367bd5c6e75a4003d096", [:mix], [], "hexpm", "b44a691700f7a1a15b4b7e2ff1fa30bebd669929ac8aa43cffe9e2f8bf051cf1"}, "connection": {:hex, :connection, "1.1.0", "ff2a49c4b75b6fb3e674bfc5536451607270aac754ffd1bdfe175abe4a6d7a68", [:mix], [], "hexpm", "722c1eb0a418fbe91ba7bd59a47e28008a189d47e37e0e7bb85585a016b2869c"}, "crc": {:hex, :crc, "0.10.5", "ee12a7c056ac498ef2ea985ecdc9fa53c1bfb4e53a484d9f17ff94803707dfd8", [:mix, :rebar3], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "3e673b6495a9525c5c641585af1accba59a1eb33de697bedf341e247012c2c7f"}, - "elixir_make": {:hex, :elixir_make, "0.8.4", "4960a03ce79081dee8fe119d80ad372c4e7badb84c493cc75983f9d3bc8bde0f", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:certifi, "~> 2.0", [hex: :certifi, repo: "hexpm", optional: true]}], "hexpm", "6e7f1d619b5f61dfabd0a20aa268e575572b542ac31723293a4c1a567d5ef040"}, + "elixir_make": {:hex, :elixir_make, "0.9.0", "6484b3cd8c0cee58f09f05ecaf1a140a8c97670671a6a0e7ab4dc326c3109726", [:mix], [], "hexpm", "db23d4fd8b757462ad02f8aa73431a426fe6671c80b200d9710caf3d1dd0ffdb"}, "elixir_uuid": {:hex, :elixir_uuid, "1.2.1", "dce506597acb7e6b0daeaff52ff6a9043f5919a4c3315abb4143f0b00378c097", [:mix], [], "hexpm", "f7eba2ea6c3555cea09706492716b0d87397b88946e6380898c2889d68585752"}, "ex_aws": {:hex, :ex_aws, "2.5.7", "dbcda183903cded392742129bd5c67ccf59caed4ded604d5e68b96e75570d743", [:mix], [{:configparser_ex, "~> 4.0", [hex: :configparser_ex, repo: "hexpm", optional: true]}, {:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:jsx, "~> 2.8 or ~> 3.0", [hex: :jsx, repo: "hexpm", optional: true]}, {:mime, "~> 1.2 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:req, "~> 0.3", [hex: :req, repo: "hexpm", optional: true]}, {:sweet_xml, "~> 0.7", [hex: :sweet_xml, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "2c3c577550bfc4d0899e9fed9aeef91bc6a2aedd0177b1faa726c9b20d005074"}, "ex_aws_s3": {:hex, :ex_aws_s3, "2.5.5", "d718e90e0e4803c5605ca1a7cebf44236f7439f6706151ca4485fc2dffd08bc1", [:mix], [{:ex_aws, "~> 2.0", [hex: :ex_aws, repo: "hexpm", optional: false]}, {:sweet_xml, ">= 0.0.0", [hex: :sweet_xml, repo: "hexpm", optional: true]}], "hexpm", "ac34af1e9b3974168dda798d2fded5d12d52a1b5cf52abfeffed2a63d2eb5443"}, "ex_dtls": {:hex, :ex_dtls, "0.16.0", "3ae38025ccc77f6db573e2e391602fa9bbc02253c137d8d2d59469a66cbe806b", [:mix], [{:bundlex, "~> 1.5.3", [hex: :bundlex, repo: "hexpm", optional: false]}, {:unifex, "~> 1.0", [hex: :unifex, repo: "hexpm", optional: false]}], "hexpm", "2a4e30d74c6ddf95cc5b796423293c06a0da295454c3823819808ff031b4b361"}, - "ex_ice": {:hex, :ex_ice, "0.8.3", "b3a56d8cc44555705dc33ce0942d0ce3fe9fa3132a1f1bfe79b4c5b91ed1562b", [:mix], [{:elixir_uuid, "~> 1.0", [hex: :elixir_uuid, repo: "hexpm", optional: false]}, {:ex_stun, "~> 0.2.0", [hex: :ex_stun, repo: "hexpm", optional: false]}, {:ex_turn, "~> 0.1.0", [hex: :ex_turn, repo: "hexpm", optional: false]}], "hexpm", "ffc17fa8f1bfb6e744eeb7e1009f3dd2e37dfd745ec808c66faeafb93ab0e036"}, + "ex_ice": {:hex, :ex_ice, "0.9.0", "d1a7e31b9cc52faf668f001f870344d3f9094955bafb6af62d84b7b4c2dd6b36", [:mix], [{:elixir_uuid, "~> 1.0", [hex: :elixir_uuid, repo: "hexpm", optional: false]}, {:ex_stun, "~> 0.2.0", [hex: :ex_stun, repo: "hexpm", optional: false]}, {:ex_turn, "~> 0.2.0", [hex: :ex_turn, repo: "hexpm", optional: false]}], "hexpm", "8f256faeb9cc5409d2177e68918198c7ef64372a729c8e1590699546554419aa"}, "ex_libsrtp": {:hex, :ex_libsrtp, "0.7.2", "211bd89c08026943ce71f3e2c0231795b99cee748808ed3ae7b97cd8d2450b6b", [:mix], [{:bunch, "~> 1.6", [hex: :bunch, repo: "hexpm", optional: false]}, {:bundlex, "~> 1.3", [hex: :bundlex, repo: "hexpm", optional: false]}, {:membrane_precompiled_dependency_provider, "~> 0.1.0", [hex: :membrane_precompiled_dependency_provider, repo: "hexpm", optional: false]}, {:unifex, "~> 1.1", [hex: :unifex, repo: "hexpm", optional: false]}], "hexpm", "2e20645d0d739a4ecdcf8d4810a0c198120c8a2f617f2b75b2e2e704d59f492a"}, "ex_rtcp": {:hex, :ex_rtcp, "0.4.0", "f9e515462a9581798ff6413583a25174cfd2101c94a2ebee871cca7639886f0a", [:mix], [], "hexpm", "28956602cf210d692fcdaf3f60ca49681634e1deb28ace41246aee61ee22dc3b"}, "ex_rtp": {:hex, :ex_rtp, "0.4.0", "1f1b5c1440a904706011e3afbb41741f5da309ce251cb986690ce9fd82636658", [:mix], [], "hexpm", "0f72d80d5953a62057270040f0f1ee6f955c08eeae82ac659c038001d7d5a790"}, "ex_sdp": {:hex, :ex_sdp, "1.1.0", "a93d72d00704efd83f7e144e4ca9822ca4aea5b5d851353d092de40e1ad0ecdc", [:mix], [{:bunch, "~> 1.3", [hex: :bunch, repo: "hexpm", optional: false]}, {:elixir_uuid, "~> 1.2", [hex: :elixir_uuid, repo: "hexpm", optional: false]}], "hexpm", "f5c033abcda958a9b090210f9429f24b74b003c28c24175c58a033a5205a1cfe"}, "ex_stun": {:hex, :ex_stun, "0.2.0", "feb1fc7db0356406655b2a617805e6c712b93308c8ea2bf0ba1197b1f0866deb", [:mix], [], "hexpm", "1e01ba8290082ccbf37acaa5190d1f69b51edd6de2026a8d6d51368b29d115d0"}, - "ex_turn": {:hex, :ex_turn, "0.1.0", "177405aadf3d754567d0d37cf881a83f9cacf8f45314d188633b04c4a9e7c1ec", [:mix], [{:ex_stun, "~> 0.2.0", [hex: :ex_stun, repo: "hexpm", optional: false]}], "hexpm", "d677737fb7d45274d5dac19fe3c26b9038b6effbc0a6b3e7417bccc76b6d1cd3"}, - "ex_webrtc": {:hex, :ex_webrtc, "0.6.2", "2f51d4cb2217637d0134857c74611dc08e99d180dc782489435eb6cde3973270", [:mix], [{:crc, "~> 0.10", [hex: :crc, repo: "hexpm", optional: false]}, {:ex_dtls, "~> 0.16.0", [hex: :ex_dtls, repo: "hexpm", optional: false]}, {:ex_ice, "~> 0.8.3", [hex: :ex_ice, repo: "hexpm", optional: false]}, {:ex_libsrtp, "~> 0.7.1", [hex: :ex_libsrtp, repo: "hexpm", optional: false]}, {:ex_rtcp, "~> 0.4.0", [hex: :ex_rtcp, repo: "hexpm", optional: false]}, {:ex_rtp, "~> 0.4.0", [hex: :ex_rtp, repo: "hexpm", optional: false]}, {:ex_sctp, "0.1.0", [hex: :ex_sctp, repo: "hexpm", optional: true]}, {:ex_sdp, "~> 1.0", [hex: :ex_sdp, repo: "hexpm", optional: false]}], "hexpm", "9dd839285d0761776bb67acbe3131f73772d7ed6f5a2a7b44d586a31a4df2309"}, + "ex_turn": {:hex, :ex_turn, "0.2.0", "4e1f9b089e9a5ee44928d12370cc9ea7a89b84b2f6256832de65271212eb80de", [:mix], [{:ex_stun, "~> 0.2.0", [hex: :ex_stun, repo: "hexpm", optional: false]}], "hexpm", "08e884f0af2c4a147e3f8cd4ffe33e3452a256389f0956e55a8c4d75bf0e74cd"}, + "ex_webrtc": {:git, "https://github.com/elixir-webrtc/ex_webrtc.git", "a7a7f2975149e8da1fb1392eb842dec204fac2ba", []}, "excoveralls": {:hex, :excoveralls, "0.16.1", "0bd42ed05c7d2f4d180331a20113ec537be509da31fed5c8f7047ce59ee5a7c5", [:mix], [{:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "dae763468e2008cf7075a64cb1249c97cb4bc71e236c5c2b5e5cdf1cfa2bf138"}, "finch": {:hex, :finch, "0.19.0", "c644641491ea854fc5c1bbaef36bfc764e3f08e7185e1f084e35e0672241b76d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.6.2 or ~> 1.7", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 1.1", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "fc5324ce209125d1e2fa0fcd2634601c52a787aff1cd33ee833664a5af4ea2b6"}, - "fishjam_protos": {:git, "https://github.com/fishjam-cloud/protos.git", "d3f40c0230df478544af89d4ea58555ded985ee1", [sparse: "fishjam_protos"]}, + "fishjam_protos": {:git, "https://github.com/fishjam-cloud/protos.git", "0bcb420955d0441a355c49be0a492d9b827fbbe8", [sparse: "fishjam_protos"]}, "gen_state_machine": {:hex, :gen_state_machine, "3.0.0", "1e57f86a494e5c6b14137ebef26a7eb342b3b0070c7135f2d6768ed3f6b6cdff", [:mix], [], "hexpm", "0a59652574bebceb7309f6b749d2a41b45fdeda8dbb4da0791e355dd19f0ed15"}, "hackney": {:hex, :hackney, "1.20.1", "8d97aec62ddddd757d128bfd1df6c5861093419f8f7a4223823537bad5d064e2", [:rebar3], [{:certifi, "~> 2.12.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~> 6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~> 1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~> 1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.4.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "fe9094e5f1a2a2c0a7d10918fee36bfec0ec2a979994cff8cfe8058cd9af38e3"}, "heap": {:hex, :heap, "2.0.2", "d98cb178286cfeb5edbcf17785e2d20af73ca57b5a2cf4af584118afbcf917eb", [:mix], [], "hexpm", "ba9ea2fe99eb4bcbd9a8a28eaf71cbcac449ca1d8e71731596aace9028c9d429"}, @@ -87,7 +87,7 @@ "protobuf": {:hex, :protobuf, "0.13.0", "7a9d9aeb039f68a81717eb2efd6928fdf44f03d2c0dfdcedc7b560f5f5aae93d", [:mix], [{:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "21092a223e3c6c144c1a291ab082a7ead32821ba77073b72c68515aa51fef570"}, "qex": {:hex, :qex, "0.5.1", "0d82c0f008551d24fffb99d97f8299afcb8ea9cf99582b770bd004ed5af63fd6", [:mix], [], "hexpm", "935a39fdaf2445834b95951456559e9dc2063d0a055742c558a99987b38d6bab"}, "ratio": {:hex, :ratio, "3.0.2", "60a5976872a4dc3d873ecc57eed1738589e99d1094834b9c935b118231297cfb", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:numbers, "~> 5.2.0", [hex: :numbers, repo: "hexpm", optional: false]}], "hexpm", "3a13ed5a30ad0bfd7e4a86bf86d93d2b5a06f5904417d38d3f3ea6406cdfc7bb"}, - "req": {:hex, :req, "0.5.7", "b722680e03d531a2947282adff474362a48a02aa54b131196fbf7acaff5e4cee", [:mix], [{:brotli, "~> 0.3.1", [hex: :brotli, repo: "hexpm", optional: true]}, {:ezstd, "~> 1.0", [hex: :ezstd, repo: "hexpm", optional: true]}, {:finch, "~> 0.17", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 2.0.6 or ~> 2.1", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 1.0", [hex: :nimble_csv, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "c6035374615120a8923e8089d0c21a3496cf9eda2d287b806081b8f323ceee29"}, + "req": {:hex, :req, "0.5.8", "50d8d65279d6e343a5e46980ac2a70e97136182950833a1968b371e753f6a662", [:mix], [{:brotli, "~> 0.3.1", [hex: :brotli, repo: "hexpm", optional: true]}, {:ezstd, "~> 1.0", [hex: :ezstd, repo: "hexpm", optional: true]}, {:finch, "~> 0.17", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 2.0.6 or ~> 2.1", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 1.0", [hex: :nimble_csv, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "d7fc5898a566477e174f26887821a3c5082b243885520ee4b45555f5d53f40ef"}, "rustler": {:hex, :rustler, "0.26.0", "06a2773d453ee3e9109efda643cf2ae633dedea709e2455ac42b83637c9249bf", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:toml, "~> 0.6", [hex: :toml, repo: "hexpm", optional: false]}], "hexpm", "42961e9d2083d004d5a53e111ad1f0c347efd9a05cb2eb2ffa1d037cdc74db91"}, "shmex": {:hex, :shmex, "0.5.1", "81dd209093416bf6608e66882cb7e676089307448a1afd4fc906c1f7e5b94cf4", [:mix], [{:bunch_native, "~> 0.5.0", [hex: :bunch_native, repo: "hexpm", optional: false]}, {:bundlex, "~> 1.0", [hex: :bundlex, repo: "hexpm", optional: false]}], "hexpm", "c29f8286891252f64c4e1dac40b217d960f7d58def597c4e606ff8fbe71ceb80"}, "sippet": {:hex, :sippet, "1.0.16", "614d472d4d7e2b7f0828c554aaf9a0238e0c6e903dbb17334f5cb2baa58da1c2", [:mix], [{:elixir_make, "~> 0.7", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:gen_state_machine, ">= 3.0.0", [hex: :gen_state_machine, repo: "hexpm", optional: false]}, {:sippet_uri, "~> 0.1", [hex: :sippet_uri, repo: "hexpm", optional: false]}], "hexpm", "1a23af1ce85adeae89863daaded233637075a7dd031e589b4f343ae08901667c"}, @@ -99,6 +99,6 @@ "telemetry_metrics": {:hex, :telemetry_metrics, "1.0.0", "29f5f84991ca98b8eb02fc208b2e6de7c95f8bb2294ef244a176675adc7775df", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "f23713b3847286a534e005126d4c959ebcca68ae9582118ce436b521d1d47d5d"}, "toml": {:hex, :toml, "0.7.0", "fbcd773caa937d0c7a02c301a1feea25612720ac3fa1ccb8bfd9d30d822911de", [:mix], [], "hexpm", "0690246a2478c1defd100b0c9b89b4ea280a22be9a7b313a8a058a2408a2fa70"}, "unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"}, - "unifex": {:hex, :unifex, "1.2.0", "90d1ec5e6d788350e07e474f7bd8b0ee866d6606beb9ca4e20dbb26328712a84", [:mix], [{:bunch, "~> 1.0", [hex: :bunch, repo: "hexpm", optional: false]}, {:bundlex, "~> 1.4", [hex: :bundlex, repo: "hexpm", optional: false]}, {:shmex, "~> 0.5.0", [hex: :shmex, repo: "hexpm", optional: false]}], "hexpm", "7a8395aabc3ba6cff04bbe5b995de7f899a38eb57f189e49927d6b8b6ccb6883"}, + "unifex": {:hex, :unifex, "1.2.1", "6841c170a6e16509fac30b19e4e0a19937c33155a59088b50c15fc2c36251b6b", [:mix], [{:bunch, "~> 1.0", [hex: :bunch, repo: "hexpm", optional: false]}, {:bundlex, "~> 1.4", [hex: :bundlex, repo: "hexpm", optional: false]}, {:shmex, "~> 0.5.0", [hex: :shmex, repo: "hexpm", optional: false]}], "hexpm", "8c9d2e3c48df031e9995dd16865bab3df402c0295ba3a31f38274bb5314c7d37"}, "zarex": {:hex, :zarex, "1.0.5", "58239e3ee5d75f343262bb4df5cf466555a1c689f920e5d3651a9333972f7c7e", [:mix], [], "hexpm", "9fb72ef0567c2b2742f5119a1ba8a24a2fabb21b8d09820aefbf3e592fa9a46a"}, }