1%%% 2%%% Copyright 2011, Boundary 3%%% 4%%% Licensed under the Apache License, Version 2.0 (the "License"); 5%%% you may not use this file except in compliance with the License. 6%%% You may obtain a copy of the License at 7%%% 8%%% http://www.apache.org/licenses/LICENSE-2.0 9%%% 10%%% Unless required by applicable law or agreed to in writing, software 11%%% distributed under the License is distributed on an "AS IS" BASIS, 12%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13%%% See the License for the specific language governing permissions and 14%%% limitations under the License. 15%%% 16 17 18%%%------------------------------------------------------------------- 19%%% File: folsom_ewma.erl 20%%% @author joe williams <j@boundary.com> 21%%% @doc 22%%% based on https://github.com/codahale/metrics/blob/development/src/main/java/com/yammer/metrics/stats/EWMA.java 23%%% references: 24%%% http://www.teamquest.com/pdfs/whitepaper/ldavg1.pdf 25%%% http://www.teamquest.com/pdfs/whitepaper/ldavg2.pdf 26%%% @end 27%%%----------------------------------------------------------------- 28 29 30-module(folsom_ewma). 31 32-define(M1_ALPHA, 1 - math:exp(-5 / 60.0)). 33-define(M5_ALPHA, 1 - math:exp(-5 / 60.0 / 5)). 34-define(M15_ALPHA, 1 - math:exp(-5 / 60.0 / 15)). 35-define(D1_ALPHA, 1 - math:exp(-5 / 60.0 / 1440)). 36 37-record(ewma, { 38 alpha, 39 interval = 5, % seconds 40 initialized = false, 41 rate = 0, 42 total = 0 43 }). 44 45-export([update/2, 46 new/2, 47 rate/1, 48 tick/1, 49 one_minute_ewma/0, 50 five_minute_ewma/0, 51 fifteen_minute_ewma/0, 52 one_day_ewma/0]). 53 54 55% API 56 57one_minute_ewma() -> 58 new(?M1_ALPHA, 5). 59 60five_minute_ewma() -> 61 new(?M5_ALPHA, 5). 62 63fifteen_minute_ewma() -> 64 new(?M15_ALPHA, 5). 65 66one_day_ewma() -> 67 new(?D1_ALPHA, 5). 68 69new(Alpha, Interval) -> 70 #ewma{alpha = Alpha, interval = Interval}. 71 72update(#ewma{total = Total} = EWMA, Value) -> 73 EWMA#ewma{total = Total + Value}. 74 75tick(#ewma{total = Total, rate = Rate, initialized = Init, interval = Interval, alpha = Alpha} = EWMA) -> 76 InstantRate = Total / Interval, 77 Rate1 = rate_calc(Init, Alpha, Rate, InstantRate), 78 EWMA#ewma{rate = Rate1, initialized = true, total = 0}. 79 80rate(#ewma{rate = Rate}) -> 81 Rate. 82 83% Internal API 84 85rate_calc(true, Alpha, Rate, InstantRate) -> 86 Rate1 = Rate + (Alpha * (InstantRate - Rate)), 87 Rate1; 88rate_calc(false, _, _, InstantRate) -> 89 InstantRate. 90