add log support
This commit is contained in:
parent
9bed8c8622
commit
582b819e9f
@ -246,13 +246,17 @@
|
||||
status = 0
|
||||
}).
|
||||
|
||||
%% 设备分类
|
||||
-define(DEVICE_HOST, 1).
|
||||
-define(DEVICE_TERMINAL, 2).
|
||||
|
||||
%% 操作日志表
|
||||
-record(log, {
|
||||
log_id :: integer(),
|
||||
%% 操作名称名称
|
||||
action_name = <<>>,
|
||||
%% 设备分类名称
|
||||
assoc_name = <<>>,
|
||||
device_type :: integer(),
|
||||
%% 关联ID
|
||||
assoc_id :: term(),
|
||||
%% 创建时间
|
||||
|
||||
41
apps/iot/src/http_handler/http_log_handler.erl
Normal file
41
apps/iot/src/http_handler/http_log_handler.erl
Normal file
@ -0,0 +1,41 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @author licheng5
|
||||
%%% @copyright (C) 2020, <COMPANY>
|
||||
%%% @doc
|
||||
%%%
|
||||
%%% @end
|
||||
%%% Created : 26. 4月 2020 3:36 下午
|
||||
%%%-------------------------------------------------------------------
|
||||
-module(http_log_handler).
|
||||
-author("licheng5").
|
||||
-include("iot.hrl").
|
||||
|
||||
%% API
|
||||
-export([handle_request/4]).
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%% helper methods
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
handle_request(_, "/log/list", GetParams, _PostParams) ->
|
||||
Size0 = maps:get(<<"size">>, GetParams, <<"10">>),
|
||||
Size = binary_to_integer(Size0),
|
||||
true = Size > 0,
|
||||
|
||||
case log_model:get_last_logs(Size) of
|
||||
{ok, Logs} ->
|
||||
LogInfos = lists:map(fun log_model:to_map/1, Logs),
|
||||
|
||||
{ok, 200, iot_util:json_data(LogInfos)};
|
||||
{error, Reason} ->
|
||||
lager:warning("[host_handler] get a error: ~p", [Reason]),
|
||||
{ok, 200, iot_util:json_error(-1, <<"database error">>)}
|
||||
end;
|
||||
|
||||
handle_request(_, Path, _, _) ->
|
||||
Path1 = list_to_binary(Path),
|
||||
{ok, 200, iot_util:json_error(-1, <<"url: ", Path1/binary, " not found">>)}.
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%% helper methods
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
@ -64,7 +64,7 @@ supported_gzip(AcceptEncoding) when is_binary(AcceptEncoding) ->
|
||||
parse_body(Req0) ->
|
||||
ContentType = cowboy_req:header(<<"content-type">>, Req0),
|
||||
case ContentType of
|
||||
<<"application/json">> ->
|
||||
<<"application/json", _/binary>> ->
|
||||
{ok, Body, Req1} = read_body(Req0),
|
||||
{ok, catch jiffy:decode(Body, [return_maps]), Req1};
|
||||
<<"application/x-www-form-urlencoded">> ->
|
||||
|
||||
@ -42,7 +42,10 @@ start_http_server() ->
|
||||
Dispatcher = cowboy_router:compile([
|
||||
{'_', [
|
||||
{"/host/[...]", http_protocol, [http_host_handler]},
|
||||
{"/api/[...]", http_protocol, [http_api_handler]},
|
||||
{"/terminal/[...]", http_protocol, [http_terminal_handler]},
|
||||
{"/scenario/[...]", http_protocol, [http_scenario_handler]},
|
||||
{"/log/[...]", http_protocol, [http_log_handler]},
|
||||
{"/iot/[...]", http_protocol, [http_iot_handler]},
|
||||
{"/router/[...]", http_protocol, [http_router_handler]}
|
||||
]}
|
||||
]),
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
-include("iot.hrl").
|
||||
|
||||
%% API
|
||||
-export([insert_hosts/0, insert_services/1, insert_terminals/1, insert_routers/0]).
|
||||
-export([insert_hosts/0, insert_services/1, insert_terminals/1, insert_routers/0, insert_logs/0]).
|
||||
-export([start_router/1]).
|
||||
-export([rsa_encode/1]).
|
||||
-export([start_issue/0]).
|
||||
@ -43,6 +43,18 @@ insert_hosts() ->
|
||||
host_model:add_host(Host)
|
||||
end, lists:seq(1, 1)).
|
||||
|
||||
insert_logs() ->
|
||||
lists:foreach(fun(Id0) ->
|
||||
Log = #log{
|
||||
log_id = Id0,
|
||||
device_type = ?DEVICE_HOST,
|
||||
action_name = <<"主机上线"/utf8>>,
|
||||
assoc_id = <<"1">>,
|
||||
create_ts = Id0 + 123456
|
||||
},
|
||||
log_model:add_log(Log)
|
||||
end, lists:seq(1, 500000)).
|
||||
|
||||
insert_services(HostId) ->
|
||||
lists:foreach(fun(Id0) ->
|
||||
Q0 = queue:new(),
|
||||
|
||||
@ -14,10 +14,10 @@
|
||||
-define(TAB_NAME, log).
|
||||
|
||||
%% API
|
||||
-export([get_logs/1, add_log/1, delete/1, table_size/0]).
|
||||
-export([get_logs/1, add_log/1, delete/1, table_size/0, get_last_logs/1]).
|
||||
-export([to_map/1]).
|
||||
|
||||
%% 获取app信息
|
||||
%% 获取app信息, 该函数的效率较低
|
||||
-spec get_logs(Limit :: integer()) -> {ok, Logs :: list()} | {error, Reason :: any()}.
|
||||
get_logs(Limit) when is_integer(Limit), Limit > 0 ->
|
||||
Fun = fun() ->
|
||||
@ -36,6 +36,20 @@ get_logs(Limit) when is_integer(Limit), Limit > 0 ->
|
||||
{error, Error}
|
||||
end.
|
||||
|
||||
%% 获取最新的n条记录
|
||||
-spec get_last_logs(N :: integer()) -> {ok, Logs :: [#log{}]} | {error, Reason :: any()}.
|
||||
get_last_logs(N) when N > 0 ->
|
||||
Fun = fun() ->
|
||||
Keys = read_last_keys(N),
|
||||
lists:flatmap(fun(Key) -> mnesia:read(?TAB_NAME, Key, read) end, lists:reverse(Keys))
|
||||
end,
|
||||
case mnesia:transaction(Fun) of
|
||||
{atomic, Logs} when is_list(Logs) ->
|
||||
{ok, Logs};
|
||||
{aborted, Error} ->
|
||||
{error, Error}
|
||||
end.
|
||||
|
||||
-spec add_log(Log :: #log{}) -> ok | {error, Reason :: binary()}.
|
||||
add_log(Log = #log{}) ->
|
||||
case mnesia:transaction(fun() -> mnesia:write(?TAB_NAME, Log, write) end) of
|
||||
@ -54,6 +68,24 @@ delete(LogId) when is_binary(LogId) ->
|
||||
{error, Reason}
|
||||
end.
|
||||
|
||||
%% 从后向前变量表
|
||||
read_last_keys(N) when N >= 1 ->
|
||||
case mnesia:last(?TAB_NAME) of
|
||||
'$end_of_table' ->
|
||||
[];
|
||||
LastKey ->
|
||||
read_last_keys0(N - 1, LastKey, [LastKey])
|
||||
end.
|
||||
read_last_keys0(0, _, Keys) ->
|
||||
Keys;
|
||||
read_last_keys0(N, Key, Keys) ->
|
||||
case mnesia:prev(?TAB_NAME, Key) of
|
||||
'$end_of_table' ->
|
||||
Keys;
|
||||
PrevKey ->
|
||||
read_last_keys0(N - 1, PrevKey, [PrevKey|Keys])
|
||||
end.
|
||||
|
||||
%% 获取app表的数据大小
|
||||
table_size() ->
|
||||
mnesia:table_info(?TAB_NAME, size).
|
||||
@ -67,9 +99,28 @@ sort(Logs) when is_list(Logs) ->
|
||||
lists:sort(fun(#log{create_ts = Ts0}, #log{create_ts = Ts1}) -> Ts0 > Ts1 end, Logs).
|
||||
|
||||
%% 将数据转换成hash
|
||||
to_map(#log{log_id = LogId, action_name = ActionName, assoc_name = AssocName, assoc_id = AssocId, create_ts = CreateTs}) ->
|
||||
to_map(#log{log_id = LogId, action_name = ActionName, device_type = DeviceType, assoc_id = AssocId, create_ts = CreateTs}) ->
|
||||
DeviceInfo = case DeviceType of
|
||||
?DEVICE_HOST ->
|
||||
case host_model:get_host(AssocId) of
|
||||
{ok, Host} ->
|
||||
host_model:to_map(Host);
|
||||
_ ->
|
||||
#{}
|
||||
end;
|
||||
?DEVICE_TERMINAL ->
|
||||
case terminal_model:get_terminal(AssocId) of
|
||||
{ok, Terminal} ->
|
||||
terminal_model:to_map(Terminal);
|
||||
_ ->
|
||||
#{}
|
||||
end
|
||||
end,
|
||||
|
||||
#{
|
||||
<<"log_id">> => LogId,
|
||||
<<"action_name">> => ActionName,
|
||||
<<"device_type">> => DeviceType,
|
||||
<<"device_info">> => DeviceInfo,
|
||||
<<"create_ts">> => CreateTs
|
||||
}.
|
||||
Loading…
x
Reference in New Issue
Block a user