├── erlmon-1.0
├── build
│ └── .gitignore
├── lib
│ └── .gitignore
├── .gitignore
├── c_src
│ ├── .gitignore
│ ├── erlua.h
│ ├── erlua.c
│ ├── commands.h
│ └── commands.c
├── include
│ ├── lua.hrl
│ ├── config.hrl
│ ├── debug.hrl
│ ├── erlmon.hrl
│ └── lua_api.hrl
├── sys.config
├── wwwroot
│ ├── nitrogen
│ │ ├── nitrogen.css
│ │ ├── gray_bl.png
│ │ ├── gray_br.png
│ │ ├── gray_tl.png
│ │ ├── gray_tr.png
│ │ ├── spinner.gif
│ │ ├── black_bl.png
│ │ ├── black_br.png
│ │ ├── black_tl.png
│ │ ├── black_tr.png
│ │ ├── checkmark.png
│ │ ├── flash_bg.png
│ │ ├── spinner2.gif
│ │ ├── white_bl.png
│ │ ├── white_br.png
│ │ ├── white_tl.png
│ │ ├── white_tr.png
│ │ ├── jquery-ui
│ │ │ └── images
│ │ │ │ ├── ui-icons_222222_256x240.png
│ │ │ │ ├── ui-icons_2e83ff_256x240.png
│ │ │ │ ├── ui-icons_454545_256x240.png
│ │ │ │ ├── ui-icons_888888_256x240.png
│ │ │ │ ├── ui-icons_cd0a0a_256x240.png
│ │ │ │ ├── ui-bg_flat_0_aaaaaa_40x100.png
│ │ │ │ ├── ui-bg_flat_75_ffffff_40x100.png
│ │ │ │ ├── ui-bg_glass_55_fbf9ee_1x400.png
│ │ │ │ ├── ui-bg_glass_65_ffffff_1x400.png
│ │ │ │ ├── ui-bg_glass_75_dadada_1x400.png
│ │ │ │ ├── ui-bg_glass_75_e6e6e6_1x400.png
│ │ │ │ ├── ui-bg_glass_95_fef1ec_1x400.png
│ │ │ │ └── ui-bg_highlight-soft_75_cccccc_1x100.png
│ │ ├── reset.css
│ │ ├── facebox.css
│ │ ├── basic.css
│ │ ├── elements.css
│ │ ├── web_app_theme.css
│ │ ├── facebox.js
│ │ ├── livevalidation.js
│ │ └── style.css
│ └── template.html
├── lua
│ ├── authentication.lua
│ ├── monitors
│ │ ├── loopback.lua
│ │ ├── port.lua
│ │ ├── file.lua
│ │ ├── process.lua
│ │ └── monitors.lua
│ ├── smtp.lua
│ ├── tests.lua
│ ├── erlmon.lua
│ ├── lunit
│ └── lunit-console.lua
├── src
│ ├── debug_console.erl
│ ├── erlmon_helper.erl
│ ├── debug_file.erl
│ ├── pages
│ │ ├── erlmon_index.erl
│ │ ├── helper.erl
│ │ ├── login.erl
│ │ ├── web_index.erl
│ │ ├── web_config.erl
│ │ └── web_node.erl
│ ├── state_mon_sup.erl
│ ├── config_sup.erl
│ ├── erlmon_smtp_sup.erl
│ ├── disk_monitor_sup.erl
│ ├── process_list_sup.erl
│ ├── node_down_handler.erl
│ ├── node_sup.erl
│ ├── lua_driver.erl
│ ├── storage_sup.erl
│ ├── config_file_change_handler.erl
│ ├── state_change_handler.erl
│ ├── timestamp.erl
│ ├── file_monitor_sup.erl
│ ├── state_change_em.erl
│ ├── process_monitor_sup.erl
│ ├── tcp_port_monitor_sup.erl
│ ├── erlmon_sup.erl
│ ├── erlmon_smtp_message.erl
│ ├── email_msg.erl
│ ├── monitor_sup.erl
│ ├── state_change_sup.erl
│ ├── erlmon.erl
│ ├── df.erl
│ ├── file_monitor_man.erl
│ ├── erlwww_app.erl
│ ├── debug.erl
│ ├── process_monitor_man.erl
│ ├── tcp_port_monitor_man.erl
│ ├── disk_monitor.erl
│ ├── tcp_port_monitor.erl
│ ├── ps.erl
│ ├── alert_handler.erl
│ ├── process_list.erl
│ ├── storage.erl
│ ├── state_change.erl
│ ├── process_monitor.erl
│ ├── config.erl
│ ├── erlmon_smtp.erl
│ ├── node.erl
│ ├── file_monitor.erl
│ └── lua.erl
├── erlmon
├── ebin
│ ├── erlmon.app
│ └── erlwww.app
├── Emakefile
├── Makefile
├── config.lua
├── Rakefile
├── Makefile.Linux
├── Makefile.Darwin
├── config.example.lua
└── tests
│ └── lua_test.erl
├── .gitignore
├── LICENSE
└── README
/erlmon-1.0/build/.gitignore:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/erlmon-1.0/lib/.gitignore:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/erlmon-1.0/.gitignore:
--------------------------------------------------------------------------------
1 | build/*
2 |
--------------------------------------------------------------------------------
/erlmon-1.0/c_src/.gitignore:
--------------------------------------------------------------------------------
1 | *.o
2 |
--------------------------------------------------------------------------------
/erlmon-1.0/include/lua.hrl:
--------------------------------------------------------------------------------
1 | -record(lua, {port}).
2 |
3 | -define(STD_TIMEOUT, 100).
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.beam
2 | *.log
3 | */src/test.erl
4 | *.dump
5 | */Mnesia*
6 | *.sw?
7 | *.so
8 |
--------------------------------------------------------------------------------
/erlmon-1.0/include/config.hrl:
--------------------------------------------------------------------------------
1 | %% config state
2 | -record(config_state,{status={},lua_state=none}).
3 |
--------------------------------------------------------------------------------
/erlmon-1.0/sys.config:
--------------------------------------------------------------------------------
1 | [{kernel, [{inet_dist_listen_min, 9500}, {inet_dist_listen_max, 9505}]}].
2 |
--------------------------------------------------------------------------------
/erlmon-1.0/wwwroot/nitrogen/nitrogen.css:
--------------------------------------------------------------------------------
1 | @import url(reset.css);
2 | @import url(basic.css);
3 | @import url(elements.css);
--------------------------------------------------------------------------------
/erlmon-1.0/wwwroot/nitrogen/gray_bl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrikmazey/erlmon/HEAD/erlmon-1.0/wwwroot/nitrogen/gray_bl.png
--------------------------------------------------------------------------------
/erlmon-1.0/wwwroot/nitrogen/gray_br.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrikmazey/erlmon/HEAD/erlmon-1.0/wwwroot/nitrogen/gray_br.png
--------------------------------------------------------------------------------
/erlmon-1.0/wwwroot/nitrogen/gray_tl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrikmazey/erlmon/HEAD/erlmon-1.0/wwwroot/nitrogen/gray_tl.png
--------------------------------------------------------------------------------
/erlmon-1.0/wwwroot/nitrogen/gray_tr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrikmazey/erlmon/HEAD/erlmon-1.0/wwwroot/nitrogen/gray_tr.png
--------------------------------------------------------------------------------
/erlmon-1.0/wwwroot/nitrogen/spinner.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrikmazey/erlmon/HEAD/erlmon-1.0/wwwroot/nitrogen/spinner.gif
--------------------------------------------------------------------------------
/erlmon-1.0/wwwroot/nitrogen/black_bl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrikmazey/erlmon/HEAD/erlmon-1.0/wwwroot/nitrogen/black_bl.png
--------------------------------------------------------------------------------
/erlmon-1.0/wwwroot/nitrogen/black_br.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrikmazey/erlmon/HEAD/erlmon-1.0/wwwroot/nitrogen/black_br.png
--------------------------------------------------------------------------------
/erlmon-1.0/wwwroot/nitrogen/black_tl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrikmazey/erlmon/HEAD/erlmon-1.0/wwwroot/nitrogen/black_tl.png
--------------------------------------------------------------------------------
/erlmon-1.0/wwwroot/nitrogen/black_tr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrikmazey/erlmon/HEAD/erlmon-1.0/wwwroot/nitrogen/black_tr.png
--------------------------------------------------------------------------------
/erlmon-1.0/wwwroot/nitrogen/checkmark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrikmazey/erlmon/HEAD/erlmon-1.0/wwwroot/nitrogen/checkmark.png
--------------------------------------------------------------------------------
/erlmon-1.0/wwwroot/nitrogen/flash_bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrikmazey/erlmon/HEAD/erlmon-1.0/wwwroot/nitrogen/flash_bg.png
--------------------------------------------------------------------------------
/erlmon-1.0/wwwroot/nitrogen/spinner2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrikmazey/erlmon/HEAD/erlmon-1.0/wwwroot/nitrogen/spinner2.gif
--------------------------------------------------------------------------------
/erlmon-1.0/wwwroot/nitrogen/white_bl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrikmazey/erlmon/HEAD/erlmon-1.0/wwwroot/nitrogen/white_bl.png
--------------------------------------------------------------------------------
/erlmon-1.0/wwwroot/nitrogen/white_br.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrikmazey/erlmon/HEAD/erlmon-1.0/wwwroot/nitrogen/white_br.png
--------------------------------------------------------------------------------
/erlmon-1.0/wwwroot/nitrogen/white_tl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrikmazey/erlmon/HEAD/erlmon-1.0/wwwroot/nitrogen/white_tl.png
--------------------------------------------------------------------------------
/erlmon-1.0/wwwroot/nitrogen/white_tr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrikmazey/erlmon/HEAD/erlmon-1.0/wwwroot/nitrogen/white_tr.png
--------------------------------------------------------------------------------
/erlmon-1.0/lua/authentication.lua:
--------------------------------------------------------------------------------
1 |
2 | function authenticate(login,password)
3 | return Erlmon.http.login == login and Erlmon.http.password == password
4 | end
5 |
--------------------------------------------------------------------------------
/erlmon-1.0/wwwroot/nitrogen/jquery-ui/images/ui-icons_222222_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrikmazey/erlmon/HEAD/erlmon-1.0/wwwroot/nitrogen/jquery-ui/images/ui-icons_222222_256x240.png
--------------------------------------------------------------------------------
/erlmon-1.0/wwwroot/nitrogen/jquery-ui/images/ui-icons_2e83ff_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrikmazey/erlmon/HEAD/erlmon-1.0/wwwroot/nitrogen/jquery-ui/images/ui-icons_2e83ff_256x240.png
--------------------------------------------------------------------------------
/erlmon-1.0/wwwroot/nitrogen/jquery-ui/images/ui-icons_454545_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrikmazey/erlmon/HEAD/erlmon-1.0/wwwroot/nitrogen/jquery-ui/images/ui-icons_454545_256x240.png
--------------------------------------------------------------------------------
/erlmon-1.0/wwwroot/nitrogen/jquery-ui/images/ui-icons_888888_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrikmazey/erlmon/HEAD/erlmon-1.0/wwwroot/nitrogen/jquery-ui/images/ui-icons_888888_256x240.png
--------------------------------------------------------------------------------
/erlmon-1.0/wwwroot/nitrogen/jquery-ui/images/ui-icons_cd0a0a_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrikmazey/erlmon/HEAD/erlmon-1.0/wwwroot/nitrogen/jquery-ui/images/ui-icons_cd0a0a_256x240.png
--------------------------------------------------------------------------------
/erlmon-1.0/wwwroot/nitrogen/jquery-ui/images/ui-bg_flat_0_aaaaaa_40x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrikmazey/erlmon/HEAD/erlmon-1.0/wwwroot/nitrogen/jquery-ui/images/ui-bg_flat_0_aaaaaa_40x100.png
--------------------------------------------------------------------------------
/erlmon-1.0/wwwroot/nitrogen/jquery-ui/images/ui-bg_flat_75_ffffff_40x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrikmazey/erlmon/HEAD/erlmon-1.0/wwwroot/nitrogen/jquery-ui/images/ui-bg_flat_75_ffffff_40x100.png
--------------------------------------------------------------------------------
/erlmon-1.0/wwwroot/nitrogen/jquery-ui/images/ui-bg_glass_55_fbf9ee_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrikmazey/erlmon/HEAD/erlmon-1.0/wwwroot/nitrogen/jquery-ui/images/ui-bg_glass_55_fbf9ee_1x400.png
--------------------------------------------------------------------------------
/erlmon-1.0/wwwroot/nitrogen/jquery-ui/images/ui-bg_glass_65_ffffff_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrikmazey/erlmon/HEAD/erlmon-1.0/wwwroot/nitrogen/jquery-ui/images/ui-bg_glass_65_ffffff_1x400.png
--------------------------------------------------------------------------------
/erlmon-1.0/wwwroot/nitrogen/jquery-ui/images/ui-bg_glass_75_dadada_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrikmazey/erlmon/HEAD/erlmon-1.0/wwwroot/nitrogen/jquery-ui/images/ui-bg_glass_75_dadada_1x400.png
--------------------------------------------------------------------------------
/erlmon-1.0/wwwroot/nitrogen/jquery-ui/images/ui-bg_glass_75_e6e6e6_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrikmazey/erlmon/HEAD/erlmon-1.0/wwwroot/nitrogen/jquery-ui/images/ui-bg_glass_75_e6e6e6_1x400.png
--------------------------------------------------------------------------------
/erlmon-1.0/wwwroot/nitrogen/jquery-ui/images/ui-bg_glass_95_fef1ec_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrikmazey/erlmon/HEAD/erlmon-1.0/wwwroot/nitrogen/jquery-ui/images/ui-bg_glass_95_fef1ec_1x400.png
--------------------------------------------------------------------------------
/erlmon-1.0/src/debug_console.erl:
--------------------------------------------------------------------------------
1 |
2 | -module(debug_console).
3 | -author(darrik@darmasoft.com).
4 |
5 | -export([log/3]).
6 |
7 | log(Format, Args, _Options) ->
8 | io:format(Format ++ "~n", Args).
9 |
10 |
--------------------------------------------------------------------------------
/erlmon-1.0/wwwroot/nitrogen/jquery-ui/images/ui-bg_highlight-soft_75_cccccc_1x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrikmazey/erlmon/HEAD/erlmon-1.0/wwwroot/nitrogen/jquery-ui/images/ui-bg_highlight-soft_75_cccccc_1x100.png
--------------------------------------------------------------------------------
/erlmon-1.0/erlmon:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | if [ -z $1 ]; then
3 | erl -pa ebin/ -config sys -name erlmon -eval "application:start(erlmon)."
4 | else
5 | erl -pa ebin/ -s erlmon -config sys -name $1 -eval "application:start(erlmon)."
6 | fi
7 |
--------------------------------------------------------------------------------
/erlmon-1.0/ebin/erlmon.app:
--------------------------------------------------------------------------------
1 | {application, erlmon,
2 | [{description, "erlang monitoring system"},
3 | {vsn, "1.0"},
4 | {modules, [erlmon]},
5 | {registered, []},
6 | {applications, [kernel, stdlib]},
7 | {env, []},
8 | {mod, {erlmon, []}}]}.
9 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/erlmon_helper.erl:
--------------------------------------------------------------------------------
1 |
2 | -module(erlmon_helper).
3 | -author(darrik@darmasoft.com).
4 |
5 | -export([
6 | list_to_number/1
7 | ]).
8 |
9 | list_to_number(L) ->
10 | try list_to_float(L) of
11 | N -> N
12 | catch
13 | _:_ -> list_to_integer(L)
14 | end.
15 |
--------------------------------------------------------------------------------
/erlmon-1.0/include/debug.hrl:
--------------------------------------------------------------------------------
1 |
2 | % log message
3 | -record(debug_log_msg, { sender, format, args = [] }).
4 |
5 | % add logmethod
6 | -record(debug_log_add_method, { sender, module, options }).
7 |
8 | % remove logmethod
9 | -record(debug_log_rem_method, { sender, module, options }).
10 |
11 |
--------------------------------------------------------------------------------
/erlmon-1.0/ebin/erlwww.app:
--------------------------------------------------------------------------------
1 | {application, erlwww, [
2 | {description, "Nitrogen Website"},
3 | {mod, {erlwww_app, []}},
4 | {env, [
5 | {platform, mochiweb}, %% {inets|yaws|mochiweb}
6 | %%{port, 8000},
7 | {session_timeout, 20},
8 | {sign_key, "SIGN_KEY"},
9 | {www_root, "./wwwroot"}
10 | ]}
11 | ]}.
12 |
--------------------------------------------------------------------------------
/erlmon-1.0/Emakefile:
--------------------------------------------------------------------------------
1 | { './src/*', [
2 | { i, "./include" },
3 | { outdir, "./ebin" },
4 | debug_info
5 | ]}.
6 |
7 | { './src/*/*', [
8 | { i, "./include" },
9 | { outdir, "./ebin" },
10 | debug_info
11 | ]}.
12 |
13 | { './src/*/*/*', [
14 | { i, "./include" },
15 | { outdir, "./ebin" },
16 | debug_info
17 | ]}.
18 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/debug_file.erl:
--------------------------------------------------------------------------------
1 |
2 | -module(debug_file).
3 | -author(darrik@darmasoft.com).
4 |
5 | -export([log/3]).
6 |
7 | log(Format, Args, Options) ->
8 | {filename, Filename} = Options,
9 | {ok, WD} = file:open(Filename, [append]),
10 | io:format(WD, Format ++ "~n", Args),
11 | file:close(WD),
12 | true.
13 |
14 |
15 |
--------------------------------------------------------------------------------
/erlmon-1.0/Makefile:
--------------------------------------------------------------------------------
1 |
2 | OS = $(shell uname)
3 |
4 | .PHONY: all clean test
5 |
6 | all:
7 | $(MAKE) -f Makefile.$(OS)
8 |
9 | clean:
10 | $(MAKE) -f Makefile.$(OS) clean
11 |
12 | test:
13 | $(MAKE) -f Makefile.$(OS) test
14 |
15 | runtests:
16 | erlc tests/* && erl -pa ebin -s lua_test test -noshell -s init stop
17 |
18 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/pages/erlmon_index.erl:
--------------------------------------------------------------------------------
1 | -module (erlmon_index).
2 | -include_lib ("nitrogen/include/wf.inc").
3 | -compile(export_all).
4 |
5 | main() ->
6 | #template { file="./wwwroot/template.html"}.
7 |
8 | title() ->
9 | "erlmon index".
10 |
11 | body() ->
12 | #label{text="web_index body."}.
13 |
14 | event(_) -> ok.
15 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/pages/helper.erl:
--------------------------------------------------------------------------------
1 | -module (helper).
2 | -include_lib ("nitrogen/include/wf.inc").
3 | -compile(export_all).
4 |
5 | menu(MenuItems) ->
6 | Items = lists:map(fun({_Name,Text,Url}) ->
7 | ["
",wf:f("~s",[Url,Text]),"",Items,""].
9 |
10 | flash_msg(Error) -> wf:flash( #label { text= Error } ).
11 |
--------------------------------------------------------------------------------
/erlmon-1.0/lua/monitors/loopback.lua:
--------------------------------------------------------------------------------
1 |
2 | -- "loopback" Monitor
3 | -- monitor for unit tests
4 | -- if they are functions they will be called as necessary.
5 | -- by default, restart simply calls stop, then start
6 | function monitor_loopback(name,cmd)
7 |
8 | Erlmon.monitors.add("loopback",name,cmd)
9 |
10 | end
11 |
12 | function unmonitor_loopback(name)
13 | Erlmon.monitors.remove("loopback",name)
14 | end
15 |
16 |
--------------------------------------------------------------------------------
/erlmon-1.0/lua/smtp.lua:
--------------------------------------------------------------------------------
1 |
2 | function _add_smtp(host)
3 | local smtp = {}
4 | host.smtp = smtp
5 | smtp.auth = {}
6 |
7 | smtp.address = ""
8 | smtp.host = "localhost"
9 | smtp.port = 25
10 | smtp.auth.type = 'none'
11 | smtp.auth.username = ''
12 | smtp.auth.password = ''
13 |
14 | end
15 |
16 | -- convenience function if you just want to set a
17 | -- global alert address.
18 | function alert(address)
19 | Erlmon.smtp.address = address
20 | end
21 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/state_mon_sup.erl:
--------------------------------------------------------------------------------
1 |
2 | -module(state_mon_sup).
3 | -author(darrik@darmasoft.com).
4 |
5 | -behaviour(supervisor).
6 |
7 | -export([start_link/0]).
8 | -export([init/1]).
9 |
10 | start_link() ->
11 | supervisor:start_link({local, ?MODULE}, ?MODULE, []).
12 |
13 | init(_) ->
14 | debug:log("state_mon_sup: starting state_mon"),
15 | Child = {state_mon, {state_mon, start, []}, permanent, 2000, worker, [state_mon]},
16 | {ok, {{one_for_one, 1, 1}, [Child]}}.
17 |
--------------------------------------------------------------------------------
/erlmon-1.0/config.lua:
--------------------------------------------------------------------------------
1 | -- this require isn't specifically required as it will be added
2 | -- when executed inside of erlmon, but they are necessary to
3 | -- test the file on the command line, by typing lua config.lua
4 | require "lua/erlmon"
5 |
6 | -- Global Erlmon Settings
7 | Erlmon.http.login = 'admin'
8 | Erlmon.http.password = 'admin'
9 |
10 | Erlmon.smtp.host = "mail.foo.com"
11 |
12 | -- Global SMTP Settings
13 | alert("chad@foo.com")
14 |
15 | -- Monitors
16 | monitor_port(11211)
17 |
18 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/config_sup.erl:
--------------------------------------------------------------------------------
1 |
2 | -module(config_sup).
3 | -author(darrik@darmasoft.com).
4 |
5 | -behaviour(supervisor).
6 |
7 | -export([start_link/0]).
8 | -export([init/1]).
9 |
10 | start_link() ->
11 | R = supervisor:start_link({local, ?MODULE}, ?MODULE, []),
12 | erlmon:finished(?MODULE),
13 | R.
14 |
15 | init(_) ->
16 | debug:log("config_sup: starting config"),
17 | Child = {config, {config, start_link, []}, permanent, 2000, worker, [config]},
18 | {ok, {{one_for_one, 1, 1}, [Child]}}.
19 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/erlmon_smtp_sup.erl:
--------------------------------------------------------------------------------
1 |
2 | -module(erlmon_smtp_sup).
3 | -author(darrik@darmasoft.com).
4 |
5 | -behaviour(supervisor).
6 |
7 | -export([start_link/0]).
8 | -export([init/1]).
9 |
10 | start_link() ->
11 | R = supervisor:start_link({local, ?MODULE}, ?MODULE, []),
12 | erlmon:finished(?MODULE),
13 | R.
14 |
15 | init(_) ->
16 | debug:log("erlmon_smtp_sup: starting"),
17 | GChild = {erlmon_smtp, {erlmon_smtp, start_link, []}, permanent, 2000, worker, [erlmon_smtp]},
18 | {ok, {{one_for_one, 1, 1}, [GChild]}}.
19 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/disk_monitor_sup.erl:
--------------------------------------------------------------------------------
1 |
2 | -module(disk_monitor_sup).
3 | -author(darrik@darmasoft.com).
4 |
5 | -behaviour(supervisor).
6 |
7 | -export([start_link/0]).
8 | -export([init/1]).
9 |
10 | start_link() ->
11 | R = supervisor:start_link({local, ?MODULE}, ?MODULE, []),
12 | erlmon:finished(?MODULE),
13 | R.
14 |
15 | init(_) ->
16 | debug:log("disk_monitor_sup: starting"),
17 | DMSChild = {disk_monitor, {disk_monitor, start, []}, temporary, brutal_kill, worker, [disk_monitor]},
18 | {ok, {{simple_one_for_one, 0, 1}, [DMSChild]}}.
19 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/process_list_sup.erl:
--------------------------------------------------------------------------------
1 |
2 | -module(process_list_sup).
3 | -author(darrik@darmasoft.com).
4 |
5 | -behaviour(supervisor).
6 |
7 | -export([start_link/0]).
8 | -export([init/1]).
9 |
10 | start_link() ->
11 | R = supervisor:start_link({local, ?MODULE}, ?MODULE, []),
12 | erlmon:finished(?MODULE),
13 | R.
14 |
15 | init(_) ->
16 | debug:log("process_list_sup: starting process_list"),
17 | Child = {process_list, {process_list, start_link, []}, permanent, 2000, worker, [process_list]},
18 | {ok, {{one_for_one, 1, 1}, [Child]}}.
19 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/node_down_handler.erl:
--------------------------------------------------------------------------------
1 |
2 | -module(node_down_handler).
3 | -author(darrik@darmasoft.com).
4 |
5 | -behaviour(gen_event).
6 |
7 | -include("include/erlmon.hrl").
8 |
9 | -export([init/1]).
10 | -export([handle_event/2]).
11 | -export([terminate/2]).
12 |
13 | init(_) ->
14 | {ok, []}.
15 |
16 | handle_event(#state_change{objtype=node, new_state=down}=Event, State) ->
17 | debug:log("node_down_handler: ~p", [Event]),
18 | {ok, State};
19 | handle_event(_Event, State) ->
20 | {ok, State}.
21 |
22 | terminate(_Args, _State) ->
23 | ok.
24 |
--------------------------------------------------------------------------------
/erlmon-1.0/lua/monitors/port.lua:
--------------------------------------------------------------------------------
1 | -- Port Monitoring
2 | function _add_monitor_port_function(host_monitors)
3 | host_monitors.monitor_port = function(hostorport,port,options)
4 | if port == nil then
5 | port = hostorport
6 | hostorport = 'localhost'
7 | end
8 | if options == nil then
9 | options = {}
10 | end
11 |
12 | options.host = hostorport
13 | options.port = port
14 |
15 | -- 'tcp_port' becuase must match erlang monitor name
16 | return host_monitors.add("tcp_port",nil,options)
17 | end
18 | end
19 |
20 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/node_sup.erl:
--------------------------------------------------------------------------------
1 |
2 | -module(node_sup).
3 | -author(darrik@darmasoft.com).
4 |
5 | -behaviour(supervisor).
6 |
7 | -export([start_link/0]).
8 | -export([init/1]).
9 |
10 | start_link() ->
11 | R = supervisor:start_link({local, ?MODULE}, ?MODULE, []),
12 | wait_for_node(),
13 | erlmon:finished(?MODULE),
14 | R.
15 |
16 | init(_) ->
17 | debug:log("node_sup: starting node"),
18 | Child = {node, {node, start, []}, permanent, 2000, worker, [node]},
19 | {ok, {{one_for_one, 1, 1}, [Child]}}.
20 |
21 | wait_for_node() ->
22 | node:status().
23 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/lua_driver.erl:
--------------------------------------------------------------------------------
1 | -module(lua_driver).
2 |
3 | -export([open/0, close/1]).
4 |
5 | -include("lua.hrl").
6 |
7 | open() ->
8 | {ok, L} = load_driver(),
9 | #lua{port=L}.
10 |
11 | close(#lua{port=Port}) ->
12 | port_close(Port).
13 |
14 |
15 | %% Private functions
16 | load_driver() ->
17 | SearchDir = filename:join([filename:dirname(code:which(lua_driver)), "..", "lib"]),
18 | case erl_ddll:load(SearchDir, liberlua) of
19 | ok ->
20 | {ok, open_port({spawn, 'liberlua'}, [binary])};
21 | Error ->
22 | Error
23 | end.
24 |
--------------------------------------------------------------------------------
/erlmon-1.0/lua/monitors/file.lua:
--------------------------------------------------------------------------------
1 | -- File Monitor
2 | -- To write a monitor, you must implement the monitor_X method,
3 | -- where X is the name of the monitor.
4 |
5 | function monitor_file(name,startcmd,stopcmd,restartcmd)
6 |
7 | -- we need a table with the commands, so build from parameters
8 | -- if needed
9 | if not (type(startcmd) == "table") then
10 | startcmd = { start = startcmd,
11 | stop = stopcmd,
12 | restart = restartcmd }
13 | end
14 |
15 | Erlmon.monitors.add("file",name,startcmd)
16 |
17 | end
18 |
19 |
20 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/storage_sup.erl:
--------------------------------------------------------------------------------
1 |
2 | -module(storage_sup).
3 | -author(darrik@darmasoft.com).
4 |
5 | -behaviour(supervisor).
6 |
7 | -export([start_link/0]).
8 | -export([init/1]).
9 |
10 | start_link() ->
11 | R = supervisor:start_link({local, ?MODULE}, ?MODULE, []),
12 | wait_for_storage(),
13 | erlmon:finished(?MODULE),
14 | R.
15 |
16 | init(_) ->
17 | debug:log("storage_sup: starting storage"),
18 | Child = {storage, {storage, start, []}, permanent, 2000, worker, [storage]},
19 | {ok, {{one_for_one, 1, 1}, [Child]}}.
20 |
21 | wait_for_storage() ->
22 | storage:status().
23 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/config_file_change_handler.erl:
--------------------------------------------------------------------------------
1 |
2 | -module(config_file_change_handler).
3 | -author(darrik@darmasoft.com).
4 |
5 | -behaviour(gen_event).
6 |
7 | -include("include/erlmon.hrl").
8 |
9 | -export([init/1]).
10 | -export([handle_event/2]).
11 | -export([terminate/2]).
12 |
13 | init(_) ->
14 | {ok, []}.
15 |
16 | handle_event(#state_change{objtype=file, obj="config.lua", new_state=file_ctime_changed}=Event, State) ->
17 | debug:log("CONFIG FILE CHANGED: ~p", [Event]),
18 | config:reload(),
19 | {ok, State};
20 | handle_event(_Event, State) ->
21 | {ok, State}.
22 |
23 | terminate(_Args, _State) ->
24 | ok.
25 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/state_change_handler.erl:
--------------------------------------------------------------------------------
1 |
2 | -module(state_change_handler).
3 | -author(darrik@darmasoft.com).
4 |
5 | -behaviour(gen_event).
6 |
7 | -include("include/erlmon.hrl").
8 |
9 | -export([init/1]).
10 | -export([handle_event/2]).
11 | -export([terminate/2]).
12 |
13 | init(_) ->
14 | {ok, []}.
15 |
16 | handle_event(#state_change{}=Event, State) ->
17 | debug:log("state_change_handler:state_change: ~p", [Event]),
18 | storage:state_change(Event),
19 | {ok, State};
20 | handle_event(Event, State) ->
21 | debug:log("state_change_handler:UNKNOWN_EVENT: ~p", [Event]),
22 | {ok, State}.
23 |
24 | terminate(_Args, _State) ->
25 | ok.
26 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/timestamp.erl:
--------------------------------------------------------------------------------
1 |
2 | -module(timestamp).
3 | -author(darrik@darmasoft.com).
4 |
5 | -export([now/0]).
6 | -export([now_i/0]).
7 |
8 | now() ->
9 | {Date, Time} = calendar:local_time(),
10 | {Y, M, D} = Date,
11 | {Hours, Mins, Secs} = Time,
12 | lists:flatten(io_lib:format("~4.4.0s~s~2.1.0s~s~2.1.0s~s~2.1.0s~s~2.1.0s~s~2.1.0s",
13 | [ integer_to_list(Y),
14 | ".",
15 | integer_to_list(M),
16 | ".",
17 | integer_to_list(D),
18 | " ",
19 | integer_to_list(Hours),
20 | ":",
21 | integer_to_list(Mins),
22 | ":",
23 | integer_to_list(Secs) ])).
24 |
25 | now_i() ->
26 | {_, T, _} = erlang:now(),
27 | T.
28 |
--------------------------------------------------------------------------------
/erlmon-1.0/lua/tests.lua:
--------------------------------------------------------------------------------
1 | require "lunit"
2 | require "erlmon"
3 |
4 | module( "erlmon_tests", lunit.testcase, package.seeall)
5 |
6 | -- monitor infrastructure basics
7 | function test_monitors()
8 | assert(not (Erlmon.monitors == nil))
9 | assert(type(Erlmon.monitors.list) == "table")
10 | assert(type(Erlmon.monitors.add) == "function")
11 | assert(type(Erlmon.monitors.remove) == "function")
12 | end
13 |
14 | function test_http_config()
15 | assert(Erlmon.http.enabled)
16 | assert(Erlmon.http.port == 9494)
17 | end
18 |
19 | function test_port_monitor()
20 | monitor_port(22)
21 | monitor_port("localhost",22)
22 | print(Erlmon.monitors.list)
23 | assert(#Erlmon.monitors.list == 2,#Erlmon.monitors.list)
24 | end
25 |
26 |
27 |
--------------------------------------------------------------------------------
/erlmon-1.0/Rakefile:
--------------------------------------------------------------------------------
1 | task :default => [:make_c, :make_erl]
2 |
3 | task :test => [:default, :make_tests] do
4 | sh "erl -pa ebin -noshell -s lua_test test -s init stop"
5 | sh "cd lua && ./lunit tests.lua"
6 | end
7 |
8 | task :clean do
9 | print "Cleaning..."
10 | sh "make clean"
11 | sh "rm priv/*.so"
12 | print " done\n"
13 | end
14 |
15 | task :make_c do
16 | sh "(cd c_src; rake compile)"
17 | end
18 |
19 | task :make_erl do
20 | print "Compiling Erlang sources..."
21 | sh "make"
22 | print "... done\n"
23 | end
24 |
25 | task :make_tests => :default do
26 | print "Compiling Erlang test sources..."
27 | sh "erlc -Iinclude/ -o ebin/ tests/*.erl"
28 | print "... done\n"
29 | end
30 |
31 | task :run do
32 | sh "erl -pa ebin"
33 | end
34 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/file_monitor_sup.erl:
--------------------------------------------------------------------------------
1 |
2 | -module(file_monitor_sup).
3 | -author(darrik@darmasoft.com).
4 |
5 | -behaviour(supervisor).
6 |
7 | -export([start_link/0]).
8 | -export([init/1]).
9 | -export([monitor/1]).
10 | -export([unmonitor/1]).
11 |
12 | monitor(Path) ->
13 | supervisor:start_child(file_monitor_sup, [Path]).
14 |
15 | unmonitor(Path) ->
16 | supervisor:terminate_child(file_monitor_sup, [Path]).
17 |
18 | start_link() ->
19 | R = supervisor:start_link({local, ?MODULE}, ?MODULE, []),
20 | erlmon:finished(?MODULE),
21 | R.
22 |
23 | init(_) ->
24 | debug:log("file_monitor_sup: starting"),
25 | FMSChild = {file_monitor, {file_monitor, start, []}, temporary, brutal_kill, worker, [file_monitor]},
26 | {ok, {{simple_one_for_one, 0, 1}, [FMSChild]}}.
27 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/state_change_em.erl:
--------------------------------------------------------------------------------
1 |
2 | -module(state_change_em).
3 | -author(darrik@darmasoft.com).
4 |
5 | -export([start_link/0]).
6 | -export([add_handler/1]).
7 | -export([add_handler/2]).
8 | -export([notify/1]).
9 | -export([stop/0]).
10 |
11 | -define(SERVER, ?MODULE).
12 |
13 | start_link() ->
14 | debug:log("state_change_em: starting"),
15 | R = gen_event:start_link({local, ?SERVER}),
16 | erlmon:finished(?MODULE),
17 | R.
18 |
19 | add_handler(Module) ->
20 | gen_event:add_handler(?SERVER, Module, []).
21 |
22 | add_handler(Module, State) ->
23 | gen_event:add_handler(?SERVER, Module, State).
24 |
25 | notify(Event) ->
26 | gen_event:notify(?SERVER, Event).
27 |
28 | stop() ->
29 | debug:log("state_change_em: stopping"),
30 | gen_event:stop(?SERVER).
31 |
32 |
--------------------------------------------------------------------------------
/erlmon-1.0/Makefile.Linux:
--------------------------------------------------------------------------------
1 | ERL_LIB=/usr/lib/erlang/lib/erl_interface-3.6.3
2 | CFLAGS=-Wall -I/usr/local/include -I$(ERL_LIB)/include -I/usr/lib/erlang/usr/include
3 | LDFLAGS=-shared -L. -L$(ERL_LIB)/lib
4 | LDLIBS=-llua
5 | STATICLIBS=$(ERL_LIB)/lib/libei.a $(ERL_LIB)/lib/liberl_interface.a
6 | GCC=/usr/bin/gcc
7 | ERL=/usr/bin/erl
8 |
9 | LIB=lib/liberlua.so
10 |
11 | ERLMODS=$(patsubst src/%.erl,ebin/%.beam,$(wildcard src/*.erl))
12 | OBJECTS=$(patsubst c_src/%.c,build/%.o,$(wildcard c_src/*.c))
13 |
14 | all: $(LIB) $(ERLMODS)
15 |
16 | build/%.o: c_src/%.c
17 | $(GCC) $(CFLAGS) -o $@ -c $<
18 |
19 | ebin/%.beam: src/%.erl
20 | $(ERL) -make
21 |
22 | $(LIB): $(OBJECTS)
23 | $(GCC) $(CFLAGS) $(LDFLAGS) $(LDLIBS) -o $(LIB) $(OBJECTS) $(STATICLIBS)
24 |
25 | clean:
26 | rm -f ebin/*.beam
27 | rm -f build/*.o
28 | rm -f lib/liberlua.so
29 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/process_monitor_sup.erl:
--------------------------------------------------------------------------------
1 |
2 | -module(process_monitor_sup).
3 | -author(darrik@darmasoft.com).
4 |
5 | -behaviour(supervisor).
6 |
7 | -export([start_link/0]).
8 | -export([init/1]).
9 | -export([monitor/1]).
10 | -export([unmonitor/1]).
11 |
12 | monitor(ProcessName) ->
13 | debug:log("process_monitor_sup:monitor(~p)", [ProcessName]),
14 | supervisor:start_child(process_monitor_sup, [ProcessName]).
15 |
16 | unmonitor(ProcessName) ->
17 | supervisor:terminate_child(tcp_port_monitor_sup, [ProcessName]).
18 |
19 | start_link() ->
20 | R = supervisor:start_link({local, ?MODULE}, ?MODULE, []),
21 | erlmon:finished(?MODULE),
22 | R.
23 |
24 | init(_) ->
25 | debug:log("process_monitor_sup: starting"),
26 | TPMChild = {process_monitor, {process_monitor, start, []}, temporary, brutal_kill, worker, [process_monitor]},
27 | {ok, {{simple_one_for_one, 0, 1}, [TPMChild]}}.
28 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/tcp_port_monitor_sup.erl:
--------------------------------------------------------------------------------
1 |
2 | -module(tcp_port_monitor_sup).
3 | -author(darrik@darmasoft.com).
4 |
5 | -behaviour(supervisor).
6 |
7 | -export([start_link/0]).
8 | -export([init/1]).
9 | -export([monitor/2]).
10 | -export([unmonitor/2]).
11 |
12 | monitor(Host, Port) ->
13 | debug:log("tcp_port_monitor_sup:monitor(~p, ~p)", [Host, Port]),
14 | supervisor:start_child(tcp_port_monitor_sup, [Host, Port]).
15 |
16 | unmonitor(Host, Port) ->
17 | supervisor:terminate_child(tcp_port_monitor_sup, [Host, Port]).
18 |
19 | start_link() ->
20 | R = supervisor:start_link({local, ?MODULE}, ?MODULE, []),
21 | erlmon:finished(?MODULE),
22 | R.
23 |
24 | init(_) ->
25 | debug:log("tcp_port_monitor_sup: starting"),
26 | TPMChild = {tcp_port_monitor, {tcp_port_monitor, start, []}, temporary, brutal_kill, worker, [tcp_port_monitor]},
27 | {ok, {{simple_one_for_one, 0, 1}, [TPMChild]}}.
28 |
--------------------------------------------------------------------------------
/erlmon-1.0/lua/monitors/process.lua:
--------------------------------------------------------------------------------
1 |
2 | -- Monitors
3 | -- To write a monitor, you must implement the monitor_X method,
4 | -- where X is the name of the monitor.
5 |
6 | -- $TODO should this be a macro?
7 | start = "start"
8 | stop = "stop"
9 | restart = "restart"
10 |
11 | -- Process Monitoring
12 | -- if start/stop/restart are strings, they will be executed as system commands
13 | -- if they are functions they will be called as necessary.
14 | -- by default, restart simply calls stop, then start
15 | function monitor_process(name,startcmd,stopcmd,restartcmd)
16 |
17 | -- we need a table with the commands, so build from parameters
18 | -- if needed
19 | if not (type(startcmd) == "table") then
20 | startcmd = { start = startcmd,
21 | stop = stopcmd,
22 | restart = restartcmd }
23 | end
24 |
25 | Erlmon.monitors.add("process",name,startcmd)
26 |
27 | end
28 |
29 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/pages/login.erl:
--------------------------------------------------------------------------------
1 | -module (login).
2 | -include_lib ("nitrogen/include/wf.inc").
3 | -compile(export_all).
4 |
5 | main() ->
6 | #template { file="./wwwroot/template.html"}.
7 |
8 | title() ->
9 | "erlmon login.".
10 |
11 | body() ->
12 | [#h1{text = "Login to erlmon." },
13 | #label { text="Login:"},
14 | #textbox { id=login, text="", next=password },
15 | #label { text="Password:"},
16 | #password { id=password},
17 | #p{},
18 | #button { text="Login", postback={click, login_button} }
19 | ].
20 |
21 | event(_) ->
22 | [Login] = wf:q(login),
23 | [Password] = wf:q(password),
24 | case config:authenticate(Login,Password) of
25 | true -> wf:user(admin),
26 | wf:redirect_from_login("/");
27 | false -> helper:flash_msg("Invalid login or password.")
28 | end.
29 |
30 |
31 | menu_items() -> helper:menu([{login,"login","/web/login"}]).
32 |
33 |
--------------------------------------------------------------------------------
/erlmon-1.0/Makefile.Darwin:
--------------------------------------------------------------------------------
1 | ERL_LIB=/opt/local/lib/erlang/lib/erl_interface-3.6.4
2 | CFLAGS=-Wall -I/opt/local/include -I$(ERL_LIB)/include -I/opt/local/lib/erlang/usr/include -I /LuaLibrary/src
3 | LDFLAGS=-dynamic -bundle -undefined suppress -flat_namespace -L. -L$(ERL_LIB)/lib
4 | LDLIBS=
5 | STATICLIBS=$(ERL_LIB)/lib/libei.a $(ERL_LIB)/lib/liberl_interface.a /usr/local/lib/liblua.a
6 | GCC=/usr/bin/gcc
7 | ERL=/opt/local/bin/erl
8 |
9 | LIB=lib/liberlua.so
10 |
11 | ERLMODS=$(patsubst src/%.erl,ebin/%.beam,$(wildcard src/*.erl))
12 | OBJECTS=$(patsubst c_src/%.c,build/%.o,$(wildcard c_src/*.c))
13 |
14 | all: $(LIB) $(ERLMODS)
15 |
16 | build/%.o: c_src/%.c
17 | $(GCC) $(CFLAGS) -o $@ -c $<
18 |
19 | ebin/%.beam: src/%.erl
20 | $(ERL) +debug_info -make
21 |
22 | $(LIB): $(OBJECTS)
23 | $(GCC) $(CFLAGS) $(LDFLAGS) $(LDLIBS) -o $(LIB) $(OBJECTS) $(STATICLIBS)
24 |
25 | clean:
26 | rm -f ebin/*.beam
27 | rm -f build/*.o
28 | rm -f lib/liberlua.so
29 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Copyright (c) 2010 DarmaSoft, LLC.
3 |
4 | Permission is hereby granted, free of charge, to any person
5 | obtaining a copy of this software and associated documentation
6 | files (the "Software"), to deal in the Software without
7 | restriction, including without limitation the rights to use,
8 | copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the
10 | Software is furnished to do so, subject to the following
11 | conditions:
12 |
13 | The above copyright notice and this permission notice shall be
14 | included in all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 | OTHER DEALINGS IN THE SOFTWARE.
24 |
25 |
--------------------------------------------------------------------------------
/erlmon-1.0/lua/erlmon.lua:
--------------------------------------------------------------------------------
1 |
2 | -- helper functions for monitors
3 |
4 | -- load monitors
5 | require "lua/monitors/monitors"
6 | require "lua/smtp"
7 |
8 | function _add_host(name)
9 | local host = {}
10 | local mt = {}
11 | mt.__index = function (table, key)
12 | return Erlmon[key]
13 | end
14 | mt.__newindex = function (table, key)
15 | return Erlmon[key]
16 | end
17 | setmetatable(host,mt)
18 | Erlmon.hosts[name] = host
19 | return host
20 | end
21 |
22 | function _erlmon()
23 |
24 | -- HTTP Console defaults
25 | local http = {}
26 | http.enabled=true
27 | http.port = 9494
28 |
29 | -- Monitors
30 | local monitors = {}
31 | _add_monitors(monitors)
32 |
33 |
34 | -- Globals
35 | local erlmon = {}
36 | erlmon.http = http
37 | erlmon.monitors = monitors
38 | erlmon.alert = alert
39 | erlmon.add_host = _add_host
40 | erlmon.hosts = {}
41 |
42 | -- Simple SMTP Alerting
43 | _add_smtp(erlmon)
44 |
45 | return erlmon
46 |
47 | end
48 |
49 | Erlmon = _erlmon()
50 |
51 | _add_convenience_monitor_functions()
52 |
53 | -- redefine the method in your config file if you want
54 | -- to have your own authentication
55 | require "lua/authentication"
56 |
--------------------------------------------------------------------------------
/erlmon-1.0/lua/monitors/monitors.lua:
--------------------------------------------------------------------------------
1 | -- if LuaFileSystem is OK as a dependency, we wouldn't have
2 | -- to specify the modules here
3 | --require "lua/monitors/file"
4 | --require "lua/monitors/process"
5 | --require "lua/monitors/loopback"
6 | require "lua/monitors/port"
7 |
8 | function _add_monitors(host_monitors)
9 |
10 | mlist = {}
11 | host_monitors.list = mlist
12 |
13 | host_monitors.add = function(mtype,name,init)
14 | -- create table if this is the first monitor of this type
15 | if mlist[mtype] == nil then mlist[mtype] = {} end
16 |
17 | -- you don't have to name your monitors
18 | -- but we should probably hash them
19 | if name == nil then
20 | table.insert(mlist[mtype],init)
21 | else
22 | mlist[mtype][name] = init
23 | end
24 |
25 | return init
26 | end
27 |
28 | host_monitors.remove = function(mtype,name)
29 | if mlist[mtype] == nil then mlist[mtype] = {} end
30 | mlist[mtype][name] = nil
31 | end
32 |
33 | _add_monitor_port_function(host_monitors)
34 | end
35 |
36 | -- allows monitor_x instead of Erlmon.monitors
37 | function _add_convenience_monitor_functions()
38 | monitor_port = Erlmon.monitors.monitor_port
39 | end
40 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/erlmon_sup.erl:
--------------------------------------------------------------------------------
1 |
2 | -module(erlmon_sup).
3 | -author(darrik@darmasoft.com).
4 |
5 | -behaviour(supervisor).
6 |
7 | -export([start_link/0]).
8 | -export([init/1]).
9 |
10 | start_link() ->
11 | R = supervisor:start_link({local, ?MODULE}, ?MODULE, []),
12 | erlmon:finished(?MODULE),
13 | R.
14 |
15 | init(_) ->
16 | debug:log("erlmon_sup: starting"),
17 | SMChild = { state_change_sup, {state_change_sup, start_link, []}, permanent, 2000, supervisor, [state_change_sup]},
18 | SChild = { storage_sup, {storage_sup, start_link, []}, permanent, 2000, supervisor, [storage_sup]},
19 | NChild = { node_sup, {node_sup, start_link, []}, permanent, 2000, supervisor, [node_sup]},
20 | PLChild = { process_list_sup, {process_list_sup, start_link, []}, permanent, 2000, supervisor, [process_list_sup]},
21 | MSChild = { monitor_sup, {monitor_sup, start_link, []}, permanent, 2000, supervisor, [monitor_sup]},
22 | CChild = { config_sup, {config_sup, start_link, []}, permanent, 2000, worker, [config_sup]},
23 | SGChild = { erlmon_smtp_sup, {erlmon_smtp_sup, start_link, []}, permanent, 2000, supervisor, [erlmon_smtp_sup]},
24 | {ok, {{one_for_one, 1, 1}, [SMChild, SChild, NChild, PLChild, MSChild, CChild, SGChild]}}.
25 |
--------------------------------------------------------------------------------
/erlmon-1.0/wwwroot/nitrogen/reset.css:
--------------------------------------------------------------------------------
1 | /* v1.0 | 20080212 */
2 |
3 | html, body, div, span, applet, object, iframe,
4 | h1, h2, h3, h4, h5, h6, p, blockquote, pre,
5 | a, abbr, acronym, address, big, cite, code,
6 | del, dfn, em, font, img, ins, kbd, q, s, samp,
7 | small, strike, strong, sub, sup, tt, var,
8 | b, u, i, center,
9 | dl, dt, dd, ol, ul, li,
10 | fieldset, form, label, legend,
11 | table, caption, tbody, tfoot, thead, tr, th, td {
12 | margin: 0;
13 | padding: 0;
14 | border: 0;
15 | outline: 0;
16 | font-size: 100%;
17 | vertical-align: baseline;
18 | background: transparent;
19 | }
20 | body {
21 | line-height: 1;
22 | }
23 | ol, ul {
24 | list-style: none;
25 | }
26 | blockquote, q {
27 | quotes: none;
28 | }
29 | blockquote:before, blockquote:after,
30 | q:before, q:after {
31 | content: '';
32 | content: none;
33 | }
34 |
35 | /* remember to define focus styles! */
36 | :focus {
37 | outline: 0;
38 | }
39 |
40 | /* remember to highlight inserts somehow! */
41 | ins {
42 | text-decoration: none;
43 | }
44 | del {
45 | text-decoration: line-through;
46 | }
47 |
48 | /* tables still need 'cellspacing="0"' in the markup */
49 | table {
50 | border-collapse: collapse;
51 | border-spacing: 0;
52 | }
53 |
--------------------------------------------------------------------------------
/README:
--------------------------------------------------------------------------------
1 |
2 | erlmon is a network and host monitoring suite, written in erlang.
3 |
4 |
5 | Copyright (c) 2010 DarmaSoft, LLC.
6 |
7 | Permission is hereby granted, free of charge, to any person
8 | obtaining a copy of this software and associated documentation
9 | files (the "Software"), to deal in the Software without
10 | restriction, including without limitation the rights to use,
11 | copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | copies of the Software, and to permit persons to whom the
13 | Software is furnished to do so, subject to the following
14 | conditions:
15 |
16 | The above copyright notice and this permission notice shall be
17 | included in all copies or substantial portions of the Software.
18 |
19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
21 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
23 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26 | OTHER DEALINGS IN THE SOFTWARE.
27 |
28 |
--------------------------------------------------------------------------------
/erlmon-1.0/include/erlmon.hrl:
--------------------------------------------------------------------------------
1 |
2 | %% announce
3 | -record(node_announce, {sender, pid, node, state}).
4 | %% ack announce
5 | -record(node_ack_announce, {sender, pid, node, state}).
6 |
7 |
8 | %% state change
9 | -record(state_change, {sender, node, objtype, obj, prev_state, new_state, data=none, ts}).
10 |
11 | %% sent alerts
12 | -record(sent_alert, {node, to, objtype, obj, prev_state, new_state, ets, ats}).
13 |
14 | %% state change filter
15 | -record(state_change_filter, {state_change, fields=[]}).
16 |
17 | %% alert filter
18 | -record(alert_filter, {scf, to}).
19 |
20 | %% announce
21 | -record(storage_announce, {sender, node}).
22 | %% ack announce
23 | -record(storage_ack_announce, {sender, node}).
24 |
25 | %% test_row
26 | -record(test, {key, value}).
27 |
28 | %% smtp_config
29 | -record(smtp_config, {authtype, port, host, address, login, pass}).
30 |
31 | %% --- monitor records --- %%
32 |
33 | %% tcp port monitor
34 | -record(tcp_port_monitor, {host, port, pid}).
35 |
36 | %% process monitor
37 | -record(process_monitor, {name, pid}).
38 |
39 | %% filesystem
40 | -record(filesystem, {path, size, used, avail, percent, mount}).
41 |
42 | %% process
43 | -record(process, {user, pid, cpu, mem, vsz, rss, tty, stat, start, time, cmd}).
44 |
45 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/erlmon_smtp_message.erl:
--------------------------------------------------------------------------------
1 |
2 | -module(erlmon_smtp_message).
3 | -author(darrik@darmasoft.com).
4 |
5 | -export([create/3]).
6 | -export([test/0]).
7 |
8 | -include("include/erlmon.hrl").
9 |
10 | create(Config, SC, To) ->
11 | From = Config#smtp_config.address,
12 | Subject = create_subject(SC),
13 | Body = create_body(SC),
14 | email_msg:simp_msg(From, To, Subject, Body).
15 |
16 | create_subject(#state_change{}=SC) ->
17 | Node = to_list(SC#state_change.node),
18 | Obj = to_list(SC#state_change.obj),
19 | ObjType = to_list(SC#state_change.objtype),
20 | PrevState = to_list(SC#state_change.prev_state),
21 | NewState = to_list(SC#state_change.new_state),
22 | lists:flatten(io_lib:format("~s:~s.~s (~s -> ~s)", [Node, ObjType, Obj, PrevState, NewState])).
23 |
24 | create_body(#state_change{}=_SC) ->
25 | "test body".
26 |
27 | to_list(Arg) when is_atom(Arg) ->
28 | atom_to_list(Arg);
29 | to_list(Arg) when is_list(Arg) ->
30 | Arg.
31 |
32 | test() ->
33 | C = #smtp_config{host="mail.darmasoft.com", address="darrik@darmasoft.com", pass="testpass"},
34 | SC = #state_change{sender=self(), node=node(), objtype=tcp_port, obj="localhost:22", prev_state=up, new_state=down, ts=timestamp:now_i()},
35 | To = "darrik@darmasoft.com",
36 | create(C, SC, To).
37 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/pages/web_index.erl:
--------------------------------------------------------------------------------
1 | -module (web_index).
2 | -include_lib ("nitrogen/include/wf.inc").
3 | -compile(export_all).
4 |
5 | main() ->
6 | #template { file="./wwwroot/template.html"}.
7 |
8 | title() ->
9 | "erlmon home.".
10 |
11 | body() ->
12 | [
13 | #h1{text="Node Status"},
14 | get_node_status()
15 | ].
16 |
17 |
18 | menu_items() -> helper:menu([{home,"dashboard","/"},{config,"configuration","/web/config"}]).
19 |
20 | event(_) -> ok.
21 |
22 | get_node_status() ->
23 | Nodes = node:status(),
24 | #table { rows=[
25 | #tablerow { cells = [
26 | #tableheader { text="Node" },
27 | #tableheader { text="Status" }
28 | ]},
29 | node_status_to_html(Nodes)
30 | ]}.
31 |
32 | node_status_to_html([{Node, Status}|T]) ->
33 | {Text, Class, Cell} = case Status of
34 | up ->
35 | {"UP", "node_status_up", #tablecell { body=#link{ text=atom_to_list(Node), url=lists:flatten(io_lib:format("/web/node/~s", [atom_to_list(Node)]))}}};
36 | down ->
37 | {"DOWN", "node_status_down", #tablecell { text=atom_to_list(Node) }};
38 | _ ->
39 | {"UNKNOWN", "node_status_unknown", #tablecell { text=atom_to_list(Node) }}
40 | end,
41 | [
42 | #tablerow { cells = [
43 | Cell,
44 | #tablecell { text=Text, class=Class }
45 | ]}
46 | | node_status_to_html(T)];
47 | node_status_to_html([]) ->
48 | [].
49 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/email_msg.erl:
--------------------------------------------------------------------------------
1 | %%
2 | %% file: email_msg.erl
3 | %% author: Michael Bradford
4 | %% description: a very simple module that creates a non-multipart
5 | %% email message.
6 | %% Doesn't support MIME or non-ascii characters
7 | %%
8 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9 | %% Usage Example
10 | %%
11 | %% 2> c(email_msg).
12 | %% {ok,email_msg}
13 | %% 3> From = "michael.bradford@t-mobile.uk.net".
14 | %% "michael.bradford@t-mobile.uk.net"
15 | %% 4> To = "test@test.co.uk".
16 | %% "test@test.co.uk"
17 | %% 5> Subject = "Testing !!!!".
18 | %% "Testing !!!!"
19 | %% 6> Content = "Hi Mike, this is a test, bye".
20 | %% "Hi Mike, this is a test, bye"
21 | %% 7> Msg = email_msg:simp_msg(From,To,Subject,Content).
22 | %% "from: michael.bradford@t-mobile.uk.net\r\nto: test@test.co.uk\r\n
23 | %% subject: Testi ng !!!!\r\n\r\nHi Mike, this is a test, bye\r\n"
24 | %% 8>
25 | %%
26 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
27 | %%
28 | -module(email_msg).
29 | -vsn('v1.0').
30 |
31 | -export([simp_msg/4]).
32 |
33 | simp_msg(From, To, Subject, Message) ->
34 | FromStr = ["from: ", From, "\r\n"],
35 | ToStr = ["to: ", To, "\r\n"],
36 | SubjStr = ["subject: ", Subject, "\r\n"],
37 | MsgStr = ["\r\n", Message],
38 | lists:concat(lists:concat([FromStr, ToStr, SubjStr, MsgStr, ["\r\n"]])).
39 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/monitor_sup.erl:
--------------------------------------------------------------------------------
1 |
2 | -module(monitor_sup).
3 | -author(darrik@darmasoft.com).
4 |
5 | -behaviour(supervisor).
6 |
7 | -export([start_link/0]).
8 | -export([init/1]).
9 |
10 | start_link() ->
11 | R = supervisor:start_link({local, ?MODULE}, ?MODULE, []),
12 | erlmon:finished(?MODULE),
13 | R.
14 |
15 | init(_) ->
16 | debug:log("monitor_sup: starting disk_monitor_sup"),
17 | DMSChild = {disk_monitor_sup, {disk_monitor_sup, start_link, []}, permanent, 2000, supervisor, [disk_monitor_sup]},
18 | FMSChild = {file_monitor_sup, {file_monitor_sup, start_link, []}, permanent, 2000, supervisor, [file_monitor_sup]},
19 | FMMChild = {file_monitor_man, {file_monitor_man, start_link, []}, permanent, 2000, worker, [file_monitor_man]},
20 | TPMSChild = {tcp_port_monitor_sup, {tcp_port_monitor_sup, start_link, []}, permanent, 2000, supervisor, [tcp_port_monitor_sup]},
21 | TPMMChild = {tcp_port_monitor_man, {tcp_port_monitor_man, start_link, []}, permanent, 2000, worker, [tcp_port_monitor_man]},
22 | PMSChild = {process_monitor_sup, {process_monitor_sup, start_link, []}, permanent, 2000, supervisor, [process_monitor_sup]},
23 | PMMChild = {process_monitor_man, {process_monitor_man, start_link, []}, permanent, 2000, worker, [process_monitor_man]},
24 | {ok, {{one_for_one, 1, 1}, [DMSChild, FMSChild, FMMChild, TPMSChild, TPMMChild, PMSChild, PMMChild]}}.
25 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/pages/web_config.erl:
--------------------------------------------------------------------------------
1 | -module (web_config).
2 | -include_lib ("nitrogen/include/wf.inc").
3 | -compile(export_all).
4 |
5 | main() ->
6 | #template { file="./wwwroot/template.html"}.
7 |
8 | title() ->
9 | "erlmon configuration".
10 |
11 | alert_status() ->
12 | Address = config:setting([smtp,address]),
13 | case length(Address) of
14 | 0 -> "no alert address set!";
15 | _ -> ["alerts sent to " ++ Address]
16 | end.
17 |
18 | body() ->
19 | case file:read_file("config.lua") of
20 | {ok, Config} ->
21 | [
22 | #h1{text="Configuration"},
23 | #p{},
24 | #label{text="Edit the configuration file for this node. Updates are applied immediately to all nodes."},
25 | #textarea {id=config, text=binary_to_list(Config), html_encode=false },
26 | #p{},
27 | #button { text="Save Config", postback={click, save_button} }
28 |
29 | ];
30 | {error, _Reason} ->
31 | [
32 | #h1{text="Configuration"},
33 | #p{},
34 | #label{text="config.lua is either missing or inaccessible. Check the file and try again, please."}
35 | ]
36 | end.
37 |
38 | menu_items() -> helper:menu([{home,"dashboard","/"},{nodes,"configuration","/web/config"}]).
39 |
40 | event(_) ->
41 | [Config] = wf:q(config),
42 | config:update_file(Config),
43 | helper:flash_msg("Config reloaded."),
44 | wf:redirect("/web/config"),
45 | ok.
46 |
47 |
--------------------------------------------------------------------------------
/erlmon-1.0/config.example.lua:
--------------------------------------------------------------------------------
1 | -- this require isn't specifically required as it will be added
2 | -- when executed inside of erlmon, but they are necessary to
3 | -- test the file on the command line, by typing lua config.lua
4 | require "lua/erlmon"
5 |
6 |
7 | -- Quick lua tutorial:
8 | -- A table can be created like this: mytable = { a = 1, b = 2 }
9 | -- then i can say mytable.a, or mytable['a']... you'll see this syntax
10 | -- all over the file. Also, tables can have 'metatables'. erlmon
11 | -- uses this extensively to lookup global properties if they're not
12 | -- overridden on a sub object. details below...
13 |
14 | -- This is where globals go.
15 |
16 | Erlmon.http.login = 'admin'
17 | Erlmon.http.password = 'admin'
18 | Erlmon.alert.email = 'me@myemail.com'
19 |
20 | -- Specific config differences can go here
21 |
22 | -- sigmund - memcached
23 | sigmund = Erlmon.add_host("sigmund.mydomain.com")
24 |
25 | -- In this example, sigmund is a lua table. if you access a property
26 | -- of sigmund that doesn't exist, the equivalent property will be accessed
27 | -- on the global Erlmon object.
28 |
29 | sigmund.http.password = "superego"
30 | sigmund.alert.email = "sigmundalerts@myemail.com"
31 |
32 | sigmund.monitor_process("memcached",
33 | { start = "/etc/init.d/memcached start",
34 | stop = "/etc/init.d/memcached stop"
35 | }
36 | )
37 |
38 | sigmund.monitor_port(11211) -- memcached
39 |
40 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/state_change_sup.erl:
--------------------------------------------------------------------------------
1 |
2 | -module(state_change_sup).
3 | -author(darrik@darmasoft.com).
4 |
5 | -behaviour(supervisor).
6 |
7 | -include("include/erlmon.hrl").
8 |
9 | -export([start_link/0]).
10 | -export([init/1]).
11 |
12 | start_link() ->
13 | R = supervisor:start_link({local, ?MODULE}, ?MODULE, []),
14 | wait_for_state_change_em(),
15 | erlmon:finished(?MODULE),
16 | R.
17 |
18 |
19 | init(_) ->
20 | debug:log("state_change_sup: starting state_change_em"),
21 | Child = {state_change_em, {state_change_em, start_link, []}, permanent, 2000, worker, [state_change_em]},
22 | {ok, {{one_for_one, 1, 1}, [Child]}}.
23 |
24 | wait_for_state_change_em() ->
25 | case whereis(state_change_em) of
26 | undefined ->
27 | wait_for_state_change_em();
28 | _ ->
29 | add_default_handlers(),
30 | add_default_filters()
31 | end.
32 |
33 | add_default_handlers() ->
34 | state_change_em:add_handler(state_change_handler),
35 | state_change_em:add_handler(config_file_change_handler),
36 | state_change_em:add_handler(node_down_handler),
37 | state_change_em:add_handler(alert_handler).
38 |
39 | add_default_filters() ->
40 | SC = #state_change{sender=nil, node=nil, objtype=file, obj="config.lua", prev_state=unchanged, new_state=file_ctime_changed, ts=nil},
41 | SCF = #state_change_filter{state_change=SC, fields=[objtype, obj, prev_state, new_state]},
42 | AF = #alert_filter{scf=SCF, to="darrik@darmasoft.com"},
43 | alert_handler:register_alert_filter(AF).
44 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/erlmon.erl:
--------------------------------------------------------------------------------
1 |
2 | -module(erlmon).
3 | -author(darrik@darmasoft.com).
4 |
5 | -behaviour(application).
6 |
7 | -include("include/erlmon.hrl").
8 |
9 | -export([start/0, start/2, stop/1, finished/1]).
10 |
11 | -define(SUPERVISORS, [
12 | erlmon_sup,
13 | state_change_sup,
14 | state_change_em,
15 | storage_sup,
16 | storage,
17 | node_sup,
18 | node,
19 | monitor_sup,
20 | disk_monitor_sup,
21 | tcp_port_monitor_sup,
22 | tcp_port_monitor_man,
23 | file_monitor_sup,
24 | file_monitor_man,
25 | process_list_sup,
26 | process_monitor_sup,
27 | process_monitor_man,
28 | config_sup,
29 | config,
30 | erlmon_smtp_sup
31 | ]).
32 |
33 | start() ->
34 | application:start(erlmon).
35 |
36 | start(_Type, _StartArgs) ->
37 | debug:log_to(file, {filename, "erlmon.log"}),
38 | debug:log_to(console, {}),
39 | debug:log("erlmon: initializing"),
40 | register(erlmon, self()),
41 | R = erlmon_sup:start_link(),
42 | wait_for_finished(?SUPERVISORS),
43 | load(),
44 | R.
45 |
46 | load() ->
47 | file_monitor:monitor("config.lua"),
48 | config:reload(),
49 | erlmon_smtp:config(),
50 | application:set_env(erlwww, port, 8000),
51 | application:start(erlwww),
52 | ok.
53 |
54 |
55 | stop(_State) ->
56 | debug:log("erlmon: stopping"),
57 | ok.
58 |
59 | wait_for_finished([]) ->
60 | debug:log("erlmon: startup complete"),
61 | ok;
62 | wait_for_finished([S|T]) ->
63 | debug:log("erlmon: waiting for ~p", [S]),
64 | receive
65 | {S, started} ->
66 | debug:log("erlmon: ~p finished", [S]),
67 | ok
68 | end,
69 | wait_for_finished(T).
70 |
71 | finished(S) ->
72 | erlmon ! {S, started}.
73 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/df.erl:
--------------------------------------------------------------------------------
1 |
2 | -module(df).
3 | -author(darrik@darmsoft.com).
4 |
5 | -export([list/0]).
6 | -export([list/1]).
7 | -export([find_path/1]).
8 |
9 | -include("include/erlmon.hrl").
10 |
11 | list() ->
12 | list([]).
13 |
14 | list([]) ->
15 | Output = os:cmd("df"),
16 | process(Output).
17 |
18 | process(Output) when is_list(Output) ->
19 | Lines = re:split(Output, "\n", [{return, list}]),
20 | [_Header|T] = Lines,
21 | lists:flatten(create_records(T)).
22 |
23 | create_records([H|[]]) ->
24 | [create_record(H)];
25 | create_records([H|T]) ->
26 | [create_record(H) | create_records(T)];
27 | create_records([]) ->
28 | [].
29 |
30 | create_record([Head|[]]) -> create_record(Head);
31 | create_record([]) -> [];
32 | create_record(Line) ->
33 | Fields = re:split(Line, "\s+", [{return, list}]),
34 | [Path, Size, Used, Avail, Percent, Mount] = Fields,
35 | [NewPercent|_] = lists:flatten(re:replace(Percent, "%", "")),
36 | IntPercent = binary_to_integer(NewPercent),
37 | case re:run(Path, "/dev") of
38 | {match, _} ->
39 | Rec = #filesystem{path=Path, size=Size, used=Used, avail=Avail, percent=IntPercent, mount=Mount},
40 | Rec;
41 | nomatch -> []
42 | end.
43 |
44 | binary_to_integer(Bin) ->
45 | case erl_scan:string(binary_to_list(Bin)) of
46 | {ok, Tokens, _} ->
47 | first_integer(Tokens);
48 | _ -> 0
49 | end.
50 |
51 | first_integer([{integer, _V, I}|_T]) -> I;
52 | first_integer([_H|T]) -> first_integer(T);
53 | first_integer([]) -> 0.
54 |
55 | find_path(Path) ->
56 | find_path(Path, list()).
57 |
58 | find_path(Path, [H=#filesystem{path=Path}|_T]) ->
59 | H;
60 | find_path(Path, [_H|T]) ->
61 | find_path(Path, T);
62 | find_path(_Path, []) ->
63 | not_found.
64 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/file_monitor_man.erl:
--------------------------------------------------------------------------------
1 |
2 | -module(file_monitor_man).
3 | -author(darrik@darmasoft.com).
4 |
5 | -export([start_link/0]).
6 | -export([init/0]).
7 | -export([monitor/1]).
8 | -export([unmonitor/1]).
9 |
10 |
11 | start_link() ->
12 | debug:log("file_monitor_man: starting"),
13 | register(?MODULE, Pid = spawn_link(?MODULE, init, [])),
14 | erlmon:finished(?MODULE),
15 | {ok, Pid}.
16 |
17 | init() ->
18 | loop([]).
19 |
20 | loop(State) ->
21 | receive
22 | {start, Path} ->
23 | NewState = start_conditionally(Path, State),
24 | loop(NewState);
25 | {stop, Path} ->
26 | NewState = stop_conditionally(Path, State),
27 | loop(NewState);
28 | M ->
29 | debug:log("file_monitor_man: UNKNOWN: ~p", [M]),
30 | loop(State)
31 | end.
32 |
33 | monitor(Path) ->
34 | wait_for_manager(),
35 | ?MODULE ! {start, Path},
36 | ok.
37 |
38 | unmonitor(Path) ->
39 | ?MODULE ! {stop, Path},
40 | ok.
41 |
42 | start_conditionally(Path, []) ->
43 | debug:log("file_monitor_man: monitoring ~p", [Path]),
44 | file_monitor_sup:monitor(Path),
45 | [Path];
46 | start_conditionally(Path, [Path|T]) ->
47 | debug:log("file_monitor_man: ~p already monitored", [Path]),
48 | [Path|T];
49 | start_conditionally(Path, [H|T]) ->
50 | [H | start_conditionally(Path, T)].
51 |
52 | stop_conditionally(Path, []) ->
53 | debug:log("file_monitor_man: not monitoring ~p", [Path]),
54 | [];
55 | stop_conditionally(Path, [Path|T]) ->
56 | debug:log("file_monitor_man: no longer monitoring ~p", [Path]),
57 | file_monitor_sup:unmonitor(Path),
58 | T;
59 | stop_conditionally(Path, [H|T]) ->
60 | [H | stop_conditionally(Path, T)].
61 |
62 | wait_for_manager() ->
63 | case whereis(file_monitor_man) of
64 | undefined ->
65 | wait_for_manager();
66 | _ ->
67 | ok
68 | end.
69 |
70 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/erlwww_app.erl:
--------------------------------------------------------------------------------
1 | -module (erlwww_app).
2 | -export ([start/2, stop/1, route/1, request/1]).
3 | -behavior(application).
4 |
5 | start(_, _) -> nitrogen:start(erlwww).
6 | stop(_) -> nitrogen:stop().
7 |
8 | %% route/1 lets you define new URL routes to your web pages,
9 | %% or completely create a new routing scheme.
10 | %% The 'Path' argument specifies the request path. Your
11 | %% function should return either an atom which is the page module
12 | %% to run, or a tuple containing {Module, PathInfo}. PathInfo
13 | %% can be accessed using wf:get_path_info().
14 | %%
15 | %% Uncomment the line below to direct requests
16 | %% from "/web/newroute" to the web_index module:
17 | %%
18 | %% route("/web/newroute") -> web_index;
19 | %%
20 | %% Uncomment the line below to direct requests
21 | %% from "/web/newroute" to the web_index module,
22 | %% with trailing PathInfo included:
23 | %%
24 | %% route("/web/newroute/" ++ PathInfo) -> {web_index, PathInfo};
25 |
26 | route("/web/login") -> login;
27 | route("/web/config") -> web_config;
28 | route("/web/node/" ++ PathInfo) -> {web_node, PathInfo};
29 | route(Path) -> nitrogen:route(Path).
30 |
31 |
32 | %% request/1 is executed before every Nitrogen page, and lets
33 | %% you add authentication and authorization. The 'Module' argument
34 | %% is the name of the page module.
35 | %% This function should return either 'ok' if processing can proceed,
36 | %% or it can return a full-fledged page by treating it just like the main function
37 | %% of a page. Alternatively, you can use the wf:redirect* functions to
38 | %% issue a client-side redirect to a new page.
39 |
40 | request(Module) ->
41 | case Module of
42 | login ->
43 | ok;
44 | _ ->
45 | User = wf:user(),
46 | case User of
47 | undefined -> wf:redirect_to_login("/web/login");
48 | _ -> ok
49 | end
50 | end.
51 |
--------------------------------------------------------------------------------
/erlmon-1.0/wwwroot/nitrogen/facebox.css:
--------------------------------------------------------------------------------
1 | #facebox .b {
2 | background:url(/images/facebox/b.png);
3 | }
4 |
5 | #facebox .tl {
6 | background:url(/images/facebox/tl.png);
7 | }
8 |
9 | #facebox .tr {
10 | background:url(/images/facebox/tr.png);
11 | }
12 |
13 | #facebox .bl {
14 | background:url(/images/facebox/bl.png);
15 | }
16 |
17 | #facebox .br {
18 | background:url(/images/facebox/br.png);
19 | }
20 |
21 | #facebox {
22 | position: absolute;
23 | top: 0;
24 | left: 0;
25 | z-index: 100;
26 | text-align: left;
27 | }
28 |
29 | #facebox .popup {
30 | position: relative;
31 | }
32 |
33 | #facebox table {
34 | border-collapse: collapse;
35 | }
36 |
37 | #facebox td {
38 | border-bottom: 0;
39 | padding: 0;
40 | }
41 |
42 | #facebox .body {
43 | padding: 10px;
44 | background: #fff;
45 | width: 370px;
46 | }
47 |
48 | #facebox .loading {
49 | text-align: center;
50 | }
51 |
52 | #facebox .image {
53 | text-align: center;
54 | }
55 |
56 | #facebox img {
57 | border: 0;
58 | margin: 0;
59 | }
60 |
61 | #facebox .footer {
62 | border-top: 1px solid #DDDDDD;
63 | padding-top: 5px;
64 | margin-top: 10px;
65 | text-align: right;
66 | }
67 |
68 | #facebox .tl, #facebox .tr, #facebox .bl, #facebox .br {
69 | height: 10px;
70 | width: 10px;
71 | overflow: hidden;
72 | padding: 0;
73 | }
74 |
75 | #facebox_overlay {
76 | position: fixed;
77 | top: 0px;
78 | left: 0px;
79 | height:100%;
80 | width:100%;
81 | background:url(/images/facebox/overlay.png);
82 | z-index:99;
83 | }
84 |
85 | .facebox_hide {
86 | z-index:-100;
87 | }
88 |
89 | .facebox_overlayBG {
90 | background-color: #000;
91 | z-index: 99;
92 | }
93 |
94 | * html #facebox_overlay { /* ie6 hack */
95 | position: absolute;
96 | height: expression(document.body.scrollHeight > document.body.offsetHeight ? document.body.scrollHeight : document.body.offsetHeight + 'px');
97 | }
98 |
--------------------------------------------------------------------------------
/erlmon-1.0/c_src/erlua.h:
--------------------------------------------------------------------------------
1 | typedef struct _lua_drv_t {
2 | ErlDrvPort port;
3 | lua_State *L;
4 | } lua_drv_t;
5 |
6 |
7 | #ifdef __cplusplus
8 | extern "C" {
9 | #endif
10 |
11 | /* Fix a silly Lua warning */
12 |
13 | void luaL_openlibs (lua_State *L);
14 |
15 | /* Commands */
16 |
17 | void erl_lua_call(lua_drv_t *driver_data, char *buf, int index);
18 | void erl_lua_concat(lua_drv_t *driver_data, char *buf, int index);
19 | void erl_lua_getfield (lua_drv_t *driver_data, char *buf, int index);
20 | void erl_lua_getglobal(lua_drv_t *driver_data, char *buf, int index);
21 | void erl_lua_gettop(lua_drv_t *driver_data, char *buf, int index);
22 | void erl_lua_next(lua_drv_t *driver_data, char *buf, int index);
23 | void erl_lua_pushboolean(lua_drv_t *driver_data, char *buf, int index);
24 | void erl_lua_pushinteger(lua_drv_t *driver_data, char *buf, int index);
25 | void erl_lua_pushstring(lua_drv_t *driver_data, char *buf, int index);
26 | void erl_lua_pushnil(lua_drv_t *driver_data, char *buf, int index);
27 | void erl_lua_pushnumber(lua_drv_t *driver_data, char *buf, int index);
28 | void erl_lua_remove(lua_drv_t *driver_data, char *buf, int index);
29 | void erl_lua_setfield(lua_drv_t *driver_data, char *buf, int index);
30 | void erl_lua_setglobal(lua_drv_t *driver_data, char *buf, int index);
31 | void erl_lua_toboolean(lua_drv_t *driver_data, char *buf, int index);
32 | void erl_lua_tointeger(lua_drv_t *driver_data, char *buf, int index);
33 | void erl_lua_tolstring(lua_drv_t *driver_data, char *buf, int index);
34 | void erl_lua_tonumber(lua_drv_t *driver_data, char *buf, int index);
35 | void erl_lua_type(lua_drv_t *driver_data, char *buf, int index);
36 |
37 | void erl_lual_dostring (lua_drv_t *driver_data, char *buf, int index);
38 | void erl_lual_dofile (lua_drv_t *driver_data, char *buf, int index);
39 |
40 | void erl_lua_no_command (lua_drv_t *driver_data);
41 |
42 | #ifdef __cplusplus
43 | }
44 | #endif /* __cplusplus */
45 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/debug.erl:
--------------------------------------------------------------------------------
1 |
2 | -module(debug).
3 | -author(darrik@darmasoft.com).
4 |
5 | -export([log/1]).
6 | -export([log/2]).
7 |
8 | -export([log_to/2]).
9 | -export([no_log_to/2]).
10 |
11 | -export([init/0]).
12 |
13 | -include_lib("include/debug.hrl").
14 |
15 | log(Format) ->
16 | log(Format, []).
17 |
18 | log(Format, Args) ->
19 | start(),
20 | debug_srv ! #debug_log_msg{sender=self(), format=Format, args=Args},
21 | true.
22 |
23 | log_to(Mod, Options) ->
24 | start(),
25 | ModString = atom_to_list(Mod),
26 | NewModString = lists:flatten(["debug_"|ModString]),
27 | NewMod = list_to_atom(NewModString),
28 | debug_srv ! #debug_log_add_method{sender=self(), module=NewMod, options=Options},
29 | true.
30 |
31 | no_log_to(Mod, Options) ->
32 | start(),
33 | debug_srv ! #debug_log_rem_method{sender=self(), module=Mod, options=Options},
34 | true.
35 |
36 | start() ->
37 | case whereis(debug_srv) of
38 | undefined ->
39 | register(debug_srv, spawn(debug, init, []));
40 | _Pid -> true
41 | end,
42 | true.
43 |
44 | init() ->
45 | loop([]).
46 |
47 | loop(State) ->
48 | receive
49 | #debug_log_msg{sender=_Sender, format=Format, args=Args} ->
50 | dispatch("[~s] " ++ Format, [timestamp:now()|Args], State),
51 | loop(State);
52 | #debug_log_add_method{sender=_Sender, module=Mod, options=Options} ->
53 | NewState = add_to_state({Mod, Options}, State),
54 | loop(NewState);
55 | #debug_log_rem_method{sender=_Sender, module=Mod, options=Options} ->
56 | NewState = remove_from_state({Mod, Options}, State),
57 | loop(NewState)
58 | end.
59 |
60 | add_to_state(Tuple, [Tuple|T]) -> [Tuple|T];
61 | add_to_state(Tuple, [H|T]) -> [H|add_to_state(Tuple, T)];
62 | add_to_state(Tuple, []) -> [Tuple|[]].
63 |
64 | remove_from_state(Tuple, [Tuple|T]) -> T;
65 | remove_from_state(Tuple, [H|T]) -> [H|remove_from_state(Tuple, T)];
66 | remove_from_state(_Tuple, []) -> [].
67 |
68 | dispatch(Format, Args, [{Mod, Options}|T]) ->
69 | apply(Mod, log, [Format, Args, Options]),
70 | dispatch(Format, Args, T);
71 | dispatch(_Format, _Args, []) -> true.
72 |
73 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/process_monitor_man.erl:
--------------------------------------------------------------------------------
1 |
2 | -module(process_monitor_man).
3 | -author(darrik@darmasoft.com).
4 |
5 | -export([start_link/0]).
6 | -export([init/0]).
7 | -export([monitor/1]).
8 | -export([unmonitor/1]).
9 | -export([status/0]).
10 |
11 | -include("include/erlmon.hrl").
12 |
13 | start_link() ->
14 | debug:log("process_monitor_man: starting"),
15 | register(?MODULE, Pid = spawn_link(?MODULE, init, [])),
16 | erlmon:finished(?MODULE),
17 | {ok, Pid}.
18 |
19 | init() ->
20 | loop([]).
21 |
22 | loop(State) ->
23 | receive
24 | {Sender, status} ->
25 | Sender ! {ok, State},
26 | loop(State);
27 | {start, ProcessName} ->
28 | NewState = start_conditionally(ProcessName, State),
29 | loop(NewState);
30 | {stop, ProcessName} ->
31 | NewState = stop_conditionally(ProcessName, State),
32 | loop(NewState);
33 | M ->
34 | debug:log("process_monitor_man: UNKNOWN: ~p", [M]),
35 | loop(State)
36 | end.
37 |
38 | status() ->
39 | ?MODULE ! {self(), status},
40 | receive
41 | {ok, Status} -> ok
42 | end,
43 | Status.
44 |
45 | monitor(ProcessName) ->
46 | ?MODULE ! {start, ProcessName},
47 | ok.
48 |
49 | unmonitor(ProcessName) ->
50 | ?MODULE ! {stop, ProcessName},
51 | ok.
52 |
53 | start_conditionally(ProcessName, []) ->
54 | debug:log("process_monitor_man: monitoring ~p", [ProcessName]),
55 | {ok, Pid} = process_monitor_sup:monitor(ProcessName),
56 | [#process_monitor{name=ProcessName, pid=Pid}];
57 | start_conditionally(ProcessName, [H=#process_monitor{name=ProcessName, pid=Pid}|T]) ->
58 | debug:log("process_monitor_man: ~p already monitored (~p)", [ProcessName, Pid]),
59 | [H|T];
60 | start_conditionally(ProcessName, [H|T]) ->
61 | [H | start_conditionally(ProcessName, T)].
62 |
63 | stop_conditionally(ProcessName, []) ->
64 | debug:log("process_monitor_man: not monitoring ~p", [ProcessName]),
65 | [];
66 | stop_conditionally(ProcessName, [#process_monitor{name=ProcessName, pid=Pid}|T]) ->
67 | debug:log("process_monitor_man: no longer monitoring ~p (~p)", [ProcessName, Pid]),
68 | process_monitor_sup:unmonitor(ProcessName),
69 | Pid ! stop,
70 | T;
71 | stop_conditionally(ProcessName, [H|T]) ->
72 | [H | stop_conditionally(ProcessName, T)].
73 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/tcp_port_monitor_man.erl:
--------------------------------------------------------------------------------
1 |
2 | -module(tcp_port_monitor_man).
3 | -author(darrik@darmasoft.com).
4 |
5 | -export([start_link/0]).
6 | -export([init/0]).
7 | -export([monitor/2]).
8 | -export([unmonitor/2]).
9 | -export([status/0]).
10 |
11 | -include("include/erlmon.hrl").
12 |
13 | start_link() ->
14 | debug:log("tcp_port_monitor_man: starting"),
15 | register(?MODULE, Pid = spawn_link(?MODULE, init, [])),
16 | erlmon:finished(?MODULE),
17 | {ok, Pid}.
18 |
19 | init() ->
20 | loop([]).
21 |
22 | loop(State) ->
23 | receive
24 | {Sender, status} ->
25 | Sender ! {ok, State},
26 | loop(State);
27 | {start, Host, Port} ->
28 | NewState = start_conditionally(Host, Port, State),
29 | loop(NewState);
30 | {stop, Host, Port} ->
31 | NewState = stop_conditionally(Host, Port, State),
32 | loop(NewState);
33 | M ->
34 | debug:log("tcp_port_monitor_man: UNKNOWN: ~p", [M]),
35 | loop(State)
36 | end.
37 |
38 | monitor(Host, Port) ->
39 | ?MODULE ! {start, Host, Port},
40 | ok.
41 |
42 | unmonitor(Host, Port) ->
43 | ?MODULE ! {stop, Host, Port},
44 | ok.
45 |
46 | status() ->
47 | ?MODULE ! {self(), status},
48 | receive
49 | {ok, Status} -> ok
50 | end,
51 | Status.
52 |
53 | start_conditionally(Host, Port, []) ->
54 | debug:log("tcp_port_monitor_man: monitoring ~p:~p", [Host, Port]),
55 | {ok, Pid} = tcp_port_monitor_sup:monitor(Host, Port),
56 | [#tcp_port_monitor{host=Host, port=Port, pid=Pid}];
57 | start_conditionally(Host, Port, [#tcp_port_monitor{host=Host, port=Port}|_T]=State) ->
58 | debug:log("tcp_port_monitor_man: ~p:~p already monitored", [Host, Port]),
59 | State;
60 | start_conditionally(Host, Port, [H|T]) ->
61 | [H | start_conditionally(Host, Port, T)].
62 |
63 | stop_conditionally(Host, Port, []) ->
64 | debug:log("tcp_port_monitor_man: not monitoring ~p:~p", [Host, Port]),
65 | [];
66 | stop_conditionally(Host, Port, [#tcp_port_monitor{host=Host, port=Port, pid=Pid}|T]) ->
67 | debug:log("tcp_port_monitor_man: no longer monitoring ~p:~p (~p)", [Host, Port, Pid]),
68 | tcp_port_monitor_sup:unmonitor(Host, Port),
69 | Pid ! stop,
70 | T;
71 | stop_conditionally(Host, Port, [H|T]) ->
72 | [H | stop_conditionally(Host, Port, T)].
73 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/disk_monitor.erl:
--------------------------------------------------------------------------------
1 |
2 | -module(disk_monitor).
3 | -author(darrik@darmasoft.com).
4 |
5 | -export([start/1]).
6 | -export([start_all/0]).
7 | -export([init/1]).
8 | -export([monitor/1]).
9 |
10 | -include("include/erlmon.hrl").
11 |
12 | monitor(Path) ->
13 | disk_monitor_sup:monitor(Path).
14 |
15 | start_all() ->
16 | start_each(df:list()).
17 |
18 | start_each([#filesystem{path=Path}|T]) ->
19 | start(Path),
20 | start_each(T);
21 | start_each([]) -> ok.
22 |
23 | start(Path) ->
24 | {ok, spawn_link(?MODULE, init, [Path])}.
25 |
26 | init(Path) ->
27 | debug:log("disk_monitor:init(~p)", [Path]),
28 | Filesystem = df:find_path(Path),
29 | case Filesystem of
30 | not_found ->
31 | null;
32 | #filesystem{} ->
33 | loop(first, Filesystem)
34 | end.
35 |
36 | loop(OldState, Filesystem) ->
37 | receive
38 | stop ->
39 | stopped
40 | after
41 | 3000 ->
42 | #filesystem{path=Path, percent=_Percent} = Filesystem,
43 | NewFilesystem = df:find_path(Path),
44 | #filesystem{path=Path, percent=NewPercent, mount=Mount} = NewFilesystem,
45 | ObjName = lists:flatten([Path, ":"| Mount]),
46 | case NewPercent > 90 of
47 | false ->
48 | case OldState of
49 | alert ->
50 | state_change_em:notify(#state_change{sender=self(), node=node(), objtype=disk, obj=ObjName, prev_state=alert, new_state=ok, data=NewPercent, ts=timestamp:now_i()}),
51 | loop(ok, NewFilesystem);
52 | first ->
53 | state_change_em:notify(#state_change{sender=self(), node=node(), objtype=disk, obj=ObjName, prev_state=none, new_state=ok, data=NewPercent, ts=timestamp:now_i()}),
54 | loop(ok, NewFilesystem);
55 | _ ->
56 | loop(ok, NewFilesystem)
57 | end;
58 | true ->
59 | case OldState of
60 | ok ->
61 | state_change_em:notify(#state_change{sender=self(), node=node(), objtype=disk, obj=ObjName, prev_state=ok, new_state=alert, data=NewPercent, ts=timestamp:now_i()}),
62 | loop(alert, NewFilesystem);
63 | first ->
64 | state_change_em:notify(#state_change{sender=self(), node=node(), objtype=disk, obj=ObjName, prev_state=none, new_state=alert, data=NewPercent, ts=timestamp:now_i()}),
65 | loop(alert, NewFilesystem);
66 | _ ->
67 | loop(alert, NewFilesystem)
68 | end
69 | end
70 | end.
71 |
--------------------------------------------------------------------------------
/erlmon-1.0/tests/lua_test.erl:
--------------------------------------------------------------------------------
1 | -module(lua_test).
2 |
3 | -include_lib("eunit/include/eunit.hrl").
4 |
5 | small_integer_test() ->
6 | push_to_helper(1, pushinteger, tointeger).
7 |
8 | zero_integer_test() ->
9 | push_to_helper(0, pushinteger, tointeger).
10 |
11 | small_negative_integer_test() ->
12 | push_to_helper(-2, pushinteger, tointeger).
13 |
14 |
15 | small_number_test() ->
16 | push_to_helper(2, pushnumber, tonumber).
17 |
18 | small_negative_number_test() ->
19 | push_to_helper(-2, pushnumber, tonumber).
20 |
21 | zero_number_test() ->
22 | push_to_helper(0, pushnumber, tonumber).
23 |
24 | big_number_test() ->
25 | push_to_helper(5000000000, pushnumber, tonumber).
26 |
27 | big_floating_number_test() ->
28 | push_to_helper(5000000000.234, pushnumber, tonumber).
29 |
30 | big_negative_number_test() ->
31 | push_to_helper(-5000000000, pushnumber, tonumber).
32 |
33 | big_negative_float_number_test() ->
34 | push_to_helper(-5000000000.234, pushnumber, tonumber).
35 |
36 |
37 | string_test() ->
38 | push_to_helper("testing", pushstring, tolstring).
39 |
40 |
41 | call_test() ->
42 | {ok, L} = lua:new_state(),
43 | ?assertMatch(ok, lua:getfield(L, global, "type")),
44 | ?assertMatch(ok, lua:pushnumber(L, 1)),
45 | ?assertMatch(ok, lua:call(L, 1, 1)),
46 | ?assertMatch({ok, "number"}, lua:tolstring(L, 1)).
47 |
48 | set_get_global_test() ->
49 | {ok, L} = lua:new_state(),
50 | ?assertMatch(ok, lua:pushnumber(L, 23)),
51 | ?assertMatch(ok, lua:setfield(L, global, "foo")),
52 | ?assertMatch(ok, lua:getfield(L, global, "foo")),
53 | ?assertMatch({ok, 23}, lua:tonumber(L, 1)).
54 |
55 |
56 | push_to_helper(Val, Push, To) ->
57 | {ok, L} = lua:new_state(),
58 | ?assertMatch(ok, lua:Push(L, Val)),
59 | ?assertMatch({ok, Val}, lua:To(L, 1)).
60 |
61 | gettable_test() ->
62 | {ok, L} = lua:new_state(),
63 | ?assertMatch(ok, lua:dostring(L, "t={a=1}")),
64 | ?assertMatch([{"a",1}], lua:gettable(L, global,"t")).
65 |
66 | gettable_int_key_test() ->
67 | {ok, L} = lua:new_state(),
68 | ?assertMatch(ok,lua:dostring(L, "t={};table.insert(t,'foo')")),
69 | ?assertMatch([{1,"foo"}], lua:gettable(L, global,"t")).
70 |
71 | gettable_int_key_table_test() ->
72 | {ok, L} = lua:new_state(),
73 | ?assertMatch(ok,lua:dostring(L, "t={};table.insert(t,{bar=1})")),
74 | ?assertMatch([{1,[{"bar",1}]}], lua:gettable(L, global,"t")).
75 |
76 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/pages/web_node.erl:
--------------------------------------------------------------------------------
1 | -module (web_node).
2 | -include_lib ("nitrogen/include/wf.inc").
3 | -compile(export_all).
4 |
5 | main() ->
6 | #template { file="./wwwroot/template.html"}.
7 |
8 | title() ->
9 | "node info".
10 |
11 | body() ->
12 | Node = wf:get_path_info(),
13 | [
14 | #h1{text=lists:flatten(io_lib:format("Node Info : ~s", [Node]))},
15 | monitor_status_table(Node)
16 | ].
17 |
18 |
19 | menu_items() -> helper:menu([{home,"dashboard","/"},{config,"configuration","/web/config"}]).
20 |
21 | event(_) -> ok.
22 |
23 | monitor_status_table(Node) ->
24 | NodeAtom = list_to_atom(Node),
25 | HeaderRow = #tablerow { cells=[
26 | #tableheader { text="Object Type" },
27 | #tableheader { text="Object" },
28 | #tableheader { text="Status" }
29 | ]},
30 | Rows = lists:flatten([
31 | HeaderRow,
32 | tcp_port_monitor_status_table(NodeAtom),
33 | process_monitor_status_table(NodeAtom)
34 | ]),
35 | #table { rows=Rows }.
36 |
37 | tcp_port_monitor_status_table(Node) ->
38 | case {node(), Node} of
39 | {Node, Node} ->
40 | Status = tcp_port_monitor:status();
41 | {_, Node} ->
42 | Status = rpc:call(Node, tcp_port_monitor, status, [])
43 | end,
44 | tcp_port_monitor_status_rows(Status).
45 |
46 | tcp_port_monitor_status_rows([{ObjType,Host,Port,Pid}|T]) ->
47 | {ok, Status} = tcp_port_monitor:status(Pid),
48 | {Text, Class} = case Status of
49 | up -> {"UP", "monitor_status_up"};
50 | down -> {"DOWN", "monitor_status_down"};
51 | _ -> {Status, "monitor_status_unknown"}
52 | end,
53 | [ #tablerow { cells=[
54 | #tablecell { text=ObjType },
55 | #tablecell { text=lists:flatten(io_lib:format("~s:~p", [Host, Port])) },
56 | #tablecell { text=Text, class=Class }
57 | ]} | tcp_port_monitor_status_rows(T) ];
58 | tcp_port_monitor_status_rows([]) ->
59 | [].
60 |
61 | process_monitor_status_table(Node) ->
62 | case {node(), Node} of
63 | {Node, Node} ->
64 | Status = process_monitor:status();
65 | {_, Node} ->
66 | Status = rpc:call(Node, process_monitor, status, [])
67 | end,
68 | process_monitor_status_rows(Status).
69 |
70 | process_monitor_status_rows([{ObjType,ObjName,Pid}|T]) ->
71 | {ok, Status} = process_monitor:status(Pid),
72 | {Text, Class} = case Status of
73 | up -> {"UP", "monitor_status_up"};
74 | down -> {"DOWN", "monitor_status_down"};
75 | _ -> {Status, "monitor_status_unknown"}
76 | end,
77 | [
78 | #tablerow { cells=[
79 | #tablecell { text=ObjType },
80 | #tablecell { text=ObjName },
81 | #tablecell { text=Text, class=Class }
82 | ]} | process_monitor_status_rows(T) ];
83 | process_monitor_status_rows([]) ->
84 | [].
85 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/tcp_port_monitor.erl:
--------------------------------------------------------------------------------
1 |
2 | -module(tcp_port_monitor).
3 | -author(darrik@darmasoft.com).
4 |
5 | -export([start/2]).
6 | -export([init/1]).
7 | -export([monitor/1,monitor/2]).
8 | -export([unmonitor/2]).
9 | -export([status/0]).
10 | -export([status/1]).
11 |
12 | -include("include/erlmon.hrl").
13 |
14 | status() ->
15 | tcp_port_monitor_man:status().
16 |
17 | status(Pid) ->
18 | Pid ! {self(), status},
19 | receive
20 | {ok, Status} -> ok
21 | end,
22 | {ok, Status}.
23 |
24 | %% Config sends us, from Lua, something like:
25 | %% monitor([{"memcached",[{"host","localhost"},{"port",11211}]}]})
26 | monitor([]) ->
27 | [];
28 | monitor([Description|T]) ->
29 | {_Name,Args} = Description,
30 | {"host",Host} = lists:keyfind("host",1,Args),
31 | {"port",Port} = lists:keyfind("port",1,Args),
32 | monitor(Host,Port),
33 | monitor(T).
34 |
35 | monitor(Host, Port) ->
36 | tcp_port_monitor_man:monitor(Host, Port).
37 |
38 | unmonitor(Host, Port) ->
39 | tcp_port_monitor_man:unmonitor(Host, Port).
40 |
41 | start(Host, Port) ->
42 | debug:log("tcp_port_monitor:start([~p, ~p])", [Host, Port]),
43 | {ok, spawn_link(?MODULE, init, [[Host, Port]])}.
44 |
45 | init([Host, Port]) ->
46 | debug:log("tcp_port_monitor: initializing monitor for ~p:~p", [Host, Port]),
47 | loop([Host, Port], unmonitored).
48 |
49 | loop([Host, Port], State) ->
50 | ObjName = lists:concat(io_lib:format("~s~s~p", [Host, ":",Port])),
51 | receive
52 | stop ->
53 | state_change_em:notify(#state_change{sender=self(), node=node(), objtype=tcp_port, obj=ObjName, prev_state=State, new_state=unmonitored, ts=timestamp:now_i()});
54 | {Sender, status} ->
55 | Sender ! {ok, State},
56 | loop([Host, Port], State);
57 | M ->
58 | debug:log("tcp_port_monitor: ~p: UNKNOWN: ~p", [self(), M])
59 | after
60 | 3000 ->
61 | case gen_tcp:connect(Host, Port, [binary, {packet, 0}]) of
62 | {ok, Sock} ->
63 | gen_tcp:close(Sock),
64 | case State of
65 | up ->
66 | NewState = up,
67 | loop([Host, Port], NewState);
68 | OldState ->
69 | state_change_em:notify(#state_change{sender=self(), node=node(), objtype=tcp_port, obj=ObjName, prev_state=OldState, new_state=up, ts=timestamp:now_i()}),
70 | NewState = up,
71 | loop([Host, Port], NewState)
72 | end;
73 | {error, _Reason} ->
74 | case State of
75 | down ->
76 | NewState = down,
77 | loop([Host, Port], NewState);
78 | OldState ->
79 | state_change_em:notify(#state_change{sender=self(), node=node(), objtype=tcp_port, obj=ObjName, prev_state=OldState, new_state=down, ts=timestamp:now_i()}),
80 | NewState = down,
81 | loop([Host, Port], NewState)
82 | end
83 | end
84 | end.
85 |
86 |
--------------------------------------------------------------------------------
/erlmon-1.0/wwwroot/nitrogen/basic.css:
--------------------------------------------------------------------------------
1 | /*** FONTS ***/
2 |
3 | body, table, table td { font-size: 1em; font-family: "Lucida Grande", "Segoe UI", Tahoma, Helvetica, Arial, sans-serif; line-height: 1.7em; }
4 |
5 | h1 { font-family: 'Arial'; font-size: 2.2em; font-weight: bold; }
6 | h2 { font-family: 'Arial', Georgia; font-size: 1.7em; font-weight: bold; }
7 | h3 { font-family: 'Arial', Georgia; font-size: 1.2em; font-weight: bold; }
8 | h4 { font-family: 'Arial', Georgia; font-size: 0.9em; text-transform: uppercase; }
9 |
10 | a, a:visited { text-decoration: none; }
11 | a:hover, a:active { text-decoration: underline; }
12 |
13 | input[type=text], input[type=password], textarea {
14 | font-family: "Trebuchet MS", Arial, Helvetica, sans-serif; font-weight: bold; font-size: 1.1em; line-height: 1.1em;
15 | }
16 |
17 | input[type=submit], input[type=button] {
18 | font-family: "Lucida Grande", "Segoe UI", Tahoma, Helvetica, Arial, sans-serif; font-size: 1em;
19 | }
20 |
21 | .big { font-size: 120%; line-height: 180%; }
22 | .small { font-size: 90%; }
23 | .error { font-size: 10px; }
24 |
25 |
26 | /*** COLORS ***/
27 |
28 | body, table, table td { color: #525252; }
29 |
30 | a, a:visited, a:active, a:hover { color: #4488FF; }
31 |
32 | h1 { color: #000000; }
33 | h2 { color: #84B712; }
34 | h3 { color: #84B712; }
35 | h4 { color: #000000; }
36 |
37 | input[type=text], input[type=password], textarea { border: solid 1px #99AACC; }
38 | input[type=submit], input[type=button] { color: #333333; }
39 | input[type=submit]:HOVER, input[type=button]:HOVER { color: #3333FF; }
40 |
41 | .error { color: #ffff00; }
42 |
43 | hr { background-color: #E0E0E0; }
44 |
45 | /*** POSITIONING ***/
46 |
47 | body, img, table, form { border: 0px; margin: 0px; padding: 0px}
48 | table td { vertical-align: top; padding: 4px 7px 4px 7px; }
49 |
50 | img { vertical-align: middle; }
51 |
52 | table { border-collapse:collapse; }
53 |
54 | p { clear: both; margin: 0px 0px 0px 0px; padding: 1em 0px 0px 0px; }
55 |
56 | h1 { margin: 0px 0px 0px 0px; padding: 0em 0px 0.75em 0px; }
57 | h2 { margin: 0px 0px 0px 0px; padding: 0em 0px 0.5em 0px; }
58 | h3 { margin: 0px 0px 0px 0px; padding: 0em 0px 0.5em 0px; }
59 | h4 { margin: 0px 0px 0px 0px; padding: 0.2em 0px 0.1em 0px; }
60 |
61 | input[type=text], input[type=password], textarea { padding: 5px 5px 5px 5px; margin: 0px 7px 0px 0px; }
62 | input[type=submit], input[type=button] { margin-right: 7px; }
63 | input[type=checkbox] { vertical-align: middle; margin-right: 10px; }
64 | label { vertical-align: middle; }
65 | hr { margin: 12px 0px 12px 0px; padding: 0px 0px 0px 0px; height: 1px; border: 0px; }
66 | .error { margin-top: 2px; }
67 |
68 | /*** EXTRAS ***/
69 | :focus { outline: 0; }
70 |
71 | ul {
72 | list-style-type: disc;
73 | padding-left: 20px;
74 | padding-top: 7px;
75 | }
76 |
77 |
78 |
79 | .description {
80 | font-size: 0.8em;
81 | color: #000000;
82 | }
83 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/ps.erl:
--------------------------------------------------------------------------------
1 |
2 | -module(ps).
3 | -author(darrik@darmsoft.com).
4 |
5 | -export([list/0]).
6 | -export([list/1]).
7 | -export([dump/1]).
8 | -export([find/1]).
9 | -export([pid_for_process/1]).
10 | -export([name_for_pid/1]).
11 |
12 | -include("include/erlmon.hrl").
13 |
14 | list() ->
15 | list([]).
16 |
17 | list([]) ->
18 | Output = os:cmd("ps aux"),
19 | process(Output).
20 |
21 | process(Output) when is_list(Output) ->
22 | Lines = re:split(Output, "\n", [{return, list}]),
23 | [_Header|T] = Lines,
24 | create_records(T).
25 |
26 | create_records([H|T]) ->
27 | [create_record(H) | create_records(T)];
28 | create_records([]) ->
29 | [].
30 |
31 | create_record([Head|[]]) -> create_record(Head);
32 | create_record([]) -> [];
33 | create_record(Line) ->
34 | Fields = re:split(Line, "\s+", [{return, list}]),
35 | [User, Pid, Cpu, Mem, Vsz, Rss, Tty, Stat, Start, Time | Cmd] = Fields,
36 | Rec = #process{user=User, pid=erlmon_helper:list_to_number(Pid), cpu=erlmon_helper:list_to_number(Cpu), mem=erlmon_helper:list_to_number(Mem), vsz=erlmon_helper:list_to_number(Vsz), rss=erlmon_helper:list_to_number(Rss), tty=Tty, stat=Stat, start=Start, time=Time, cmd=collapse(Cmd)},
37 | Rec.
38 |
39 | dump([Process|T]) ->
40 | debug:log("~p", [Process]),
41 | dump(T).
42 |
43 | collapse([]) -> "";
44 | collapse([I]) -> I;
45 | collapse([H|T]) ->
46 | H ++ " " ++ collapse(T).
47 |
48 | find(Pname) ->
49 | find(Pname, list()).
50 |
51 | find(Pname, [H = #process{cmd=Pname}|_T]) -> H;
52 | find(Pname, [_H|T]) ->
53 | find(Pname, T);
54 | find(_Pname, []) ->
55 | not_found.
56 |
57 | find_regex(Pregex) ->
58 | find_regex(Pregex, list()).
59 |
60 | find_regex(Pregex, [H|T]) ->
61 | #process{cmd=Pname} = H,
62 | REReturn = re:run(Pname, Pregex),
63 | case REReturn of
64 | {match, _} -> H;
65 | nomatch -> find_regex(Pregex, T)
66 | end;
67 | find_regex(_Pregex, []) ->
68 | not_found.
69 |
70 | find_pid(Pid) ->
71 | find_pid(Pid, list()).
72 |
73 | find_pid(Pid, [H = #process{pid=Pid}|_T]) -> H;
74 | find_pid(Pid, [_H|T]) -> find_pid(Pid, T);
75 | find_pid(_Pid, []) -> not_found.
76 |
77 | pid_for_process(Pname) ->
78 | Process = find(Pname),
79 | case Process of
80 | not_found -> pid_for_process_regex(Pname);
81 | P ->
82 | #process{pid=Pid} = P,
83 | Pid
84 | end.
85 |
86 | pid_for_process_regex(Pregex) ->
87 | Process = find_regex(Pregex),
88 | case Process of
89 | not_found -> null;
90 | P ->
91 | #process{pid=Pid} = P,
92 | Pid
93 | end.
94 |
95 | name_for_pid(Pid) when is_integer(Pid) ->
96 | Process = find_pid(lists:flatten(io_lib:format("~p", [Pid]))),
97 | case Process of
98 | not_found -> null;
99 | P ->
100 | #process{cmd=Cmd} = P,
101 | Cmd
102 | end;
103 | name_for_pid(Pid) ->
104 | Process = find_pid(Pid),
105 | case Process of
106 | not_found -> null;
107 | P ->
108 | #process{cmd=Cmd} = P,
109 | Cmd
110 | end.
111 |
--------------------------------------------------------------------------------
/erlmon-1.0/wwwroot/nitrogen/elements.css:
--------------------------------------------------------------------------------
1 | .label {
2 | display: block;
3 | font-weight: bold;
4 | font-size: 0.9em;
5 | margin-top: 7px;
6 | }
7 |
8 | .value {
9 | display: block;
10 | font-weight: bold;
11 | padding: 0px 0px 0px 0px;
12 | margin-top: 2px;
13 | margin-bottom: 10px;
14 | color: #000000;
15 | }
16 |
17 | /*** ROUNDED PANEL ***/
18 | table.rounded_panel.black td { background: #000000; }
19 | table.rounded_panel.gray td { background: #F1F1F1; }
20 | table.rounded_panel.black td { background: #000000; }
21 | table.rounded_panel.white td { background: #FFFFFF; }
22 | table.rounded_panel tr.chrome td { font-size: 1px; line-height: 1px; padding: 0 0 0 0; margin: 0 0 0 0; border: 0; }
23 | table.rounded_panel tr.chrome img { padding: 0 0 0 0; margin: 0 0 0 0; border: 0; }
24 |
25 |
26 | table.rounded_panel { margin: 0px 0px 0px 0px; padding: 0px 0px 0px 0px; border: 0px; }
27 | table.rounded_panel td { padding: 0px 0px 0px 0px; }
28 | table.rounded_panel td.content { padding: 4px 20px 4px 20px; }
29 |
30 | table.rounded_panel { margin: 0px 0px 0px 0px; padding: 0px 0px 0px 0px; border: 0px; }
31 | table.rounded_panel td { padding: 0px 0px 0px 0px; }
32 | table.rounded_panel td.content { padding: 4px 20px 4px 20px; }
33 |
34 |
35 | /*** INPLACE EDITING ***/
36 |
37 | div.inplace_textbox div.view {
38 | cursor: pointer;
39 | }
40 |
41 | div.inplace_textbox .label {
42 | display: inline;
43 | }
44 |
45 | div.inplace_textbox .instructions {
46 | padding-left: 12px;
47 | font-size: 0.8em;
48 | }
49 |
50 | div.inplace_textbox .LV_invalid {
51 | position: relative;
52 | margin-right: 7px;
53 | color:#CC0000;
54 | background-color: #FFFF99;
55 | border: solid 2px #D0D0C0;
56 | }
57 |
58 | .flash_container {
59 | }
60 |
61 | .flash {
62 | color: #303030;
63 | background-color: #FAEC7F;
64 | border: #FFE800 solid 2px;
65 | padding: 3px 5px 3px 5px;
66 | margin-bottom: 7px;
67 | }
68 |
69 | .flash .flash_content {
70 | margin-right: 50px;
71 | }
72 |
73 | .flash .flash_close_button {
74 | float: right;
75 | font-size: 90%;
76 | }
77 |
78 | .wizard {
79 | }
80 |
81 | .wizard .wizard_title {
82 | font-family: 'Arial', Georgia; font-size: 1.2em; font-weight: bold;
83 | }
84 |
85 | .wizard .wizard_body {
86 | margin-top: 20px;
87 | margin-bottom: 20px;
88 | }
89 |
90 | .wizard .wizard_buttons {
91 | padding-right: 40px;
92 | text-align:right;
93 | }
94 |
95 | .wizard .wizard_buttons input {
96 | margin-right: 20px;
97 | }
98 |
99 | /*** VALIDATION ***/
100 |
101 | .LV_validation_message {
102 | vertical-align: middle;
103 | display: inline;
104 | line-height: 100%;
105 | position: absolute;
106 | font-weight:bold;
107 | margin: 0px 0px 0px 7px;
108 | padding: 5px 7px 5px 7px;
109 | opacity: 0.8;
110 | -moz-opacity: 0.8;
111 | filter:alpha(opacity=80);
112 | }
113 |
114 | /*
115 | .LV_valid {
116 | background-image: url(/nitrogen/checkmark.png);
117 | margin: 2px 0px 5px 0px;
118 | padding: 0px 20px 20px 0px;
119 | color:#00CC00;
120 | }
121 | */
122 |
123 | .LV_invalid {
124 | color:#CC0000;
125 | background-color: #FFFF99;
126 | border: solid 2px #D0D0C0;
127 | }
128 |
129 | /*.LV_valid_field,
130 | input.LV_valid_field:hover,
131 | input.LV_valid_field:active,
132 | textarea.LV_valid_field:hover,
133 | textarea.LV_valid_field:active {
134 | border: 1px solid #00CC00;
135 | }
136 |
137 | .LV_invalid_field,
138 | input.LV_invalid_field:hover,
139 | input.LV_invalid_field:active,
140 | textarea.LV_invalid_field:hover,
141 | textarea.LV_invalid_field:active {
142 | border: 1px solid #CC0000;
143 | }*/
--------------------------------------------------------------------------------
/erlmon-1.0/src/alert_handler.erl:
--------------------------------------------------------------------------------
1 |
2 | -module(alert_handler).
3 | -author(darrik@darmasoft.com).
4 |
5 | -behaviour(gen_event).
6 |
7 | -include("include/erlmon.hrl").
8 |
9 | -export([init/1]).
10 | -export([code_change/3]).
11 | -export([handle_state_change/2]).
12 | -export([handle_event/2]).
13 | -export([handle_call/3]).
14 | -export([handle_cast/2]).
15 | -export([handle_info/2]).
16 | -export([terminate/2]).
17 | -export([test/0]).
18 | -export([register_alert_filter/1]).
19 | -export([unregister_alert_filter/1]).
20 | -export([match_all_filter/1]).
21 |
22 | init(_) ->
23 | {ok, []}.
24 |
25 | handle_event(#state_change{}=Event, State) ->
26 | debug:log("alert_handler:state_change: ~p", [Event]),
27 | dispatch_state_change(Event, State),
28 | {ok, State};
29 | handle_event({add_alert_filter, #alert_filter{}=AF}, State) ->
30 | debug:log("alert_handler:add_alert_filter: ~p", [AF]),
31 | NewState = add_filter(AF, State),
32 | {ok, NewState};
33 | handle_event({remove_alert_filter, #alert_filter{}=AF}, State) ->
34 | debug:log("alert_handler:remove_alert_filter: ~p", [AF]),
35 | NewState = remove_filter(AF, State),
36 | {ok, NewState};
37 | handle_event(_Event, State) ->
38 | {ok, State}.
39 |
40 | handle_call(_Request, _From, State) ->
41 | Reply = ok,
42 | {reply, Reply, State}.
43 |
44 | handle_cast(_Msg, State) ->
45 | {noreply, State}.
46 |
47 | handle_info(_Info, State) ->
48 | {noreply, State}.
49 |
50 | terminate(_Args, _State) ->
51 | ok.
52 |
53 | add_filter(AF, [AF|_T]=State) ->
54 | debug:log("alert_handler: alert_filter already exists"),
55 | State;
56 | add_filter(AF, [H|T]) ->
57 | [H|add_filter(AF, T)];
58 | add_filter(AF, []) ->
59 | debug:log("alert_handler: alert_filter added"),
60 | [AF].
61 |
62 | remove_filter(AF, [AF|T]) ->
63 | debug:log("alert_handler: alert_filter removed"),
64 | T;
65 | remove_filter(AF, [H|T]) ->
66 | [H|remove_filter(AF, T)];
67 | remove_filter(_AF, []) ->
68 | debug:log("alert_handler: alert_filter does not exist"),
69 | [].
70 |
71 | register_alert_filter(#alert_filter{}=AF) ->
72 | state_change_em:notify({add_alert_filter, AF}).
73 |
74 | unregister_alert_filter(#alert_filter{}=AF) ->
75 | state_change_em:notify({remove_alert_filter, AF}).
76 |
77 | test() ->
78 | SC = #state_change{sender=nil, node=nil, objtype=file, obj=nil, prev_state=nil, new_state=file_ctime_changed, ts=nil},
79 | SF = #state_change_filter{state_change=SC, fields=[objtype, new_state]},
80 | #alert_filter{scf=SF, to="darrik@darmasoft.com"}.
81 |
82 | code_change(_OldVsn, State, _Extra) ->
83 | {ok, State}.
84 |
85 | dispatch_state_change(#state_change{}=SC, State) ->
86 | debug:log("alert_handler: handling state_change for ~p:~p", [SC#state_change.objtype, SC#state_change.obj]),
87 | spawn(?MODULE, handle_state_change, [SC, State]),
88 | ok.
89 |
90 | handle_state_change(SC, [#alert_filter{scf=#state_change_filter{}=SCF, to=ToAddress}|T]) ->
91 | case state_change:match(SC, SCF) of
92 | true ->
93 | debug:log("alert_handler: ~p:~p (~p -> ~p) matched filter!", [SC#state_change.objtype, SC#state_change.obj, SC#state_change.prev_state, SC#state_change.new_state]),
94 | erlmon_smtp:alert(SC, ToAddress),
95 | alert_sent;
96 | false ->
97 | handle_state_change(SC, T)
98 | end;
99 | handle_state_change(SC, [_H|T]) ->
100 | handle_state_change(SC, T);
101 | handle_state_change(SC, []) ->
102 | debug:log("alert_handler: ~p:~p (~p -> ~p) did not match any filters", [SC#state_change.objtype, SC#state_change.obj, SC#state_change.prev_state, SC#state_change.new_state]),
103 | no_alert.
104 |
105 | match_all_filter(ToAddress) ->
106 | SC = #state_change{sender=nil, node=nil, objtype=nil, obj=nil, prev_state=nil, new_state=nil, ts=nil},
107 | SCF = #state_change_filter{state_change=SC, fields=[]},
108 | #alert_filter{scf=SCF, to=ToAddress}.
109 |
110 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/process_list.erl:
--------------------------------------------------------------------------------
1 |
2 | -module(process_list).
3 | -author(darrik@darmasoft.com).
4 |
5 | -include("include/erlmon.hrl").
6 |
7 | -define(TIMEOUT, 5000).
8 |
9 | -export([
10 | start_link/0,
11 | init/1,
12 | handle_call/3,
13 | handle_cast/2,
14 | handle_info/2,
15 | terminate/2,
16 | code_change/3
17 | ]).
18 |
19 | -export([
20 | count/0,
21 | get_by_regexp/1,
22 | get_by_cmd/1,
23 | get_by_user/1,
24 | get_by_pid/1,
25 | list/0,
26 | refresh/0,
27 | refresh_timer/1
28 | ]).
29 |
30 | start_link() ->
31 | R = gen_server:start_link({local, ?MODULE}, ?MODULE, [], []),
32 | spawn(process_list, refresh_timer, [?TIMEOUT]),
33 | R.
34 |
35 | init([]) ->
36 | {ok, []}.
37 |
38 | handle_call({count}, _From, State) ->
39 | Response = length(State),
40 | {reply, Response, State};
41 | handle_call({get, regexp, CmdRe}, _From, State) ->
42 | Response = get_processes_by_cmd_re(CmdRe, State),
43 | {reply, Response, State};
44 | handle_call({get, pid, Pid}, _From, State) ->
45 | Response = get_processes_by_pid(Pid, State),
46 | {reply, Response, State};
47 | handle_call({get, user, User}, _From, State) ->
48 | Response = get_processes_by_user(User, State),
49 | {reply, Response, State};
50 | handle_call({get, cmd, Cmd}, _From, State) ->
51 | Response = get_processes_by_cmd(Cmd, State),
52 | {reply, Response, State};
53 | handle_call({list}, _From, State) ->
54 | Response = {ok, State},
55 | {reply, Response, State};
56 | handle_call(_Msg, _From, State) ->
57 | Response = {error, unknown_call},
58 | {reply, Response, State}.
59 |
60 | handle_cast({refresh}, _State) ->
61 | NewState = ps:list(),
62 | {noreply, NewState};
63 | handle_cast(_Msg, State) ->
64 | {noreply, State}.
65 |
66 | handle_info(_Msg, State) ->
67 | {noreply, State}.
68 |
69 | terminate(_Reason, _State) ->
70 | ok.
71 |
72 | code_change(_OldVersion, State, _Extra) ->
73 | {ok, State}.
74 |
75 | list() ->
76 | gen_server:call(?MODULE, {list}).
77 |
78 | refresh() ->
79 | R = gen_server:cast(?MODULE, {refresh}),
80 | spawn(process_list, refresh_timer, [?TIMEOUT]),
81 | R.
82 |
83 | count() ->
84 | gen_server:call(?MODULE, {count}).
85 |
86 | get_by_pid(Pid) ->
87 | gen_server:call(?MODULE, {get, pid, Pid}).
88 |
89 | get_by_user(User) ->
90 | gen_server:call(?MODULE, {get, user, User}).
91 |
92 | get_by_cmd(Cmd) ->
93 | gen_server:call(?MODULE, {get, cmd, Cmd}).
94 |
95 | get_by_regexp(CmdRe) ->
96 | gen_server:call(?MODULE, {get, regexp, CmdRe}).
97 |
98 |
99 | get_processes_by_pid(Pid, State) when is_list(Pid) ->
100 | PidInt = list_to_integer(Pid),
101 | get_processes_by_pid(PidInt, State);
102 | get_processes_by_pid(Pid, [#process{pid=Pid}=Process|T]) ->
103 | [Process|get_processes_by_pid(Pid, T)];
104 | get_processes_by_pid(Pid, [_H|T]) ->
105 | get_processes_by_pid(Pid, T);
106 | get_processes_by_pid(_Pid, []) ->
107 | [].
108 |
109 | get_processes_by_user(User, [#process{user=User}=Process|T]) ->
110 | [Process|get_processes_by_user(User, T)];
111 | get_processes_by_user(User, [_H|T]) ->
112 | get_processes_by_user(User, T);
113 | get_processes_by_user(_User, []) ->
114 | [].
115 |
116 | get_processes_by_cmd(Cmd, [#process{cmd=Cmd}=Process|T]) ->
117 | [Process|get_processes_by_cmd(Cmd, T)];
118 | get_processes_by_cmd(Cmd, [_H|T]) ->
119 | get_processes_by_cmd(Cmd, T);
120 | get_processes_by_cmd(_Cmd, []) ->
121 | [].
122 |
123 | get_processes_by_cmd_re(CmdRe, [#process{cmd=Cmd}=Process|T]) ->
124 | ReRet = re:run(Cmd, CmdRe),
125 | case ReRet of
126 | {match, _} -> [Process|get_processes_by_cmd_re(CmdRe, T)];
127 | nomatch -> get_processes_by_cmd_re(CmdRe, T)
128 | end;
129 | get_processes_by_cmd_re(CmdRe, [_H|T]) ->
130 | get_processes_by_cmd_re(CmdRe, T);
131 | get_processes_by_cmd_re(_CmdRe, []) ->
132 | [].
133 |
134 | refresh_timer(T) ->
135 | receive
136 | after
137 | T ->
138 | refresh()
139 | end.
140 |
141 |
--------------------------------------------------------------------------------
/erlmon-1.0/lua/lunit:
--------------------------------------------------------------------------------
1 | #! /bin/sh
2 |
3 | # This file is part of lunit 0.5.
4 | #
5 | # For Details about lunit look at: http://www.mroth.net/lunit/
6 | #
7 | # Author: Michael Roth
8 | #
9 | # Copyright (c) 2004-2009 Michael Roth
10 | #
11 | # Permission is hereby granted, free of charge, to any person
12 | # obtaining a copy of this software and associated documentation
13 | # files (the "Software"), to deal in the Software without restriction,
14 | # including without limitation the rights to use, copy, modify, merge,
15 | # publish, distribute, sublicense, and/or sell copies of the Software,
16 | # and to permit persons to whom the Software is furnished to do so,
17 | # subject to the following conditions:
18 | #
19 | # The above copyright notice and this permission notice shall be
20 | # included in all copies or substantial portions of the Software.
21 | #
22 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
26 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
27 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 |
30 |
31 | if test $# = 0 ; then
32 | echo "$0: Usage Error. Try $0 --help" >&2
33 | exit 1
34 | fi
35 |
36 | if [ `uname` = "Darwin" ]; then
37 | scriptname="$(readlink -n "$0")"
38 | else
39 | scriptname="$(readlink -n -f "$0")"
40 | fi
41 | interpreter="lua"
42 | options=""
43 |
44 | while true ; do
45 | case "$1" in
46 | -h|--help)
47 | cat <
50 | This program comes WITHOUT WARRANTY OF ANY KIND.
51 |
52 | Usage: lunit [OPTIONS] [--] scripts
53 |
54 | Options:
55 |
56 | -i, --interpreter LUA Complete path of the lua binary to use.
57 | -p, --path PATH Sets the LUA_PATH environment for the tests.
58 | --cpath CPATH Sets the LUA_CPATH environment for the tests.
59 | -r, --runner RUNNER Testrunner to use, defaults to 'lunit-console'.
60 | -t, --test PATTERN Which tests to run, may contain * or ? wildcards.
61 | --loadonly Only load the tests.
62 | --dontforce Do not force to load $scriptname*.lua.
63 | -h, --help Print this help screen.
64 | --version Print lunit version.
65 |
66 | Please report bugs to .
67 | EOT
68 | exit ;;
69 |
70 | --version)
71 | echo "lunit 0.5 Copyright 2004-2009 Michael Roth "
72 | exit ;;
73 |
74 | -i|--interpreter)
75 | interpreter="$2"
76 | shift 2 ;;
77 |
78 | -p|--path)
79 | LUA_PATH="$2"
80 | export LUA_PATH
81 | shift 2 ;;
82 |
83 | --cpath)
84 | LUA_CPATH="$2"
85 | export LUA_CPATH
86 | shift 2 ;;
87 |
88 | --loadonly)
89 | options="$options $1"
90 | shift 1 ;;
91 |
92 | --dontforce)
93 | scriptname=""
94 | shift 1 ;;
95 |
96 | -r|--runner|-t|--test)
97 | options="$options $1 $2"
98 | shift 2 ;;
99 |
100 | --)
101 | break ;;
102 |
103 | -*)
104 | echo "$0: Invalid option: $1" >&2
105 | exit 1 ;;
106 |
107 | *)
108 | break ;;
109 | esac
110 | done
111 |
112 |
113 | exec "$interpreter" - "$scriptname" $options "$@" < 0 or stats.failed > 0 then
126 | os.exit(1)
127 | end
128 | EOT
129 |
--------------------------------------------------------------------------------
/erlmon-1.0/lua/lunit-console.lua:
--------------------------------------------------------------------------------
1 |
2 | --[[--------------------------------------------------------------------------
3 |
4 | This file is part of lunit 0.5.
5 |
6 | For Details about lunit look at: http://www.mroth.net/lunit/
7 |
8 | Author: Michael Roth
9 |
10 | Copyright (c) 2006-2008 Michael Roth
11 |
12 | Permission is hereby granted, free of charge, to any person
13 | obtaining a copy of this software and associated documentation
14 | files (the "Software"), to deal in the Software without restriction,
15 | including without limitation the rights to use, copy, modify, merge,
16 | publish, distribute, sublicense, and/or sell copies of the Software,
17 | and to permit persons to whom the Software is furnished to do so,
18 | subject to the following conditions:
19 |
20 | The above copyright notice and this permission notice shall be
21 | included in all copies or substantial portions of the Software.
22 |
23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
26 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
27 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
28 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
29 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 |
31 | --]]--------------------------------------------------------------------------
32 |
33 |
34 |
35 | --[[
36 |
37 | begin()
38 | run(testcasename, testname)
39 | err(fullname, message, traceback)
40 | fail(fullname, where, message, usermessage)
41 | pass(testcasename, testname)
42 | done()
43 |
44 | Fullname:
45 | testcase.testname
46 | testcase.testname:setupname
47 | testcase.testname:teardownname
48 |
49 | --]]
50 |
51 |
52 | require "lunit"
53 |
54 | module( "lunit-console", package.seeall )
55 |
56 |
57 | local function printformat(format, ...)
58 | io.write( string.format(format, ...) )
59 | end
60 |
61 |
62 | local columns_printed = 0
63 |
64 | local function writestatus(char)
65 | if columns_printed == 0 then
66 | io.write(" ")
67 | end
68 | if columns_printed == 60 then
69 | io.write("\n ")
70 | columns_printed = 0
71 | end
72 | io.write(char)
73 | io.flush()
74 | columns_printed = columns_printed + 1
75 | end
76 |
77 |
78 | local msgs = {}
79 |
80 |
81 | function begin()
82 | local total_tc = 0
83 | local total_tests = 0
84 |
85 | for tcname in lunit.testcases() do
86 | total_tc = total_tc + 1
87 | for testname, test in lunit.tests(tcname) do
88 | total_tests = total_tests + 1
89 | end
90 | end
91 |
92 | printformat("Loaded testsuite with %d tests in %d testcases.\n\n", total_tests, total_tc)
93 | end
94 |
95 |
96 | function run(testcasename, testname)
97 | -- NOP
98 | end
99 |
100 |
101 | function err(fullname, message, traceback)
102 | writestatus("E")
103 | msgs[#msgs+1] = "Error! ("..fullname.."):\n"..message.."\n\t"..table.concat(traceback, "\n\t") .. "\n"
104 | end
105 |
106 |
107 | function fail(fullname, where, message, usermessage)
108 | writestatus("F")
109 | local text = "Failure ("..fullname.."):\n"..
110 | where..": "..message.."\n"
111 |
112 | if usermessage then
113 | text = text .. where..": "..usermessage.."\n"
114 | end
115 |
116 | msgs[#msgs+1] = text
117 | end
118 |
119 |
120 | function pass(testcasename, testname)
121 | writestatus(".")
122 | end
123 |
124 |
125 |
126 | function done()
127 | printformat("\n\n%d Assertions checked.\n", lunit.stats.assertions )
128 | print()
129 |
130 | for i, msg in ipairs(msgs) do
131 | printformat( "%3d) %s\n", i, msg )
132 | end
133 |
134 | printformat("Testsuite finished (%d passed, %d failed, %d errors).\n",
135 | lunit.stats.passed, lunit.stats.failed, lunit.stats.errors )
136 | end
137 |
138 |
139 |
140 |
141 |
142 |
--------------------------------------------------------------------------------
/erlmon-1.0/wwwroot/template.html:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
17 |
18 | [[[page:title()]]]
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
49 |
50 |
51 | [[[page:body()]]]
52 |
53 |
56 |
57 |
62 |
63 |
64 |
81 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/storage.erl:
--------------------------------------------------------------------------------
1 |
2 | -module(storage).
3 | -author(darrik@darmasoft.com).
4 |
5 | -export([start/0]).
6 | -export([init/0]).
7 |
8 | -export([announce/2]).
9 |
10 | -export([state_change/1]).
11 | -export([alert_sent/1]).
12 |
13 | -export([test/2]).
14 | -export([status/0]).
15 |
16 | -include("include/erlmon.hrl").
17 |
18 | start() ->
19 | debug:log_to(console, {}),
20 | register(?MODULE, Pid=spawn_link(?MODULE, init, [])),
21 | {ok, Pid}.
22 |
23 | init() ->
24 | debug:log("storage: initializing"),
25 | debug:log("storage: touching world"),
26 | Nodes = net_adm:world(),
27 | debug:log("storage: found ~p", [Nodes]),
28 | NodeCount = length(Nodes),
29 | case NodeCount > 1 of
30 | true ->
31 | debug:log("storage: we are not the first; announcing"),
32 | init_storage(false),
33 | announce_storage_to_nodes(Nodes);
34 | false ->
35 | debug:log("storage: we are first; initializing"),
36 | init_storage(true)
37 | end,
38 | erlmon:finished(?MODULE),
39 | loop([]).
40 |
41 | loop(State) ->
42 | receive
43 | {Sender, status} ->
44 | debug:log("storage: received status request"),
45 | Sender ! {ok, ok},
46 | loop(State);
47 | Msg = #state_change{} ->
48 | debug:log("storage: received state_change"),
49 | store(Msg),
50 | loop(State);
51 | #sent_alert{}=Alert ->
52 | debug:log("storage: received sent_alert"),
53 | store(Alert),
54 | loop(State);
55 | #storage_ack_announce{sender=Sender, node=Node} ->
56 | debug:log("storage: received ACK announce from ~p on ~p", [Sender, Node]),
57 | loop(State);
58 | #storage_announce{sender=Sender, node=Node} ->
59 | debug:log("storage: received announce from ~p on ~p", [Sender, Node]),
60 | copy_storage_to_node(Node),
61 | Sender ! #storage_ack_announce{sender=self(), node=node()},
62 | loop(State);
63 | M ->
64 | debug:log("storage: UNKNOWN: ~p", [M]),
65 | loop(State)
66 | end.
67 |
68 | announce(Sender, Node) ->
69 | storage ! #storage_announce{sender=Sender, node=Node},
70 | ok.
71 |
72 | announce_storage_to_nodes([Node|T]) when Node =:= node() ->
73 | debug:log("storage: not announcing to self"),
74 | announce_storage_to_nodes(T);
75 | announce_storage_to_nodes([Node|T]) ->
76 | debug:log("storage: announcing to ~p", [Node]),
77 | Pid = rpc:call(Node, erlang, whereis, [storage]),
78 | debug:log("storage: found storage at ~p on ~p", [Pid, Node]),
79 | Pid ! #storage_announce{sender=self(), node=node()},
80 | announce_storage_to_nodes(T);
81 | announce_storage_to_nodes([]) -> ok.
82 |
83 | init_storage(false) ->
84 | debug:log("storage: initializing storage"),
85 | mnesia:start();
86 | init_storage(true) ->
87 | init_storage(false),
88 | debug:log("storage: initializing schema"),
89 | mnesia:change_table_copy_type(schema, node(), ram_copies),
90 | create_tables(),
91 | wait_for_tables().
92 |
93 | create_tables() ->
94 | mnesia:create_table(test, [{attributes, record_info(fields, test)}, {type, bag}, {ram_copies, [node()]}]),
95 | mnesia:create_table(state_change, [{attributes, record_info(fields, state_change)}, {type, bag}, {ram_copies, [node()]}]),
96 | mnesia:create_table(sent_alert, [{attributes, record_info(fields, sent_alert)}, {type, bag}, {ram_copies, [node()]}]).
97 |
98 | copy_tables(Node) ->
99 | _R1 = mnesia:add_table_copy(test, Node, ram_copies),
100 | _R2 = mnesia:add_table_copy(state_change, Node, ram_copies),
101 | _R3 = mnesia:add_table_copy(sent_alert, Node, ram_copies).
102 |
103 | wait_for_tables() ->
104 | mnesia:wait_for_tables([test, state_change, sent_alert], 10000).
105 |
106 | copy_storage_to_node(Node) ->
107 | debug:log("storage: copying storage to ~p", [Node]),
108 | _R1 = mnesia:change_config(extra_db_nodes, [Node]),
109 | _R2 = mnesia:change_table_copy_type(schema, Node, ram_copies),
110 | copy_tables(Node).
111 |
112 | test(K, V) ->
113 | Row = #test{key=K, value=V},
114 | F = fun() ->
115 | mnesia:write(Row)
116 | end,
117 | mnesia:transaction(F).
118 |
119 | state_change(Msg) ->
120 | storage ! Msg.
121 |
122 | alert_sent(Msg) ->
123 | storage ! Msg.
124 |
125 | store(Msg) ->
126 | F = fun() -> mnesia:write(Msg) end,
127 | mnesia:transaction(F).
128 |
129 | status() ->
130 | storage ! {self(), status},
131 | receive
132 | {ok, Status} -> ok
133 | end,
134 | Status.
135 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/state_change.erl:
--------------------------------------------------------------------------------
1 |
2 | -module(state_change).
3 | -author(darrik@darmasoft.com).
4 |
5 | -include("include/erlmon.hrl").
6 |
7 | -export([match/3]).
8 | -export([match/2]).
9 | -export([collect_booleans/1]).
10 | -export([and_booleans/1]).
11 | -export([match_field/3]).
12 | -export([test_same/0, test_diff/0, test_filter/0]).
13 |
14 | match(#state_change{}=SCA, #state_change_filter{state_change=SCB, fields=Fields}) ->
15 | match(SCA, SCB, Fields).
16 |
17 | match(#state_change{}=SCA, #state_change{}=SCB, Fields) when is_list(Fields) ->
18 | and_booleans(match_fields(SCA, SCB, Fields)).
19 |
20 | match_fields(#state_change{}=SCA, #state_change{}=SCB, [Field|T]=Fields) when is_list(Fields) ->
21 | [match_field(SCA, SCB, Field)|match(SCA, SCB, T)];
22 | match_fields(#state_change{}, #state_change{}, []) ->
23 | [].
24 |
25 |
26 | match_field(#state_change{}=SCA, #state_change{}=SCB, sender) ->
27 | case {SCA#state_change.sender, SCB#state_change.sender} of
28 | {_A, _A} ->
29 | true;
30 | {_A, _B} ->
31 | false
32 | end;
33 | match_field(#state_change{}=SCA, #state_change{}=SCB, node) ->
34 | case {SCA#state_change.node, SCB#state_change.node} of
35 | {_A, _A} ->
36 | true;
37 | {_A, _B} ->
38 | false
39 | end;
40 | match_field(#state_change{}=SCA, #state_change{}=SCB, objtype) ->
41 | case {SCA#state_change.objtype, SCB#state_change.objtype} of
42 | {_A, _A} ->
43 | true;
44 | {_A, _B} ->
45 | false
46 | end;
47 | match_field(#state_change{}=SCA, #state_change{}=SCB, obj) ->
48 | case {SCA#state_change.obj, SCB#state_change.obj} of
49 | {_A, _A} ->
50 | true;
51 | {_A, _B} ->
52 | false
53 | end;
54 | match_field(#state_change{}=SCA, #state_change{}=SCB, prev_state) ->
55 | case {SCA#state_change.prev_state, SCB#state_change.prev_state} of
56 | {_A, _A} ->
57 | true;
58 | {_A, _B} ->
59 | false
60 | end;
61 | match_field(#state_change{}=SCA, #state_change{}=SCB, new_state) ->
62 | case {SCA#state_change.new_state, SCB#state_change.new_state} of
63 | {_A, _A} ->
64 | true;
65 | {_A, _B} ->
66 | false
67 | end;
68 | match_field(#state_change{}=SCA, #state_change{}=SCB, data) ->
69 | case {SCA#state_change.data, SCB#state_change.data} of
70 | {_A, _A} ->
71 | true;
72 | {_A, _B} ->
73 | false
74 | end;
75 | match_field(#state_change{}=SCA, #state_change{}=SCB, ts) ->
76 | case {SCA#state_change.ts, SCB#state_change.ts} of
77 | {_A, _A} ->
78 | true;
79 | {_A, _B} ->
80 | false
81 | end;
82 | match_field(#state_change{}, #state_change{}, _Field) ->
83 | true.
84 |
85 |
86 | collect_booleans([true, true|T]) ->
87 | collect_booleans([true|T]);
88 | collect_booleans([false, false|T]) ->
89 | collect_booleans([false|T]);
90 | collect_booleans([true, false|T]) ->
91 | [true|collect_booleans([false|T])];
92 | collect_booleans([false, true|T]) ->
93 | [false|collect_booleans([true|T])];
94 | collect_booleans([true]) ->
95 | [true];
96 | collect_booleans([false]) ->
97 | [false];
98 | collect_booleans([]) ->
99 | [].
100 |
101 | and_booleans([true|T]) ->
102 | and_booleans(T);
103 | and_booleans([false|_T]) ->
104 | false;
105 | and_booleans(true) ->
106 | true;
107 | and_booleans(false) ->
108 | false;
109 | and_booleans([]) ->
110 | true.
111 |
112 | test_same() ->
113 | SCA = #state_change{sender=self(), node=node(), objtype=file, obj="config.lua", prev_state=unchanged, new_state=file_ctime_changed, ts=timestamp:now_i()},
114 | SCB = #state_change{sender=self(), node=node(), objtype=file, obj="config.lua", prev_state=unchanged, new_state=file_ctime_changed, ts=timestamp:now_i()},
115 | [SCA, SCB].
116 |
117 | test_diff() ->
118 | SCA = #state_change{sender=self(), node=node(), objtype=tcp_port, obj="localhost:22", prev_state=down, new_state=up, ts=timestamp:now_i()},
119 | SCB = #state_change{sender=self(), node=node(), objtype=tcp_port, obj="localhost:22", prev_state=up, new_state=down, ts=timestamp:now_i()},
120 | [SCA, SCB].
121 |
122 | test_filter() ->
123 | SCA = #state_change{sender=self(), node=node(), objtype=tcp_port, obj="localhost:22", prev_state=down, new_state=up, ts=timestamp:now_i()},
124 | SCB = #state_change{sender=self(), node=node(), objtype=tcp_port, obj="localhost:22", prev_state=up, new_state=down, ts=timestamp:now_i()},
125 | Fields = [objtype, obj],
126 | SCF = #state_change_filter{state_change=SCB, fields=Fields},
127 | [SCA, SCF].
128 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/process_monitor.erl:
--------------------------------------------------------------------------------
1 |
2 | -module(process_monitor).
3 | -author(darrik@darmasoft.com).
4 |
5 | -export([start/1]).
6 | -export([init/1]).
7 | -export([monitor/1]).
8 | -export([unmonitor/1]).
9 | -export([status/0]).
10 | -export([status/1]).
11 |
12 | -include("include/erlmon.hrl").
13 |
14 | status() ->
15 | process_monitor_man:status().
16 |
17 | status(_Pid) ->
18 | {ok, running}.
19 |
20 | monitor(ProcessName) ->
21 | process_monitor_man:monitor(ProcessName).
22 |
23 | unmonitor(ProcessName) ->
24 | process_monitor_man:unmonitor(ProcessName).
25 |
26 | start(ProcessName) ->
27 | {ok, spawn_link(?MODULE, init, [ProcessName])}.
28 |
29 | init(Pid) when is_integer(Pid) ->
30 | debug:log("process_monitor: starting for ~p", [Pid]),
31 | Name = ps:name_for_pid(Pid),
32 | case Name of
33 | null ->
34 | state_change_em:notify(#state_change{sender=self(), node=node(), objtype=process, obj=Pid, prev_state=unknown, new_state=not_running, ts=timestamp:now_i()});
35 | P ->
36 | state_change_em:notify(#state_change{sender=self(), node=node(), objtype=process, obj=P, prev_state=unknown, new_state=running, ts=timestamp:now_i()}),
37 | loop(lists:flatten(io_lib:format("~p", [Pid])), P, running)
38 | end;
39 | init(ProcessName) ->
40 | debug:log("process_monitor: starting for ~p", [ProcessName]),
41 | Pid = ps:pid_for_process(ProcessName),
42 | case Pid of
43 | null ->
44 | state_change_em:notify(#state_change{sender=self(), node=node(), objtype=process, obj=ProcessName, prev_state=unknown, new_state=not_running, ts=timestamp:now_i()}),
45 | loop(null, ProcessName, not_running);
46 | P ->
47 | state_change_em:notify(#state_change{sender=self(), node=node(), objtype=process, obj=ProcessName, prev_state=unknown, new_state=running, ts=timestamp:now_i()}),
48 | loop(P, ProcessName, running)
49 | end.
50 |
51 | loop(Pid, ProcessName, running) ->
52 | receive
53 | stop ->
54 | state_change_em:notify(#state_change{sender=self(), node=node(), objtype=process, obj=ProcessName, prev_state=running, new_state=unmonitored, ts=timestamp:now_i()})
55 | after
56 | 3000 ->
57 | Cpid = ps:pid_for_process(ProcessName),
58 | case Cpid of
59 | null ->
60 | state_change_em:notify(#state_change{sender=self(), node=node(), objtype=process, obj=ProcessName, prev_state=running, new_state=not_running, ts=timestamp:now_i()}),
61 | loop(null, ProcessName, not_running);
62 | Pid ->
63 | loop(Pid, ProcessName, running);
64 | NewPid ->
65 | state_change_em:notify(#state_change{sender=self(), node=node(), objtype=process, obj=ProcessName, prev_state=running, new_state=restarted, ts=timestamp:now_i()}),
66 | loop(NewPid, ProcessName, restarted)
67 | end
68 | end;
69 | loop(null, ProcessName, not_running) ->
70 | receive
71 | stop ->
72 | state_change_em:notify(#state_change{sender=self(), node=node(), objtype=process, obj=ProcessName, prev_state=not_running, new_state=unmonitored, ts=timestamp:now_i()})
73 | after
74 | 3000 ->
75 | Cpid = ps:pid_for_process(ProcessName),
76 | case Cpid of
77 | null ->
78 | loop(null, ProcessName, not_running);
79 | Pid ->
80 | state_change_em:notify(#state_change{sender=self(), node=node(), objtype=process, obj=ProcessName, prev_state=not_running, new_state=running, ts=timestamp:now_i()}),
81 | loop(Pid, ProcessName, running)
82 | end
83 | end;
84 | loop(Pid, ProcessName, restarted) ->
85 | receive
86 | stop ->
87 | state_change_em:notify(#state_change{sender=self(), node=node(), objtype=process, obj=ProcessName, prev_state=restarted, new_state=unmonitored, ts=timestamp:now_i()})
88 | after
89 | 3000 ->
90 | Cpid = ps:pid_for_process(ProcessName),
91 | case Cpid of
92 | null ->
93 | state_change_em:notify(#state_change{sender=self(), node=node(), objtype=process, obj=ProcessName, prev_state=restarted, new_state=not_running, ts=timestamp:now_i()}),
94 | loop(null, ProcessName, not_running);
95 | Pid ->
96 | state_change_em:notify(#state_change{sender=self(), node=node(), objtype=process, obj=ProcessName, prev_state=restarted, new_state=running, ts=timestamp:now_i()}),
97 | loop(Pid, ProcessName, running);
98 | NewPid ->
99 | state_change_em:notify(#state_change{sender=self(), node=node(), objtype=process, obj=ProcessName, prev_state=restarted, new_state=restarted, ts=timestamp:now_i()}),
100 | loop(NewPid, ProcessName, restarted)
101 | end
102 | end.
103 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/config.erl:
--------------------------------------------------------------------------------
1 | -module(config).
2 | -behaviour(gen_server).
3 | -author(chad@inakanetworks.com).
4 | -include("include/erlmon.hrl").
5 | -include("include/config.hrl").
6 | -include_lib("eunit/include/eunit.hrl").
7 | -define(SERVER, {global, ?MODULE}).
8 | -define(CONFIG_FILE, "config.lua").
9 |
10 | -export([
11 | authenticate/2,
12 | reload/0,
13 | setting/1,
14 | settings/0,
15 | start_link/0,
16 | update_file/1 ]).
17 |
18 | %% gen_server callbacks
19 | -export([init/1, handle_call/3, handle_cast/2, handle_info/2,
20 | terminate/2, code_change/3]).
21 |
22 | %% The config system is the glue between the lua configuration
23 | %% code and the Erlang system. The goal of the system is for
24 | %% each piece to do as little as possible. In this case, the config
25 | %% system simply starts a special case file_monitor that watches the
26 | %% erlmon config file. When a change is detected the file is reloaded.
27 |
28 | reload() ->
29 | debug:log("CONFIG:reload"),
30 | gen_server:call(config, {reload,event}).
31 |
32 | update_file(Content) ->
33 | file:write_file(?CONFIG_FILE,Content).
34 |
35 | authenticate(Login,Password) ->
36 | debug:log("CONFIG:authenticating"),
37 | gen_server:call(config, {authenticate, Login, Password}).
38 |
39 | %% config settings can be accessed as:
40 | %% config:setting([smtp,auth,username]) => "bob"
41 |
42 | settings() ->
43 | gen_server:call(config,erlmon).
44 |
45 | setting(Type) when is_atom(Type) ->
46 | setting([Type]);
47 |
48 | setting(Types) ->
49 | Settings = gen_server:call(config,erlmon),
50 | find_setting(Settings,Types).
51 |
52 | find_setting(Settings,[Type|Types]) ->
53 | Result = lists:keyfind(atom_to_list(Type),1,Settings),
54 | case Result of
55 | false ->
56 | Result;
57 | {_Name,NewSettings} -> find_setting(NewSettings,Types)
58 | end;
59 |
60 | find_setting(Settings,[]) ->
61 | Settings.
62 |
63 | start_link() ->
64 | gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
65 |
66 | init([]) ->
67 | debug:log("CONFIG: init~n"),
68 | {ok,State} = lua:new_state(),
69 | debug:log("CONFIG: lua state initialized. ~n"),
70 | erlmon:finished(?MODULE),
71 | {ok, #config_state{lua_state=State}}.
72 |
73 | %% reload config
74 | handle_call({reload,_ReloadType}, _From, _State) ->
75 | debug:log("CONFIG: loading lua file"),
76 | {ok, L} = lua:new_state(),
77 | NewState = #config_state{lua_state=L},
78 | Reply = lua:dofile(L,?CONFIG_FILE),
79 | case Reply of
80 | {error,_} ->
81 | debug:log("CONFIG: error in configuration file, NOT reloading.",[]),
82 | {reply, Reply, _State};
83 | _ ->
84 | Config = lua:gettable(L,global,"Erlmon"),
85 |
86 | {"monitors",Methods} = lists:keyfind("monitors",1,Config),
87 | {"list",Monitors} = lists:keyfind("list",1,Methods),
88 | apply_config_list(Monitors),
89 | debug:log("CONFIG: reloaded"),
90 | {reply, Reply, NewState}
91 | end;
92 |
93 | handle_call(lua_state, _From, State) ->
94 | {reply,State#config_state.lua_state,State};
95 |
96 | handle_call(erlmon, _From, State) ->
97 | L = State#config_state.lua_state,
98 | Reply = lua:gettable(L,global,"Erlmon"),
99 | {reply,Reply,State};
100 |
101 | %% call lua authenticate method
102 | handle_call({authenticate, Login, Password}, _From, State) ->
103 | L = State#config_state.lua_state,
104 | lua:getfield(L, global, "authenticate"),
105 | lua:pushstring(L, Login),
106 | lua:pushstring(L, Password),
107 | lua:call(L, 2, 1),
108 | {ok,boolean,Reply} = lua:pop(L),
109 | debug:log("CONFIG: Authenticate: Lua returned: ~p",[Reply]),
110 | {reply, Reply, State};
111 |
112 | handle_call(_Request, _From, State) ->
113 | Reply = ok,
114 | {reply, Reply, State}.
115 |
116 | handle_cast(_Msg, State) ->
117 | {noreply, State}.
118 |
119 | handle_info(_Info, State) ->
120 | {noreply, State}.
121 |
122 | terminate(_Reason, _State) ->
123 | ok.
124 |
125 | code_change(_OldVsn, State, _Extra) ->
126 | {ok, State}.
127 |
128 | apply_config_list(List) ->
129 | lists:map(fun({Monitor,MonitorList}) -> apply_monitors(Monitor,MonitorList) end,List),
130 | ok.
131 |
132 | apply_monitors(Monitor,MonitorList) ->
133 | debug:log("CONFIG: Telling monitor ~p to start the following monitors: ~p ",[Monitor,MonitorList]),
134 | Mod = list_to_atom(Monitor ++ "_monitor"),
135 | erlang:apply(Mod, monitor, [MonitorList]),
136 | ok.
137 |
138 | %% testcases
139 | config_test() -> ok.
140 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/erlmon_smtp.erl:
--------------------------------------------------------------------------------
1 |
2 | -module(erlmon_smtp).
3 | -author(darrik@darmasoft.com).
4 |
5 | -export([start_link/0]).
6 | -export([init/0]).
7 | -export([status/0]).
8 | -export([get_config/0]).
9 | -export([config/0]).
10 | -export([config/1]).
11 | -export([alert/2]).
12 |
13 | -include("include/erlmon.hrl").
14 |
15 | start_link() ->
16 | register(?MODULE, Pid=spawn_link(?MODULE, init, [])),
17 | {ok, Pid}.
18 |
19 | init() ->
20 | debug:log("erlmon_smtp: initializing"),
21 | state_change_em:notify(#state_change{sender=self(), node=node(), objtype=smtp, obj=self(), prev_state=down, new_state=disabled, ts=timestamp:now_i()}),
22 | loop({disabled, nil}).
23 |
24 | loop({OldStatus, OldConfig}=State) ->
25 | receive
26 | {Sender, get_config} ->
27 | Sender ! {ok, OldConfig},
28 | loop({OldStatus, OldConfig});
29 | {alert, SC, To} ->
30 | debug:log("erlmon_smtp: state_change alert: ~p", [SC]),
31 | Msg = create_msg(OldConfig, SC, To),
32 | send_msg(OldConfig, Msg, To),
33 | storage:alert_sent(#sent_alert{node=node(), to=To, objtype=SC#state_change.objtype, obj=SC#state_change.obj, prev_state=SC#state_change.prev_state, new_state=SC#state_change.new_state, ets=SC#state_change.ts, ats=timestamp:now_i()}),
34 | loop(State);
35 | {Sender, status} ->
36 | {Status, _Config} = State,
37 | Sender ! {status, Status},
38 | loop(State);
39 | {Sender, config, #smtp_config{}=C} ->
40 | debug:log("erlmon_smtp:config: ~p", [C]),
41 | {NewStatus, NewConfig} = set_config(State, C),
42 | Sender ! {ok, NewStatus},
43 | state_change_em:notify(#state_change{sender=self(), node=node(), objtype=smtp, obj=self(), prev_state=OldStatus, new_state=NewStatus, ts=timestamp:now_i()}),
44 | loop({NewStatus, NewConfig});
45 | {'DOWN', _Ref, _Type, _Pid, _Reason} ->
46 | debug:log("erlmon_smtp: lost primary gateway"),
47 | {ok, NewStatus} = find_primary_smtp(),
48 | loop({NewStatus, OldConfig});
49 | M ->
50 | debug:log("erlmon_smtp:UNKNOWN: ~p", [M]),
51 | loop(State)
52 | end.
53 |
54 | create_msg(Config, SC, To) ->
55 | erlmon_smtp_message:create(Config, SC, To).
56 |
57 | send_msg(Config, Msg, To) ->
58 | debug:log("erlmon_smtp: sending message: ~p", [Msg]),
59 | {ok, Pid} = smtp_fsm:start(Config#smtp_config.host),
60 | smtp_fsm:ehlo(Pid),
61 | if length(Config#smtp_config.login) > 0 ->
62 | smtp_fsm:login_login(Pid, Config#smtp_config.login, Config#smtp_config.pass);
63 | true -> ok
64 | end,
65 | smtp_fsm:sendemail(Pid, Config#smtp_config.address, To, Msg),
66 | smtp_fsm:close(Pid).
67 |
68 | get_config() ->
69 | erlmon_smtp ! {self(), get_config},
70 | receive
71 | {ok, Config} -> Config
72 | end.
73 |
74 | config() ->
75 | Host = config:setting([smtp,host]),
76 | Address = config:setting([smtp,address]),
77 | Port = config:setting([smtp,port]),
78 | Authtype = config:setting([smtp,auth,type]),
79 | Login = config:setting([smtp,auth,login]),
80 | Password = config:setting([smtp,auth,password]),
81 | SC = #smtp_config{host=Host,port=Port,authtype=Authtype,address=Address,login=Login,pass=Password},
82 | config(SC).
83 |
84 | config(Config) ->
85 | erlmon_smtp ! {self(), config, Config},
86 | receive
87 | {ok, Reply} -> ok
88 | end,
89 | Reply.
90 |
91 | set_config(State, Config) ->
92 | case State of
93 | {_Status, Config} ->
94 | debug:log("erlmon_smtp: config already set"),
95 | State;
96 | _ ->
97 | debug:log("erlmon_smtp: setting config: ~p", [Config]),
98 | {ok, NewStatus} = find_primary_smtp(),
99 | {NewStatus, Config}
100 | end.
101 |
102 | status() ->
103 | erlmon_smtp ! {self(), status},
104 | receive
105 | {status, Reply} -> ok
106 | end,
107 | Reply.
108 |
109 | find_primary_smtp() ->
110 | case global:whereis_name(erlmon_smtp) of
111 | undefined ->
112 | debug:log("erlmon_smtp: no primary smtp gateway. becoming primary."),
113 | case global:register_name(erlmon_smtp, whereis(erlmon_smtp)) of
114 | yes ->
115 | debug:log("erlmon_smtp: primary smtp gateway"),
116 | {ok, primary};
117 | no ->
118 | debug:log("erlmon_smtp: failed to become primary gateway"),
119 | erlang:monitor(process, global:whereis_name(erlmon_smtp)),
120 | {ok, enabled}
121 | end;
122 | Pid ->
123 | debug:log("erlmon_smtp: primary smtp gateway found: ~p", [Pid]),
124 | debug:log("erlmon_smtp: becoming secondary"),
125 | erlang:monitor(process, Pid),
126 | {ok, secondary}
127 | end.
128 |
129 | alert(#state_change{}=SC, To) ->
130 | debug:log("erlmon_smtp: raising alert"),
131 | case global:whereis_name(erlmon_smtp) of
132 | undefined ->
133 | {error, no_primary_smtp};
134 | Pid ->
135 | Pid ! {alert, SC, To},
136 | ok
137 | end.
138 |
--------------------------------------------------------------------------------
/erlmon-1.0/c_src/erlua.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #include "erlua.h"
9 | #include "commands.h"
10 |
11 | static ErlDrvData start (ErlDrvPort port, char* cmd);
12 | static void stop (ErlDrvData handle);
13 | static void process (ErlDrvData handle, ErlIOVec *ev);
14 |
15 | static ErlDrvEntry lua_driver_entry = {
16 | NULL, /* init */
17 | start, /* startup */
18 | stop, /* shutdown */
19 | NULL, /* output */
20 | NULL, /* ready_input */
21 | NULL, /* ready_output */
22 | "liberlua", /* the name of the driver */
23 | NULL, /* finish */
24 | NULL, /* handle */
25 | NULL, /* control */
26 | NULL, /* timeout */
27 | process, /* process */
28 | NULL, /* ready_async */
29 | NULL, /* flush */
30 | NULL, /* call */
31 | NULL, /* event */
32 | ERL_DRV_EXTENDED_MARKER, /* ERL_DRV_EXTENDED_MARKER */
33 | ERL_DRV_EXTENDED_MAJOR_VERSION, /* ERL_DRV_EXTENDED_MAJOR_VERSION */
34 | ERL_DRV_EXTENDED_MAJOR_VERSION, /* ERL_DRV_EXTENDED_MINOR_VERSION */
35 | ERL_DRV_FLAG_USE_PORT_LOCKING /* ERL_DRV_FLAGs */
36 | };
37 |
38 | DRIVER_INIT(lua_driver) {
39 | return &lua_driver_entry;
40 | }
41 |
42 | static ErlDrvData
43 | start(ErlDrvPort port, char *cmd)
44 | {
45 | lua_State *L;
46 | L = luaL_newstate();
47 | luaL_openlibs(L);
48 |
49 | lua_drv_t* retval = (lua_drv_t*) driver_alloc(sizeof(lua_drv_t));
50 | retval->port = port;
51 | retval->L = L;
52 |
53 | return (ErlDrvData) retval;
54 | }
55 |
56 | static void
57 | stop(ErlDrvData handle)
58 | {
59 | lua_drv_t* driver_data = (lua_drv_t*) handle;
60 | lua_close(driver_data->L);
61 | driver_free(driver_data);
62 | }
63 |
64 | static void
65 | process(ErlDrvData handle, ErlIOVec *ev)
66 | {
67 | lua_drv_t *driver_data = (lua_drv_t*) handle;
68 | char *buf = ev->binv[1]->orig_bytes;
69 | int index = 0;
70 | int arty, version;
71 | long command;
72 |
73 | ei_decode_version(buf, &index, &version);
74 | ei_decode_tuple_header(buf, &index, &arty);
75 | ei_decode_long(buf, &index, &command);
76 |
77 | // printf("Command: %ld\n", command);
78 | // printf("sizeof: int: %ld, long: %ld, long long: %ld\n", sizeof(int), sizeof(long), sizeof(long long));
79 |
80 | switch(command) {
81 | case ERL_LUA_CALL:
82 | erl_lua_call(driver_data, buf, index);
83 | break;
84 | case ERL_LUA_CONCAT:
85 | erl_lua_concat(driver_data, buf, index);
86 | break;
87 | case ERL_LUA_GETFIELD:
88 | erl_lua_getfield(driver_data, buf, index);
89 | break;
90 | case ERL_LUA_GETGLOBAL:
91 | erl_lua_getglobal(driver_data, buf, index);
92 | break;
93 | case ERL_LUA_GETTOP:
94 | erl_lua_gettop(driver_data, buf, index);
95 | break;
96 | case ERL_LUA_NEXT:
97 | erl_lua_next(driver_data, buf, index);
98 | break;
99 |
100 | case ERL_LUA_PUSHBOOLEAN:
101 | erl_lua_pushboolean(driver_data, buf, index);
102 | break;
103 | case ERL_LUA_PUSHINTEGER:
104 | erl_lua_pushinteger(driver_data, buf, index);
105 | break;
106 | case ERL_LUA_PUSHSTRING:
107 | erl_lua_pushstring(driver_data, buf, index);
108 | break;
109 | case ERL_LUA_PUSHNIL:
110 | erl_lua_pushnil(driver_data, buf, index);
111 | break;
112 | case ERL_LUA_PUSHNUMBER:
113 | erl_lua_pushnumber(driver_data, buf, index);
114 | break;
115 | case ERL_LUA_REMOVE:
116 | erl_lua_remove(driver_data, buf, index);
117 | break;
118 | case ERL_LUA_SETFIELD:
119 | erl_lua_setfield(driver_data, buf, index);
120 | break;
121 | case ERL_LUA_SETGLOBAL:
122 | erl_lua_setglobal(driver_data, buf, index);
123 | break;
124 | case ERL_LUA_TOBOOLEAN:
125 | erl_lua_toboolean(driver_data, buf, index);
126 | break;
127 | case ERL_LUA_TOINTEGER:
128 | erl_lua_tointeger(driver_data, buf, index);
129 | break;
130 | case ERL_LUA_TOLSTRING:
131 | erl_lua_tolstring(driver_data, buf, index);
132 | break;
133 | case ERL_LUA_TONUMBER:
134 | erl_lua_tonumber(driver_data, buf, index);
135 | break;
136 | case ERL_LUA_TYPE:
137 | erl_lua_type(driver_data, buf, index);
138 | break;
139 |
140 | case ERL_LUAL_DOSTRING:
141 | erl_lual_dostring(driver_data, buf, index);
142 | break;
143 |
144 | case ERL_LUAL_DOFILE:
145 | erl_lual_dofile(driver_data, buf, index);
146 | break;
147 |
148 | default:
149 | erl_lua_no_command(driver_data);
150 | }
151 | }
152 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/node.erl:
--------------------------------------------------------------------------------
1 |
2 | -module(node).
3 | -author(darrik@darmasoft.com).
4 |
5 | -export([start/0]).
6 | -export([init/0]).
7 | -export([monitor_node/1]).
8 | -export([status/0]).
9 |
10 | -include("include/erlmon.hrl").
11 |
12 | start() ->
13 | register(?MODULE, Pid=spawn_link(?MODULE, init, [])),
14 | {ok, Pid}.
15 |
16 | init() ->
17 | debug:log("node: initializing"),
18 | State = net_adm:world(),
19 | debug:log("node: initial state: ~p", [State]),
20 | NewState = start_monitoring_nodes(State),
21 | debug:log("node: final state: ~p", [NewState]),
22 | announce(NewState, NewState),
23 | erlmon:finished(?MODULE),
24 | loop(NewState).
25 |
26 | loop(State) ->
27 | receive
28 | {Sender, _Status} ->
29 | debug:log("node: received status request"),
30 | Sender ! {ok, State},
31 | loop(State);
32 | {node_status, Node, Status} ->
33 | debug:log("node: received node_status: ~p:~p", [Node, Status]),
34 | NewState = set_node_status(Node, Status, State),
35 | loop(NewState);
36 | _Msg = #node_ack_announce{sender=_Sender, pid=Pid, node=Node, state=TheirState} ->
37 | debug:log("node: received ack_announce for ~p on ~p~n~p", [Pid, Node, TheirState]),
38 | case node_monitored(Node, State) of
39 | true ->
40 | NewState = State;
41 | false ->
42 | start_monitoring_node(Node),
43 | NewState = set_node_status(Node, up, State)
44 | end,
45 | loop(NewState);
46 | _Msg = #node_announce{sender=_Sender, pid=Pid, node=Node, state=TheirState} ->
47 | debug:log("node: received announce for ~p on ~p~n~p", [Pid, Node, TheirState]),
48 | case node_monitored(Node, State) of
49 | true ->
50 | NewState = State;
51 | false ->
52 | start_monitoring_node(Node),
53 | NewState = set_node_status(Node, up, State),
54 | Pid ! #node_ack_announce{sender=self(), pid=self(), node=node(), state=State}
55 | end,
56 | loop(NewState);
57 | M ->
58 | debug:log("node:UNKNOWN: ~p", [M]),
59 | loop(State)
60 | end.
61 |
62 | start_monitoring_nodes([Node|T]) ->
63 | [start_monitoring_node(Node)|start_monitoring_nodes(T)];
64 | start_monitoring_nodes([]) -> [].
65 |
66 | start_monitoring_node(Node) ->
67 | case Node == node() of
68 | false ->
69 | %erlang:monitor_node(Node, true),
70 | %debug:log("monitoring node: ~p", [Node]),
71 | spawn(node, monitor_node, [Node]),
72 | {Node, up};
73 | true ->
74 | {Node, up}
75 | end.
76 |
77 | announce([{Node, up}|T], State) ->
78 | debug:log("node: announce(~p)", [Node]),
79 | case Node == node() of
80 | false ->
81 | Pid = find_node_pid(Node),
82 | case Pid of
83 | undefined ->
84 | debug:log("can not announce to node ~p: undefined Pid", [Node]);
85 | _ ->
86 | debug:log("node: announcing to ~p on ~p", [Pid, Node]),
87 | Pid ! #node_announce{sender=self(), pid=self(), node=node(), state=State}
88 | end,
89 | announce(T, State);
90 | true ->
91 | debug:log("node: not announcing to self"),
92 | state_change_em:notify(#state_change{sender=self(), node=node(), objtype=?MODULE, obj=node(), prev_state=down, new_state=up, ts=timestamp:now_i()}),
93 | announce(T, State)
94 | end;
95 | announce([], _State) ->
96 | [].
97 |
98 | find_node_pid(Node) when is_atom(Node) ->
99 | rpc:call(Node, erlang, whereis, [node]).
100 |
101 | monitor_node(Node) ->
102 | debug:log("node: monitoring ~p (~p)", [Node, self()]),
103 | state_change_em:notify(#state_change{sender=self(), node=node(), objtype=?MODULE, obj=Node, prev_state=down, new_state=up, ts=timestamp:now_i()}),
104 | erlang:monitor_node(Node, true),
105 | receive
106 | {nodedown, Node} ->
107 | debug:log("node: received nodedown for ~p (~p)", [Node, self()]),
108 | state_change_em:notify(#state_change{sender=self(), node=node(), objtype=?MODULE, obj=Node, prev_state=up, new_state=down, ts=timestamp:now_i()}),
109 | node ! {node_status, Node, down};
110 | M ->
111 | debug:log("node:UNKNOWN: ~p (~p)", [M, self()])
112 | end.
113 |
114 | %add_node_to_state(Node, [Node|_T]=State) ->
115 | % State;
116 | %add_node_to_state(Node, [H|T]) ->
117 | % [H|add_node_to_state(Node, T)];
118 | %add_node_to_state(Node, []) ->
119 | % [Node].
120 | %
121 | %remove_node_from_state(Node, [Node|T]) ->
122 | % T;
123 | %remove_node_from_state(Node, [H|T]) ->
124 | % [H|remove_node_from_state(Node, T)];
125 | %remove_node_from_state(Node, []) ->
126 | % [].
127 |
128 | node_monitored(Node, [{Node, up}|_T]) ->
129 | debug:log("node: node (~p) already monitored!", [Node]),
130 | true;
131 | node_monitored(Node, [_H|T]) ->
132 | node_monitored(Node, T);
133 | node_monitored(Node, []) ->
134 | debug:log("node: node (~p) not monitored yet", [Node]),
135 | false.
136 |
137 | set_node_status(Node, Status, [{Node, _}|T]) ->
138 | [{Node, Status}|T];
139 | set_node_status(Node, Status, [H|T]) ->
140 | [H|set_node_status(Node, Status, T)];
141 | set_node_status(Node, Status, []) ->
142 | [{Node, Status}].
143 |
144 | status() ->
145 | node ! {self(), status},
146 | receive
147 | {ok, Status} -> ok
148 | end,
149 | Status.
150 |
--------------------------------------------------------------------------------
/erlmon-1.0/c_src/commands.h:
--------------------------------------------------------------------------------
1 | /* General Lua API */
2 |
3 | #define ERL_LUA_ALLOC 1
4 | #define ERL_LUA_ATPANIC 2
5 | #define ERL_LUA_CALL 3
6 | #define ERL_LUA_CFUNCTION 4
7 | #define ERL_LUA_CHECKSTACK 5
8 | #define ERL_LUA_CLOSE 6
9 | #define ERL_LUA_CONCAT 7
10 | #define ERL_LUA_CPCALL 8
11 | #define ERL_LUA_CREATETABLE 9
12 | #define ERL_LUA_DUMP 10
13 | #define ERL_LUA_EQUAL 11
14 | #define ERL_LUA_ERROR 12
15 | #define ERL_LUA_GC 13
16 | #define ERL_LUA_GETALLOCF 14
17 | #define ERL_LUA_GETFENV 15
18 | #define ERL_LUA_GETFIELD 16
19 | #define ERL_LUA_GETGLOBAL 17
20 | #define ERL_LUA_GETMETATABLE 18
21 | #define ERL_LUA_GETTABLE 19
22 | #define ERL_LUA_GETTOP 20
23 | #define ERL_LUA_INSERT 21
24 | #define ERL_LUA_ISBOOLEAN 22
25 | #define ERL_LUA_ISCFUNCTION 23
26 | #define ERL_LUA_ISFUNCTION 24
27 | #define ERL_LUA_ISLIGHTUSERDATA 25
28 | #define ERL_LUA_ISNIL 26
29 | #define ERL_LUA_ISNONE 27
30 | #define ERL_LUA_ISNONEORNIL 28
31 | #define ERL_LUA_ISNUMBER 29
32 | #define ERL_LUA_ISSTRING 30
33 | #define ERL_LUA_ISTABLE 31
34 | #define ERL_LUA_ISTHREAD 32
35 | #define ERL_LUA_ISUSERDATA 33
36 | #define ERL_LUA_LESSTHAN 34
37 | #define ERL_LUA_LOAD 35
38 | #define ERL_LUA_NEWSTATE 36
39 | #define ERL_LUA_NEWTABLE 37
40 | #define ERL_LUA_NEWTHREAD 38
41 | #define ERL_LUA_NEWUSERDATA 39
42 | #define ERL_LUA_NEXT 40
43 | #define ERL_LUA_OBJLEN 41
44 | #define ERL_LUA_PCALL 42
45 | #define ERL_LUA_POP 43
46 | #define ERL_LUA_PUSHBOOLEAN 44
47 | #define ERL_LUA_PUSHCCLOSURE 45
48 | #define ERL_LUA_PUSHCFUNCTION 46
49 | #define ERL_LUA_PUSHFSTRING 47
50 | #define ERL_LUA_PUSHINTEGER 48
51 | #define ERL_LUA_PUSHLIGHTUSERDATA 49
52 | #define ERL_LUA_PUSHLITERAL 50
53 | #define ERL_LUA_PUSHLSTRING 51
54 | #define ERL_LUA_PUSHNIL 52
55 | #define ERL_LUA_PUSHNUMBER 53
56 | #define ERL_LUA_PUSHSTRING 54
57 | #define ERL_LUA_PUSHTHREAD 55
58 | #define ERL_LUA_PUSHVALUE 56
59 | #define ERL_LUA_PUSHVFSTRING 57
60 | #define ERL_LUA_RAWEQUAL 58
61 | #define ERL_LUA_RAWGET 59
62 | #define ERL_LUA_RAWGETI 60
63 | #define ERL_LUA_RAWSET 61
64 | #define ERL_LUA_RAWSETI 62
65 | #define ERL_LUA_REGISTER 63
66 | #define ERL_LUA_REMOVE 64
67 | #define ERL_LUA_REPLACE 65
68 | #define ERL_LUA_RESUME 66
69 | #define ERL_LUA_SETALLOCF 67
70 | #define ERL_LUA_SETFENV 68
71 | #define ERL_LUA_SETFIELD 69
72 | #define ERL_LUA_SETGLOBAL 70
73 | #define ERL_LUA_SETMETATABLE 71
74 | #define ERL_LUA_SETTABLE 72
75 | #define ERL_LUA_SETTOP 73
76 | #define ERL_LUA_STATUS 74
77 | #define ERL_LUA_TOBOOLEAN 75
78 | #define ERL_LUA_TOCFUNCTION 76
79 | #define ERL_LUA_TOINTEGER 77
80 | #define ERL_LUA_TOLSTRING 78
81 | #define ERL_LUA_TONUMBER 79
82 | #define ERL_LUA_TOPOINTER 80
83 | #define ERL_LUA_TOSTRING 81
84 | #define ERL_LUA_TOTHREAD 82
85 | #define ERL_LUA_TOUSERDATA 83
86 | #define ERL_LUA_TYPE 84
87 | #define ERL_LUA_TYPENAME 85
88 | #define ERL_LUA_XMOVE 86
89 | #define ERL_LUA_YIELD 87
90 |
91 |
92 | /* Lua Auxiliary Library */
93 |
94 | #define ERL_LUAL_ADDCHAR 88
95 | #define ERL_LUAL_ADDLSTRING 89
96 | #define ERL_LUAL_ADDSIZE 90
97 | #define ERL_LUAL_ADDSTRING 91
98 | #define ERL_LUAL_ADDVALUE 92
99 | #define ERL_LUAL_ARGCHECK 93
100 | #define ERL_LUAL_ARGERROR 94
101 | #define ERL_LUAL_BUFFINIT 95
102 | #define ERL_LUAL_CALLMETA 96
103 | #define ERL_LUAL_CHECKANY 97
104 | #define ERL_LUAL_CHECKINT 98
105 | #define ERL_LUAL_CHECKINTEGER 99
106 | #define ERL_LUAL_CHECKLONG 100
107 | #define ERL_LUAL_CHECKLSTRING 101
108 | #define ERL_LUAL_CHECKNUMBER 102
109 | #define ERL_LUAL_CHECKOPTION 103
110 | #define ERL_LUAL_CHECKSTACK 104
111 | #define ERL_LUAL_CHECKSTRING 105
112 | #define ERL_LUAL_CHECKTYPE 106
113 | #define ERL_LUAL_CHECKUDATA 107
114 | #define ERL_LUAL_DOFILE 108
115 | #define ERL_LUAL_DOSTRING 109
116 | #define ERL_LUAL_ERROR 110
117 | #define ERL_LUAL_GETMETAFIELD 111
118 | #define ERL_LUAL_GETMETATABLE 112
119 | #define ERL_LUAL_GSUB 113
120 | #define ERL_LUAL_LOADBUFFER 114
121 | #define ERL_LUAL_LOADFILE 115
122 | #define ERL_LUAL_LOADSTRING 116
123 | #define ERL_LUAL_NEWMETATABLE 117
124 | #define ERL_LUAL_NEWSTATE 118
125 | #define ERL_LUAL_OPENLIBS 119
126 | #define ERL_LUAL_OPTINT 120
127 | #define ERL_LUAL_OPTINTEGER 121
128 | #define ERL_LUAL_OPTLONG 122
129 | #define ERL_LUAL_OPTLSTRING 123
130 | #define ERL_LUAL_OPTNUMBER 124
131 | #define ERL_LUAL_OPTSTRING 125
132 | #define ERL_LUAL_PREPBUFFER 126
133 | #define ERL_LUAL_PUSHRESULT 127
134 | #define ERL_LUAL_REF 128
135 | #define ERL_LUAL_REGISTER 129
136 | #define ERL_LUAL_TYPENAME 130
137 | #define ERL_LUAL_TYPERROR 131
138 | #define ERL_LUAL_UNREF 132
139 | #define ERL_LUAL_WHERE 133
140 |
141 | #define ATOM_OK driver_mk_atom("ok")
142 | #define ATOM_ERROR driver_mk_atom("error")
143 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/file_monitor.erl:
--------------------------------------------------------------------------------
1 |
2 | -module(file_monitor).
3 | -author(darrik@darmasoft.com).
4 |
5 | -export([start/1]).
6 | -export([init/1]).
7 | -export([monitor/1]).
8 |
9 | -include_lib("kernel/include/file.hrl").
10 | -include("include/erlmon.hrl").
11 |
12 | monitor(Path) ->
13 | file_monitor_man:monitor(Path).
14 |
15 | start(FileName) ->
16 | {ok, spawn_link(?MODULE, init, [FileName])}.
17 |
18 | init(FileName) ->
19 | case file:read_file_info(FileName) of
20 | {ok, FileInfo} ->
21 | debug:log("fileinfo: ~p", [FileInfo]),
22 | state_change_em:notify(#state_change{sender=self(), node=node(), objtype=file, obj=FileName, prev_state=unmonitored, new_state=unchanged, ts=timestamp:now_i()}),
23 | loop(FileName, FileInfo);
24 | {error, Reason} ->
25 | debug:log("error: ~p", [Reason])
26 | end.
27 |
28 | loop(FileName, State) ->
29 | receive
30 | M ->
31 | debug:log("file_monitor: ~p: UNKNOWN: ~p", [self(), M])
32 | after
33 | 3000 ->
34 | case file:read_file_info(FileName) of
35 | {ok, State} ->
36 | NewState = State,
37 | loop(FileName, NewState);
38 | State ->
39 | NewState = State,
40 | loop(FileName, NewState);
41 | {ok, FileInfo} ->
42 | diff(FileName, State, FileInfo),
43 | NewState = FileInfo,
44 | loop(FileName, NewState);
45 | {error, Reason} ->
46 | state_change_em:notify(#state_change{sender=self(), node=node(), objtype=file, obj=FileName, prev_state=unchanged, new_state=nonexistent, ts=timestamp:now_i()}),
47 | NewState = {error, Reason},
48 | loop(FileName, NewState)
49 | end
50 | end.
51 |
52 | diff(FileName, {error, _Reason}, _NewFileInfo) ->
53 | state_change_em:notify(#state_change{sender=self(), node=node(), objtype=file, obj=FileName, prev_state=nonexistent, new_state=unchanged, ts=timestamp:now_i()}),
54 | ok;
55 | diff(FileName, OldFileInfo, NewFileInfo) ->
56 | case {OldFileInfo#file_info.size, NewFileInfo#file_info.size} of
57 | {_SA, _SA} ->
58 | same;
59 | {SA, SB} ->
60 | state_change_em:notify(#state_change{sender=self(), node=node(), objtype=file, obj=FileName, prev_state=unchanged, new_state=file_size_changed, data={SA, SB}, ts=timestamp:now_i()})
61 | end,
62 | case {OldFileInfo#file_info.type, NewFileInfo#file_info.type} of
63 | {_TA, _TA} ->
64 | same;
65 | {TA, TB} ->
66 | state_change_em:notify(#state_change{sender=self(), node=node(), objtype=file, obj=FileName, prev_state=unchanged, new_state=file_type_changed, data={TA, TB}, ts=timestamp:now_i()})
67 | end,
68 | case {OldFileInfo#file_info.access, NewFileInfo#file_info.access} of
69 | {_AA, _AA} ->
70 | same;
71 | {AA, AB} ->
72 | state_change_em:notify(#state_change{sender=self(), node=node(), objtype=file, obj=FileName, prev_state=unchanged, new_state=file_access_changed, data={AA, AB}, ts=timestamp:now_i()})
73 | end,
74 | case {OldFileInfo#file_info.atime, NewFileInfo#file_info.atime} of
75 | {_ATA, _ATA} ->
76 | same;
77 | {ATA, ATB} ->
78 | state_change_em:notify(#state_change{sender=self(), node=node(), objtype=file, obj=FileName, prev_state=unchanged, new_state=file_atime_changed, data={ATA, ATB}, ts=timestamp:now_i()})
79 | end,
80 | case {OldFileInfo#file_info.mtime, NewFileInfo#file_info.mtime} of
81 | {_MTA, _MTA} ->
82 | same;
83 | {MTA, MTB} ->
84 | state_change_em:notify(#state_change{sender=self(), node=node(), objtype=file, obj=FileName, prev_state=unchanged, new_state=file_mtime_changed, data={MTA, MTB}, ts=timestamp:now_i()})
85 | end,
86 | case {OldFileInfo#file_info.ctime, NewFileInfo#file_info.ctime} of
87 | {_CTA, _CTA} ->
88 | same;
89 | {CTA, CTB} ->
90 | state_change_em:notify(#state_change{sender=self(), node=node(), objtype=file, obj=FileName, prev_state=unchanged, new_state=file_ctime_changed, data={CTA, CTB}, ts=timestamp:now_i()})
91 | end,
92 | case {OldFileInfo#file_info.mode, NewFileInfo#file_info.mode} of
93 | {_MA, _MA} ->
94 | same;
95 | {MA, MB} ->
96 | state_change_em:notify(#state_change{sender=self(), node=node(), objtype=file, obj=FileName, prev_state=unchanged, new_state=file_mode_changed, data={MA, MB}, ts=timestamp:now_i()})
97 | end,
98 | case {OldFileInfo#file_info.links, NewFileInfo#file_info.links} of
99 | {_LA, _LA} ->
100 | same;
101 | {LA, LB} ->
102 | state_change_em:notify(#state_change{sender=self(), node=node(), objtype=file, obj=FileName, prev_state=unchanged, new_state=file_links_changed, data={LA, LB}, ts=timestamp:now_i()})
103 | end,
104 | case {OldFileInfo#file_info.major_device, NewFileInfo#file_info.major_device} of
105 | {_MDA, _MDA} ->
106 | same;
107 | {MDA, MDB} ->
108 | state_change_em:notify(#state_change{sender=self(), node=node(), objtype=file, obj=FileName, prev_state=unchanged, new_state=file_major_device_changed, data={MDA, MDB}, ts=timestamp:now_i()})
109 | end,
110 | case {OldFileInfo#file_info.minor_device, NewFileInfo#file_info.minor_device} of
111 | {_MIDA, _MIDA} ->
112 | same;
113 | {MIDA, MIDB} ->
114 | state_change_em:notify(#state_change{sender=self(), node=node(), objtype=file, obj=FileName, prev_state=unchanged, new_state=file_minor_device_changed, data={MIDA, MIDB}, ts=timestamp:now_i()})
115 | end,
116 | case {OldFileInfo#file_info.inode, NewFileInfo#file_info.inode} of
117 | {_IA, _IA} ->
118 | same;
119 | {IA, IB} ->
120 | state_change_em:notify(#state_change{sender=self(), node=node(), objtype=file, obj=FileName, prev_state=unchanged, new_state=file_inode_changed, data={IA, IB}, ts=timestamp:now_i()})
121 | end,
122 | case {OldFileInfo#file_info.uid, NewFileInfo#file_info.uid} of
123 | {_UIDA, _UIDA} ->
124 | same;
125 | {UIDA, UIDB} ->
126 | state_change_em:notify(#state_change{sender=self(), node=node(), objtype=file, obj=FileName, prev_state=unchanged, new_state=file_uid_changed, data={UIDA, UIDB}, ts=timestamp:now_i()})
127 | end,
128 | case {OldFileInfo#file_info.gid, NewFileInfo#file_info.gid} of
129 | {_GIDA, _GIDA} ->
130 | same;
131 | {GIDA, GIDB} ->
132 | state_change_em:notify(#state_change{sender=self(), node=node(), objtype=file, obj=FileName, prev_state=unchanged, new_state=file_gid_changed, data={GIDA, GIDB}, ts=timestamp:now_i()})
133 | end.
134 |
--------------------------------------------------------------------------------
/erlmon-1.0/include/lua_api.hrl:
--------------------------------------------------------------------------------
1 | % Lua Type Defs
2 |
3 | -define(LUA_TNIL, 0 ).
4 | -define(LUA_TBOOLEAN, 1 ).
5 | -define(LUA_TLIGHTUSERDATA, 2 ).
6 | -define(LUA_TNUMBER, 3 ).
7 | -define(LUA_TSTRING, 4 ).
8 | -define(LUA_TTABLE, 5 ).
9 | -define(LUA_TFUNCTION, 6 ).
10 | -define(LUA_TUSERDATA, 7 ).
11 | -define(LUA_TTHREAD, 8 ).
12 |
13 | % General Lua API
14 |
15 | -define(ERL_LUA_ALLOC, 1 ).
16 | -define(ERL_LUA_ATPANIC, 2 ).
17 | -define(ERL_LUA_CALL, 3 ).
18 | -define(ERL_LUA_CFUNCTION, 4 ).
19 | -define(ERL_LUA_CHECKSTACK, 5 ).
20 | -define(ERL_LUA_CLOSE, 6 ).
21 | -define(ERL_LUA_CONCAT, 7 ).
22 | -define(ERL_LUA_CPCALL, 8 ).
23 | -define(ERL_LUA_CREATETABLE, 9 ).
24 | -define(ERL_LUA_DUMP, 10).
25 | -define(ERL_LUA_EQUAL, 11).
26 | -define(ERL_LUA_ERROR, 12).
27 | -define(ERL_LUA_GC, 13).
28 | -define(ERL_LUA_GETALLOCF, 14).
29 | -define(ERL_LUA_GETFENV, 15).
30 | -define(ERL_LUA_GETFIELD, 16).
31 | -define(ERL_LUA_GETGLOBAL, 17).
32 | -define(ERL_LUA_GETMETATABLE, 18).
33 | -define(ERL_LUA_GETTABLE, 19).
34 | -define(ERL_LUA_GETTOP, 20).
35 | -define(ERL_LUA_INSERT, 21).
36 | -define(ERL_LUA_ISBOOLEAN, 22).
37 | -define(ERL_LUA_ISCFUNCTION, 23).
38 | -define(ERL_LUA_ISFUNCTION, 24).
39 | -define(ERL_LUA_ISLIGHTUSERDATA, 25).
40 | -define(ERL_LUA_ISNIL, 26).
41 | -define(ERL_LUA_ISNONE, 27).
42 | -define(ERL_LUA_ISNONEORNIL, 28).
43 | -define(ERL_LUA_ISNUMBER, 29).
44 | -define(ERL_LUA_ISSTRING, 30).
45 | -define(ERL_LUA_ISTABLE, 31).
46 | -define(ERL_LUA_ISTHREAD, 32).
47 | -define(ERL_LUA_ISUSERDATA, 33).
48 | -define(ERL_LUA_LESSTHAN, 34).
49 | -define(ERL_LUA_LOAD, 35).
50 | -define(ERL_LUA_NEWSTATE, 36).
51 | -define(ERL_LUA_NEWTABLE, 37).
52 | -define(ERL_LUA_NEWTHREAD, 38).
53 | -define(ERL_LUA_NEWUSERDATA, 39).
54 | -define(ERL_LUA_NEXT, 40).
55 | -define(ERL_LUA_OBJLEN, 41).
56 | -define(ERL_LUA_PCALL, 42).
57 | -define(ERL_LUA_POP, 43).
58 | -define(ERL_LUA_PUSHBOOLEAN, 44).
59 | -define(ERL_LUA_PUSHCCLOSURE, 45).
60 | -define(ERL_LUA_PUSHCFUNCTION, 46).
61 | -define(ERL_LUA_PUSHFSTRING, 47).
62 | -define(ERL_LUA_PUSHINTEGER, 48).
63 | -define(ERL_LUA_PUSHLIGHTUSERDATA, 49).
64 | -define(ERL_LUA_PUSHLITERAL, 50).
65 | -define(ERL_LUA_PUSHLSTRING, 51).
66 | -define(ERL_LUA_PUSHNIL, 52).
67 | -define(ERL_LUA_PUSHNUMBER, 53).
68 | -define(ERL_LUA_PUSHSTRING, 54).
69 | -define(ERL_LUA_PUSHTHREAD, 55).
70 | -define(ERL_LUA_PUSHVALUE, 56).
71 | -define(ERL_LUA_PUSHVFSTRING, 57).
72 | -define(ERL_LUA_RAWEQUAL, 58).
73 | -define(ERL_LUA_RAWGET, 59).
74 | -define(ERL_LUA_RAWGETI, 60).
75 | -define(ERL_LUA_RAWSET, 61).
76 | -define(ERL_LUA_RAWSETI, 62).
77 | -define(ERL_LUA_REGISTER, 63).
78 | -define(ERL_LUA_REMOVE, 64).
79 | -define(ERL_LUA_REPLACE, 65).
80 | -define(ERL_LUA_RESUME, 66).
81 | -define(ERL_LUA_SETALLOCF, 67).
82 | -define(ERL_LUA_SETFENV, 68).
83 | -define(ERL_LUA_SETFIELD, 69).
84 | -define(ERL_LUA_SETGLOBAL, 70).
85 | -define(ERL_LUA_SETMETATABLE, 71).
86 | -define(ERL_LUA_SETTABLE, 72).
87 | -define(ERL_LUA_SETTOP, 73).
88 | -define(ERL_LUA_STATUS, 74).
89 | -define(ERL_LUA_TOBOOLEAN, 75).
90 | -define(ERL_LUA_TOCFUNCTION, 76).
91 | -define(ERL_LUA_TOINTEGER, 77).
92 | -define(ERL_LUA_TOLSTRING, 78).
93 | -define(ERL_LUA_TONUMBER, 79).
94 | -define(ERL_LUA_TOPOINTER, 80).
95 | -define(ERL_LUA_TOSTRING, 81).
96 | -define(ERL_LUA_TOTHREAD, 82).
97 | -define(ERL_LUA_TOUSERDATA, 83).
98 | -define(ERL_LUA_TYPE, 84).
99 | -define(ERL_LUA_TYPENAME, 85).
100 | -define(ERL_LUA_XMOVE, 86).
101 | -define(ERL_LUA_YIELD, 87).
102 |
103 |
104 | %% Lua Auxiliary Library
105 |
106 | -define(ERL_LUAL_ADDCHAR, 88 ).
107 | -define(ERL_LUAL_ADDLSTRING, 89 ).
108 | -define(ERL_LUAL_ADDSIZE, 90 ).
109 | -define(ERL_LUAL_ADDSTRING, 91 ).
110 | -define(ERL_LUAL_ADDVALUE, 92 ).
111 | -define(ERL_LUAL_ARGCHECK, 93 ).
112 | -define(ERL_LUAL_ARGERROR, 94 ).
113 | -define(ERL_LUAL_BUFFINIT, 95 ).
114 | -define(ERL_LUAL_CALLMETA, 96 ).
115 | -define(ERL_LUAL_CHECKANY, 97 ).
116 | -define(ERL_LUAL_CHECKINT, 98 ).
117 | -define(ERL_LUAL_CHECKINTEGER, 99 ).
118 | -define(ERL_LUAL_CHECKLONG, 100).
119 | -define(ERL_LUAL_CHECKLSTRING, 101).
120 | -define(ERL_LUAL_CHECKNUMBER, 102).
121 | -define(ERL_LUAL_CHECKOPTION, 103).
122 | -define(ERL_LUAL_CHECKSTACK, 104).
123 | -define(ERL_LUAL_CHECKSTRING, 105).
124 | -define(ERL_LUAL_CHECKTYPE, 106).
125 | -define(ERL_LUAL_CHECKUDATA, 107).
126 | -define(ERL_LUAL_DOFILE, 108).
127 | -define(ERL_LUAL_DOSTRING, 109).
128 | -define(ERL_LUAL_ERROR, 110).
129 | -define(ERL_LUAL_GETMETAFIELD, 111).
130 | -define(ERL_LUAL_GETMETATABLE, 112).
131 | -define(ERL_LUAL_GSUB, 113).
132 | -define(ERL_LUAL_LOADBUFFER, 114).
133 | -define(ERL_LUAL_LOADFILE, 115).
134 | -define(ERL_LUAL_LOADSTRING, 116).
135 | -define(ERL_LUAL_NEWMETATABLE, 117).
136 | -define(ERL_LUAL_NEWSTATE, 118).
137 | -define(ERL_LUAL_OPENLIBS, 119).
138 | -define(ERL_LUAL_OPTINT, 120).
139 | -define(ERL_LUAL_OPTINTEGER, 121).
140 | -define(ERL_LUAL_OPTLONG, 122).
141 | -define(ERL_LUAL_OPTLSTRING, 123).
142 | -define(ERL_LUAL_OPTNUMBER, 124).
143 | -define(ERL_LUAL_OPTSTRING, 125).
144 | -define(ERL_LUAL_PREPBUFFER, 126).
145 | -define(ERL_LUAL_PUSHRESULT, 127).
146 | -define(ERL_LUAL_REF, 128).
147 | -define(ERL_LUAL_REGISTER, 129).
148 | -define(ERL_LUAL_TYPENAME, 130).
149 | -define(ERL_LUAL_TYPERROR, 131).
150 | -define(ERL_LUAL_UNREF, 132).
151 | -define(ERL_LUAL_WHERE, 133).
--------------------------------------------------------------------------------
/erlmon-1.0/wwwroot/nitrogen/web_app_theme.css:
--------------------------------------------------------------------------------
1 | * {margin:0;padding:0}
2 | .clear { clear: both; height: 0; }
3 |
4 | h1 { margin: 15px 0; font-size: 22px; font-weight: normal; }
5 | h2 { font-size: 22px; margin: 15px 0; font-weight: normal;}
6 | h3 { font-size: 18px; margin: 10px 0; font-weight: normal;}
7 | h4 { font-size: 14px; margin: 5px 0; font-weight: bold;}
8 | hr {height: 1px; border: 0; }
9 | p { margin: 15px 0;}
10 | a img { border: none; }
11 |
12 | body {
13 | font-size: 12px;
14 | font-family: sans-serif;
15 | }
16 |
17 | #container {
18 | min-width: 960px;
19 | }
20 |
21 | #header, #wrapper {
22 | padding: 0 20px;
23 | }
24 |
25 | #header {
26 | /*position: relative;*/
27 | padding-top: 1px;
28 | }
29 |
30 | #header h1 {
31 | margin: 0;
32 | padding: 0;
33 | font-size: 30px;
34 | }
35 |
36 | #header h1 a:link, #header h1 a:active, #header h1 a:hover, #header h1 a:visited {
37 | text-decoration: none;
38 | }
39 |
40 | #main {
41 | /*width: 70%;*/
42 | /*float: left;*/
43 | }
44 |
45 | .actions-bar {
46 | padding: 10px 1px;
47 | }
48 |
49 | .actions-bar .actions {
50 | float: left;
51 | }
52 |
53 |
54 | .actions-bar .pagination {
55 | float: right;
56 | padding: 1px 0;
57 | }
58 |
59 | #sidebar {
60 | width: 28%;
61 | float: right;
62 | }
63 |
64 | #sidebar h3 {
65 | padding: 10px 15px;
66 | margin: 0;
67 | font-size: 13px;
68 | }
69 |
70 | #sidebar .block {
71 | margin-bottom: 20px;
72 | padding-bottom: 10px;
73 | }
74 |
75 | #sidebar .block .content {
76 | padding: 0 15px;
77 | }
78 |
79 | #sidebar ul.navigation li a:link, #sidebar ul.navigation li a:visited {
80 | display: block;
81 | padding: 10px 15px;
82 | }
83 |
84 | #sidebar .block .sidebar-block, #sidebar .notice {
85 | padding:10px;
86 | }
87 |
88 | #wrapper {
89 | padding-top: 20px;
90 | }
91 |
92 | #main .block {
93 | margin-bottom: 20px;
94 | padding-top: 1px;
95 | }
96 |
97 | #main .block .content .inner {
98 | padding: 0 15px 15px;
99 | }
100 |
101 | #main .main p.first {
102 | margin-top: 0;
103 | }
104 |
105 | #user-navigation {
106 | position: absolute;
107 | top: 0px;
108 | right: 20px;
109 | }
110 |
111 | #main-navigation {
112 | width: 100%;
113 | }
114 |
115 | #user-navigation ul, #main-navigation ul, .secondary-navigation ul, #sidebar ul.navigation {
116 | margin: 0;
117 | padding: 0;
118 | list-style-type: none;
119 | }
120 |
121 | #user-navigation ul li, #main-navigation ul li, .secondary-navigation ul li {
122 | float: left;
123 | }
124 |
125 | #main-navigation ul li {
126 | margin-right: 5px;
127 | }
128 |
129 | #user-navigation ul li {
130 | padding: 5px 10px;
131 | }
132 |
133 | #main-navigation ul li a:link, #main-navigation ul li a:visited, #main-navigation ul li a:hover, #main-navigation ul li a:active,
134 | .secondary-navigation ul li a:link, .secondary-navigation ul li a:visited, .secondary-navigation ul li a:hover, .secondary-navigation ul li a:active,
135 | #user-navigation ul li a:link, #user-navigation ul li a:visited, #user-navigation ul li a:hover, #user-navigation ul li a:active {
136 | text-decoration: none;
137 | }
138 |
139 | #main-navigation ul li a {
140 | font-size: 15px;
141 | display: block;
142 | padding: 8px 15px;
143 | }
144 |
145 | .secondary-navigation {
146 | font-size: 13px;
147 | border-bottom-width: 10px;
148 | border-bottom-style: solid;
149 | }
150 |
151 | .secondary-navigation ul li a {
152 | display: block;
153 | padding: 10px 15px;
154 | }
155 |
156 | #footer {
157 | padding-bottom: 20px;
158 | }
159 |
160 | /* pagination */
161 |
162 | .pagination a, .pagination span {
163 | padding: 2px 5px;
164 | margin-right: 5px;
165 | display: block;
166 | float: left;
167 | border-style: solid;
168 | border-width: 1px;
169 | }
170 |
171 | .pagination span.current {
172 | font-weight: bold;
173 | }
174 |
175 | .pagination a {
176 | text-decoration: none;
177 | }
178 |
179 | /* tables */
180 | .table {
181 | width: 100%;
182 | border-collapse: collapse;
183 | margin-bottom: 15px;
184 | }
185 |
186 | .table th {
187 | padding: 10px;
188 | font-weight: bold;
189 | text-align: left;
190 | }
191 |
192 | .table th.first {
193 | /*width: 30px;*/
194 | }
195 |
196 | .table th.last {
197 | /*width: 200px;*/
198 | }
199 |
200 | .table .checkbox {
201 | margin-left: 10px;
202 | }
203 |
204 | .table td {
205 | padding: 10px;
206 | }
207 |
208 | .table td.last {
209 | text-align: right;
210 | }
211 |
212 | /* forms */
213 |
214 | input.checkbox {
215 | margin: 0;
216 | padding: 0;
217 | }
218 |
219 | .form .group {
220 | margin-bottom: 15px;
221 | }
222 |
223 | .form div.left {
224 | width: 20%;
225 | float: left;
226 | }
227 |
228 | .form div.right {
229 | width: 75%;
230 | float: right;
231 | }
232 |
233 | .form .columns .column {
234 | width: 48%;
235 | }
236 |
237 | .form .columns .left {
238 | float: left;
239 | }
240 |
241 | .form .columns .right {
242 | float: right;
243 | }
244 |
245 | .form label.label, .form input.text_field, .form textarea.text_area {
246 | font-size: 1.2em;
247 | padding: 1px 0;
248 | margin: 0;
249 | }
250 |
251 | textarea.textarea {
252 | width: 75%;
253 | height: 300px;
254 | }
255 |
256 | .form label.right {
257 | text-align: right;
258 | }
259 |
260 | .form input.checkbox, .form input.radio {
261 | margin-right: 5px;
262 | }
263 |
264 | .form label.checkbox, .form label.radio {
265 | line-height: 1.5em;
266 | }
267 |
268 | .form label.label {
269 | display: block;
270 | padding-bottom: 2px;
271 | font-weight: bold;
272 | }
273 |
274 | .form div.fieldWithErrors label.label {
275 | display: inline;
276 | }
277 |
278 | .form .fieldWithErrors .error {
279 | color: red;
280 | }
281 |
282 | .form input.text_field, .form textarea.text_area {
283 | width: 100%;
284 | border-width: 1px;
285 | border-style: solid;
286 | }
287 |
288 | /* lists */
289 |
290 | ul.list {
291 | margin: 0;
292 | padding: 0;
293 | list-style-type: none;
294 | }
295 |
296 | ul.list li {
297 | clear: left;
298 | padding-bottom: 5px;
299 | }
300 |
301 | ul.list li .left {
302 | float: left;
303 | }
304 |
305 | ul.list li .left .avatar {
306 | width: 50px;
307 | height: 50px;
308 | }
309 |
310 | ul.list li .item {
311 | margin-left: 80px;
312 | }
313 |
314 | ul.list li .item .avatar {
315 | float: left;
316 | margin: 0 5px 5px 0;
317 | width: 30px;
318 | height: 30px;
319 | }
320 |
321 | /* box */
322 |
323 | #box {
324 | width: 500px;
325 | margin: 0px auto;
326 | }
327 |
328 | #box .block {
329 | margin-bottom: 20px;
330 | }
331 |
332 | #box .block h2 {
333 | padding: 10px 15px;
334 | margin: 0;
335 | }
336 |
337 | #box .block .content {
338 | padding: 10px 20px;
339 | }
340 |
341 | .teaser {
342 | font-size: .8em;
343 | color: #aaa;
344 | }
345 |
346 | tr.even {
347 | background: #ddd;
348 | }
349 |
350 | tr.odd {
351 | background: #fff;
352 | }
353 |
354 |
--------------------------------------------------------------------------------
/erlmon-1.0/src/lua.erl:
--------------------------------------------------------------------------------
1 | -module(lua).
2 |
3 | -export([new_state/0,
4 | close/1,
5 | call/3,
6 | concat/2,
7 | dostring/2,
8 | dofile/2,
9 | dump_table/2,
10 | getfield/3,
11 | getglobal/2,
12 | gettable/3,
13 | gettable/2,
14 | gettop/1,
15 | next/2,
16 | pop/1,
17 | push/2,
18 | pushboolean/2,
19 | pushinteger/2,
20 | pushstring/2,
21 | pushnil/1,
22 | pushnumber/2,
23 | remove/2,
24 | setfield/3,
25 | setglobal/2,
26 | toboolean/2,
27 | tointeger/2,
28 | tolstring/2,
29 | tonumber/2,
30 | type/2,
31 | type_atom/2
32 | ]).
33 |
34 | -include("lua.hrl").
35 | -include("lua_api.hrl").
36 |
37 | new_state() ->
38 | {ok, lua_driver:open()}.
39 |
40 | close(L) ->
41 | lua_driver:close(L).
42 |
43 | dostring(#lua{port=Port}, Code) ->
44 | port_command(Port, term_to_binary({?ERL_LUAL_DOSTRING, Code})),
45 | receive_simple_response().
46 |
47 | dofile(#lua{port=Port}, Filename) ->
48 | port_command(Port, term_to_binary({?ERL_LUAL_DOFILE, Filename})),
49 | receive_simple_response().
50 |
51 | call(L, Args, Results) ->
52 | command(L, {?ERL_LUA_CALL, Args, Results}),
53 | receive_simple_response().
54 |
55 | concat(L, N) ->
56 | command(L, {?ERL_LUA_CONCAT, N}).
57 |
58 | dump_table(L, N) ->
59 | dump_table(L, N, none).
60 |
61 | dump_table(L, N, NextKey) ->
62 | io:format("dump_table(~p, ~p)~n", [N, NextKey]),
63 | case NextKey of
64 | none ->
65 | Str=lists:concat(["tmpkey, tmpval = pairs(", N, ")(", N, ")"]);
66 | NK ->
67 | Str=lists:concat(["tmpkey, tmpval = pairs(", N, ")(", N, ", \"", NK, "\")"])
68 | end,
69 | io:format("Str == ~p~n", [Str]),
70 | lual:dostring(L, Str),
71 | lua:getglobal(L, "tmpkey"),
72 | {ok, T} = lua:type(L, -1),
73 | case T of
74 | ?LUA_TNIL -> [];
75 | _ ->
76 | {ok, K} = lua:tolstring(L, -1),
77 | lua:remove(L, -1),
78 | lua:getglobal(L, "tmpval"),
79 | {ok, VT} = lua:type(L, -1),
80 | io:format("type == ~p~n", [VT]),
81 | case VT of
82 | ?LUA_TNUMBER ->
83 | {ok, V} = lua:tonumber(L, -1);
84 | ?LUA_TTABLE ->
85 | V = dump_table(L, lists:concat([N, ".", K]));
86 | _ ->
87 | {ok, V} = lua:tolstring(L, -1)
88 | end,
89 | lua:remove(L, -1),
90 | [{list_to_atom(K),V}|dump_table(L, N, K)]
91 | end.
92 |
93 | getfield(L, global, Name) ->
94 | getglobal(L, Name);
95 | getfield(L, Index, Name) ->
96 | command(L, {?ERL_LUA_GETFIELD, Index, Name}),
97 | receive_simple_response().
98 |
99 | getglobal(L, Name) ->
100 | command(L, {?ERL_LUA_GETGLOBAL, Name}),
101 | receive_simple_response().
102 |
103 | gettable(L, global, Name) when is_atom(Name) ->
104 | gettable(L, global, atom_to_list(Name));
105 | gettable(L, global, Name) ->
106 | getfield(L, global, Name),
107 | {ok, T} = gettop(L),
108 | Table = gettable(L, T),
109 | lua:remove(L, T),
110 | Table.
111 |
112 | gettable(L, T) ->
113 | pushnil(L),
114 | gettablekey(L, T).
115 |
116 | gettablekey(L, T) ->
117 | next(L, T),
118 | {ok, OT} = gettop(L),
119 | case OT of
120 | T ->
121 | [];
122 | _ ->
123 | %% values can be tables or anything else
124 | %% recurse on tables
125 | case type_atom(L, -1) of
126 | {ok, table} ->
127 | %% keys can be strings or numbers
128 | case type_atom(L, -2) of
129 | {ok, number} ->
130 | {ok, Key} = tonumber(L, -2);
131 | _KT ->
132 | {ok, Key} = tolstring(L, -2)
133 | end,
134 | KV = {Key, gettable(L, T + 2)},
135 | remove(L, -1),
136 | [KV|gettablekey(L, T)];
137 | _TA ->
138 | {ok, _Type, Val} = pop(L),
139 | %% keys can be strings or numbers
140 | case type_atom(L, -1) of
141 | {ok, number} ->
142 | {ok, Key} = tonumber(L, -1);
143 | _KT ->
144 | {ok, Key} = tolstring(L, -1)
145 | end,
146 | [{Key, Val}|gettablekey(L, T)]
147 | end
148 | end.
149 |
150 | gettop(L) ->
151 | command(L, {?ERL_LUA_GETTOP}),
152 | receive_valued_response().
153 |
154 | next(L, Index) ->
155 | command(L, {?ERL_LUA_NEXT, Index}),
156 | receive_simple_response().
157 |
158 | pop(L) ->
159 | {ok, R} = gettop(L),
160 | if
161 | R < 1 ->
162 | {ok, empty};
163 | true ->
164 | {ok, T} = type_atom(L, R),
165 | case T of
166 | number ->
167 | {ok, N} = tonumber(L, R),
168 | remove(L, R),
169 | {ok, number, N};
170 | string ->
171 | {ok, N} = tolstring(L, R),
172 | remove(L, R),
173 | {ok, string, N};
174 | boolean ->
175 | {other, N} = toboolean(L, R),
176 | remove(L, R),
177 | {ok, boolean, N};
178 | function ->
179 | remove(L, R),
180 | {ok, function, function};
181 | _ ->
182 | remove(L, R),
183 | {ok, unknown, unknown}
184 | end
185 | end.
186 |
187 | push(L, Term) when is_number(Term) ->
188 | pushnumber(L, Term);
189 | push(L, Term) when is_list(Term) ->
190 | pushstring(L, Term);
191 | push(L, true) ->
192 | pushboolean(L, true);
193 | push(L, false) ->
194 | pushboolean(L, false);
195 | push(L, Term) when is_atom(Term) ->
196 | pushstring(L, atom_to_list(Term)).
197 |
198 | pushboolean(L, Bool) ->
199 | command(L, {?ERL_LUA_PUSHBOOLEAN, Bool}),
200 | receive_simple_response().
201 |
202 | pushinteger(L, Int) when is_integer(Int) ->
203 | command(L, {?ERL_LUA_PUSHINTEGER, Int}),
204 | receive_simple_response().
205 |
206 | pushstring(L, String) when is_list(String) ->
207 | command(L, {?ERL_LUA_PUSHSTRING, String}),
208 | receive_simple_response().
209 |
210 | pushnil(L) ->
211 | command(L, {?ERL_LUA_PUSHNIL}),
212 | receive_simple_response().
213 |
214 | pushnumber(L, Num) when is_number(Num) ->
215 | command(L, {?ERL_LUA_PUSHNUMBER, Num}),
216 | receive_simple_response().
217 |
218 | remove(L, Index) ->
219 | command(L, {?ERL_LUA_REMOVE, Index}),
220 | receive_simple_response().
221 |
222 | setfield(L, global, Name) ->
223 | setglobal(L, Name);
224 | setfield(L, Index, Name) ->
225 | command(L, {?ERL_LUA_SETFIELD, Index, Name}),
226 | receive_simple_response().
227 |
228 | setglobal(L, Name) ->
229 | command(L, {?ERL_LUA_SETGLOBAL, Name}),
230 | receive_simple_response().
231 |
232 | toboolean(L, Index) ->
233 | command(L, {?ERL_LUA_TOBOOLEAN, Index}),
234 | receive_valued_response().
235 |
236 | tointeger(L, Index) ->
237 | command(L, {?ERL_LUA_TOINTEGER, Index}),
238 | receive_valued_response().
239 |
240 | tolstring(L, Index) ->
241 | command(L, {?ERL_LUA_TOLSTRING, Index}),
242 | receive_valued_response().
243 |
244 | tonumber(L, Index) ->
245 | command(L, {?ERL_LUA_TONUMBER, Index}),
246 | {ok, Value} = receive_valued_response(),
247 | Value2 = list_to_binary(Value),
248 | {ok, binary_to_term(Value2)}.
249 |
250 | type(L, Index) ->
251 | command(L, {?ERL_LUA_TYPE, Index}),
252 | receive_valued_response().
253 |
254 | type_atom(L, Index) ->
255 | command(L, {?ERL_LUA_TYPE, Index}),
256 | R = receive_valued_response(),
257 | case R of
258 | {ok, Str} ->
259 | {ok, type_int_to_atom(Str)};
260 | _ ->
261 | R
262 | end.
263 |
264 | type_int_to_atom(TypeInt) when is_integer(TypeInt) ->
265 | case TypeInt of
266 | 0 ->
267 | Atom = nil;
268 | 1 ->
269 | Atom = boolean;
270 | 2 ->
271 | Atom = light_user_data;
272 | 3 ->
273 | Atom = number;
274 | 4 ->
275 | Atom = string;
276 | 5 ->
277 | Atom = table;
278 | 6 ->
279 | Atom = function;
280 | 7 ->
281 | Atom = user_data;
282 | 8 ->
283 | Atom = thread;
284 | _ ->
285 | Atom = unknown
286 | end,
287 | Atom.
288 |
289 | command(#lua{port=Port}, Data) ->
290 | port_command(Port, term_to_binary(Data)).
291 |
292 | receive_simple_response() ->
293 | receive
294 | ok ->
295 | ok;
296 | error ->
297 | {error, lua_error};
298 | {error, Reason} ->
299 | {error, Reason};
300 | Other ->
301 | {other, Other}
302 | after ?STD_TIMEOUT ->
303 | {error, timeout}
304 | end.
305 |
306 | receive_valued_response() ->
307 | receive
308 | {ok, Str} ->
309 | {ok, Str};
310 | error ->
311 | {error, lua_error};
312 | Other ->
313 | {other, Other}
314 | after ?STD_TIMEOUT ->
315 | {error, timeout}
316 | end.
317 |
--------------------------------------------------------------------------------
/erlmon-1.0/wwwroot/nitrogen/facebox.js:
--------------------------------------------------------------------------------
1 | /* Facebox for Prototype, version 2.0
2 | * By Robert Gaal - http://wakoopa.com
3 | *
4 | * Heavily based on Facebox by Chris Wanstrath - http://famspam.com/facebox
5 | * First ported to Prototype by Phil Burrows - http://blog.philburrows.com
6 | *
7 | * Licensed under the MIT:
8 | * http://www.opensource.org/licenses/mit-license.php
9 | *
10 | * Need help? Join the Google Groups mailing list:
11 | * http://groups.google.com/group/facebox/
12 | *
13 | * Dependencies: prototype & script.aculo.us + images & CSS files from original facebox
14 | * Usage: Append 'rel="facebox"' to an element to call it inside a so-called facebox
15 | *
16 | *--------------------------------------------------------------------------*/
17 |
18 |
19 | var Facebox = Class.create({
20 | initialize : function(extra_set){
21 | this.settings = {
22 | show_overlay : false,
23 | loading_image : '/images/facebox/loading.gif',
24 | close_image : '/images/facebox/closelabel.gif',
25 | image_types : new RegExp('\.' + ['png', 'jpg', 'jpeg', 'gif'].join('|') + '$', 'i'),
26 | inited : true,
27 | facebox_html : '\
28 | \
29 | \
54 |
'
55 | };
56 | if (extra_set) Object.extend(this.settings, extra_set);
57 | $(document.body).insert({
58 | bottom: this.settings.facebox_html
59 | });
60 |
61 | this.preload = [ new Image(), new Image() ];
62 | this.preload[0].src = this.settings.close_image;
63 | this.preload[1].src = this.settings.loading_image;
64 |
65 | f = this;
66 | $$('#facebox .b:first, #facebox .bl, #facebox .br, #facebox .tl, #facebox .tr').each(function(elem){
67 | f.preload.push(new Image());
68 | f.preload.slice(-1).src = elem.getStyle('background-image').replace(/url\((.+)\)/, '$1');
69 | });
70 |
71 | this.facebox = $('facebox');
72 | this.keyPressListener = this.watchKeyPress.bindAsEventListener(this);
73 |
74 | this.watchClickEvents();
75 | fb = this;
76 | Event.observe($$('#facebox .close').first(), 'click', function(e){
77 | Event.stop(e);
78 | fb.close()
79 | });
80 | Event.observe($$('#facebox .close_image').first(), 'click', function(e){
81 | Event.stop(e);
82 | fb.close()
83 | });
84 | },
85 |
86 | watchKeyPress : function(e){
87 | // Close if espace is pressed or if there's a click outside of the facebox
88 | if (e.keyCode == 27 || !Event.element(e).descendantOf(this.facebox)) this.close();
89 | },
90 |
91 | watchClickEvents : function(e){
92 | var f = this;
93 | $$('a[rel=facebox]').each(function(elem,i){
94 | Event.observe(elem, 'click', function(e){
95 | Event.stop(e);
96 | f.click_handler(elem, e);
97 | });
98 | });
99 | },
100 |
101 | loading : function() {
102 | if ($$('#facebox .loading').length == 1) return true;
103 |
104 | contentWrapper = $$('#facebox .content').first();
105 | contentWrapper.childElements().each(function(elem, i){
106 | elem.remove();
107 | });
108 | contentWrapper.insert({
109 | bottom: '
'
110 | });
111 |
112 | var pageScroll = document.viewport.getScrollOffsets();
113 | this.facebox.setStyle({
114 | 'top': pageScroll.top + (document.viewport.getHeight() / 10) + 'px',
115 | 'left': document.viewport.getWidth() / 2 - (this.facebox.getWidth() / 2) + 'px'
116 | });
117 |
118 | Event.observe(document, 'keypress', this.keyPressListener);
119 | Event.observe(document, 'click', this.keyPressListener);
120 | },
121 |
122 | reveal_with_overlay : function(data, klass){
123 | this.settings.show_overlay = true;
124 | this.reveal(data, klass);
125 | },
126 |
127 | reveal : function(data, klass){
128 | this.loading();
129 | load = $$('#facebox .loading').first();
130 | if(load) load.remove();
131 |
132 | if(this.settings.show_overlay) this.show_overlay();
133 |
134 | contentWrapper = $$('#facebox .content').first();
135 | if (klass) contentWrapper.addClassName(klass);
136 | contentWrapper.insert({
137 | bottom: data
138 | });
139 |
140 | $$('#facebox .body').first().childElements().each(function(elem,i){
141 | elem.show();
142 | });
143 |
144 | if(!this.facebox.visible()) new Effect.Appear(this.facebox, {
145 | duration: .3
146 | });
147 | this.facebox.setStyle({
148 | 'left': document.viewport.getWidth() / 2 - (this.facebox.getWidth() / 2) + 'px'
149 | });
150 |
151 | Event.observe(document, 'keypress', this.keyPressListener);
152 | Event.observe(document, 'click', this.keyPressListener);
153 | },
154 |
155 | close : function(){
156 | if(this.settings.show_overlay) this.hide_overlay();
157 | new Effect.Fade('facebox', {
158 | duration: .3
159 | });
160 | },
161 |
162 | click_handler : function(elem, e){
163 | this.loading();
164 | Event.stop(e);
165 |
166 | // support for rel="facebox[.inline_popup]" syntax, to add a class
167 | var klass = elem.rel.match(/facebox\[\.(\w+)\]/);
168 | if (klass) klass = klass[1];
169 |
170 | new Effect.Appear(this.facebox, {
171 | duration: .3
172 | });
173 |
174 | if (elem.href.match(/#/)){
175 | var url = window.location.href.split('#')[0];
176 | var target = elem.href.replace(url+'#','');
177 | // var data = $$(target).first();
178 | var d = $(target);
179 | // create a new element so as to not delete the original on close()
180 | var data = new Element(d.tagName);
181 | data.innerHTML = d.innerHTML;
182 | this.reveal(data, klass);
183 | } else if (elem.href.match(this.settings.image_types)) {
184 | var image = new Image();
185 | fb = this;
186 | image.onload = function() {
187 | fb.reveal('
', klass)
188 | }
189 | image.src = elem.href;
190 | } else {
191 | var fb = this;
192 | var url = elem.href;
193 | new Ajax.Request(url, {
194 | method : 'get',
195 | onFailure : function(transport){
196 | fb.reveal(transport.responseText, klass);
197 | },
198 | onSuccess : function(transport){
199 | fb.reveal(transport.responseText, klass);
200 | }
201 | });
202 |
203 | }
204 | },
205 |
206 | show_overlay: function() {
207 | if (!$("facebox_overlay")) {
208 | new Insertion.Top(document.body, '');
209 | }
210 | this.set_overlay_size();
211 | // this.hide_selects();
212 | new Effect.Appear("facebox_overlay", {
213 | duration: 0.3
214 | });
215 | },
216 |
217 | hide_overlay: function() {
218 | // this.show_selects();
219 | new Effect.Fade("facebox_overlay", {
220 | duration: 0.3
221 | });
222 | },
223 |
224 | set_overlay_size: function() {
225 | if (window.innerHeight && window.scrollMaxY) {
226 | yScroll = window.innerHeight + window.scrollMaxY;
227 | } else if (document.body.scrollHeight > document.body.offsetHeight) {
228 | yScroll = document.body.scrollHeight;
229 | } else {
230 | yScroll = document.body.offsetHeight;
231 | }
232 | $("facebox_overlay").style['height'] = (yScroll+20) + "px";
233 | },
234 |
235 | hide_selects: function() {
236 | selects = document.getElementsByTagName("select");
237 | for (i = 0; i < selects.length; i++) {
238 | selects[i].style.visibility = "hidden";
239 | }
240 | },
241 |
242 | show_selects: function() {
243 | selects = document.getElementsByTagName("select");
244 | for (i = 0; i < selects.length; i++) {
245 | selects[i].style.visibility = "visible";
246 | }
247 | }
248 | });
249 |
250 | var facebox;
251 | document.observe('dom:loaded', function(){
252 | facebox = new Facebox();
253 | });
--------------------------------------------------------------------------------
/erlmon-1.0/c_src/commands.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 |
7 | #include "erlua.h"
8 | #include "commands.h"
9 |
10 | static void reply_ok(lua_drv_t *driver_data);
11 | static void reply_error(lua_drv_t *driver_data);
12 | static char* decode_string(char *buf, int *index);
13 |
14 |
15 | void
16 | erl_lua_call(lua_drv_t *driver_data, char *buf, int index)
17 | {
18 | long args, results;
19 |
20 | ei_decode_long(buf, &index, &args);
21 | ei_decode_long(buf, &index, &results);
22 |
23 | lua_call(driver_data->L, args, results);
24 |
25 | reply_ok(driver_data);
26 | }
27 |
28 | void
29 | erl_lua_concat(lua_drv_t *driver_data, char *buf, int index)
30 | {
31 | long n;
32 |
33 | ei_decode_long(buf, &index, &n);
34 |
35 | lua_concat(driver_data->L, n);
36 |
37 | reply_ok(driver_data);
38 | }
39 |
40 | void
41 | erl_lua_getfield(lua_drv_t *driver_data, char *buf, int index)
42 | {
43 | long i;
44 | char *name;
45 |
46 | ei_decode_long(buf, &index, &i);
47 | name = decode_string(buf, &index);
48 |
49 | lua_getfield(driver_data->L, i, name);
50 |
51 | reply_ok(driver_data);
52 | free(name);
53 | }
54 |
55 | void
56 | erl_lua_getglobal(lua_drv_t *driver_data, char *buf, int index)
57 | {
58 | char *name;
59 |
60 | name = decode_string(buf, &index);
61 |
62 | lua_getglobal(driver_data->L, name);
63 |
64 | reply_ok(driver_data);
65 | free(name);
66 | }
67 |
68 | void
69 | erl_lua_gettop(lua_drv_t *driver_data, char *buf, int index)
70 | {
71 | int size;
72 |
73 | size = lua_gettop(driver_data->L);
74 |
75 | ErlDrvTermData spec[] = {
76 | ERL_DRV_ATOM, ATOM_OK,
77 | ERL_DRV_INT, (ErlDrvTermData) size,
78 | ERL_DRV_TUPLE, 2
79 | };
80 | driver_output_term(driver_data->port, spec, sizeof(spec) / sizeof(spec[0]));
81 | }
82 |
83 | void
84 | erl_lua_next(lua_drv_t *driver_data, char *buf, int index)
85 | {
86 | long n;
87 |
88 | ei_decode_long(buf, &index, &n);
89 |
90 | lua_next(driver_data->L, n);
91 |
92 | reply_ok(driver_data);
93 | }
94 |
95 | void
96 | erl_lua_pushboolean(lua_drv_t *driver_data, char *buf, int index)
97 | {
98 | int b;
99 |
100 | ei_decode_boolean(buf, &index, &b);
101 |
102 | lua_pushboolean(driver_data->L, b);
103 |
104 | reply_ok(driver_data);
105 | }
106 |
107 | void
108 | erl_lua_pushinteger(lua_drv_t *driver_data, char *buf, int index)
109 | {
110 | long long num;
111 |
112 | ei_decode_longlong(buf, &index, &num);
113 |
114 | lua_pushinteger(driver_data->L, num);
115 |
116 | reply_ok(driver_data);
117 | }
118 |
119 | void
120 | erl_lua_pushstring(lua_drv_t *driver_data, char *buf, int index)
121 | {
122 | char *str;
123 |
124 | str = decode_string(buf, &index);
125 |
126 | lua_pushstring(driver_data->L, str);
127 |
128 | reply_ok(driver_data);
129 | free(str);
130 | }
131 |
132 | void
133 | erl_lua_pushnil(lua_drv_t *driver_data, char *buf, int index)
134 | {
135 | lua_pushnil(driver_data->L);
136 | reply_ok(driver_data);
137 | }
138 |
139 | void
140 | erl_lua_pushnumber(lua_drv_t *driver_data, char *buf, int index)
141 | {
142 | double dnum;
143 | long long lnum;
144 | int type, len;
145 |
146 | ei_get_type(buf, &index, &type, &len);
147 |
148 | switch (type) {
149 | case ERL_FLOAT_EXT:
150 | ei_decode_double(buf, &index, &dnum);
151 | lua_pushnumber(driver_data->L, dnum);
152 | break;
153 | default:
154 | ei_decode_longlong(buf, &index, &lnum);
155 | lua_pushnumber(driver_data->L, lnum);
156 | break;
157 | }
158 |
159 | reply_ok(driver_data);
160 | }
161 |
162 | void
163 | erl_lua_remove(lua_drv_t *driver_data, char *buf, int index)
164 | {
165 | long i;
166 |
167 | ei_decode_long(buf, &index, &i);
168 |
169 | lua_remove(driver_data->L, i);
170 |
171 | reply_ok(driver_data);
172 | }
173 |
174 | void
175 | erl_lua_setfield(lua_drv_t *driver_data, char *buf, int index)
176 | {
177 | long i;
178 | char *name;
179 |
180 | ei_decode_long(buf, &index, &i);
181 | name = decode_string(buf, &index);
182 |
183 | lua_setfield(driver_data->L, i, name);
184 |
185 | reply_ok(driver_data);
186 | free(name);
187 | }
188 |
189 | void
190 | erl_lua_setglobal(lua_drv_t *driver_data, char *buf, int index)
191 | {
192 | char *name;
193 |
194 | name = decode_string(buf, &index);
195 |
196 | lua_setglobal(driver_data->L, name);
197 |
198 | reply_ok(driver_data);
199 | free(name);
200 | }
201 |
202 | void
203 | erl_lua_toboolean(lua_drv_t *driver_data, char *buf, int index)
204 | {
205 | long i;
206 | int res;
207 | ErlDrvTermData spec[2];
208 | spec[0] = ERL_DRV_ATOM;
209 |
210 | ei_decode_long(buf, &index, &i);
211 |
212 | res = lua_toboolean(driver_data->L, i);
213 | if (res)
214 | spec[1] = driver_mk_atom("true");
215 | else
216 | spec[1] = driver_mk_atom("false");
217 | driver_output_term(driver_data->port, spec, sizeof(spec) / sizeof(spec[0]));
218 | }
219 |
220 | void
221 | erl_lua_tointeger(lua_drv_t *driver_data, char *buf, int index)
222 | {
223 | long i;
224 | long long res;
225 |
226 | ei_decode_long(buf, &index, &i);
227 |
228 | res = lua_tointeger(driver_data->L, i);
229 |
230 | ErlDrvTermData spec[] = {
231 | ERL_DRV_ATOM, ATOM_OK,
232 | ERL_DRV_INT, (ErlDrvTermData) res,
233 | ERL_DRV_TUPLE, 2
234 | };
235 | driver_output_term(driver_data->port, spec, sizeof(spec) / sizeof(spec[0]));
236 | }
237 |
238 | void
239 | erl_lua_tolstring(lua_drv_t *driver_data, char *buf, int index)
240 | {
241 | size_t len;
242 | long i;
243 | const char *str;
244 |
245 | ei_decode_long(buf, &index, &i);
246 |
247 | str = lua_tolstring(driver_data->L, i, &len);
248 |
249 | ErlDrvTermData spec[] = {
250 | ERL_DRV_ATOM, ATOM_OK,
251 | ERL_DRV_STRING, (ErlDrvTermData) str, len,
252 | ERL_DRV_TUPLE, 2
253 | };
254 | driver_output_term(driver_data->port, spec, sizeof(spec) / sizeof(spec[0]));
255 | }
256 |
257 |
258 | /* TODO: return a binary instead of a list that is then converted to a binary */
259 | void
260 | erl_lua_tonumber(lua_drv_t *driver_data, char *buf, int index)
261 | {
262 | long i;
263 | double res;
264 | int encode_i = 0;
265 | int size;
266 | char *eibuf;
267 |
268 | ei_decode_long(buf, &index, &i);
269 |
270 | res = lua_tonumber(driver_data->L, i);
271 |
272 | ei_encode_version(NULL, &encode_i);
273 | if ((long long) res == res) {
274 | ei_encode_longlong(NULL, &encode_i, (long long) res);
275 | size = encode_i;
276 | encode_i = 0;
277 | eibuf = malloc(sizeof(char) * (size + 1));
278 |
279 | ei_encode_version(eibuf, &encode_i);
280 | ei_encode_longlong(eibuf, &encode_i, res);
281 | } else {
282 | ei_encode_double(NULL, &encode_i, res);
283 | size = encode_i;
284 | encode_i = 0;
285 | eibuf = malloc(sizeof(char) * (size + 1));
286 |
287 | ei_encode_version(eibuf, &encode_i);
288 | ei_encode_double(eibuf, &encode_i, res);
289 | }
290 |
291 | ErlDrvTermData spec[] = {
292 | ERL_DRV_ATOM, ATOM_OK,
293 | ERL_DRV_STRING, (ErlDrvTermData) eibuf, size,
294 | ERL_DRV_TUPLE, 2
295 | };
296 | driver_output_term(driver_data->port, spec, sizeof(spec) / sizeof(spec[0]));
297 | free(eibuf);
298 | //driver_free_binary(bin);
299 | }
300 |
301 | void
302 | erl_lua_type(lua_drv_t *driver_data, char *buf, int index)
303 | {
304 | long i;
305 | int lua_t;
306 |
307 | ei_decode_long(buf, &index, &i);
308 |
309 | lua_t = lua_type(driver_data->L, i);
310 |
311 | ErlDrvTermData spec[] = {
312 | ERL_DRV_ATOM, ATOM_OK,
313 | ERL_DRV_INT, (ErlDrvTermData) lua_t,
314 | ERL_DRV_TUPLE, 2
315 | };
316 | driver_output_term(driver_data->port, spec, sizeof(spec) / sizeof(spec[0]));
317 | }
318 |
319 |
320 | void
321 | erl_lual_dostring(lua_drv_t *driver_data, char *buf, int index)
322 | {
323 | char *code;
324 |
325 | code = decode_string(buf, &index);
326 |
327 | if (!luaL_dostring(driver_data->L, code))
328 | reply_ok(driver_data);
329 | else
330 | reply_error(driver_data);
331 | }
332 |
333 | void
334 | erl_lual_dofile(lua_drv_t *driver_data, char *buf, int index)
335 | {
336 | char *code;
337 |
338 | code = decode_string(buf, &index);
339 |
340 | if (!luaL_dofile(driver_data->L, code))
341 | reply_ok(driver_data);
342 | else
343 | reply_error(driver_data);
344 | }
345 |
346 | void
347 | erl_lua_no_command(lua_drv_t *driver_data)
348 | {
349 | ErlDrvTermData spec[] = {
350 | ERL_DRV_ATOM, ATOM_ERROR,
351 | ERL_DRV_STRING, (ErlDrvTermData) "No Command Found", 16,
352 | ERL_DRV_TUPLE, 2
353 | };
354 | driver_output_term(driver_data->port, spec, sizeof(spec) / sizeof(spec[0]));
355 | }
356 |
357 |
358 | static void
359 | reply_ok(lua_drv_t *driver_data)
360 | {
361 | ErlDrvTermData spec[] = {ERL_DRV_ATOM, ATOM_OK};
362 | driver_output_term(driver_data->port, spec, sizeof(spec) / sizeof(spec[0]));
363 | }
364 |
365 | static void
366 | reply_error(lua_drv_t *driver_data)
367 | {
368 | ErlDrvTermData spec[] = {ERL_DRV_ATOM, ATOM_ERROR};
369 | driver_output_term(driver_data->port, spec, sizeof(spec) / sizeof(spec[0]));
370 | }
371 |
372 |
373 | static char*
374 | decode_string(char *buf, int *index)
375 | {
376 | int type, length;
377 | char *str;
378 |
379 | ei_get_type(buf, index, &type, &length);
380 | str = malloc(sizeof(char) * (length + 1));
381 | ei_decode_string(buf, index, str);
382 | return str;
383 | }
384 |
--------------------------------------------------------------------------------
/erlmon-1.0/wwwroot/nitrogen/livevalidation.js:
--------------------------------------------------------------------------------
1 | // LiveValidation 1.3 (standalone version)
2 | // Copyright (c) 2007-2008 Alec Hill (www.livevalidation.com)
3 | // LiveValidation is licensed under the terms of the MIT License
4 | var LiveValidation=function(B,A){this.initialize(B,A);};LiveValidation.VERSION="1.3 standalone";LiveValidation.TEXTAREA=1;LiveValidation.TEXT=2;LiveValidation.PASSWORD=3;LiveValidation.CHECKBOX=4;LiveValidation.SELECT=5;LiveValidation.FILE=6;LiveValidation.massValidate=function(C){var D=true;for(var B=0,A=C.length;B=300){this.removeMessageAndFieldClass();}var A=this;if(this.timeout){clearTimeout(A.timeout);}this.timeout=setTimeout(function(){A.validate();},A.wait);},doOnBlur:function(A){this.focused=false;this.validate(A);},doOnFocus:function(A){this.focused=true;this.removeMessageAndFieldClass();},getElementType:function(){switch(true){case (this.element.nodeName.toUpperCase()=="TEXTAREA"):return LiveValidation.TEXTAREA;case (this.element.nodeName.toUpperCase()=="INPUT"&&this.element.type.toUpperCase()=="TEXT"):return LiveValidation.TEXT;case (this.element.nodeName.toUpperCase()=="INPUT"&&this.element.type.toUpperCase()=="PASSWORD"):return LiveValidation.PASSWORD;case (this.element.nodeName.toUpperCase()=="INPUT"&&this.element.type.toUpperCase()=="CHECKBOX"):return LiveValidation.CHECKBOX;case (this.element.nodeName.toUpperCase()=="INPUT"&&this.element.type.toUpperCase()=="FILE"):return LiveValidation.FILE;case (this.element.nodeName.toUpperCase()=="SELECT"):return LiveValidation.SELECT;case (this.element.nodeName.toUpperCase()=="INPUT"):throw new Error("LiveValidation::getElementType - Cannot use LiveValidation on an "+this.element.type+" input!");default:throw new Error("LiveValidation::getElementType - Element must be an input, select, or textarea!");}},doValidations:function(){this.validationFailed=false;for(var C=0,A=this.validations.length;CNumber(C)){Validate.fail(K);}break;}return true;},Format:function(C,E){var C=String(C);var E=E||{};var A=E.failureMessage||"Not valid!";var B=E.pattern||/./;var D=E.negate||false;if(!D&&!B.test(C)){Validate.fail(A);}if(D&&B.test(C)){Validate.fail(A);}return true;},Email:function(B,C){var C=C||{};var A=C.failureMessage||"Must be a valid email address!";Validate.Format(B,{failureMessage:A,pattern:/^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i});return true;},Length:function(F,G){var F=String(F);var G=G||{};var E=((G.minimum)||(G.minimum==0))?G.minimum:null;var H=((G.maximum)||(G.maximum==0))?G.maximum:null;var C=((G.is)||(G.is==0))?G.is:null;var A=G.wrongLengthMessage||"Must be "+C+" characters long!";var B=G.tooShortMessage||"Must not be less than "+E+" characters long!";var D=G.tooLongMessage||"Must not be more than "+H+" characters long!";switch(true){case (C!==null):if(F.length!=Number(C)){Validate.fail(A);}break;case (E!==null&&H!==null):Validate.Length(F,{tooShortMessage:B,minimum:E});Validate.Length(F,{tooLongMessage:D,maximum:H});break;case (E!==null):if(F.lengthNumber(H)){Validate.fail(D);}break;default:throw new Error("Validate::Length - Length(s) to validate against must be provided!");}return true;},Inclusion:function(H,F){var F=F||{};var K=F.failureMessage||"Must be included in the list!";var G=(F.caseSensitive===false)?false:true;if(F.allowNull&&H==null){return true;}if(!F.allowNull&&H==null){Validate.fail(K);}var D=F.within||[];if(!G){var A=[];for(var C=0,B=D.length;C