[#30] sending last metrics when the dashboard connects to the backend
This commit is contained in:
parent
c1866bfee5
commit
6ca87d0d63
|
@ -23,6 +23,11 @@ defmodule POABackend.Receivers.Dashboard do
|
||||||
|
|
||||||
use POABackend.Receiver
|
use POABackend.Receiver
|
||||||
|
|
||||||
|
# we store the last metrics in a ETS table because when a dashboard is connected it can wait a lot until
|
||||||
|
# the stats get updated
|
||||||
|
|
||||||
|
@last_metrics_table :last_metrics_table
|
||||||
|
|
||||||
alias __MODULE__
|
alias __MODULE__
|
||||||
alias POABackend.Protocol.Message
|
alias POABackend.Protocol.Message
|
||||||
|
|
||||||
|
@ -95,6 +100,8 @@ defmodule POABackend.Receivers.Dashboard do
|
||||||
def init_receiver(opts) do
|
def init_receiver(opts) do
|
||||||
:ok = start_websockets_server(opts)
|
:ok = start_websockets_server(opts)
|
||||||
|
|
||||||
|
:ok = set_up_last_metrics_table()
|
||||||
|
|
||||||
{:ok, %{clients: []}}
|
{:ok, %{clients: []}}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -105,6 +112,17 @@ defmodule POABackend.Receivers.Dashboard do
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_message({:add_client, client}, %{clients: clients} = state) do
|
def handle_message({:add_client, client}, %{clients: clients} = state) do
|
||||||
|
|
||||||
|
# we send the latest metrics in order to catch up
|
||||||
|
stored_metrics = :ets.tab2list(@last_metrics_table)
|
||||||
|
|
||||||
|
for {_, metrics} <- stored_metrics do
|
||||||
|
metrics_list = Map.to_list(metrics)
|
||||||
|
for {_, metric} <- metrics_list do
|
||||||
|
send(client, metric)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
{:ok, %{state | clients: [client | clients]}}
|
{:ok, %{state | clients: [client | clients]}}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -163,6 +181,8 @@ defmodule POABackend.Receivers.Dashboard do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
save_metrics(metrics)
|
||||||
|
|
||||||
:ok
|
:ok
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -170,4 +190,49 @@ defmodule POABackend.Receivers.Dashboard do
|
||||||
dispatch_metric([metric], clients)
|
dispatch_metric([metric], clients)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp save_metrics(metrics) do
|
||||||
|
for metric <- metrics do
|
||||||
|
case metric.data["type"] do
|
||||||
|
"information" ->
|
||||||
|
save_last_information(metric)
|
||||||
|
"statistics" ->
|
||||||
|
save_last_stats(metric)
|
||||||
|
_ ->
|
||||||
|
:continue
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
|
||||||
|
defp save_last_information(%Message{} = metric) do
|
||||||
|
case :ets.lookup(@last_metrics_table, metric.agent_id) do
|
||||||
|
[] ->
|
||||||
|
:ets.insert(@last_metrics_table, {metric.agent_id, %{information: metric}})
|
||||||
|
[{_, last_metrics}] ->
|
||||||
|
last_metrics = Map.put(last_metrics, :information, metric)
|
||||||
|
:ets.insert(@last_metrics_table, {metric.agent_id, last_metrics})
|
||||||
|
end
|
||||||
|
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
|
||||||
|
defp save_last_stats(%Message{} = metric) do
|
||||||
|
case :ets.lookup(@last_metrics_table, metric.agent_id) do
|
||||||
|
[] ->
|
||||||
|
:ets.insert(@last_metrics_table, {metric.agent_id, %{stats: metric}})
|
||||||
|
[{_, last_metrics}] ->
|
||||||
|
last_metrics = Map.put(last_metrics, :stats, metric)
|
||||||
|
:ets.insert(@last_metrics_table, {metric.agent_id, last_metrics})
|
||||||
|
end
|
||||||
|
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
|
||||||
|
defp set_up_last_metrics_table do
|
||||||
|
:ets.new(@last_metrics_table, [:named_table])
|
||||||
|
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
|
@ -8,8 +8,9 @@ defmodule Receivers.DashboardTest do
|
||||||
defmodule Client do
|
defmodule Client do
|
||||||
use WebSockex
|
use WebSockex
|
||||||
|
|
||||||
def send(client, message) do
|
def send(client, message, caller) do
|
||||||
WebSockex.send_frame(client, {:text, message})
|
WebSockex.send_frame(client, {:text, message})
|
||||||
|
Kernel.send(caller, :message_sent)
|
||||||
end
|
end
|
||||||
|
|
||||||
def start_link(address, state, opts \\ []) do
|
def start_link(address, state, opts \\ []) do
|
||||||
|
@ -45,10 +46,32 @@ defmodule Receivers.DashboardTest do
|
||||||
assert_receive ^expected_message, 20_000
|
assert_receive ^expected_message, 20_000
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "When the Dashboard connects already exists last metrics in the Backend" do
|
||||||
|
|
||||||
|
# we send the metrics twice in order to complete all the cases in the Receiver
|
||||||
|
# when the ets doesn't have the agentid and when it already exists
|
||||||
|
POABackend.Metric.add(:ethereum_metrics, [information_message(), stats_message(), information_message()])
|
||||||
|
POABackend.Metric.add(:ethereum_metrics, [information_message2(), stats_message2()])
|
||||||
|
|
||||||
|
Client.start_link("http://localhost:8181/ws", self(), [{:extra_headers, [{"wssecret", "mywssecret"}]}])
|
||||||
|
|
||||||
|
expected_information_message = expected_information_message()
|
||||||
|
expected_stats_message = expected_stats_message()
|
||||||
|
expected_information_message2 = expected_information_message2()
|
||||||
|
expected_stats_message2 = expected_stats_message2()
|
||||||
|
|
||||||
|
assert_receive ^expected_information_message, 20_000
|
||||||
|
assert_receive ^expected_stats_message, 20_000
|
||||||
|
assert_receive ^expected_information_message2, 20_000
|
||||||
|
assert_receive ^expected_stats_message2, 20_000
|
||||||
|
end
|
||||||
|
|
||||||
test "handle messages from the client to the server (test coverage)" do
|
test "handle messages from the client to the server (test coverage)" do
|
||||||
{:ok, client} = Client.start_link("http://localhost:8181/ws", self(), [{:extra_headers, [{"wssecret", "mywssecret"}]}])
|
{:ok, client} = Client.start_link("http://localhost:8181/ws", self(), [{:extra_headers, [{"wssecret", "mywssecret"}]}])
|
||||||
|
|
||||||
Client.send(client, "hello")
|
Client.send(client, "hello", self())
|
||||||
|
|
||||||
|
assert_receive :message_sent, 20_000
|
||||||
end
|
end
|
||||||
|
|
||||||
test "http call to the server (test coverage)" do
|
test "http call to the server (test coverage)" do
|
||||||
|
@ -65,4 +88,35 @@ defmodule Receivers.DashboardTest do
|
||||||
Message.new("agentid1", :ethereum_metric, :data, %{a: "a", b: "b", c: "c"})
|
Message.new("agentid1", :ethereum_metric, :data, %{a: "a", b: "b", c: "c"})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp information_message do
|
||||||
|
Message.new("agentid", :ethereum_metric, :data, %{"type" => "information"})
|
||||||
|
end
|
||||||
|
|
||||||
|
defp stats_message do
|
||||||
|
Message.new("agentid", :ethereum_metric, :data, %{"type" => "statistics"})
|
||||||
|
end
|
||||||
|
|
||||||
|
defp information_message2 do
|
||||||
|
Message.new("agentid2", :ethereum_metric, :data, %{"type" => "information"})
|
||||||
|
end
|
||||||
|
|
||||||
|
defp stats_message2 do
|
||||||
|
Message.new("agentid2", :ethereum_metric, :data, %{"type" => "statistics"})
|
||||||
|
end
|
||||||
|
|
||||||
|
defp expected_information_message do
|
||||||
|
"{\"data\":{\"type\":\"information\"},\"agent_id\":\"agentid\"}"
|
||||||
|
end
|
||||||
|
|
||||||
|
defp expected_stats_message do
|
||||||
|
"{\"data\":{\"type\":\"statistics\"},\"agent_id\":\"agentid\"}"
|
||||||
|
end
|
||||||
|
|
||||||
|
defp expected_information_message2 do
|
||||||
|
"{\"data\":{\"type\":\"information\"},\"agent_id\":\"agentid2\"}"
|
||||||
|
end
|
||||||
|
|
||||||
|
defp expected_stats_message2 do
|
||||||
|
"{\"data\":{\"type\":\"statistics\"},\"agent_id\":\"agentid2\"}"
|
||||||
|
end
|
||||||
end
|
end
|
|
@ -1,6 +1,8 @@
|
||||||
defmodule Receivers.ReceiversTest do
|
defmodule Receivers.ReceiversTest do
|
||||||
use ExUnit.Case
|
use ExUnit.Case
|
||||||
|
|
||||||
|
alias POABackend.Protocol.Message
|
||||||
|
|
||||||
test "__using__ Receiver" do
|
test "__using__ Receiver" do
|
||||||
defmodule Receiver1 do
|
defmodule Receiver1 do
|
||||||
use POABackend.Receiver
|
use POABackend.Receiver
|
||||||
|
@ -64,15 +66,19 @@ defmodule Receivers.ReceiversTest do
|
||||||
|
|
||||||
{:ok, _} = Receiver2.start_link(state)
|
{:ok, _} = Receiver2.start_link(state)
|
||||||
|
|
||||||
POABackend.Metric.add(:ethereum_metrics, [:message1, :message2])
|
message1 = Message.new("agentID", :ethereum_metric, :data, %{"data" => :nodata})
|
||||||
POABackend.Metric.add(:ethereum_metrics, :message3)
|
message2 = Message.new("agentID2", :ethereum_metric, :data, %{"data" => :nodata})
|
||||||
|
message3 = Message.new("agentID3", :ethereum_metric, :data, %{"data" => :nodata})
|
||||||
|
|
||||||
|
POABackend.Metric.add(:ethereum_metrics, [message1, message2])
|
||||||
|
POABackend.Metric.add(:ethereum_metrics, message3)
|
||||||
|
|
||||||
metrics_pid = Process.whereis(:ethereum_metrics)
|
metrics_pid = Process.whereis(:ethereum_metrics)
|
||||||
|
|
||||||
send(metrics_pid, :nothing_happens)
|
send(metrics_pid, :nothing_happens)
|
||||||
|
|
||||||
assert_receive {:metric_received, :message1}, 20_000
|
assert_receive {:metric_received, ^message1}, 20_000
|
||||||
assert_receive {:metric_received, :message2}, 20_000
|
assert_receive {:metric_received, ^message2}, 20_000
|
||||||
assert_receive {:metric_received, :message3}, 20_000
|
assert_receive {:metric_received, ^message3}, 20_000
|
||||||
end
|
end
|
||||||
end
|
end
|
Loading…
Reference in New Issue