You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ch...@apache.org on 2018/12/06 21:44:19 UTC

qpid-dispatch git commit: DISPATCH-1210: Scraper shows unsettled messages

Repository: qpid-dispatch
Updated Branches:
  refs/heads/master 2dde7030f -> 8701feb7f


DISPATCH-1210: Scraper shows unsettled messages

Compute message settlement earlier and display summary totals
for connections, sessions, and links in details display.


Project: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/commit/8701feb7
Tree: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/tree/8701feb7
Diff: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/diff/8701feb7

Branch: refs/heads/master
Commit: 8701feb7f6924bdb7f126881c50d2a6368434e8f
Parents: 2dde703
Author: Chuck Rolke <cr...@redhat.com>
Authored: Thu Dec 6 16:42:05 2018 -0500
Committer: Chuck Rolke <cr...@redhat.com>
Committed: Thu Dec 6 16:42:05 2018 -0500

----------------------------------------------------------------------
 tools/scraper/amqp_detail.py | 72 +++++++++++++++++++++++++++------------
 tools/scraper/common.py      |  3 ++
 tools/scraper/parser.py      | 18 +++++++---
 tools/scraper/scraper.py     | 29 ++++++++++------
 4 files changed, 84 insertions(+), 38 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/8701feb7/tools/scraper/amqp_detail.py
----------------------------------------------------------------------
diff --git a/tools/scraper/amqp_detail.py b/tools/scraper/amqp_detail.py
index fd64234..7f02633 100755
--- a/tools/scraper/amqp_detail.py
+++ b/tools/scraper/amqp_detail.py
@@ -64,6 +64,9 @@ class ConnectionDetail():
         # combined amqp_error frames on this connection
         self.amqp_errors = 0
 
+        # unsettled transfer count
+        self.unsettled = 0
+
         # session_list holds all SessionDetail records either active or retired
         # Sessions for a connection are identified by the local channel number.
         # There may be many sessions all using the same channel number.
@@ -123,6 +126,8 @@ class SessionDetail:
 
         self.amqp_errors = 0
 
+        self.unsettled = 0
+
         self.channel = -1
         self.peer_chan = -1
 
@@ -263,6 +268,10 @@ class LinkDetail():
 
         self.amqp_errors = 0
 
+        self.unsettled = 0
+        self.unsettled_list = []
+
+
         # paired handles
         self.output_handle = -1
         self.input_handle = -1
@@ -295,7 +304,10 @@ class AllDetails():
     #
     #
     def format_errors(self, n_errors):
-        return ("<span style=\"background-color:yellow\">%d</span>" % n_errors) if n_errors > 0 else ""
+        return ("<span style=\"background-color:yellow\">errors: %d</span>" % n_errors) if n_errors > 0 else ""
+
+    def format_unsettled(self, n_unsettled):
+        return ("<span style=\"background-color:orange\">unsettled: %d</span>" % n_unsettled) if n_unsettled > 0 else ""
 
     def classify_connection(self, id):
         """
@@ -426,9 +438,7 @@ class AllDetails():
                     conn_details.unaccounted_frame_list.append(plf)
                     continue
                 # session required
-                channel = plf.data.channel # For incoming begin this is the remote channel
-                                           # For outgoing begin this is the local channel
-                                           # Assume they are the same for the time being
+                channel = plf.data.channel # Assume in/out channels are the same for the time being
                 sess_details = conn_details.FindSession(channel)
                 if sess_details == None:
                     sess_details = SessionDetail(conn_details, conn_details.GetSeqNo(), plf.datetime)
@@ -543,6 +553,32 @@ class AllDetails():
                                                  (splf.data.conn_id))
                             sdispmap[did] = splf
 
+    def compute_settlement(self):
+        for conn in self.rtr.conn_list:
+            id = self.rtr.conn_id(conn)
+            conn_detail = self.rtr.details.conn_details[id]
+            for sess in conn_detail.session_list:
+                for link in sess.link_list:
+                    for plf in link.frame_list:
+                        if plf.data.transfer:
+                            tdid = plf.data.delivery_id
+                            if plf.data.direction == "->":
+                                rmap = sess.rx_rcvr_disposition_map
+                                tmap = sess.rx_sndr_disposition_map
+                            else:
+                                rmap = sess.tx_rcvr_disposition_map
+                                tmap = sess.tx_sndr_disposition_map
+                            plf.data.disposition_display = self.resolve_settlement(link, plf,
+                                                                                   rmap.get(tdid),
+                                                                                   tmap.get(tdid))
+                            if common.transfer_is_possibly_unsettled(plf):
+                                if tdid not in link.unsettled_list:
+                                    link.unsettled_list.append(tdid)
+                                    link.unsettled += 1
+                                    sess.unsettled += 1
+                                    conn_detail.unsettled += 1
+
+
     def show_html(self):
         for conn in self.rtr.conn_list:
             id = self.rtr.conn_id(conn)
@@ -556,8 +592,9 @@ class AllDetails():
             peer = self.rtr.conn_peer_display.get(id, "")  # peer container id
             peerconnid = self.comn.conn_peers_connid.get(id, "")
             # show the connection title
-            print("%s %s %s %s (nFrames=%d) %s<br>" % \
-                  (id, dir, peerconnid, peer, len(conn_frames), self.format_errors(conn_detail.amqp_errors)))
+            print("%s %s %s %s (nFrames=%d) %s %s<br>" % \
+                  (id, dir, peerconnid, peer, len(conn_frames), self.format_errors(conn_detail.amqp_errors),
+                   self.format_unsettled(conn_detail.unsettled)))
             # data div
             print("<div id=\"%s_data\" style=\"display:none; margin-bottom: 2px; margin-left: 10px\">" % id)
 
@@ -577,9 +614,10 @@ class AllDetails():
                 # show the session 'toggle goto' and title
                 print("<a href=\"javascript:toggle_node('%s_sess_%s')\">%s%s</a>" %
                       (id, sess.conn_epoch, text.lozenge(), text.nbsp()))
-                print("Session %s: channel: %s, peer channel: %s; Time: start %s, Counts: frames: %d %s<br>" % \
+                print("Session %s: channel: %s, peer channel: %s; Time: start %s, Counts: frames: %d %s %s<br>" % \
                       (sess.conn_epoch, sess.channel, sess.peer_chan, sess.time_start, \
-                       sess.FrameCount(), self.format_errors(sess.amqp_errors)))
+                       sess.FrameCount(), self.format_errors(sess.amqp_errors),
+                       self.format_unsettled(sess.unsettled)))
                 print("<div id=\"%s_sess_%s\" style=\"display:none; margin-bottom: 2px; margin-left: 10px\">" %
                       (id, sess.conn_epoch))
                 # show the session-level frames
@@ -597,7 +635,7 @@ class AllDetails():
                 print("<table")
                 print("<tr><th>Link</th> <th>Dir</th> <th>Role</th>  <th>Address</th>  <th>Class</th>  "
                       "<th>snd-settle-mode</th>  <th>rcv-settle-mode</th>  <th>Start time</th>  <th>Frames</th> "
-                      "<th>AMQP errors</tr>")
+                      "<th>AMQP errors</th> <th>Unsettled</th> </tr>")
                 for link in sess.link_list:
                     # show the link toggle and title
                     showthis = ("<a href=\"javascript:toggle_node('%s_sess_%s_link_%s')\">%s</a>" %
@@ -606,11 +644,12 @@ class AllDetails():
                                 (id, sess.conn_epoch, link.session_seq, link.display_name))
                     role = "receiver" if link.is_receiver else "sender"
                     print("<tr><td>%s %s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td>"
-                          "<td>%s</td><td>%d</td><td>%s</td></tr>" % \
+                          "<td>%s</td><td>%d</td><td>%s</td> <td>%s</td></tr>" % \
                           (showthis, visitthis, link.direction, role, link.first_address,
                            (link.sender_class + '-' + link.receiver_class), link.snd_settle_mode,
                            link.rcv_settle_mode, link.time_start, link.FrameCount(),
-                           self.format_errors(link.amqp_errors)))
+                           self.format_errors(link.amqp_errors),
+                           self.format_unsettled(link.unsettled)))
                 print("</table>")
                 # second loop prints the link's frames
                 for link in sess.link_list:
@@ -622,17 +661,6 @@ class AllDetails():
                     print("<h4>Connection %s Session %s Link %s</h4>" %
                           (id, sess.conn_epoch, link.display_name))
                     for plf in link.frame_list:
-                        if plf.data.name == "transfer":
-                            tdid = plf.data.delivery_id
-                            if plf.data.direction == "->":
-                                rmap = sess.rx_rcvr_disposition_map
-                                tmap = sess.rx_sndr_disposition_map
-                            else:
-                                rmap = sess.tx_rcvr_disposition_map
-                                tmap = sess.tx_sndr_disposition_map
-                            plf.data.disposition_display = self.resolve_settlement(link, plf,
-                                                                                   rmap.get(tdid),
-                                                                                   tmap.get(tdid))
                         print(plf.adverbl_link_to(), plf.datetime, plf.data.direction, peer, plf.data.web_show_str,
                               plf.data.disposition_display, "<br>")
                     print("</div>")  # end link <id>_sess_<conn_epoch>_link_<sess_seq>

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/8701feb7/tools/scraper/common.py
----------------------------------------------------------------------
diff --git a/tools/scraper/common.py b/tools/scraper/common.py
index 0a74f3c..654b8b4 100755
--- a/tools/scraper/common.py
+++ b/tools/scraper/common.py
@@ -140,3 +140,6 @@ class RestartRec():
         self.event = _event
         self.datetime = _datetime
 
+def transfer_is_possibly_unsettled(plf):
+    return (plf.data.transfer and
+            not (plf.data.transfer_settled or plf.data.final_disposition is not None))

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/8701feb7/tools/scraper/parser.py
----------------------------------------------------------------------
diff --git a/tools/scraper/parser.py b/tools/scraper/parser.py
index d33a0c7..5f74266 100755
--- a/tools/scraper/parser.py
+++ b/tools/scraper/parser.py
@@ -123,7 +123,7 @@ class LogLineData:
         self.target = ""
         self.first = ""  # undecorated number - '10'
         self.last = ""  # undecorated number - '20'
-        self.settled = ""  # Disposition or Transfer settled field
+        self.settled = ""  # Disposition or Transfer settled field from log line
         self.disposition_state = "?absent?"
         self.snd_settle_mode = ""  # Attach
         self.rcv_settle_mode = ""  # Attach
@@ -259,8 +259,7 @@ class DescribedType:
         :return:
         """
         self.dtype = _dtype
-        self.oline = str(_line)
-        self.line = self.oline
+        self.line = str(_line)
         self.dtype_name = DescribedType.dtype_name(self.dtype)
         self.dtype_number = DescribedType.dtype_number(self.dtype)
 
@@ -751,7 +750,6 @@ class ParsedLogLine(object):
                 ParsedLogLine.server_info_key in _line or
                 ParsedLogLine.router_ls_key in _line):
             raise ValueError("Line is not a candidate for parsing")
-        self.oline = _line  # original line
         self.index = _log_index  # router prefix 0 for A, 1 for B
         self.instance = _instance  # router instance in log file
         self.lineno = _lineno  # log line number
@@ -950,7 +948,17 @@ def parse_log_file(fn, log_index, comn):
                 search_for_in_progress = False
                 rtr.container_name = line[(line.find(key2) + len(key2)):].strip().split()[0]
             elif key3 in line:
-                pl = ParsedLogLine(log_index, instance, lineno, line, comn, rtr)
+                pl = None
+                try:
+                    pl = ParsedLogLine(log_index, instance, lineno, line, comn, rtr)
+                except ValueError as ve:
+                    pass
+                except Exception as e:
+                    # t, v, tb = sys.exc_info()
+                    if hasattr(e, 'message'):
+                        sys.stderr.write("Failed to parse file '%s', line %d : %s\n" % (fn, lineno, e.message))
+                    else:
+                        sys.stderr.write("Failed to parse file '%s', line %d : %s\n" % (fn, lineno, e))
                 if pl is not None:
                     if pl.data.is_router_ls:
                         rtr.router_ls.append(pl)

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/8701feb7/tools/scraper/scraper.py
----------------------------------------------------------------------
diff --git a/tools/scraper/scraper.py b/tools/scraper/scraper.py
index 2e998b1..981d3ff 100755
--- a/tools/scraper/scraper.py
+++ b/tools/scraper/scraper.py
@@ -227,6 +227,12 @@ def main_except(argv):
     comn.shorteners.short_data_names.sort_customers()
     comn.shorteners.short_link_names.sort_customers()
 
+    # compute settlement
+    if not comn.args.skip_detail:
+        for rtrlist in comn.routers:
+            for rtr in rtrlist:
+                rtr.details.compute_settlement()
+
     #
     # Start producing the output stream
     #
@@ -334,11 +340,11 @@ def main_except(argv):
 
     # print the connection peer tables
     #
-    # +------+--------------------+-----+--------------------+-------+-------+----------+--------+
-    # | View |       Router       | Dir |       Peer         | Log   | N     | Transfer | AMQP   |
-    # |      +-----------+--------+     +--------+-----------+ lines | links | bytes    | errors |
-    # |      | container | connid |     | connid | container |       |       |          |        |
-    # +------+-----------+--------+-----+--------+-----------+-------+-------+----------+--------+
+    # +------+--------------------+-----+--------------------+-------+-------+----------+--------+-------+
+    # | View |       Router       | Dir |       Peer         | Log   | N     | Transfer | AMQP   | unset |
+    # |      +-----------+--------+     +--------+-----------+ lines | links | bytes    | errors | tled  |
+    # |      | container | connid |     | connid | container |       |       |          |        |       |
+    # +------+-----------+--------+-----+--------+-----------+-------+-------+----------+--------+-------+
 
     print("<a name=\"c_connections\"></a>")
     print("<h3>Connections</h3>")
@@ -352,7 +358,7 @@ def main_except(argv):
     print("<h3>Connections by ConnectionId</h3>")
     print(
         "<table><tr> <th rowspan=\"2\">View</th> <th colspan=\"2\">Router</th> <th rowspan=\"2\">Dir</th> <th colspan=\"2\">Peer</th> <th rowspan=\"2\">Log lines</th> "
-        "<th rowspan=\"2\">N links</th><th rowspan=\"2\">Transfer bytes</th> <th rowspan=\"2\">AMQP errors</th> <th rowspan=\"2\">Open time</th> <th rowspan=\"2\">Close time</th></tr>")
+        "<th rowspan=\"2\">N links</th><th rowspan=\"2\">Transfer bytes</th> <th rowspan=\"2\">AMQP errors</th> <th rowspan=\"2\">Unsettled</th> <th rowspan=\"2\">Open time</th> <th rowspan=\"2\">Close time</th></tr>")
     print("<tr> <th>container</th> <th>connid</th> <th>connid</th> <th>container</th></tr>")
 
     tConn = 0
@@ -378,13 +384,14 @@ def main_except(argv):
                 etime = rtr.conn_close_time.get(id, text.nbsp())
                 if etime != text.nbsp():
                     etime = etime.datetime
+                conn_details = rtr.details.conn_details[id]
                 print("<tr>")
                 print("<td> <input type=\"checkbox\" id=\"cb_sel_%s\" " % id)
                 print("checked=\"true\" onclick=\"javascript:show_if_cb_sel_%s()\"> </td>" % (id))
                 print("<td>%s</td><td><a href=\"#cd_%s\">%s</a></td><td>%s</td><td>%s</td><td>%s</td><td>%s</td>"
-                      "<td>%d</td><td>%s</td><td>%d</td><td>%s</td><td>%s</td></tr>" %
+                      "<td>%d</td><td>%s</td><td>%d</td><td>%d</td><td>%s</td><td>%s</td></tr>" %
                       (rid, id, id, rtr.conn_dir[id], peerconnid, peer, rtr.conn_log_lines[id], n_links,
-                       rtr.conn_xfer_bytes[id], errs, stime, etime))
+                       rtr.conn_xfer_bytes[id], errs, conn_details.unsettled, stime, etime))
                 tLines += rtr.conn_log_lines[id]
                 tBytes += rtr.conn_xfer_bytes[id]
     print(
@@ -470,7 +477,7 @@ def main_except(argv):
             n_aborted += 1
         if plf.data.flow_drain:
             n_drain += 1
-        if plf.data.transfer and not (plf.data.transfer_settled or plf.data.final_disposition is not None):
+        if common.transfer_is_possibly_unsettled(plf):
             if plf.data.no_parent_link:
                 n_unsettled_no_parent += 1 # possibly unsettled
             else:
@@ -542,7 +549,7 @@ def main_except(argv):
           "style=\"display:none; font-weight: normal; margin-bottom: 2px; margin-left: 10px\" "
           "id=\"noteworthy_unsettled\">")
     for plf in tree:
-        if plf.data.transfer and not (plf.data.transfer_settled or plf.data.final_disposition is not None) and not plf.data.no_parent_link:
+        if common.transfer_is_possibly_unsettled(plf) and not plf.data.no_parent_link:
             show_noteworthy_line(plf, comn)
     print("</div>")
     # possible unsettled transfers
@@ -552,7 +559,7 @@ def main_except(argv):
           "style=\"display:none; font-weight: normal; margin-bottom: 2px; margin-left: 10px\" "
           "id=\"noteworthy_unsettled_qm\">")
     for plf in tree:
-        if plf.data.transfer and not (plf.data.transfer_settled or plf.data.final_disposition is not None) and plf.data.no_parent_link:
+        if common.transfer_is_possibly_unsettled(plf) and plf.data.no_parent_link:
             show_noteworthy_line(plf, comn)
     print("</div>")
     print("<hr>")


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org