Packages

macula

0.7.7
7.1.0 7.0.0 6.0.0 5.2.2 5.2.1 5.2.0 5.1.0 5.0.0 4.8.0 4.7.1 4.7.0 4.6.0 4.5.0 4.4.10 4.4.9 4.4.8 4.4.7 4.4.6 4.4.5 4.4.4 4.4.3 4.4.2 4.4.1 4.4.0 4.3.1 4.3.0 4.2.9 4.2.8 4.2.7 4.2.6 4.2.5 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.1 4.1.0 4.0.0 3.16.0 3.15.3 3.15.2 3.15.1 3.14.0 3.13.0 3.12.1 3.12.0 3.11.1 3.11.0 3.10.3 3.10.2 3.10.1 3.9.0 3.8.0 3.7.0 3.5.0 3.4.0 3.3.0 3.2.0 3.1.0 3.0.0 2.1.1 2.1.0 2.0.0 1.5.2 1.5.1 1.4.30 1.4.29 1.4.28 1.4.27 1.4.26 1.4.25 1.4.24 1.4.23 1.4.22 1.4.21 1.4.20 1.4.19 1.4.18 1.4.17 1.4.16 1.4.15 1.4.14 1.4.13 1.4.11 1.4.10 1.4.9 1.4.8 1.4.7 1.4.6 1.4.5 1.4.4 1.4.3 1.4.2 1.4.1 1.4.0 1.3.1 1.3.0 1.2.0 1.1.0 1.0.10 1.0.9 1.0.8 1.0.7 1.0.6 1.0.5 1.0.4 1.0.3 1.0.2 1.0.1 1.0.0 0.48.6 0.48.5 0.48.4 0.48.3 0.48.2 0.48.1 0.48.0 0.47.1 0.47.0 0.46.3 0.46.1 0.46.0 0.45.3 0.45.2 0.45.1 0.45.0 0.44.2 0.44.1 0.44.0 0.43.3 0.43.2 0.43.1 0.43.0 0.42.9 0.42.8 0.42.7 0.42.6 0.42.5 0.42.4 0.42.3 0.42.2 0.42.1 0.42.0 0.41.1 0.41.0 0.40.1 0.40.0 0.39.9 0.39.8 0.39.7 0.39.6 0.39.5 0.39.4 0.39.3 0.39.2 0.39.1 0.39.0 0.38.8 0.38.7 0.38.6 0.38.5 0.38.4 0.38.3 0.38.2 0.38.1 0.38.0 0.37.7 0.37.6 0.37.5 0.37.4 0.37.3 0.37.2 0.37.1 0.37.0 0.36.6 0.36.5 0.36.4 0.36.3 0.36.2 0.36.1 0.36.0 0.35.4 0.35.3 0.35.2 0.35.1 0.35.0 0.34.1 0.34.0 0.33.1 0.33.0 0.32.5 0.32.4 0.32.3 0.32.2 0.32.1 0.32.0 0.31.9 0.31.8 0.31.7 0.31.6 0.31.5 0.31.4 0.31.3 0.31.2 0.31.1 0.31.0 0.30.10 0.30.9 0.30.8 0.30.7 0.30.6 0.30.5 0.30.4 0.30.3 0.30.2 0.30.1 0.30.0 0.29.0 0.28.3 0.28.2 0.28.1 0.28.0 0.27.1 0.27.0 0.26.1 0.26.0 0.25.6 0.25.5 0.25.4 0.25.3 0.25.2 0.25.1 0.25.0 0.24.6 0.24.5 0.24.4 0.24.3 0.24.2 0.24.1 0.24.0 0.23.3 0.23.2 0.23.1 0.23.0 0.22.12 0.22.11 0.22.10 0.22.9 0.22.8 0.22.7 0.22.6 0.22.5 0.22.4 0.22.3 0.22.2 0.22.1 0.22.0 0.21.7 0.21.6 0.21.5 0.21.4 0.21.2 0.21.1 0.21.0 0.20.25 0.20.24 0.20.23 0.20.22 0.20.21 0.20.20 0.20.19 0.20.18 0.20.17 0.20.16 0.20.15 0.20.14 0.20.13 0.20.12 0.20.11 0.20.10 0.20.9 0.20.8 0.20.7 0.20.6 0.20.5 0.20.3 0.20.2 0.20.1 0.20.0 0.19.2 0.19.1 0.19.0 0.18.1 0.18.0 0.17.4 0.17.3 0.17.2 0.17.1 0.17.0 0.16.6 0.16.5 0.16.4 0.16.3 0.16.2 0.16.1 0.16.0 0.15.1 0.15.0 0.14.3 0.14.2 0.14.1 0.14.0 0.12.6 0.12.5 0.12.3 0.11.3 0.10.2 0.10.1 0.10.0 0.9.2 0.9.1 0.9.0 0.8.25 0.8.24 0.8.23 0.8.22 0.8.21 0.8.20 0.8.19 0.8.18 0.8.17 0.8.16 0.8.15 0.8.14 0.8.13 0.8.12 0.8.11 0.8.10 0.8.9 0.8.8 0.8.7 0.8.6 0.8.5 0.8.4 0.8.3 0.8.2 0.8.1 0.8.0 0.7.30 0.7.29 0.7.28 0.7.27 0.7.26 0.7.25 0.7.24 0.7.23 0.7.22 0.7.21 0.7.20 0.7.19 0.7.18 0.7.17 0.7.16 0.7.15 0.7.14 0.7.13 0.7.12 0.7.11 0.7.10 0.7.9 0.7.8 0.7.7 0.7.6 0.7.5 0.7.4 0.7.3 0.7.2 0.7.1 0.7.0 0.6.7 0.6.6 0.6.5 0.6.4 0.6.3 0.6.2 0.6.1 0.6.0 0.5.0 0.4.4 0.4.3 0.4.2 0.4.1 0.4.0 0.3.4 0.3.3 0.3.2 0.3.1

Macula HTTP/3 Mesh SDK — connect, subscribe, publish, call, advertise

Current section

Files

Jump to
macula src macula_gateway_diagnostics.erl
Raw

src/macula_gateway_diagnostics.erl

%%%-------------------------------------------------------------------
%%% @doc
%%% Macula Gateway Diagnostics Service
%%%
%%% Provides simple diagnostic procedures that clients can call to verify
%%% connectivity and test the gateway's RPC functionality.
%%%
%%% Available procedures:
%%% - com.macula.diagnostics.hello - Returns a friendly greeting with gateway info
%%% - com.macula.diagnostics.echo - Echoes back the arguments sent by client
%%% - com.macula.diagnostics.info - Returns detailed gateway information
%%%
%%% Usage:
%%% The diagnostics service automatically registers when the gateway starts.
%%% Clients can call these procedures using the Macula SDK:
%%%
%%% Elixir:
%%% {:ok, result} = MaculaSdk.Client.call(client, "com.macula.diagnostics.hello", %{})
%%%
%%% Result:
%%% %{
%%% "message" => "Hello from Macula Gateway!",
%%% "gateway" => "macula@127.0.0.1",
%%% "realm" => "com.example.realm",
%%% "uptime_seconds" => 42,
%%% "timestamp" => 1699612800
%%% }
%%% @end
%%%-------------------------------------------------------------------
-module(macula_gateway_diagnostics).
-behaviour(gen_server).
%% API
-export([
start_link/1,
register_procedures/1
]).
%% gen_server callbacks
-export([
init/1,
handle_call/3,
handle_cast/2,
handle_info/2,
terminate/2
]).
-record(state, {
gateway_pid :: pid(),
realm :: binary(),
started_at :: integer()
}).
%%%===================================================================
%%% API Functions
%%%===================================================================
%% @doc Start the diagnostics service
-spec start_link(proplists:proplist()) -> {ok, pid()} | {error, term()}.
start_link(Opts) ->
gen_server:start_link({local, ?MODULE}, ?MODULE, Opts, []).
%% @doc Register diagnostic procedures with the gateway
-spec register_procedures(pid()) -> ok.
register_procedures(GatewayPid) ->
gen_server:cast(?MODULE, {register_procedures, GatewayPid}).
%%%===================================================================
%%% gen_server callbacks
%%%===================================================================
init(Opts) ->
Realm = proplists:get_value(realm, Opts, <<"macula.default">>),
io:format("Starting diagnostics service for realm: ~s~n", [Realm]),
State = #state{
gateway_pid = undefined,
realm = Realm,
started_at = erlang:system_time(second)
},
{ok, State}.
handle_call(_Request, _From, State) ->
{reply, {error, unknown_request}, State}.
handle_cast({register_procedures, GatewayPid}, State) ->
%% Register diagnostic procedures
Procedures = [
<<"com.macula.diagnostics.hello">>,
<<"com.macula.diagnostics.echo">>,
<<"com.macula.diagnostics.info">>
],
lists:foreach(fun(Procedure) ->
GatewayPid ! {register, self(), Procedure}
end, Procedures),
io:format("Registered ~p diagnostic procedures~n", [length(Procedures)]),
{noreply, State#state{gateway_pid = GatewayPid}};
handle_cast(_Request, State) ->
{noreply, State}.
%% Handle RPC invocations from gateway
handle_info({invoke, CallerPid, CallId, Procedure, Args}, State) ->
Result = handle_procedure(Procedure, Args, State),
%% Send result back to caller
CallerPid ! {call_result, CallId, Result},
{noreply, State};
%% Handle registration confirmations
handle_info({registered, Procedure}, State) ->
io:format("Diagnostic procedure registered: ~s~n", [Procedure]),
{noreply, State};
handle_info(_Info, State) ->
{noreply, State}.
terminate(_Reason, _State) ->
ok.
%%%===================================================================
%%% Internal Functions
%%%===================================================================
%% @private
handle_procedure(<<"com.macula.diagnostics.hello">>, _Args, State) ->
Uptime = erlang:system_time(second) - State#state.started_at,
#{
<<"message">> => <<"Hello from Macula Gateway!">>,
<<"gateway">> => list_to_binary(atom_to_list(node())),
<<"realm">> => State#state.realm,
<<"uptime_seconds">> => Uptime,
<<"timestamp">> => erlang:system_time(second),
<<"version">> => <<"0.1.0">>,
<<"protocol">> => <<"HTTP/3 (QUIC)">>
};
handle_procedure(<<"com.macula.diagnostics.echo">>, Args, _State) ->
#{
<<"echo">> => Args,
<<"timestamp">> => erlang:system_time(second)
};
handle_procedure(<<"com.macula.diagnostics.info">>, _Args, State) ->
Uptime = erlang:system_time(second) - State#state.started_at,
%% Get memory info
MemoryInfo = erlang:memory(),
TotalMemory = proplists:get_value(total, MemoryInfo, 0),
ProcessMemory = proplists:get_value(processes, MemoryInfo, 0),
%% Get process count
ProcessCount = erlang:system_info(process_count),
#{
<<"gateway">> => #{
<<"node">> => list_to_binary(atom_to_list(node())),
<<"realm">> => State#state.realm,
<<"uptime_seconds">> => Uptime,
<<"version">> => <<"0.1.0">>
},
<<"system">> => #{
<<"otp_version">> => list_to_binary(erlang:system_info(otp_release)),
<<"erts_version">> => list_to_binary(erlang:system_info(version)),
<<"process_count">> => ProcessCount,
<<"memory_bytes">> => TotalMemory,
<<"process_memory_bytes">> => ProcessMemory
},
<<"timestamp">> => erlang:system_time(second)
};
handle_procedure(_Unknown, _Args, _State) ->
#{
<<"error">> => <<"unknown_procedure">>,
<<"timestamp">> => erlang:system_time(second)
}.