From d0b1f48457bd26a0bb3f5e1b35c833533ed2ce01 Mon Sep 17 00:00:00 2001 From: Piotr Nosek Date: Thu, 13 Nov 2014 14:05:29 +0100 Subject: [PATCH 1/4] Add latency measurement for XMPP messages --- src/tsung/ts_jabber.erl | 18 ++++++++++++++++++ src/tsung/ts_jabber_common.erl | 13 ++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/tsung/ts_jabber.erl b/src/tsung/ts_jabber.erl index 5e9df8472..4b8210be6 100644 --- a/src/tsung/ts_jabber.erl +++ b/src/tsung/ts_jabber.erl @@ -50,6 +50,7 @@ userid/1]). -export ([starttls_bidi/2, + message_bidi/2, presence_bidi/2]). %%---------------------------------------------------------------------- @@ -165,6 +166,7 @@ parse_bidi(Data, State) -> RcvdXml = binary_to_list(Data), BidiElements = [{"]*subscribe[\"\']", presence_bidi}, + {"@@@([^@]+)@@@", message_bidi}, {" case re:run(RcvdXml,Regex) of @@ -180,6 +182,22 @@ presence_bidi(RcvdXml, State)-> {match,SubMatches} = re:run(RcvdXml,"]*subscribe[\"\'][^>]*>",[global]), bidi_resp(subscribed,RcvdXml,SubMatches,State). +message_bidi(RcvdXml, State) -> + {match, [NodeStamp]} = re:run(RcvdXml, "@@@([^@]+)@@@", [{capture, all_but_first, list}]), + [NodeS, StampS] = string:tokens(NodeStamp, ","), + case integer_to_list(erlang:phash2(node())) of + NodeS -> + [MegaS, SecsS, MicroS] = string:tokens(StampS, ";"), + Mega = list_to_integer(MegaS), + Secs = list_to_integer(SecsS), + Micro = list_to_integer(MicroS), + Latency = timer:now_diff(erlang:now(), {Mega, Secs, Micro}), + ts_mon:add({ sample, msg_latency, Latency }); + _ -> + ignore + end, + {nodata, State}. + starttls_bidi(_RcvdXml, #state_rcv{socket= Socket}=State)-> ssl:start(), Req = subst(State#state_rcv.request#ts_request.param, State#state_rcv.dynvars), diff --git a/src/tsung/ts_jabber_common.erl b/src/tsung/ts_jabber_common.erl index 95646a0f3..994d449a9 100644 --- a/src/tsung/ts_jabber_common.erl +++ b/src/tsung/ts_jabber_common.erl @@ -482,11 +482,22 @@ registration(#jabber{username=Name,passwd=Passwd,resource=Resource})-> %% Purpose: send message to defined user at the Service (aim, ...) %%---------------------------------------------------------------------- message(Dest, #jabber{size=Size,data=undefined}, Service) when is_integer(Size) -> + {Mega, Secs, Micro} = erlang:now(), + TS = integer_to_list(Mega) ++ ";" + ++ integer_to_list(Secs) ++ ";" + ++ integer_to_list(Micro), + Stamp = "@@@" ++ integer_to_list(erlang:phash2(node())) ++ "," ++ TS ++ "@@@", + PadLen = Size - length(Stamp), + Data = case PadLen > 0 of + true -> ts_utils:urandomstr_noflat(PadLen); + false -> "" + end, + StampAndData = Stamp ++ Data, put(previous, Dest), list_to_binary([ "",ts_utils:urandomstr_noflat(Size), ""]); + "' type='chat'>",StampAndData, ""]); message(Dest, #jabber{data=Data}, Service) when is_list(Data) -> put(previous, Dest), list_to_binary([ From d30368cd381b98d25d49e52b0b4ef6ed64914074 Mon Sep 17 00:00:00 2001 From: Piotr Nosek Date: Mon, 17 Nov 2014 11:47:57 +0100 Subject: [PATCH 2/4] Add info about XMPP message stamp to docs --- docs/conf-sessions.rst | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/docs/conf-sessions.rst b/docs/conf-sessions.rst index 4ea294efd..343098c2f 100644 --- a/docs/conf-sessions.rst +++ b/docs/conf-sessions.rst @@ -265,6 +265,26 @@ Here is an example of a session definition for the Jabber/XMPP protocol: +Message stamping +"""""""" + +It is possible to stamp chat message by setting ``stamped`` attribute of +```` element inside request to ``true``. The stamp will include current +timestamp and ID of the sender node. If the recipient will recognise the node ID, +it will compare the timestamp inside message with the current one. The difference +will be reported as ``xmpp_msg_latency`` metric. The aim of node ID comparison +is to avoid slight inconsistencies of timestamps on different Tsung nodes. + +Only a fraction of requests will hit the same node they originated from, +but with request rate high enough this fraction should be sufficient. + +``stamped`` is allowed only with ``size`` attribute. ``data`` will cause +``stamped`` to be ignored. There is a minimal length of the stamp, +roughly 10-20 bytes. When ``size`` is greater than stamp length, random +padding will be added to the stamp. If the stamp length is higher than +``size``, then only stamp will be used as messagecontent, effectively +exceeding specified length. + StartTLS """""""" From 264849bfb3c8360ecfa08892e17b51527e7b172e Mon Sep 17 00:00:00 2001 From: Piotr Nosek Date: Mon, 17 Nov 2014 11:49:04 +0100 Subject: [PATCH 3/4] Improve XMPP message stamping --- include/ts_jabber.hrl | 1 + src/tsung/ts_jabber.erl | 2 +- src/tsung/ts_jabber_common.erl | 17 +++++++++++------ src/tsung_controller/ts_config_jabber.erl | 2 ++ tsung-1.0.dtd | 1 + 5 files changed, 16 insertions(+), 7 deletions(-) diff --git a/include/ts_jabber.hrl b/include/ts_jabber.hrl index a49044016..77385a9aa 100644 --- a/include/ts_jabber.hrl +++ b/include/ts_jabber.hrl @@ -36,6 +36,7 @@ size, data, type, + stamped = false, jud_param, regexp, cle, diff --git a/src/tsung/ts_jabber.erl b/src/tsung/ts_jabber.erl index 4b8210be6..af889dfaa 100644 --- a/src/tsung/ts_jabber.erl +++ b/src/tsung/ts_jabber.erl @@ -192,7 +192,7 @@ message_bidi(RcvdXml, State) -> Secs = list_to_integer(SecsS), Micro = list_to_integer(MicroS), Latency = timer:now_diff(erlang:now(), {Mega, Secs, Micro}), - ts_mon:add({ sample, msg_latency, Latency }); + ts_mon:add({ sample, xmpp_msg_latency, Latency }); _ -> ignore end, diff --git a/src/tsung/ts_jabber_common.erl b/src/tsung/ts_jabber_common.erl index 994d449a9..fa0d963ac 100644 --- a/src/tsung/ts_jabber_common.erl +++ b/src/tsung/ts_jabber_common.erl @@ -481,12 +481,8 @@ registration(#jabber{username=Name,passwd=Passwd,resource=Resource})-> %% Func: message/3 %% Purpose: send message to defined user at the Service (aim, ...) %%---------------------------------------------------------------------- -message(Dest, #jabber{size=Size,data=undefined}, Service) when is_integer(Size) -> - {Mega, Secs, Micro} = erlang:now(), - TS = integer_to_list(Mega) ++ ";" - ++ integer_to_list(Secs) ++ ";" - ++ integer_to_list(Micro), - Stamp = "@@@" ++ integer_to_list(erlang:phash2(node())) ++ "," ++ TS ++ "@@@", +message(Dest, #jabber{size=Size,data=undefined,stamped=Stamped}, Service) when is_integer(Size) -> + Stamp = generate_stamp(Stamped), PadLen = Size - length(Stamp), Data = case PadLen > 0 of true -> ts_utils:urandomstr_noflat(PadLen); @@ -505,6 +501,15 @@ message(Dest, #jabber{data=Data}, Service) when is_list(Data) -> Dest, "@", Service, "' type='chat'>",Data, ""]). +generate_stamp(false) -> + ""; +generate_stamp(true) -> + {Mega, Secs, Micro} = erlang:now(), + TS = integer_to_list(Mega) ++ ";" + ++ integer_to_list(Secs) ++ ";" + ++ integer_to_list(Micro), + "@@@" ++ integer_to_list(erlang:phash2(node())) ++ "," ++ TS ++ "@@@". + %%---------------------------------------------------------------------- %% Func: presence/0 %%---------------------------------------------------------------------- diff --git a/src/tsung_controller/ts_config_jabber.erl b/src/tsung_controller/ts_config_jabber.erl index 65774b7e2..de8765edb 100644 --- a/src/tsung_controller/ts_config_jabber.erl +++ b/src/tsung_controller/ts_config_jabber.erl @@ -57,6 +57,7 @@ parse_config(Element = #xmlElement{name=jabber}, TypeStr = ts_config:getAttr(string,Element#xmlElement.attributes, type, "chat"), Ack = ts_config:getAttr(atom,Element#xmlElement.attributes, ack, no_ack), Dest= ts_config:getAttr(atom,Element#xmlElement.attributes, destination,random), + Stamped = ts_config:getAttr(atom,Element#xmlElement.attributes, stamped, false), Size= ts_config:getAttr(integer,Element#xmlElement.attributes, size,0), Data= ts_config:getAttr(string,Element#xmlElement.attributes, data,undefined), @@ -137,6 +138,7 @@ parse_config(Element = #xmlElement{name=jabber}, id = XMPPId, data = Data, type = Type, + stamped = Stamped, regexp = RE, dest = Dest, size = Size, diff --git a/tsung-1.0.dtd b/tsung-1.0.dtd index 736962943..9afe1889a 100644 --- a/tsung-1.0.dtd +++ b/tsung-1.0.dtd @@ -263,6 +263,7 @@ repeat | if | change_type | foreach | set_option | interaction )*> size NMTOKEN "0" data CDATA #IMPLIED type NMTOKEN #REQUIRED + stamped (true | false) "false" show (away|chat|dnd|xa) "chat" status CDATA "Available" nick CDATA #IMPLIED From 0c37ad453b48184252bbcdb8578e95b95d0c14bd Mon Sep 17 00:00:00 2001 From: Piotr Nosek Date: Mon, 17 Nov 2014 12:37:28 +0100 Subject: [PATCH 4/4] Report XMPP message latency in milliseconds --- docs/conf-sessions.rst | 7 ++++--- src/tsung/ts_jabber.erl | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/conf-sessions.rst b/docs/conf-sessions.rst index 343098c2f..415a2a5fe 100644 --- a/docs/conf-sessions.rst +++ b/docs/conf-sessions.rst @@ -272,15 +272,16 @@ It is possible to stamp chat message by setting ``stamped`` attribute of ```` element inside request to ``true``. The stamp will include current timestamp and ID of the sender node. If the recipient will recognise the node ID, it will compare the timestamp inside message with the current one. The difference -will be reported as ``xmpp_msg_latency`` metric. The aim of node ID comparison -is to avoid slight inconsistencies of timestamps on different Tsung nodes. +will be reported as ``xmpp_msg_latency`` metric (in milliseconds). +The aim of node ID comparison is to avoid slight inconsistencies +of timestamps on different Tsung nodes. Only a fraction of requests will hit the same node they originated from, but with request rate high enough this fraction should be sufficient. ``stamped`` is allowed only with ``size`` attribute. ``data`` will cause ``stamped`` to be ignored. There is a minimal length of the stamp, -roughly 10-20 bytes. When ``size`` is greater than stamp length, random +roughly 30 bytes. When ``size`` is greater than stamp length, random padding will be added to the stamp. If the stamp length is higher than ``size``, then only stamp will be used as messagecontent, effectively exceeding specified length. diff --git a/src/tsung/ts_jabber.erl b/src/tsung/ts_jabber.erl index af889dfaa..510878bdb 100644 --- a/src/tsung/ts_jabber.erl +++ b/src/tsung/ts_jabber.erl @@ -192,7 +192,7 @@ message_bidi(RcvdXml, State) -> Secs = list_to_integer(SecsS), Micro = list_to_integer(MicroS), Latency = timer:now_diff(erlang:now(), {Mega, Secs, Micro}), - ts_mon:add({ sample, xmpp_msg_latency, Latency }); + ts_mon:add({ sample, xmpp_msg_latency, Latency / 1000}); _ -> ignore end,