add many stuff owo
This commit is contained in:
parent
4bce1c0146
commit
62e636cfe7
9 changed files with 208 additions and 3 deletions
31
config/config.example.exs
Normal file
31
config/config.example.exs
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
use Mix.Config
|
||||||
|
|
||||||
|
config :elstat,
|
||||||
|
# where will elstat (backend and frontend)
|
||||||
|
# be served
|
||||||
|
port: 8069,
|
||||||
|
|
||||||
|
# which services will be managed by elstat?
|
||||||
|
# this follows a service spec
|
||||||
|
# the example here is for elixire
|
||||||
|
services: [
|
||||||
|
%{
|
||||||
|
id: :elixire,
|
||||||
|
description: "elixi.re",
|
||||||
|
adapter: Elstat.Adapter.Elixire,
|
||||||
|
adapter_opts: %{
|
||||||
|
base_url: "https://elixi.re",
|
||||||
|
},
|
||||||
|
# every 10 seconds
|
||||||
|
poll: 10,
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
id: :genserver,
|
||||||
|
description: "genserver, elixire main server",
|
||||||
|
adapter: Elstat.Adapter.Ping,
|
||||||
|
adapter_opts: %{
|
||||||
|
address: "192.168.1.1",
|
||||||
|
},
|
||||||
|
poll: 15,
|
||||||
|
},
|
||||||
|
]
|
|
@ -1,4 +1,29 @@
|
||||||
use Mix.Config
|
use Mix.Config
|
||||||
|
|
||||||
config :elstat,
|
config :elstat,
|
||||||
port: 8069
|
port: 8069,
|
||||||
|
|
||||||
|
# which services will be managed by elstat?
|
||||||
|
# this follows a service spec
|
||||||
|
# the example here is for elixire
|
||||||
|
services: [
|
||||||
|
%{
|
||||||
|
id: :elixire,
|
||||||
|
human_id: "elixi.re",
|
||||||
|
adapter: Elstat.Adapter.Elixire,
|
||||||
|
adapter_opts: %{
|
||||||
|
base_url: "https://elixi.re",
|
||||||
|
},
|
||||||
|
# every 10 seconds
|
||||||
|
poll: 10,
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
id: :genserver,
|
||||||
|
human_id: "genserver, elixire main server",
|
||||||
|
adapter: Elstat.Adapter.Ping,
|
||||||
|
adapter_opts: %{
|
||||||
|
address: "192.168.1.1",
|
||||||
|
},
|
||||||
|
poll: 15,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
7
lib/adapters/adapter.ex
Normal file
7
lib/adapters/adapter.ex
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
defmodule Elstat.Adapter do
|
||||||
|
@type adapter_check_res :: {:ok, any()} | {:error, any()}
|
||||||
|
|
||||||
|
@type adp_args :: Map.t
|
||||||
|
|
||||||
|
@callback check(adp_args) :: adapter_check_res
|
||||||
|
end
|
31
lib/adapters/elixire.ex
Normal file
31
lib/adapters/elixire.ex
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
defmodule Elstat.Adapter.Elixire do
|
||||||
|
@behaviour Elstat.Adapter
|
||||||
|
|
||||||
|
use GenServer
|
||||||
|
require Logger
|
||||||
|
|
||||||
|
def start_link(service_opts) do
|
||||||
|
GenServer.start_link(__MODULE__, service_opts, [])
|
||||||
|
end
|
||||||
|
|
||||||
|
def init(service_opts) do
|
||||||
|
Logger.info("Elixire adapter started with #{inspect service_opts}")
|
||||||
|
{:ok, %{}}
|
||||||
|
end
|
||||||
|
|
||||||
|
def check(args) do
|
||||||
|
addr = args.base_url
|
||||||
|
|
||||||
|
req_start = :erlang.monotonic_time(:millisecond)
|
||||||
|
resp = HTTPoison.get!("#{addr}/api/hello")
|
||||||
|
req_end = :erlang.monotonic_time(:millisecond)
|
||||||
|
|
||||||
|
delta = req_end - req_start
|
||||||
|
|
||||||
|
{:ok, {:map, %{
|
||||||
|
status: resp.status_code == 200,
|
||||||
|
latency: {:millisecond, delta},
|
||||||
|
}}}
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
22
lib/adapters/ping.ex
Normal file
22
lib/adapters/ping.ex
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
defmodule Elstat.Adapter.Ping do
|
||||||
|
@behaviour Elstat.Adapter
|
||||||
|
|
||||||
|
use GenServer
|
||||||
|
require Logger
|
||||||
|
|
||||||
|
def start_link(service_opts) do
|
||||||
|
GenServer.start_link(__MODULE__, service_opts, [])
|
||||||
|
end
|
||||||
|
|
||||||
|
def init(service_opts) do
|
||||||
|
Logger.info("Ping started with #{inspect service_opts}")
|
||||||
|
{:ok, %{}}
|
||||||
|
end
|
||||||
|
|
||||||
|
def check(args) do
|
||||||
|
{cmd_output, _} = System.cmd("ping", ["-c", "1", args.address])
|
||||||
|
alive? = not Regex.match?(~r/100(\.0)?% packet loss/, cmd_output)
|
||||||
|
{:ok, {:bool, alive?}}
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
80
lib/manager.ex
Normal file
80
lib/manager.ex
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
defmodule Elstat.Error.Service do
|
||||||
|
defexception message: "default message"
|
||||||
|
end
|
||||||
|
|
||||||
|
defmodule Elstat.ServiceWorker do
|
||||||
|
require Logger
|
||||||
|
|
||||||
|
def start_link(service) do
|
||||||
|
Logger.info "spawning worker for #{inspect service.id}"
|
||||||
|
|
||||||
|
worker_pid = spawn(fn ->
|
||||||
|
worker_func(service)
|
||||||
|
end)
|
||||||
|
|
||||||
|
{:ok, worker_pid}
|
||||||
|
end
|
||||||
|
|
||||||
|
def worker_func(service) do
|
||||||
|
adapter = service.adapter
|
||||||
|
|
||||||
|
result = adapter.check(service.adapter_opts)
|
||||||
|
Logger.info "result from #{inspect adapter} #{inspect service.id}: #{inspect result}"
|
||||||
|
|
||||||
|
man_pid = :global.whereis_name Elstat.Manager
|
||||||
|
send man_pid, {:service_info, {service.id, result}}
|
||||||
|
|
||||||
|
Process.sleep(service.poll * 1000)
|
||||||
|
worker_func(service)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defmodule Elstat.Manager do
|
||||||
|
@moduledoc """
|
||||||
|
Elstat's service manager.
|
||||||
|
"""
|
||||||
|
use GenServer
|
||||||
|
require Logger
|
||||||
|
|
||||||
|
def start_link(opts) do
|
||||||
|
GenServer.start_link(__MODULE__, :ok, [name: {:global, Elstat.Manager}] ++ opts)
|
||||||
|
end
|
||||||
|
|
||||||
|
def build_services() do
|
||||||
|
services = Application.fetch_env!(:elstat, :services)
|
||||||
|
|
||||||
|
workers = services
|
||||||
|
|> Enum.map(fn service ->
|
||||||
|
service_id = service.id
|
||||||
|
|
||||||
|
# each service worker will enter an infinite loop
|
||||||
|
# polling the service (via an adapter) and giving
|
||||||
|
# information back to the manager, so it can
|
||||||
|
# process and show those via its API.
|
||||||
|
%{
|
||||||
|
id: service_id,
|
||||||
|
start: {Elstat.ServiceWorker, :start_link, [service]}
|
||||||
|
}
|
||||||
|
end)
|
||||||
|
|
||||||
|
# spawn the managere alongside service workers
|
||||||
|
[ Elstat.Manager | workers]
|
||||||
|
end
|
||||||
|
|
||||||
|
# server callbacks
|
||||||
|
def init(:ok) do
|
||||||
|
services = Application.fetch_env!(:elstat, :services)
|
||||||
|
|
||||||
|
# TODO : send data to db
|
||||||
|
|
||||||
|
{:ok, %{
|
||||||
|
services: services,
|
||||||
|
}}
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_info({:service_info, data}, state) do
|
||||||
|
Logger.debug "got service data! #{inspect data}"
|
||||||
|
{:noreply, state}
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -9,13 +9,18 @@ defmodule Elstat.Supervisor do
|
||||||
def init(:ok) do
|
def init(:ok) do
|
||||||
Logger.info "starting sup"
|
Logger.info "starting sup"
|
||||||
|
|
||||||
children = [
|
base_children = [
|
||||||
%{
|
%{
|
||||||
id: Elstat.Cowboy,
|
id: Elstat.Cowboy,
|
||||||
start: {Elstat.Cowboy, :start_link, []},
|
start: {Elstat.Cowboy, :start_link, []},
|
||||||
}
|
},
|
||||||
|
{Sqlitex.Server, ['elstat.db', [name: Sqlitex.Server]]}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
service_children = Elstat.Manager.build_services()
|
||||||
|
|
||||||
|
children = service_children ++ base_children
|
||||||
|
Logger.debug "final children #{inspect children}"
|
||||||
Supervisor.init(children, strategy: :one_for_one)
|
Supervisor.init(children, strategy: :one_for_one)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
1
mix.exs
1
mix.exs
|
@ -23,6 +23,7 @@ defmodule Elstat.MixProject do
|
||||||
defp deps do
|
defp deps do
|
||||||
[
|
[
|
||||||
{:httpoison, "~> 1.1.1"},
|
{:httpoison, "~> 1.1.1"},
|
||||||
|
{:sqlitex, "~> 1.4.2"},
|
||||||
{:cowboy, "~> 2.4.0"}
|
{:cowboy, "~> 2.4.0"}
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
3
mix.lock
3
mix.lock
|
@ -2,6 +2,8 @@
|
||||||
"certifi": {:hex, :certifi, "2.3.1", "d0f424232390bf47d82da8478022301c561cf6445b5b5fb6a84d49a9e76d2639", [:rebar3], [{:parse_trans, "3.2.0", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm"},
|
"certifi": {:hex, :certifi, "2.3.1", "d0f424232390bf47d82da8478022301c561cf6445b5b5fb6a84d49a9e76d2639", [:rebar3], [{:parse_trans, "3.2.0", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"cowboy": {:hex, :cowboy, "2.4.0", "f1b72fabe9c8a5fc64ac5ac85fb65474d64733d1df52a26fad5d4ba3d9f70a9f", [:rebar3], [{:cowlib, "~> 2.3.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.5.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm"},
|
"cowboy": {:hex, :cowboy, "2.4.0", "f1b72fabe9c8a5fc64ac5ac85fb65474d64733d1df52a26fad5d4ba3d9f70a9f", [:rebar3], [{:cowlib, "~> 2.3.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.5.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"cowlib": {:hex, :cowlib, "2.3.0", "bbd58ef537904e4f7c1dd62e6aa8bc831c8183ce4efa9bd1150164fe15be4caa", [:rebar3], [], "hexpm"},
|
"cowlib": {:hex, :cowlib, "2.3.0", "bbd58ef537904e4f7c1dd62e6aa8bc831c8183ce4efa9bd1150164fe15be4caa", [:rebar3], [], "hexpm"},
|
||||||
|
"decimal": {:hex, :decimal, "1.5.0", "b0433a36d0e2430e3d50291b1c65f53c37d56f83665b43d79963684865beab68", [:mix], [], "hexpm"},
|
||||||
|
"esqlite": {:hex, :esqlite, "0.2.4", "3a8a352c190afe2d6b828b252a6fbff65b5cc1124647f38b15bdab3bf6fd4b3e", [:rebar3], [], "hexpm"},
|
||||||
"hackney": {:hex, :hackney, "1.12.1", "8bf2d0e11e722e533903fe126e14d6e7e94d9b7983ced595b75f532e04b7fdc7", [:rebar3], [{:certifi, "2.3.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "5.1.1", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"},
|
"hackney": {:hex, :hackney, "1.12.1", "8bf2d0e11e722e533903fe126e14d6e7e94d9b7983ced595b75f532e04b7fdc7", [:rebar3], [{:certifi, "2.3.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "5.1.1", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"httpoison": {:hex, :httpoison, "1.1.1", "96ed7ab79f78a31081bb523eefec205fd2900a02cda6dbc2300e7a1226219566", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"},
|
"httpoison": {:hex, :httpoison, "1.1.1", "96ed7ab79f78a31081bb523eefec205fd2900a02cda6dbc2300e7a1226219566", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"idna": {:hex, :idna, "5.1.1", "cbc3b2fa1645113267cc59c760bafa64b2ea0334635ef06dbac8801e42f7279c", [:rebar3], [{:unicode_util_compat, "0.3.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"},
|
"idna": {:hex, :idna, "5.1.1", "cbc3b2fa1645113267cc59c760bafa64b2ea0334635ef06dbac8801e42f7279c", [:rebar3], [{:unicode_util_compat, "0.3.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
|
@ -9,6 +11,7 @@
|
||||||
"mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], [], "hexpm"},
|
"mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], [], "hexpm"},
|
||||||
"parse_trans": {:hex, :parse_trans, "3.2.0", "2adfa4daf80c14dc36f522cf190eb5c4ee3e28008fc6394397c16f62a26258c2", [:rebar3], [], "hexpm"},
|
"parse_trans": {:hex, :parse_trans, "3.2.0", "2adfa4daf80c14dc36f522cf190eb5c4ee3e28008fc6394397c16f62a26258c2", [:rebar3], [], "hexpm"},
|
||||||
"ranch": {:hex, :ranch, "1.5.0", "f04166f456790fee2ac1aa05a02745cc75783c2bfb26d39faf6aefc9a3d3a58a", [:rebar3], [], "hexpm"},
|
"ranch": {:hex, :ranch, "1.5.0", "f04166f456790fee2ac1aa05a02745cc75783c2bfb26d39faf6aefc9a3d3a58a", [:rebar3], [], "hexpm"},
|
||||||
|
"sqlitex": {:hex, :sqlitex, "1.4.2", "b18f2b53cefbc9cca0bd17d51386f9caa7cf341144cb314e5cd9fd2a1f9b0845", [:mix], [{:decimal, "~> 1.1", [hex: :decimal, repo: "hexpm", optional: false]}, {:esqlite, "~> 0.2.4", [hex: :esqlite, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], [], "hexpm"},
|
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], [], "hexpm"},
|
||||||
"unicode_util_compat": {:hex, :unicode_util_compat, "0.3.1", "a1f612a7b512638634a603c8f401892afbf99b8ce93a45041f8aaca99cadb85e", [:rebar3], [], "hexpm"},
|
"unicode_util_compat": {:hex, :unicode_util_compat, "0.3.1", "a1f612a7b512638634a603c8f401892afbf99b8ce93a45041f8aaca99cadb85e", [:rebar3], [], "hexpm"},
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue