%% ------------------------------------------------------------------- %% %% Machi: a small village of replicated files %% %% Copyright (c) 2014 Basho Technologies, Inc. All Rights Reserved. %% %% This file is provided to you under the Apache License, %% Version 2.0 (the "License"); you may not use this file %% except in compliance with the License. You may obtain %% a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% %% ------------------------------------------------------------------- %%% File : handle_errors.erl %%% Author : Ulf Norell %%% Description : %%% Created : 26 Mar 2012 by Ulf Norell -module(event_logger). -compile(export_all). -behaviour(gen_server). %% API -export([start_link/0, event/1, event/2, get_events/0, start_logging/0]). -export([timestamp/0]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -define(SERVER, ?MODULE). -record(state, { start_time, events = [] }). -record(event, { timestamp, data }). %%==================================================================== %% API %%==================================================================== %%-------------------------------------------------------------------- %% Function: start_link() -> {ok,Pid} | ignore | {error,Error} %% Description: Starts the server %%-------------------------------------------------------------------- start_link() -> gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). start_logging() -> gen_server:call(?MODULE, {start, timestamp()}). event(EventData) -> event(EventData, timestamp()). event(EventData, Timestamp) -> gen_server:call(?MODULE, #event{ timestamp = Timestamp, data = EventData }). async_event(EventData) -> gen_server:cast(?MODULE, #event{ timestamp = timestamp(), data = EventData }). get_events() -> gen_server:call(?MODULE, get_events). %%==================================================================== %% gen_server callbacks %%==================================================================== %%-------------------------------------------------------------------- %% Function: init(Args) -> {ok, State} | %% {ok, State, Timeout} | %% ignore | %% {stop, Reason} %% Description: Initiates the server %%-------------------------------------------------------------------- init([]) -> {ok, #state{}}. %%-------------------------------------------------------------------- %% Function: %% handle_call(Request, From, State) -> %% {reply, Reply, State} | %% {reply, Reply, State, Timeout} | %% {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, Reply, State} | %% {stop, Reason, State} %% Description: Handling call messages %%-------------------------------------------------------------------- handle_call(Event = #event{}, _From, State) -> {reply, ok, add_event(Event, State)}; handle_call({start, Now}, _From, S) -> {reply, ok, S#state{ events = [], start_time = Now }}; handle_call(get_events, _From, S) -> {reply, lists:reverse([ {E#event.timestamp, E#event.data} || E <- S#state.events]), S#state{ events = [] }}; handle_call(Request, _From, State) -> {reply, {error, {bad_call, Request}}, State}. %%-------------------------------------------------------------------- %% Function: handle_cast(Msg, State) -> {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, State} %% Description: Handling cast messages %%-------------------------------------------------------------------- handle_cast(Event = #event{}, State) -> {noreply, add_event(Event, State)}; handle_cast(_Msg, State) -> {noreply, State}. %%-------------------------------------------------------------------- %% Function: handle_info(Info, State) -> {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, State} %% Description: Handling all non call/cast messages %%-------------------------------------------------------------------- handle_info(_Info, State) -> {noreply, State}. %%-------------------------------------------------------------------- %% Function: terminate(Reason, State) -> void() %% Description: This function is called by a gen_server when it is about to %% terminate. It should be the opposite of Module:init/1 and do any necessary %% cleaning up. When it returns, the gen_server terminates with Reason. %% The return value is ignored. %%-------------------------------------------------------------------- terminate(_Reason, _State) -> ok. %%-------------------------------------------------------------------- %% Func: code_change(OldVsn, State, Extra) -> {ok, NewState} %% Description: Convert process state when code is changed %%-------------------------------------------------------------------- code_change(_OldVsn, State, _Extra) -> {ok, State}. %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- add_event(#event{timestamp = Now, data = Data}, State) -> Event = #event{ timestamp = Now, data = Data }, State#state{ events = [Event|State#state.events] }. timestamp() -> lamport_clock:get().