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
|
||||
|
||||
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
|
||||
Logger.info "starting sup"
|
||||
|
||||
children = [
|
||||
base_children = [
|
||||
%{
|
||||
id: Elstat.Cowboy,
|
||||
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)
|
||||
end
|
||||
|
||||
|
|
1
mix.exs
1
mix.exs
|
@ -23,6 +23,7 @@ defmodule Elstat.MixProject do
|
|||
defp deps do
|
||||
[
|
||||
{:httpoison, "~> 1.1.1"},
|
||||
{:sqlitex, "~> 1.4.2"},
|
||||
{:cowboy, "~> 2.4.0"}
|
||||
]
|
||||
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"},
|
||||
"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"},
|
||||
"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"},
|
||||
"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"},
|
||||
|
@ -9,6 +11,7 @@
|
|||
"mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], [], "hexpm"},
|
||||
"parse_trans": {:hex, :parse_trans, "3.2.0", "2adfa4daf80c14dc36f522cf190eb5c4ee3e28008fc6394397c16f62a26258c2", [: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"},
|
||||
"unicode_util_compat": {:hex, :unicode_util_compat, "0.3.1", "a1f612a7b512638634a603c8f401892afbf99b8ce93a45041f8aaca99cadb85e", [:rebar3], [], "hexpm"},
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue