[#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
|
||||
|
||||
# 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 POABackend.Protocol.Message
|
||||
|
||||
|
@ -95,6 +100,8 @@ defmodule POABackend.Receivers.Dashboard do
|
|||
def init_receiver(opts) do
|
||||
:ok = start_websockets_server(opts)
|
||||
|
||||
:ok = set_up_last_metrics_table()
|
||||
|
||||
{:ok, %{clients: []}}
|
||||
end
|
||||
|
||||
|
@ -105,6 +112,17 @@ defmodule POABackend.Receivers.Dashboard do
|
|||
end
|
||||
|
||||
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]}}
|
||||
end
|
||||
|
||||
|
@ -163,6 +181,8 @@ defmodule POABackend.Receivers.Dashboard do
|
|||
end
|
||||
end
|
||||
|
||||
save_metrics(metrics)
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
|
@ -170,4 +190,49 @@ defmodule POABackend.Receivers.Dashboard do
|
|||
dispatch_metric([metric], clients)
|
||||
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
|
|
@ -8,8 +8,9 @@ defmodule Receivers.DashboardTest do
|
|||
defmodule Client do
|
||||
use WebSockex
|
||||
|
||||
def send(client, message) do
|
||||
def send(client, message, caller) do
|
||||
WebSockex.send_frame(client, {:text, message})
|
||||
Kernel.send(caller, :message_sent)
|
||||
end
|
||||
|
||||
def start_link(address, state, opts \\ []) do
|
||||
|
@ -45,10 +46,32 @@ defmodule Receivers.DashboardTest do
|
|||
assert_receive ^expected_message, 20_000
|
||||
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
|
||||
{: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
|
||||
|
||||
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"})
|
||||
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
|
|
@ -1,6 +1,8 @@
|
|||
defmodule Receivers.ReceiversTest do
|
||||
use ExUnit.Case
|
||||
|
||||
alias POABackend.Protocol.Message
|
||||
|
||||
test "__using__ Receiver" do
|
||||
defmodule Receiver1 do
|
||||
use POABackend.Receiver
|
||||
|
@ -64,15 +66,19 @@ defmodule Receivers.ReceiversTest do
|
|||
|
||||
{:ok, _} = Receiver2.start_link(state)
|
||||
|
||||
POABackend.Metric.add(:ethereum_metrics, [:message1, :message2])
|
||||
POABackend.Metric.add(:ethereum_metrics, :message3)
|
||||
message1 = Message.new("agentID", :ethereum_metric, :data, %{"data" => :nodata})
|
||||
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)
|
||||
|
||||
send(metrics_pid, :nothing_happens)
|
||||
|
||||
assert_receive {:metric_received, :message1}, 20_000
|
||||
assert_receive {:metric_received, :message2}, 20_000
|
||||
assert_receive {:metric_received, :message3}, 20_000
|
||||
assert_receive {:metric_received, ^message1}, 20_000
|
||||
assert_receive {:metric_received, ^message2}, 20_000
|
||||
assert_receive {:metric_received, ^message3}, 20_000
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue