Packages

Library with otter common functions

Current section

Files

Jump to
otter_lib src otter_lib_snapshot_count.erl
Raw

src/otter_lib_snapshot_count.erl

%%%-------------------------------------------------------------------
%%% Licensed to the Apache Software Foundation (ASF) under one
%%% or more contributor license agreements. See the NOTICE file
%%% distributed with this work for additional information
%%% regarding copyright ownership. The ASF licenses this file
%%% 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.
%%%
%%% @doc
%%% This module implements a simple way of giving operational visibility
%%% of events in the system. It expects a Key and Data where the
%%% Key is used to increment a counter in a table and also to store the
%%% last received Data for that Key. The Data is preferred to be a list
%%% of `{K,V}' tuples, if it is any other format, it uses `[{data, Data}]'
%%% to store the last information.
%%%
%%% The ETS tables holding the counters/snapshots must be initialized
%%% before the feature can be used. The application using this module should
%%% call `otter_lib_snapshot_count:sup_init()' from a persistent process.
%%% The simplest is to call from the application supervisor init. The call
%%% only creaes the ETS tables that need an owner process to stay around.
%%% @end
%%%-------------------------------------------------------------------
-module(otter_lib_snapshot_count).
-export([
delete_all_counters/0,
delete_counter/1,
get_snap/1,
list_counts/0,
snapshot/2,
sup_init/0
]).
%%--------------------------------------------------------------------
%% @doc Increase a counter for the given Key and store the Data. If the data
%% is a property (key-value) list then it adds the timestamp in
%% `{Year, Month, Day, Hour, Min, Sec, Us}' format to the list with key
%% `snap_timestamp`. If it is not a property list then it stores the
%% data in a property list with key `data' and adds the timestamp.
%% It returns the current counter value for the key.
%% @end
%%--------------------------------------------------------------------
-spec snapshot(Key :: term(), Data :: term()) -> integer().
snapshot(Key, [{_, _} |_ ] = Data) ->
{_, _, Us} = os:timestamp(),
{{Year, Month, Day}, {Hour, Min, Sec}} = calendar:local_time(),
ets:insert(
otter_snapshot_store,
{
Key,
[
{snap_timestamp, {Year, Month, Day, Hour, Min, Sec, Us}}
| Data
]
}
),
case catch ets:update_counter(otter_snapshot_count, Key, 1) of
{'EXIT', {badarg, _}} ->
ets:insert(otter_snapshot_count, {Key, 1});
Cnt ->
Cnt
end;
snapshot(Key, Data) ->
snapshot(Key, [{data, Data}]).
%%--------------------------------------------------------------------
%% @doc List all the counters with their values
%% @end
%%--------------------------------------------------------------------
-spec list_counts() -> [{Key :: term(), Counter :: integer()}].
list_counts() ->
ets:tab2list(otter_snapshot_count).
%%--------------------------------------------------------------------
%% @doc Return the last stored data (snapshot) for a key
%% @end
%%--------------------------------------------------------------------
-spec get_snap(Key :: term()) -> term().
get_snap(Key) ->
ets:lookup(otter_snapshot_store, Key).
%%--------------------------------------------------------------------
%% @doc Delete the counter and data (snapshot) for a key
%% @end
%%--------------------------------------------------------------------
-spec delete_counter(Key :: term()) -> ok.
delete_counter(Key) ->
ets:delete(otter_snapshot_store, Key),
ets:delete(otter_snapshot_count, Key),
ok.
%%--------------------------------------------------------------------
%% @doc Delete all counters and data (snapshot)
%% @end
%%--------------------------------------------------------------------
-spec delete_all_counters() -> ok.
delete_all_counters() ->
ets:delete_all_objects(otter_snapshot_store),
ets:delete_all_objects(otter_snapshot_count),
ok.
%%--------------------------------------------------------------------
%% @doc Initialize the ETS tables to store counters/snapshots. Should be
%% called from a persistent process/
%% @end
%%--------------------------------------------------------------------
-spec sup_init() -> term().
sup_init() ->
[
ets:new(Tab, [named_table, public, {Concurrency, true}]) ||
{Tab, Concurrency} <- [
{otter_snapshot_count, write_concurrency},
{otter_snapshot_store, write_concurrency}
]
].