%%% %%% Copyright 2011, Boundary %%% %%% Licensed 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: folsom_ewma.erl %%% @author joe williams %%% @doc %%% based on https://github.com/codahale/metrics/blob/development/src/main/java/com/yammer/metrics/stats/EWMA.java %%% references: %%% http://www.teamquest.com/pdfs/whitepaper/ldavg1.pdf %%% http://www.teamquest.com/pdfs/whitepaper/ldavg2.pdf %%% @end %%%----------------------------------------------------------------- -module(folsom_ewma). -define(M1_ALPHA, 1 - math:exp(-5 / 60.0)). -define(M5_ALPHA, 1 - math:exp(-5 / 60.0 / 5)). -define(M15_ALPHA, 1 - math:exp(-5 / 60.0 / 15)). -define(D1_ALPHA, 1 - math:exp(-5 / 60.0 / 1440)). -record(ewma, { alpha, interval = 5, % seconds initialized = false, rate = 0, total = 0 }). -export([update/2, new/2, rate/1, tick/1, one_minute_ewma/0, five_minute_ewma/0, fifteen_minute_ewma/0, one_day_ewma/0]). % API one_minute_ewma() -> new(?M1_ALPHA, 5). five_minute_ewma() -> new(?M5_ALPHA, 5). fifteen_minute_ewma() -> new(?M15_ALPHA, 5). one_day_ewma() -> new(?D1_ALPHA, 5). new(Alpha, Interval) -> #ewma{alpha = Alpha, interval = Interval}. update(#ewma{total = Total} = EWMA, Value) -> EWMA#ewma{total = Total + Value}. tick(#ewma{total = Total, rate = Rate, initialized = Init, interval = Interval, alpha = Alpha} = EWMA) -> InstantRate = Total / Interval, Rate1 = rate_calc(Init, Alpha, Rate, InstantRate), EWMA#ewma{rate = Rate1, initialized = true, total = 0}. rate(#ewma{rate = Rate}) -> Rate. % Internal API rate_calc(true, Alpha, Rate, InstantRate) -> Rate1 = Rate + (Alpha * (InstantRate - Rate)), Rate1; rate_calc(false, _, _, InstantRate) -> InstantRate.