From 90cd10632ff2bcc6c541ac544728f18097290301 Mon Sep 17 00:00:00 2001
From: Anders Svensson <anders@erlang.org>
Date: Wed, 21 May 2014 00:46:56 +0200
Subject: Count decode errors independently of result codes

Since the former doesn't exclude the latter.

Counter values are returned by diameter:service_info/2. They can
currently only be retrieved for a service, not for individual transports
or peer connections.
---
 lib/diameter/src/base/diameter_traffic.erl | 22 ++++++++++++----------
 1 file changed, 12 insertions(+), 10 deletions(-)

(limited to 'lib/diameter')

diff --git a/lib/diameter/src/base/diameter_traffic.erl b/lib/diameter/src/base/diameter_traffic.erl
index 34f08a2710..908f5ff9bf 100644
--- a/lib/diameter/src/base/diameter_traffic.erl
+++ b/lib/diameter/src/base/diameter_traffic.erl
@@ -635,7 +635,7 @@ reply(Msg, Dict, TPid, Dict0, Fs, ReqPkt) ->
     Pkt = encode(Dict,
                  reset(make_answer_packet(Msg, ReqPkt), Dict, Dict0),
                  Fs),
-    incr_A(send, Pkt, Dict, TPid, Dict0),  %% count outgoing result codes
+    incr_A(send, Pkt, Dict, TPid, Dict0),  %% count outgoing
     send(TPid, Pkt).
 
 %% reset/3
@@ -1010,18 +1010,20 @@ find(Pred, [H|T]) ->
 incr_A(_, #diameter_packet{msg = undefined = No}, _, _, _) ->
     No;
 
-%% Incoming with decode errors.
-incr_A(recv = D, #diameter_packet{header = H, errors = [_|_]}, _, TPid, _) ->
-    incr(TPid, {diameter_codec:msg_id(H), D, error});
-
-%% Incoming without errors or outgoing. Outgoing with encode errors
-%% never gets here since encode fails.
+%% Incoming or outgoing. Outgoing with encode errors never gets here
+%% since encode fails.
 incr_A(Dir, Pkt, Dict, TPid, Dict0) ->
     #diameter_packet{header = #diameter_header{is_error = E}
                             = Hdr,
-                     msg = Msg}
+                     msg = Msg,
+                     errors = Es}
         = Pkt,
 
+    Id = diameter_codec:msg_id(Hdr),
+
+    %% Count incoming decode errors.
+    recv /= Dir orelse [] == Es orelse incr(TPid, {Id, Dir, error}),
+
     %% Exit on a missing result code.
     T = rc_counter(Dict, Msg),
     T == false andalso x(no_result_code, answer, [Dir, Pkt]),
@@ -1031,7 +1033,7 @@ incr_A(Dir, Pkt, Dict, TPid, Dict0) ->
     is_result(RC, E, Dict0)
         orelse x({invalid_error_bit, RC}, answer, [Dir, Pkt]),
 
-    incr(TPid, {diameter_codec:msg_id(Hdr), Dir, Ctr}).
+    incr(TPid, {Id, Dir, Ctr}).
 
 %% No E-bit: can't be 3xxx.
 is_result(RC, false, _Dict0) ->
@@ -1408,7 +1410,7 @@ handle_answer(SvcName,
 
 handle_A(Pkt, SvcName, Dict, Dict0, App, #request{transport = TPid} = Req) ->
     try
-        incr_A(recv, Pkt, Dict, TPid, Dict0) %% count incoming result codes
+        incr_A(recv, Pkt, Dict, TPid, Dict0) %% count incoming
     of
         _ -> answer(Pkt, SvcName, App, Req)
     catch
-- 
cgit v1.2.3


From 6642bfc89b9a9863ea1f4864d28b96b075beedd8 Mon Sep 17 00:00:00 2001
From: Anders Svensson <anders@erlang.org>
Date: Wed, 21 May 2014 01:07:00 +0200
Subject: Count decode errors in incoming requests

Errors were only counted in incoming answers. Counters are keyed on
tuples of the same form:

  {{ApplicationId, CommandCode, Rbit}, recv, error}
---
 lib/diameter/src/base/diameter_peer_fsm.erl |  2 ++
 lib/diameter/src/base/diameter_traffic.erl  | 21 +++++++++++++++++++--
 lib/diameter/src/base/diameter_watchdog.erl |  3 ++-
 3 files changed, 23 insertions(+), 3 deletions(-)

(limited to 'lib/diameter')

diff --git a/lib/diameter/src/base/diameter_peer_fsm.erl b/lib/diameter/src/base/diameter_peer_fsm.erl
index ae890d67d7..4978c1e049 100644
--- a/lib/diameter/src/base/diameter_peer_fsm.erl
+++ b/lib/diameter/src/base/diameter_peer_fsm.erl
@@ -650,6 +650,8 @@ handle_request(Type, #diameter_packet{} = Pkt, #state{dictionary = D} = S) ->
 %% send_answer/3
 
 send_answer(Type, ReqPkt, #state{transport = TPid, dictionary = Dict} = S) ->
+    diameter_traffic:incr_R(recv, ReqPkt, TPid),
+
     #diameter_packet{header = H,
                      transport_data = TD}
         = ReqPkt,
diff --git a/lib/diameter/src/base/diameter_traffic.erl b/lib/diameter/src/base/diameter_traffic.erl
index 908f5ff9bf..29d21fa7dc 100644
--- a/lib/diameter/src/base/diameter_traffic.erl
+++ b/lib/diameter/src/base/diameter_traffic.erl
@@ -32,7 +32,8 @@
 -export([receive_message/4]).
 
 %% towards diameter_peer_fsm and diameter_watchdog
--export([incr_A/4]).
+-export([incr_A/4,
+         incr_R/3]).
 
 %% towards diameter_service
 -export([make_recvdata/1,
@@ -137,6 +138,18 @@ incr_A(Dir, Pkt, TPid, Dict0) ->
             E
     end.
 
+%% ---------------------------------------------------------------------------
+%% incr_R/3
+%% ---------------------------------------------------------------------------
+
+%% incr_R/3
+
+incr_R(recv = D, #diameter_packet{header = H, errors = [_|_]}, TPid) ->
+    incr_error(diameter_codec:msg_id(H), D, TPid);
+
+incr_R(_, _, _) ->
+    ok.
+
 %% ---------------------------------------------------------------------------
 %% pending/1
 %% ---------------------------------------------------------------------------
@@ -241,6 +254,7 @@ recv_R({#diameter_app{id = Id, dictionary = Dict} = App, Caps},
        Dict0,
        RecvData) ->
     Pkt = errors(Id, diameter_codec:decode(Id, Dict, Pkt0)),
+    incr_R(recv, Pkt, TPid),
     {Caps, Pkt, App, recv_R(App, TPid, Dict0, Caps, RecvData, Pkt)};
 %% Note that the decode is different depending on whether or not Id is
 %% ?APP_ID_RELAY.
@@ -1022,7 +1036,7 @@ incr_A(Dir, Pkt, Dict, TPid, Dict0) ->
     Id = diameter_codec:msg_id(Hdr),
 
     %% Count incoming decode errors.
-    recv /= Dir orelse [] == Es orelse incr(TPid, {Id, Dir, error}),
+    recv /= Dir orelse [] == Es orelse incr_error(Id, Dir, TPid),
 
     %% Exit on a missing result code.
     T = rc_counter(Dict, Msg),
@@ -1106,6 +1120,9 @@ x(Reason, F, A) ->
 x(T) ->
     exit(T).
 
+incr_error(Id, Dir, TPid) ->
+    incr(TPid, {Id, Dir, error}).
+    
 %% ---------------------------------------------------------------------------
 %% # send_request/4
 %%
diff --git a/lib/diameter/src/base/diameter_watchdog.erl b/lib/diameter/src/base/diameter_watchdog.erl
index c17a3bde5d..710017e62f 100644
--- a/lib/diameter/src/base/diameter_watchdog.erl
+++ b/lib/diameter/src/base/diameter_watchdog.erl
@@ -1,7 +1,7 @@
 %%
 %% %CopyrightBegin%
 %%
-%% Copyright Ericsson AB 2010-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2014. All Rights Reserved.
 %%
 %% The contents of this file are subject to the Erlang Public License,
 %% Version 1.1, (the "License"); you may not use this file except in
@@ -559,6 +559,7 @@ recv(Name, Pkt, S) ->
 
 rcv('DWR', Pkt, #watchdog{transport = TPid,
                           dictionary = Dict0}) ->
+    diameter_traffic:incr_R(recv, diameter_codec:decode(Pkt), TPid),
     EPkt = encode(dwa, Dict0, Pkt),
     diameter_traffic:incr_A(send, EPkt, TPid, Dict0),
     send(TPid, {send, EPkt}),
-- 
cgit v1.2.3


From 58a070c491e7f2f87a3c6bb09a5c05208a9aa333 Mon Sep 17 00:00:00 2001
From: Anders Svensson <anders@erlang.org>
Date: Thu, 22 May 2014 02:09:23 +0200
Subject: Count encode errors in outgoing messages

Only decode errors were counted previously. Keys are of the form
{Id, send, error}, where Id is:

  {ApplicationId, CommandCode, Rbit} | unknown

The latter will be the case if not even a #diameter_header{} can be
constructed.
---
 lib/diameter/src/base/diameter_codec.erl    | 99 +++++++++++++++++------------
 lib/diameter/src/base/diameter_peer_fsm.erl | 44 +++++++------
 lib/diameter/src/base/diameter_traffic.erl  | 89 +++++++++++++++-----------
 lib/diameter/src/base/diameter_watchdog.erl | 14 ++--
 4 files changed, 143 insertions(+), 103 deletions(-)

(limited to 'lib/diameter')

diff --git a/lib/diameter/src/base/diameter_codec.erl b/lib/diameter/src/base/diameter_codec.erl
index 0de4d53973..9db3552286 100644
--- a/lib/diameter/src/base/diameter_codec.erl
+++ b/lib/diameter/src/base/diameter_codec.erl
@@ -1,7 +1,7 @@
 %%
 %% %CopyrightBegin%
 %%
-%% Copyright Ericsson AB 2010-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2014. All Rights Reserved.
 %%
 %% The contents of this file are subject to the Erlang Public License,
 %% Version 1.1, (the "License"); you may not use this file except in
@@ -70,6 +70,12 @@ encode(Mod, #diameter_packet{} = Pkt) ->
     try
         e(Mod, Pkt)
     catch
+        exit: {_, _, #diameter_header{}} = T ->
+            %% Exit with a header in the reason to let the caller
+            %% count encode errors.
+            X = {?MODULE, encode, T},
+            diameter_lib:error_report(X, {?MODULE, encode, [Mod, Pkt]}),
+            exit(X);
         error: Reason ->
             %% Be verbose since a crash report may be truncated and
             %% encode errors are self-inflicted.
@@ -87,53 +93,62 @@ encode(Mod, Msg) ->
                                   msg = Msg}).
 
 e(_, #diameter_packet{msg = [#diameter_header{} = Hdr | As]} = Pkt) ->
-    Avps = encode_avps(As),
-    Length = size(Avps) + 20,
-
-    #diameter_header{version = Vsn,
-                     cmd_code = Code,
-                     application_id = Aid,
-                     hop_by_hop_id  = Hid,
-                     end_to_end_id  = Eid}
-        = Hdr,
-
-    Flags = make_flags(0, Hdr),
-
-    Pkt#diameter_packet{header = Hdr,
-                        bin = <<Vsn:8, Length:24,
-                                Flags:8, Code:24,
-                                Aid:32,
-                                Hid:32,
-                                Eid:32,
-                                Avps/binary>>};
+    try encode_avps(As) of
+        Avps ->
+            Length = size(Avps) + 20,
+
+            #diameter_header{version = Vsn,
+                             cmd_code = Code,
+                             application_id = Aid,
+                             hop_by_hop_id  = Hid,
+                             end_to_end_id  = Eid}
+                = Hdr,
+
+            Flags = make_flags(0, Hdr),
+
+            Pkt#diameter_packet{header = Hdr,
+                                bin = <<Vsn:8, Length:24,
+                                        Flags:8, Code:24,
+                                        Aid:32,
+                                        Hid:32,
+                                        Eid:32,
+                                        Avps/binary>>}
+    catch
+        error: Reason ->
+            exit({Reason, ?STACK, Hdr})
+    end;
 
-e(Mod, #diameter_packet{header = Hdr, msg = Msg} = Pkt) ->
+e(Mod, #diameter_packet{header = Hdr0, msg = Msg} = Pkt) ->
     #diameter_header{version = Vsn,
                      hop_by_hop_id = Hid,
                      end_to_end_id = Eid}
-        = Hdr,
+        = Hdr0,
 
     MsgName = rec2msg(Mod, Msg),
-    {Code, Flags0, Aid} = msg_header(Mod, MsgName, Hdr),
-    Flags = make_flags(Flags0, Hdr),
-
-    Avps = encode_avps(Mod, MsgName, values(Msg)),
-    Length = size(Avps) + 20,
-
-    Pkt#diameter_packet{header = Hdr#diameter_header
-                                    {length = Length,
-                                     cmd_code = Code,
-                                     application_id = Aid,
-                                     is_request       = 0 /= ?MASK(7, Flags),
-                                     is_proxiable     = 0 /= ?MASK(6, Flags),
-                                     is_error         = 0 /= ?MASK(5, Flags),
-                                     is_retransmitted = 0 /= ?MASK(4, Flags)},
-                        bin = <<Vsn:8, Length:24,
-                                Flags:8, Code:24,
-                                Aid:32,
-                                Hid:32,
-                                Eid:32,
-                                Avps/binary>>}.
+    {Code, Flags0, Aid} = msg_header(Mod, MsgName, Hdr0),
+    Flags = make_flags(Flags0, Hdr0),
+    Hdr = Hdr0#diameter_header{cmd_code = Code,
+                               application_id = Aid,
+                               is_request       = 0 /= ?MASK(7, Flags),
+                               is_proxiable     = 0 /= ?MASK(6, Flags),
+                               is_error         = 0 /= ?MASK(5, Flags),
+                               is_retransmitted = 0 /= ?MASK(4, Flags)},
+    Values = values(Msg),
+
+    try encode_avps(Mod, MsgName, Values) of
+        Avps ->
+            Length = size(Avps) + 20,
+            Pkt#diameter_packet{header = Hdr#diameter_header{length = Length},
+                                bin = <<Vsn:8, Length:24,
+                                        Flags:8, Code:24,
+                                        Aid:32,
+                                        Hid:32,
+                                        Eid:32,
+                                        Avps/binary>>}
+    catch
+        error: Reason ->
+            exit({Reason, ?STACK, Hdr})
+    end.
 
 %% make_flags/2
 
diff --git a/lib/diameter/src/base/diameter_peer_fsm.erl b/lib/diameter/src/base/diameter_peer_fsm.erl
index 4978c1e049..74086e75b0 100644
--- a/lib/diameter/src/base/diameter_peer_fsm.erl
+++ b/lib/diameter/src/base/diameter_peer_fsm.erl
@@ -296,7 +296,8 @@ handle_info(T, #state{} = State) ->
             ?LOG(stop, T),
             {stop, {shutdown, T}, State}
     catch
-        exit: {diameter_codec, encode, _} = Reason ->
+        exit: {diameter_codec, encode, T} = Reason ->
+            incr_error(send, T),
             ?LOG(stop, Reason),
             %% diameter_codec:encode/2 emits an error report. Only
             %% indicate the probable reason here.
@@ -619,7 +620,7 @@ rcv('DPA' = N,
            transport = TPid,
            dpr = {Hid, Eid}}) ->
 
-    incr_A(recv, diameter_codec:decode(Dict0, Pkt), Dict0),
+    incr_rc(recv, diameter_codec:decode(Dict0, Pkt), Dict0),
     diameter_peer:close(TPid),
     {stop, N};
 
@@ -627,10 +628,15 @@ rcv('DPA' = N,
 rcv(_, _, _) ->
     ok.
 
-%% incr_A/3
+%% incr_rc/3
 
-incr_A(Dir, Pkt, Dict0) ->
-    diameter_traffic:incr_A(Dir, Pkt, self(), Dict0).
+incr_rc(Dir, Pkt, Dict0) ->
+    diameter_traffic:incr_rc(Dir, Pkt, self(), Dict0).
+
+%% incr_error/2
+
+incr_error(Dir, Pkt) ->
+    diameter_traffic:incr_error(Dir, Pkt, self()).
 
 %% send/2
 
@@ -650,7 +656,7 @@ handle_request(Type, #diameter_packet{} = Pkt, #state{dictionary = D} = S) ->
 %% send_answer/3
 
 send_answer(Type, ReqPkt, #state{transport = TPid, dictionary = Dict} = S) ->
-    diameter_traffic:incr_R(recv, ReqPkt, TPid),
+    incr_error(recv, ReqPkt),
 
     #diameter_packet{header = H,
                      transport_data = TD}
@@ -660,18 +666,18 @@ send_answer(Type, ReqPkt, #state{transport = TPid, dictionary = Dict} = S) ->
 
     %% An answer message clears the R and T flags and retains the P
     %% flag. The E flag is set at encode.
-    Pkt0 = #diameter_packet{header
-                            = H#diameter_header{version = ?DIAMETER_VERSION,
-                                                is_request = false,
-                                                is_error = undefined,
-                                                is_retransmitted = false},
-                            msg = Msg,
-                            transport_data = TD},
-
-    Pkt = diameter_codec:encode(Dict, Pkt0),
-
-    incr_A(send, Pkt, Dict),
-    send(TPid, Pkt),
+    Pkt = #diameter_packet{header
+                           = H#diameter_header{version = ?DIAMETER_VERSION,
+                                               is_request = false,
+                                               is_error = undefined,
+                                               is_retransmitted = false},
+                           msg = Msg,
+                           transport_data = TD},
+
+    AnsPkt = diameter_codec:encode(Dict, Pkt),
+
+    incr_rc(send, AnsPkt, Dict),
+    send(TPid, AnsPkt),
     eval(PostF, S).
 
 eval([F|A], S) ->
@@ -884,7 +890,7 @@ handle_CEA(#diameter_packet{bin = Bin}
         = DPkt
         = diameter_codec:decode(Dict0, Pkt),
 
-    RC = result_code(incr_A(recv, DPkt, Dict0)),
+    RC = result_code(incr_rc(recv, DPkt, Dict0)),
 
     {SApps, IS, RCaps} = recv_CEA(DPkt, S),
 
diff --git a/lib/diameter/src/base/diameter_traffic.erl b/lib/diameter/src/base/diameter_traffic.erl
index 29d21fa7dc..f113d95b2e 100644
--- a/lib/diameter/src/base/diameter_traffic.erl
+++ b/lib/diameter/src/base/diameter_traffic.erl
@@ -32,8 +32,8 @@
 -export([receive_message/4]).
 
 %% towards diameter_peer_fsm and diameter_watchdog
--export([incr_A/4,
-         incr_R/3]).
+-export([incr_error/3,
+         incr_rc/4]).
 
 %% towards diameter_service
 -export([make_recvdata/1,
@@ -116,10 +116,35 @@ peer_down(TPid) ->
     failover(TPid).
 
 %% ---------------------------------------------------------------------------
-%% incr_A/4
+%% incr_error/3
 %% ---------------------------------------------------------------------------
 
--spec incr_A(send|recv, #diameter_packet{}, TPid, Dict0)
+%% A decoded message with errors.
+incr_error(Dir, #diameter_packet{header = H, errors = [_|_]}, TPid) ->
+    incr_error(Dir, H, TPid);
+
+%% An encoded message with errors and an identifiable header ...
+incr_error(Dir, {_, _, #diameter_header{} = H}, TPid) ->
+    incr_error(Dir, H, TPid);
+
+%% ... or not.
+incr_error(Dir, {_,_}, TPid) ->
+    incr(TPid, {unknown, Dir, error});
+
+incr_error(Dir, #diameter_header{} = H, TPid) ->
+    incr_error(Dir, diameter_codec:msg_id(H), TPid);
+
+incr_error(Dir, {_,_,_} = Id, TPid) ->
+    incr(TPid, {Id, Dir, error});
+
+incr_error(_, _, _) ->
+    false.
+
+%% ---------------------------------------------------------------------------
+%% incr_rc/4
+%% ---------------------------------------------------------------------------
+
+-spec incr_rc(send|recv, #diameter_packet{}, TPid, Dict0)
    -> {Counter, non_neg_integer()}
     | Reason
  when TPid :: pid(),
@@ -128,9 +153,9 @@ peer_down(TPid) ->
                | {'Experimental-Result', integer(), integer()},
       Reason :: atom().
 
-incr_A(Dir, Pkt, TPid, Dict0) ->
+incr_rc(Dir, Pkt, TPid, Dict0) ->
     try
-        incr_A(Dir, Pkt, Dict0, TPid, Dict0)
+        incr_rc(Dir, Pkt, Dict0, TPid, Dict0)
     catch
         exit: {invalid_error_bit = E, _} ->
             E;
@@ -138,18 +163,6 @@ incr_A(Dir, Pkt, TPid, Dict0) ->
             E
     end.
 
-%% ---------------------------------------------------------------------------
-%% incr_R/3
-%% ---------------------------------------------------------------------------
-
-%% incr_R/3
-
-incr_R(recv = D, #diameter_packet{header = H, errors = [_|_]}, TPid) ->
-    incr_error(diameter_codec:msg_id(H), D, TPid);
-
-incr_R(_, _, _) ->
-    ok.
-
 %% ---------------------------------------------------------------------------
 %% pending/1
 %% ---------------------------------------------------------------------------
@@ -254,7 +267,7 @@ recv_R({#diameter_app{id = Id, dictionary = Dict} = App, Caps},
        Dict0,
        RecvData) ->
     Pkt = errors(Id, diameter_codec:decode(Id, Dict, Pkt0)),
-    incr_R(recv, Pkt, TPid),
+    incr_error(recv, Pkt, TPid),
     {Caps, Pkt, App, recv_R(App, TPid, Dict0, Caps, RecvData, Pkt)};
 %% Note that the decode is different depending on whether or not Id is
 %% ?APP_ID_RELAY.
@@ -647,9 +660,10 @@ reply([Msg], Dict, TPid, Dict0, Fs, ReqPkt)
 
 reply(Msg, Dict, TPid, Dict0, Fs, ReqPkt) ->
     Pkt = encode(Dict,
+                 TPid,
                  reset(make_answer_packet(Msg, ReqPkt), Dict, Dict0),
                  Fs),
-    incr_A(send, Pkt, Dict, TPid, Dict0),  %% count outgoing
+    incr_rc(send, Pkt, Dict, TPid, Dict0),  %% count outgoing
     send(TPid, Pkt).
 
 %% reset/3
@@ -1014,19 +1028,19 @@ find(Pred, [H|T]) ->
 %%    code, the missing vendor id, and a zero filled payload of the minimum
 %%    required length for the omitted AVP will be added.
 
-%% incr_A/5
+%% incr_rc/5
 %%
 %% Increment a stats counter for result codes in incoming and outgoing
 %% answers.
 
 %% Outgoing message as binary: don't count. (Sending binaries is only
 %% partially supported.)
-incr_A(_, #diameter_packet{msg = undefined = No}, _, _, _) ->
+incr_rc(_, #diameter_packet{msg = undefined = No}, _, _, _) ->
     No;
 
 %% Incoming or outgoing. Outgoing with encode errors never gets here
 %% since encode fails.
-incr_A(Dir, Pkt, Dict, TPid, Dict0) ->
+incr_rc(Dir, Pkt, Dict, TPid, Dict0) ->
     #diameter_packet{header = #diameter_header{is_error = E}
                             = Hdr,
                      msg = Msg,
@@ -1036,7 +1050,7 @@ incr_A(Dir, Pkt, Dict, TPid, Dict0) ->
     Id = diameter_codec:msg_id(Hdr),
 
     %% Count incoming decode errors.
-    recv /= Dir orelse [] == Es orelse incr_error(Id, Dir, TPid),
+    recv /= Dir orelse [] == Es orelse incr_error(Dir, Id, TPid),
 
     %% Exit on a missing result code.
     T = rc_counter(Dict, Msg),
@@ -1120,9 +1134,6 @@ x(Reason, F, A) ->
 x(T) ->
     exit(T).
 
-incr_error(Id, Dir, TPid) ->
-    incr(TPid, {Id, Dir, error}).
-    
 %% ---------------------------------------------------------------------------
 %% # send_request/4
 %%
@@ -1361,7 +1372,7 @@ send_R(Pkt0,
        {Pid, Ref},
        SvcName,
        Fs) ->
-    Pkt = encode(Dict, Pkt0, Fs),
+    Pkt = encode(Dict, TPid, Pkt0, Fs),
 
     #options{timeout = Timeout}
         = Opts,
@@ -1427,7 +1438,7 @@ handle_answer(SvcName,
 
 handle_A(Pkt, SvcName, Dict, Dict0, App, #request{transport = TPid} = Req) ->
     try
-        incr_A(recv, Pkt, Dict, TPid, Dict0) %% count incoming
+        incr_rc(recv, Pkt, Dict, TPid, Dict0) %% count incoming
     of
         _ -> answer(Pkt, SvcName, App, Req)
     catch
@@ -1525,10 +1536,10 @@ msg(#diameter_packet{msg = undefined, bin = Bin}) ->
 msg(#diameter_packet{msg = Msg}) ->
     Msg.
 
-%% encode/3
+%% encode/4
 
-encode(Dict, Pkt, Fs) ->
-    P = encode(Dict, Pkt),
+encode(Dict, TPid, Pkt, Fs) ->
+    P = encode(Dict, TPid, Pkt),
     eval_packet(P, Fs),
     P.
 
@@ -1540,11 +1551,17 @@ encode(Dict, Pkt, Fs) ->
 %% support retransmission but is useful for test.
 
 %% A message to be encoded.
-encode(Dict, #diameter_packet{bin = undefined} = Pkt) ->
-    diameter_codec:encode(Dict, Pkt);
+encode(Dict, TPid, #diameter_packet{bin = undefined} = Pkt) ->
+    try
+        diameter_codec:encode(Dict, Pkt)
+    catch
+        exit: {diameter_codec, encode, T} = Reason ->
+            incr_error(send, T, TPid),
+            exit(Reason)
+    end;
 
 %% An encoded binary: just send.
-encode(_, #diameter_packet{} = Pkt) ->
+encode(_, _, #diameter_packet{} = Pkt) ->
     Pkt.
 
 %% send_request/5
@@ -1641,7 +1658,7 @@ resend_request(Pkt0,
                SvcName,
                Tmo,
                Fs) ->
-    Pkt = encode(Dict, Pkt0, Fs),
+    Pkt = encode(Dict, TPid, Pkt0, Fs),
 
     Req = Req0#request{transport = TPid,
                        packet = Pkt0,
diff --git a/lib/diameter/src/base/diameter_watchdog.erl b/lib/diameter/src/base/diameter_watchdog.erl
index 710017e62f..87b69cc60d 100644
--- a/lib/diameter/src/base/diameter_watchdog.erl
+++ b/lib/diameter/src/base/diameter_watchdog.erl
@@ -559,18 +559,20 @@ recv(Name, Pkt, S) ->
 
 rcv('DWR', Pkt, #watchdog{transport = TPid,
                           dictionary = Dict0}) ->
-    diameter_traffic:incr_R(recv, diameter_codec:decode(Pkt), TPid),
+    DPkt = diameter_codec:decode(Dict0, Pkt),
+    diameter_traffic:incr_error(recv, DPkt, TPid),
     EPkt = encode(dwa, Dict0, Pkt),
-    diameter_traffic:incr_A(send, EPkt, TPid, Dict0),
+    diameter_traffic:incr_rc(send, EPkt, TPid, Dict0),
+
     send(TPid, {send, EPkt}),
     ?LOG(send, 'DWA');
 
 rcv('DWA', Pkt, #watchdog{transport = TPid,
                           dictionary = Dict0}) ->
-    diameter_traffic:incr_A(recv,
-                            diameter_codec:decode(Dict0, Pkt),
-                            TPid,
-                            Dict0);
+    diameter_traffic:incr_rc(recv,
+                             diameter_codec:decode(Dict0, Pkt),
+                             TPid,
+                             Dict0);
 
 rcv(N, _, _)
   when N == 'CER';
-- 
cgit v1.2.3