anchor.diff:  
   %% API
   -export([current_state/1,
  -         heartbeat/1,
  +         heartbeat/2,
            set_logging/2,
            start_link/3]).
   
  
positive.code: 
  -type node_name() :: binary().
  -type node_state() :: binary().
  -type logging_level() :: 'verbose' | 'normal'.
  -type status_atom() :: 'idle' | 'ready' | 'restarting' | 'running'.
  -type status_binary() :: binary(). % <<"idle">> | <<"ready">> | <<"restarting">> | <<"running">>.
  -type gproc_error() :: ok | {error, no_node}.
  
  -record(eavg, {acc = 0 :: integer(),
                 avg = 0 :: float(),
                 n = 0   :: integer(),
                 tick_interval :: integer(),
                 tref   :: reference()
                }).
  
  -record(state, {dead_interval    :: integer(),
                  name             :: binary(),
                  
  
                  heartbeat_rate   :: #eavg{},
                  logging = normal :: logging_level(),
                  observers = []
                 }).
  
  -spec eavg_init(integer(), integer()) -> #eavg{}.
  eavg_init(N, I) ->
      TRef = erlang:start_timer(I, self(), update_avg),
      #eavg{acc=0, avg=0, n=N, tick_interval=I, tref=TRef}.
  
  -spec eavg_tick(#eavg{}) -> #eavg{}.
  eavg_tick(#eavg{acc=Acc, avg=Avg, n=N, tick_interval=I}=EAvg) ->
      ?debugVal(EAvg),
      NAvg = (Avg * (N-1) + Acc)/N,
      TRef = erlang:start_timer(I, self(), update_avg),
      EAvg#eavg{acc=0, avg=NAvg, tref=TRef}.
  
  eavg_inc(#eavg{acc=Acc}=EAvg, Count) ->
      ?debugVal(EAvg),
      ?debugVal(Count),
      EAvg#eavg{acc=Acc+Count}.
  
  eavg_value(#eavg{avg=Avg}) ->
      Avg.
  
  %%%
  %%% External API
  %%%
  -spec start_link(node_name(),HeartbeatInterval::integer(),DeadIntervalCount::integer()) ->
                          'ignore' | {'error',_} | {'ok',pid()}.
  start_link(Name, HeartbeatInterval, DeadIntervalCount) ->
      gen_fsm:start_link(?MODULE, [Name, HeartbeatInterval, DeadIntervalCount], []).
  
  -spec heartbeat({'heartbeat',node_name(),node_state()}) -> gproc_error().
  heartbeat({heartbeat, NodeName, NodeState}) ->
      case catch gproc:send({n,l,NodeName},
              {heartbeat, NodeName, status_to_atom(NodeState)}) of
          {'EXIT', _} -> ?NO_NODE;
          _ -> ok
      end.
  
  
negative.code:             gen_fsm:send_all_state_event(Pid, {Action, self()})
      end.
  
  %
  % This is split into two phases: an 'upper half' to get the minimimal work done required to wire things up
  % and a 'lower half' that takes care of things that can wait
  % 
  init([Name, HeartbeatInterval, DeadIntervalCount]) ->
  
      State = #state{name = Name,
                     dead_interval = HeartbeatInterval * DeadIntervalCount,
                     heartbeats = 0,
                     current_status = down, % Fetch from db later
                     heartbeat_rate = pushy_ema:init(DeadIntervalCount, HeartbeatInterval)},
      try
          %% The most important thing to have happen is this registration; we need to get this
          %% assigned before anyone else tries to start things up gproc:reg can only return
          %% true or throw
          true = gproc:reg({n, l, Name}),
          {ok, initializing, State, 0}
      catch
          error:badarg ->
              %% When we start up from a previous run, we have two ways that the FSM might be started;
              %% from an incoming packet, or the database record for a prior run
              %% There may be some nasty race conditions surrounding this.
              %% We may also want to *not* automatically reanimate FSMs for nodes that aren't
              %% actively reporting; but rather keep them in a 'limbo' waiting for the first
              %% packet, and if one doesn't arrive within a certain time mark them down.
              lager:error("Failed to register:~p for ~p (already exists as ~p?)",
                          [Name,self(), gproc:lookup_pid({n,l,Name}) ]),
              {stop, shutdown, State}
      end.
  
  %
  % Lower half of initialization; we have more time for complex work here.
  %
  initializing(timeout, #state{}=StateData) ->
      StateData2 = StateData#state{
                     current_status = down % TODO Fetch this from the db someday
                     },
      {next_state, down, reset_timer(create_status_record(?SAVE_MODE, down, StateData2))}.
  
  %%%
  %%% State machine internals
  %%%
  up(current_state, _From, #state{heartbeat_rate=HRate}=State) ->
      {reply, {up, push_ema:value(HRate)}, up, State}.
  
  crashed(current_state, _From, #state{heartbeat_rate=HRate}=State) ->
      {reply, {crashed, push_ema:value(HRate)}, crashed, State}.
  
  restarting(current_state, _From, #state{heartbeat_rate=HRate}=State) ->
      {reply, {restarting, push_ema:value(HRate)}, restarting, State}.
  
  %%
  %% These events are handled the same for every state
  %%
  -spec handle_event(any(), fsm_states(), #state{}) -> {any(), fsm_states(), #state{}}.
  handle_event({start_watching, Who}, StateName, #state{observers=Observers}=State) ->
      State1 = case lists:member(Who, Observers) of
          false ->
  