remove elixir code
This commit is contained in:
parent
884c9f736d
commit
f8269c8aec
18 changed files with 119 additions and 711 deletions
117
.gitignore
vendored
117
.gitignore
vendored
|
@ -10,30 +10,111 @@ thumbs.db
|
|||
/priv/yarn-debug.log*
|
||||
/priv/yarn-error.log*
|
||||
|
||||
# The directory Mix will write compiled artifacts to.
|
||||
/_build/
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# If you run "mix test --cover", coverage assets end up here.
|
||||
/cover/
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# The directory Mix downloads your dependencies sources to.
|
||||
/deps/
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# Where 3rd-party dependencies like ExDoc output generated docs.
|
||||
/doc/
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Ignore .fetch files in case you like to edit your project deps locally.
|
||||
/.fetch
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# If the VM crashes, it generates a dump, let's ignore it too.
|
||||
erl_crash.dump
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
|
||||
# Also ignore archive artifacts (built via "mix archive.build").
|
||||
*.ez
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# pyenv
|
||||
.python-version
|
||||
|
||||
# celery beat schedule file
|
||||
celerybeat-schedule
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
|
||||
# Ignore package tarball (built via "mix hex.build").
|
||||
elstat-*.tar
|
||||
|
||||
*.db
|
||||
config/config.exs
|
||||
|
||||
config.py
|
||||
|
|
20
config.example.py
Normal file
20
config.example.py
Normal file
|
@ -0,0 +1,20 @@
|
|||
PORT = 8069
|
||||
|
||||
SERVICES = {
|
||||
'elixire': {
|
||||
'description': "elixi.re's backend",
|
||||
'adapter': 'elixire',
|
||||
'adapter_args': {
|
||||
'base_url': 'https://elixi.re'
|
||||
},
|
||||
'poll': 10
|
||||
},
|
||||
'dabian': {
|
||||
'description': 'elixi.re main server',
|
||||
'adapter': 'ping',
|
||||
'adapter_args': {
|
||||
'address': '192.168.1.1'
|
||||
},
|
||||
'poll': 15
|
||||
}
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
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,27 +0,0 @@
|
|||
use Mix.Config
|
||||
|
||||
config :elstat,
|
||||
port: 8069,
|
||||
|
||||
# which services will be managed by elstat?
|
||||
# this follows a service spec
|
||||
# the example here is for elixire
|
||||
services: %{
|
||||
elixire: %{
|
||||
description: "the backend of elixi.re",
|
||||
adapter: Elstat.Adapter.Elixire,
|
||||
adapter_opts: %{
|
||||
base_url: "https://elixi.re",
|
||||
},
|
||||
# every 10 seconds
|
||||
poll: 10,
|
||||
},
|
||||
genserver: %{
|
||||
description: "genserver, elixire main server",
|
||||
adapter: Elstat.Adapter.Ping,
|
||||
adapter_opts: %{
|
||||
address: "192.168.1.1",
|
||||
},
|
||||
poll: 15,
|
||||
},
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
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
|
|
@ -1,39 +0,0 @@
|
|||
defmodule Elstat.Adapter.Elixire do
|
||||
@behaviour Elstat.Adapter
|
||||
|
||||
def adapter_spec do
|
||||
%{
|
||||
db_columns: [:timestamp, :status, :latency]
|
||||
}
|
||||
end
|
||||
|
||||
def check(args) do
|
||||
addr = args.base_url
|
||||
|
||||
req_start = :erlang.monotonic_time(:millisecond)
|
||||
status = HTTPoison.get("#{addr}/api/hello")
|
||||
req_end = :erlang.monotonic_time(:millisecond)
|
||||
|
||||
delta = req_end - req_start
|
||||
|
||||
case status do
|
||||
{:ok, resp} ->
|
||||
{:ok, {:map, %{
|
||||
status: resp.status_code == 200,
|
||||
latency: delta
|
||||
}}}
|
||||
{:error, reason} ->
|
||||
{:ok, {:map, %{
|
||||
status: false,
|
||||
|
||||
# use drops to 0 as failure on conn
|
||||
latency: 0
|
||||
}}}
|
||||
end
|
||||
end
|
||||
|
||||
def transform_val({:map, %{status: status, latency: latency}}) do
|
||||
[status, latency]
|
||||
end
|
||||
|
||||
end
|
|
@ -1,20 +0,0 @@
|
|||
defmodule Elstat.Adapter.Ping do
|
||||
@behaviour Elstat.Adapter
|
||||
|
||||
def adapter_spec do
|
||||
%{
|
||||
db_columns: [:timestamp, :status]
|
||||
}
|
||||
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
|
||||
|
||||
def transform_val({:bool, alive?}) do
|
||||
[alive?]
|
||||
end
|
||||
|
||||
end
|
33
lib/api.ex
33
lib/api.ex
|
@ -1,33 +0,0 @@
|
|||
defmodule Elstat.API.CurrentStatus do
|
||||
require Logger
|
||||
|
||||
def init(req0, state) do
|
||||
data = Elstat.Manager.get_current_state()
|
||||
|
||||
req = :cowboy_req.reply(200,
|
||||
%{"content-type" => "text/json", "Access-Control-Allow-Origin" => "*"},
|
||||
Poison.encode!(data),
|
||||
req0
|
||||
)
|
||||
|
||||
{:ok, req, state}
|
||||
end
|
||||
end
|
||||
|
||||
defmodule Elstat.API.Status do
|
||||
def init(req0, state) do
|
||||
status = Elstat.Manager.get_current_state()
|
||||
graph = Elstat.Manager.get_graph_state()
|
||||
|
||||
req = :cowboy_req.reply(200,
|
||||
%{"content-type" => "text/json", "Access-Control-Allow-Origin" => "*"},
|
||||
Poison.encode!(%{
|
||||
status: status,
|
||||
graph: graph,
|
||||
}),
|
||||
req0
|
||||
)
|
||||
|
||||
{:ok, req, state}
|
||||
end
|
||||
end
|
|
@ -1,41 +0,0 @@
|
|||
defmodule Elstat.Cowboy.DefaultHandler do
|
||||
def init(req0, state) do
|
||||
|
||||
# TODO: find a way to send a html file
|
||||
# instead of hewwo owo
|
||||
req = :cowboy_req.reply(200,
|
||||
%{"content-type" => "text/plain"},
|
||||
"hewwo",
|
||||
req0
|
||||
)
|
||||
|
||||
{:ok, req, state}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
defmodule Elstat.Cowboy do
|
||||
def start_link do
|
||||
dispatch_config = build_dispatch_config()
|
||||
|
||||
port = Application.fetch_env!(:elstat, :port)
|
||||
|
||||
{:ok, _} = :cowboy.start_clear(
|
||||
:elstat,
|
||||
[{:port, port}],
|
||||
%{env: %{dispatch: dispatch_config}}
|
||||
)
|
||||
end
|
||||
|
||||
def build_dispatch_config do
|
||||
:cowboy_router.compile([
|
||||
{:_, [
|
||||
{"/hewwo", Elstat.Cowboy.DefaultHandler, []},
|
||||
{"/api/current_status", Elstat.API.CurrentStatus, []},
|
||||
{"/api/status", Elstat.API.Status, []},
|
||||
{"/", :cowboy_static, {:priv_file, :elstat, "frontend/build/index.html"}},
|
||||
{"/[...]", :cowboy_static, {:priv_dir, :elstat, "frontend/build"}},
|
||||
]}
|
||||
])
|
||||
end
|
||||
end
|
|
@ -1,15 +0,0 @@
|
|||
defmodule Elstat do
|
||||
use Application
|
||||
|
||||
require Logger
|
||||
|
||||
def start(_type, _args) do
|
||||
Logger.info "starting app"
|
||||
Supervisor.start_link(
|
||||
[
|
||||
Elstat.Supervisor
|
||||
],
|
||||
strategy: :one_for_one
|
||||
)
|
||||
end
|
||||
end
|
244
lib/manager.ex
244
lib/manager.ex
|
@ -1,244 +0,0 @@
|
|||
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
|
||||
|> Map.keys
|
||||
|> Enum.map(fn service_id ->
|
||||
service = Map.put(services[service_id], :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
|
||||
|
||||
def get_current_state() do
|
||||
man_pid = :global.whereis_name Elstat.Manager
|
||||
GenServer.call(man_pid, {:get_current})
|
||||
end
|
||||
|
||||
def get_graph_state() do
|
||||
man_pid = :global.whereis_name Elstat.Manager
|
||||
GenServer.call(man_pid, {:get_graph})
|
||||
end
|
||||
|
||||
# server callbacks
|
||||
|
||||
def get_columns_def do
|
||||
%{
|
||||
timestamp: "timestamp bigint",
|
||||
status: "status bool",
|
||||
latency: "latency bigint",
|
||||
}
|
||||
end
|
||||
|
||||
def get_columns_name do
|
||||
%{
|
||||
timestamp: "timestamp",
|
||||
status: "status",
|
||||
latency: "latency",
|
||||
}
|
||||
end
|
||||
|
||||
def init(:ok) do
|
||||
services = Application.fetch_env!(:elstat, :services)
|
||||
|
||||
Sqlitex.with_db('elstat.db', fn(db) ->
|
||||
services
|
||||
|> Map.keys
|
||||
|> Enum.each(fn service_id ->
|
||||
service = services[service_id]
|
||||
adapter = service.adapter
|
||||
|
||||
spec = adapter.adapter_spec
|
||||
|
||||
columns = get_columns_def()
|
||||
|
||||
column_res = spec.db_columns
|
||||
|> Enum.map(fn column ->
|
||||
columns[column]
|
||||
end)
|
||||
|> Enum.join(",\n")
|
||||
|
||||
query = """
|
||||
CREATE TABLE IF NOT EXISTS #{Atom.to_string service_id} (
|
||||
#{column_res}
|
||||
);
|
||||
"""
|
||||
|
||||
Logger.debug "query for #{inspect service_id}: #{query}"
|
||||
|
||||
case Sqlitex.query(db, query) do
|
||||
{:ok, _} ->
|
||||
Logger.info "created table for #{inspect service_id}"
|
||||
{:error, _err} ->
|
||||
Logger.error "error making table for #{inspect service_id}"
|
||||
end
|
||||
end)
|
||||
end)
|
||||
|
||||
{:ok, %{
|
||||
services: services,
|
||||
serv_state: %{},
|
||||
}}
|
||||
end
|
||||
|
||||
def handle_call({:get_current}, _from, state) do
|
||||
reply = state.serv_state
|
||||
|> Map.keys
|
||||
|> Enum.map(fn key ->
|
||||
data = state.serv_state[key]
|
||||
desc = state.services[key].description
|
||||
|
||||
case data do
|
||||
{:map, data_map} ->
|
||||
{key, Map.put(data_map, :description, desc)}
|
||||
{:bool, data_bool} ->
|
||||
{key, %{
|
||||
status: data_bool,
|
||||
description: desc,
|
||||
}}
|
||||
end
|
||||
end)
|
||||
|> Map.new
|
||||
|
||||
{:reply, reply, state}
|
||||
end
|
||||
|
||||
def handle_call({:get_graph}, _from, state) do
|
||||
graph_reply = state.serv_state
|
||||
|> Map.keys
|
||||
|> Enum.map(fn key ->
|
||||
spec = state.services[key].adapter.adapter_spec
|
||||
|
||||
if Enum.member?(spec.db_columns, :latency) do
|
||||
{:ok, result} = Sqlitex.with_db('elstat.db', fn db ->
|
||||
query = """
|
||||
SELECT timestamp, latency FROM #{Atom.to_string key}
|
||||
ORDER BY timestamp DESC
|
||||
LIMIT 50
|
||||
"""
|
||||
|
||||
Logger.debug "query for latency: #{query}"
|
||||
|
||||
Sqlitex.query(db, query)
|
||||
end)
|
||||
|
||||
act = result
|
||||
|> Enum.map(fn field ->
|
||||
[Keyword.get(field, :timestamp), Keyword.get(field, :latency)]
|
||||
end)
|
||||
|
||||
{key, act}
|
||||
else
|
||||
nil
|
||||
end
|
||||
end)
|
||||
|> Enum.filter(fn d -> d != nil end)
|
||||
|> Map.new
|
||||
|
||||
Logger.debug "graph reply: #{inspect graph_reply}"
|
||||
|
||||
{:reply, graph_reply, state}
|
||||
end
|
||||
|
||||
def build_insert_query(service_id, state) do
|
||||
services = state.services
|
||||
service = services[service_id]
|
||||
spec = service.adapter.adapter_spec
|
||||
|
||||
columns_str = spec.db_columns
|
||||
|> Enum.map(fn atom ->
|
||||
Atom.to_string atom
|
||||
end)
|
||||
|> Enum.join(",")
|
||||
|
||||
query_args_str = 1..Enum.count(spec.db_columns)
|
||||
|> Enum.map(fn num ->
|
||||
"$#{num}"
|
||||
end)
|
||||
|> Enum.join(",")
|
||||
|
||||
"""
|
||||
INSERT INTO #{Atom.to_string service_id} (#{columns_str})
|
||||
VALUES (#{query_args_str})
|
||||
"""
|
||||
end
|
||||
|
||||
def handle_info({:service_info, {sid, sdata}}, state) do
|
||||
case sdata do
|
||||
{:ok, actual_data} ->
|
||||
new_serv_state = Map.put(state.serv_state, sid, actual_data)
|
||||
|
||||
query = build_insert_query(sid, state)
|
||||
|
||||
adapter = state.services[sid].adapter
|
||||
adp_args = adapter.transform_val(actual_data)
|
||||
|
||||
timestamp = :erlang.system_time(:millisecond)
|
||||
|
||||
Logger.debug "query: #{query}, timestamp: #{timestamp}, adp args: #{inspect adp_args}"
|
||||
|
||||
Sqlitex.with_db('elstat.db', fn(db) ->
|
||||
res = Sqlitex.query(db, query, bind: [timestamp | adp_args])
|
||||
IO.puts "#{inspect res}"
|
||||
end)
|
||||
|
||||
{:noreply, %{state | serv_state: new_serv_state}}
|
||||
{:error, err} ->
|
||||
Logger.warn "error on #{inspect sid}: #{inspect err}"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -1,30 +0,0 @@
|
|||
defmodule Elstat.Supervisor do
|
||||
use Supervisor
|
||||
require Logger
|
||||
|
||||
def start_link(opts) do
|
||||
Supervisor.start_link(__MODULE__, :ok, opts)
|
||||
end
|
||||
|
||||
def init(:ok) do
|
||||
Logger.info "starting sup"
|
||||
|
||||
base_children = [
|
||||
%{
|
||||
id: Elstat.Cowboy,
|
||||
start: {Elstat.Cowboy, :start_link, []},
|
||||
},
|
||||
%{
|
||||
id: Sqlitex.Server,
|
||||
start: {Sqlitex.Server, :start_link, ['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
|
||||
|
||||
end
|
32
mix.exs
32
mix.exs
|
@ -1,32 +0,0 @@
|
|||
defmodule Elstat.MixProject do
|
||||
use Mix.Project
|
||||
|
||||
def project do
|
||||
[
|
||||
app: :elstat,
|
||||
version: "0.1.0",
|
||||
elixir: "~> 1.6",
|
||||
start_permanent: Mix.env() == :prod,
|
||||
deps: deps()
|
||||
]
|
||||
end
|
||||
|
||||
# Run "mix help compile.app" to learn about applications.
|
||||
def application do
|
||||
[
|
||||
mod: {Elstat, []},
|
||||
extra_applications: [:logger]
|
||||
]
|
||||
end
|
||||
|
||||
# Run "mix help deps" to learn about dependencies.
|
||||
defp deps do
|
||||
[
|
||||
{:httpoison, "~> 1.1.1"},
|
||||
{:poison, "~> 3.1"},
|
||||
{:sqlitex, "~> 1.4.2"},
|
||||
{:cowboy, "~> 2.4.0"},
|
||||
{:distillery, "~> 1.5", runtime: false}
|
||||
]
|
||||
end
|
||||
end
|
19
mix.lock
19
mix.lock
|
@ -1,19 +0,0 @@
|
|||
%{
|
||||
"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"},
|
||||
"distillery": {:hex, :distillery, "1.5.2", "eec18b2d37b55b0bcb670cf2bcf64228ed38ce8b046bb30a9b636a6f5a4c0080", [: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"},
|
||||
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm"},
|
||||
"mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], [], "hexpm"},
|
||||
"parse_trans": {:hex, :parse_trans, "3.2.0", "2adfa4daf80c14dc36f522cf190eb5c4ee3e28008fc6394397c16f62a26258c2", [:rebar3], [], "hexpm"},
|
||||
"poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], [], "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"},
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
# Import all plugins from `rel/plugins`
|
||||
# They can then be used by adding `plugin MyPlugin` to
|
||||
# either an environment, or release definition, where
|
||||
# `MyPlugin` is the name of the plugin module.
|
||||
Path.join(["rel", "plugins", "*.exs"])
|
||||
|> Path.wildcard()
|
||||
|> Enum.map(&Code.eval_file(&1))
|
||||
|
||||
use Mix.Releases.Config,
|
||||
# This sets the default release built by `mix release`
|
||||
default_release: :default,
|
||||
# This sets the default environment used by `mix release`
|
||||
default_environment: Mix.env()
|
||||
|
||||
# For a full list of config options for both releases
|
||||
# and environments, visit https://hexdocs.pm/distillery/configuration.html
|
||||
|
||||
|
||||
# You may define one or more environments in this file,
|
||||
# an environment's settings will override those of a release
|
||||
# when building in that environment, this combination of release
|
||||
# and environment configuration is called a profile
|
||||
|
||||
environment :dev do
|
||||
# If you are running Phoenix, you should make sure that
|
||||
# server: true is set and the code reloader is disabled,
|
||||
# even in dev mode.
|
||||
# It is recommended that you build with MIX_ENV=prod and pass
|
||||
# the --env flag to Distillery explicitly if you want to use
|
||||
# dev mode.
|
||||
set dev_mode: true
|
||||
set include_erts: false
|
||||
set cookie: :"fn5>S.FMYz7!Ri/U.Svz5hXw,kKO=S,2kvDr;~8I!ufa<SB`awK,KX)iC&mv~`At"
|
||||
end
|
||||
|
||||
environment :prod do
|
||||
set include_erts: true
|
||||
set include_src: false
|
||||
set cookie: :"1>bm2160O|df!iH=}h2j6tAG4X8L(v/}S<8oS>!UZ!oI0@`si;=lmA1Wf=Ns=^?d"
|
||||
end
|
||||
|
||||
# You may define one or more releases in this file.
|
||||
# If you have not set a default release, or selected one
|
||||
# when running `mix release`, the first release in the file
|
||||
# will be used by default
|
||||
|
||||
release :elstat do
|
||||
set version: current_version(:elstat)
|
||||
set applications: [
|
||||
:runtime_tools
|
||||
]
|
||||
end
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Access-Control-Allow-Origin" content="*">
|
||||
<style>
|
||||
body { background-color: #ddd; }
|
||||
p {
|
||||
text-align: center;
|
||||
font-family: sans-serif;
|
||||
font-size: 13pt;
|
||||
}
|
||||
#pretty-box {
|
||||
padding-left: 5px;
|
||||
max-width: 500px;
|
||||
max-height: 250px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
margin: auto;
|
||||
background-color: #eee;
|
||||
border-radius: 15px;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
// https://stackoverflow.com/a/4033310
|
||||
function httpGetAsync(theUrl, callback)
|
||||
{
|
||||
var xmlHttp = new XMLHttpRequest();
|
||||
xmlHttp.onreadystatechange = function() {
|
||||
if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
|
||||
callback(xmlHttp.responseText);
|
||||
}
|
||||
xmlHttp.open("GET", theUrl, true); // true for asynchronous
|
||||
xmlHttp.send(null);
|
||||
}
|
||||
|
||||
function genText(data) {
|
||||
base = `${data.description}`;
|
||||
base += ` [${data.status ? "online" : "offline"}]`;
|
||||
|
||||
if('latency' in data) {
|
||||
base += ` - latency: ${data.latency} ms`;
|
||||
}
|
||||
|
||||
return base;
|
||||
}
|
||||
|
||||
function curStatHandler(text) {
|
||||
let box = document.getElementById('pretty-box');
|
||||
let payload = JSON.parse(text);
|
||||
|
||||
for(const service in payload) {
|
||||
let data = payload[service];
|
||||
|
||||
let elementId = `${service}-description`;
|
||||
let existingElement = document.getElementById(elementId);
|
||||
|
||||
if (existingElement === null) {
|
||||
let element = document.createElement('p');
|
||||
|
||||
element.id = elementId;
|
||||
element.innerText = genText(data);
|
||||
box.appendChild(element);
|
||||
} else {
|
||||
existingElement.innerText = genText(data);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function fetchStatus () {
|
||||
httpGetAsync("http://127.0.0.1:8069/api/current_status", curStatHandler);
|
||||
}
|
||||
|
||||
window.onload = function () {
|
||||
fetchStatus();
|
||||
setInterval(() => {
|
||||
fetchStatus();
|
||||
}, 3000)
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="pretty-box">
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1,8 +0,0 @@
|
|||
defmodule ElstatTest do
|
||||
use ExUnit.Case
|
||||
doctest Elstat
|
||||
|
||||
test "greets the world" do
|
||||
assert Elstat.hello() == :world
|
||||
end
|
||||
end
|
|
@ -1 +0,0 @@
|
|||
ExUnit.start()
|
Loading…
Reference in a new issue