gen_event, sys & proc_lib
⚠️ A crashing handler is silently removed, and all handlers run in the manager's process.
31.1 gen_event — event manager with pluggable handlers
⚠️ A crashing handler is silently removed, and all handlers run in the manager's process. For new code, consider separate processes + pg or logger handlers.
-module(console_logger).
-behaviour(gen_event).
-export([init/1, handle_event/2, handle_call/2, handle_info/2, terminate/2]).
init(_) -> {ok, []}.
handle_event({log, Msg}, State) -> io:format("LOG: ~s~n", [Msg]), {ok, State}.
handle_call(_, State) -> {ok, ok, State}.
handle_info(_, State) -> {ok, State}.
terminate(_, _) -> ok.{ok, Mgr} = gen_event:start_link({local, my_events}),
gen_event:add_handler(my_events, console_logger, []),
gen_event:notify(my_events, {log, "hello"}), % async
gen_event:sync_notify(my_events, {log, "sync"}),
gen_event:delete_handler(my_events, console_logger, []),
gen_event:add_sup_handler(...). % handler supervised by caller31.2 The sys module — debugging any OTP process
sys:get_state(kv_store),
sys:replace_state(kv_store, fun(S) -> S#{debug => true} end),
sys:get_status(kv_store),
sys:trace(kv_store, true), % print every message & state change
sys:statistics(kv_store, true),
sys:suspend(kv_store), sys:resume(kv_store),
sys:log(kv_store, {true, 10}), sys:log(kv_store, print).31.3 proc_lib & special processes
proc_lib:spawn_link/1, proc_lib:start_link/3 + proc_lib:init_ack/1 start processes that produce proper crash reports and fit into supervision trees. A special process handles system messages (sys:handle_system_msg/6) so it can be debugged/upgraded like a behaviour — this is how you write your own behaviours.
31.4 Writing your own behaviour
Modules declare -behaviour(my_behaviour). and the compiler warns about missing callbacks.
-module(my_behaviour).
-callback handle_job(Job :: term()) -> ok | {error, term()}.
-optional_callbacks([]).