コード例 #1
0
ファイル: nicknamer.py プロジェクト: apache/qpid-dispatch
 def translate(self, lname, show_popup=False, customer=None):
     '''
     Translate a long name into a short name, maybe.
     Memorize all names, translated or not
     Strip leading/trailing double quotes
     :param lname: the name
     :return: If shortened HTML string of shortened name with popup containing long name else
     not-so-long name.
     '''
     if lname.startswith("\"") and lname.endswith("\""):
         lname = lname[1:-1]
     try:
         idx = self.longnames.index(lname)
     except:
         self.longnames.append(lname)
         idx = self.longnames.index(lname)
     # return as-given if short enough
     if customer is not None:
         self.customer_dict[lname].append(customer)
     if len(lname) < self.threshold:
         return lname
     sname = self.prefix + "_" + str(idx)
     if customer is not None:
         self.customer_dict[sname].append(customer)
     if show_popup:
         return "<span title=\"" + common.html_escape(lname) + "\">" + sname + "</span>"
     else:
         return sname
コード例 #2
0
 def translate(self, lname, show_popup=False, customer=None):
     '''
     Translate a long name into a short name, maybe.
     Memorize all names, translated or not
     Strip leading/trailing double quotes
     :param lname: the name
     :param show_popup: if true then embellish returned name with long name popup
     :param customer: optional ParsedLogLine for customer_dict
     :return: If shortened HTML string of shortened name with popup containing long name else
     not-so-long name.
     '''
     if lname.startswith("\"") and lname.endswith("\""):
         lname = lname[1:-1]
     try:
         idx = self.longnames.index(lname)
     except:
         self.longnames.append(lname)
         idx = self.longnames.index(lname)
     # return as-given if short enough
     if customer is not None:
         self.customer_dict[lname].append(customer)
     if len(lname) < self.threshold:
         return lname
     sname = self.prefix + "_" + str(idx)
     if customer is not None:
         self.customer_dict[sname].append(customer)
     if show_popup:
         return "<span title=\"" + common.html_escape(lname) + "\">" + sname + "</span>"
     else:
         return sname
コード例 #3
0
ファイル: nicknamer.py プロジェクト: apache/qpid-dispatch
 def longname(self, idx, html_escape=False):
     '''
     Get the common.html_escape'd long name
     :param idx:
     :param html_escape: true if caller wants the string for html display
     :return:
     '''
     return common.html_escape(self.longnames[idx]) if html_escape else self.longnames[idx]
コード例 #4
0
ファイル: nicknamer.py プロジェクト: apache/qpid-dispatch
 def sname_to_popup(self, sname):
     if not sname.startswith(self.prefix):
         raise ValueError("Short name '%s' does not start with prefix '%s'" % (sname, self.prefix))
     try:
         lname = self.longnames[ int(sname[ (len(self.prefix) + 1): ])]
     except:
         raise ValueError("Short name '%s' did not translate to a long name" % (sname))
     return "<span title=\"" + common.html_escape(lname) + sname + "</span>"
コード例 #5
0
 def sname_to_popup(self, sname):
     if not sname.startswith(self.prefix):
         raise ValueError("Short name '%s' does not start with prefix '%s'" % (sname, self.prefix))
     try:
         lname = self.longnames[int(sname[(len(self.prefix) + 1):])]
     except:
         raise ValueError("Short name '%s' did not translate to a long name" % (sname))
     return "<span title=\"" + common.html_escape(lname) + sname + "</span>"
コード例 #6
0
 def longname(self, idx, html_escape=False):
     '''
     Get the common.html_escape'd long name
     :param idx:
     :param html_escape: true if caller wants the string for html display
     :return:
     '''
     return common.html_escape(self.longnames[idx]) if html_escape else self.longnames[idx]
コード例 #7
0
ファイル: nicknamer.py プロジェクト: apache/qpid-dispatch
 def htmlDump(self, with_link=False):
     '''
     Print the name table as an unnumbered list to stdout
     long names are common.html_escape'd
     :param with_link: true if link name link name is hyperlinked targeting itself
     :return: null
     '''
     if len(self.longnames) > 0:
         print ("<h3>" + self.prefix + " Name Index</h3>")
         print ("<ul>")
         for i in range(0, len(self.longnames)):
             name = self.prefix + "_" + str(i)
             dump_anchor = "<a name=\"%s_dump\"></a>" % (name)
             if with_link:
                 name = "<a href=\"#%s\">%s</a>" % (name, name)
             print ("<li> " + dump_anchor + name + " - " + common.html_escape(self.longnames[i]) + "</li>")
         print ("</ul>")
コード例 #8
0
 def htmlDump(self, with_link=False):
     '''
     Print the name table as an unnumbered list to stdout
     long names are common.html_escape'd
     :param with_link: true if link name link name is hyperlinked targeting itself
     :return: null
     '''
     if len(self.longnames) > 0:
         print("<h3>" + self.prefix + " Name Index</h3>")
         print("<ul>")
         for i in range(0, len(self.longnames)):
             name = self.prefix + "_" + str(i)
             dump_anchor = "<a name=\"%s_dump\"></a>" % (name)
             if with_link:
                 name = "<a href=\"#%s\">%s</a>" % (name, name)
             print("<li> " + dump_anchor + name + " - " +
                   common.html_escape(self.longnames[i]) + "</li>")
         print("</ul>")
コード例 #9
0
    def write_subfiles(self):
        # Q: Where to put the generated files? A: odir
        odir = self.odir()
        odirs = ['dummy'] # dirs indexed by log of n-lines

        os.makedirs(odir)
        for i in range(1, self.hist_max):
            nrange = ("10e%d" % (i))
            ndir = os.path.join(odir, nrange)
            os.makedirs(ndir)
            odirs.append(ndir)

        for k, c in dict_iteritems(self.connections):
            cdir = odirs[self.log_of(len(c.lines))]
            opath = os.path.join(cdir, (c.disp_name() + ".log"))
            with open(opath, 'w') as f:
                for l in c.lines:
                    f.write(l)

        xfer0 = 0
        for rc in self.conns_by_size_transfer:
            if rc.transfers == 0:
                xfer0 += 1
        print("<a name=\"c_conn_xfersize\"></a>")
        print("<h3>Connections by transfer count (N=%d)</h3>" % (len(self.conns_by_size_transfer) - xfer0))
        print("<table>")
        n = 1
        print("<tr><th>N</th><th>Connection</th> <th>Transfers</th> <th>Log lines</th> <th>Type</th> <th>AMQP detail<th></tr>")
        for rc in self.conns_by_size_transfer:
            if rc.transfers > 0:
                print("<tr><td>%d</td><td><a href=\"%s/%s\">%s</a></td> <td>%d</td> <td>%d</td> <td>%s</td> <td>%s</td></tr>" %
                      (n, rc.logfile.odir(), rc.path_name, rc.disp_name(), rc.transfers, len(rc.lines),
                       rc.peer_type, common.html_escape(rc.peer_open)))
                n += 1
        print("</table>")
        print("<hr>")

        print("<a name=\"c_conn_xfer0\"></a>")
        print("<h3>Connections with no AMQP transfers (N=%d)</h3>" % (xfer0))
        print("<table>")
        n = 1
        print("<tr><th>N</th><th>Connection</th> <th>Transfers</th> <th>Log lines</th> <th>Type</th> <th>AMQP detail<th></tr>")
        for rc in self.conns_by_size_transfer:
            if rc.transfers == 0:
                print("<tr><td>%d</td><td><a href=\"%s/%s\">%s</a></td> <td>%d</td> <td>%d</td> <td>%s</td> <td>%s</td></tr>" %
                      (n, rc.logfile.odir(), rc.path_name, rc.disp_name(), rc.transfers, len(rc.lines),
                       rc.peer_type, common.html_escape(rc.peer_open)))
                n += 1
        print("</table>")
        print("<hr>")

        print("<a name=\"c_conn_logsize\"></a>")
        print("<h3>Connections by total log line count (N=%d)</h3>" % (len(self.conns_by_size_loglines)))
        print("<table>")
        n = 1
        print("<tr><th>N</th><th>Connection</th> <th>Transfers</th> <th>Log lines</th> <th>Type</th> <th>AMQP detail<th></tr>")
        for rc in self.conns_by_size_loglines:
            print("<tr><td>%d</td><td><a href=\"%s/%s\">%s</a></td> <td>%d</td> <td>%d</td> <td>%s</td> <td>%s</td></tr>" %
                  (n, rc.logfile.odir(), rc.path_name, rc.disp_name(), rc.transfers, len(rc.lines),
                   rc.peer_type, common.html_escape(rc.peer_open)))
            n += 1
        print("</table>")
        print("<hr>")
コード例 #10
0
    def summarize_connections(self):
        # sort connections based on transfer count and on n log lines
        self.conns_by_size_transfer = self.sort_sizes(lambda x: x.transfers, lambda x: len(x.lines))
        self.conns_by_size_loglines = self.sort_sizes(lambda x: len(x.lines), lambda x: x.transfers)

        # compute log_n and file name facts for all connections
        for k, v in dict_iteritems(self.connections):
            v.log_n_lines = self.log_of(len(v.lines))
            v.generate_paths()

        # Write the web doc to stdout
        print ("""<!DOCTYPE html>
<html>
<head>
<title>%s qpid-dispatch log split</title>

<style>
    * { 
    font-family: sans-serif; 
}
table {
    border-collapse: collapse;
}
table, td, th {
    border: 1px solid black;
    padding: 3px;
}
</style>
<script src="http://ajax.googleapis.com/ajax/libs/dojo/1.4/dojo/dojo.xd.js" type="text/javascript"></script>
<!-- <script src="http://ajax.googleapis.com/ajax/libs/dojo/1.4/dojo/dojo.xd.js" type="text/javascript"></script> -->
<script type="text/javascript">
function node_is_visible(node)
{
  if(dojo.isString(node))
    node = dojo.byId(node);
  if(!node) 
    return false;
  return node.style.display == "block";
}
function set_node(node, str)
{
  if(dojo.isString(node))
    node = dojo.byId(node);
  if(!node) return;
  node.style.display = str;
}
function toggle_node(node)
{
  if(dojo.isString(node))
    node = dojo.byId(node);
  if(!node) return;
  set_node(node, (node_is_visible(node)) ? 'none' : 'block');
}
function hide_node(node)
{
  set_node(node, 'none');
}
function show_node(node)
{
  set_node(node, 'block');
}

""" % self.log_fn)

        print("</script>")
        print("</head>")
        print("<body>")
        print("""
<h3>Contents</h3>
<table>
<tr> <th>Section</th>                                                     <th>Description</th> </tr>
<tr><td><a href=\"#c_summary\"        >Summary</a></td>                   <td>Summary</td></tr>
<tr><td><a href=\"#c_restarts\"       >Router restarts</a></td>           <td>Router reboot records</td></tr>
<tr><td><a href=\"#c_router_conn\"    >Interrouter connections</a></td>   <td>Probable interrouter connections</td></tr>
<tr><td><a href=\"#c_broker_conn\"    >Broker connections</a></td>        <td>Probable broker connections</td></tr>
<tr><td><a href=\"#c_errors\"         >AMQP errors</a></td>               <td>AMQP errors</td></tr>
<tr><td><a href=\"#c_conn_xfersize\"  >Conn by N transfers</a></td>       <td>Connections sorted by transfer log count</td></tr>
<tr><td><a href=\"#c_conn_xfer0\"     >Conn with no transfers</a></td>    <td>Connections with no transfers</td></tr>
<tr><td><a href=\"#c_conn_logsize\"   >Conn by N log lines</a></td>       <td>Connections sorted by total log line count</td></tr>
<tr><td><a href=\"#c_addresses\"      >Addresses</a></td>                 <td>AMQP address usage</td></tr>
</table>
<hr>
""")
        print("<a name=\"c_summary\"></a>")
        print("<table>")
        print("<tr><th>Statistic</th>          <th>Value</th></tr>")
        print("<tr><td>File</td>               <td>%s</td></tr>" % self.log_fn)
        print("<tr><td>Router starts</td>      <td>%s</td></tr>" % str(self.instance))
        print("<tr><td>Connections</td>        <td>%s</td></tr>" % str(len(self.connections)))
        print("<tr><td>Router connections</td> <td>%s</td></tr>" % str(len(self.router_connections)))
        print("<tr><td>AMQP log lines</td>     <td>%s</td></tr>" % str(self.amqp_lines))
        print("<tr><td>AMQP errors</td>        <td>%s</td></tr>" % str(len(self.errors)))
        print("<tr><td>AMQP transfers</td>     <td>%s</td></tr>" % str(self.transfers))
        print("<tr><td>AMQP attaches</td>     <td>%s</td></tr>" % str(self.attaches))
        print("</table>")
        print("<hr>")

        # Restarts
        print("<a name=\"c_restarts\"></a>")
        print("<h3>Restarts</h3>")
        for i in range(1, (self.instance + 1)):
            rr = self.restarts[i-1]
            print("(%d) - %s<br>" % (i, rr), end='')
        print("<hr>")

        # interrouter connections
        print("<a name=\"c_router_conn\"></a>")
        print("<h3>Probable inter-router connections (N=%d)</h3>" % (len(self.router_connections)))
        print("<table>")
        print("<tr><th>Connection</th> <th>Transfers</th> <th>Log lines</th> <th>AMQP Open<th></tr>")
        for rc in self.router_connections:
            print("<tr><td><a href=\"%s/%s\">%s</a></td><td>%d</td><td>%d</td><td>%s</td></tr>" %
                  (rc.logfile.odir(), rc.path_name, rc.disp_name(), rc.transfers, len(rc.lines),
                   common.html_escape(rc.peer_open)))
        print("</table>")
        print("<hr>")

        # broker connections
        print("<a name=\"c_broker_conn\"></a>")
        print("<h3>Probable broker connections (N=%d)</h3>" % (len(self.broker_connections)))
        print("<table>")
        print("<tr><th>Connection</th> <th>Transfers</th> <th>Log lines</th> <th>AMQP Open<th></tr>")
        for rc in self.broker_connections:
            print("<tr><td><a href=\"%s/%s\">%s</a></td><td>%d</td><td>%d</td><td>%s</td></tr>" %
                  (rc.logfile.odir(), rc.path_name, rc.disp_name(), rc.transfers, len(rc.lines),
                   common.html_escape(rc.peer_open)))
        print("</table>")
        print("<hr>")

        ## histogram
        #for cursize in self.sizelist:
        #    self.histogram[self.log_of(cursize)] += len(self.sizemap[str(cursize)])
        #print()
        #print("Log lines per connection distribution")
        #for i in range(1, self.hist_max):
        #    print("N <  10e%d : %d" %(i, self.histogram[i]))
        #print("N >= 10e%d : %d" % ((self.hist_max - 1), self.histogram[self.hist_max]))

        # errors
        print("<a name=\"c_errors\"></a>")
        print("<h3>AMQP errors (N=%d)</h3>" % (len(self.errors)))
        print("<table>")
        print("<tr><th>N</th> <th>AMQP error</th></tr>")
        for i in range(len(self.errors)):
            print("<tr><td>%d</td> <td>%s</td></tr>" % (i, common.html_escape(self.errors[i].strip())))
        print("</table>")
        print("<hr>")
コード例 #11
0
ファイル: scraper.py プロジェクト: seravat/qpid-dispatch
def main_except(argv):
    # Instantiate a common block
    comn = common.Common()

    # optparse - look for data-inhibit and program mode control
    p = argparse.ArgumentParser()
    p.add_argument(
        '--skip-all-data',
        '-sa',
        action='store_true',
        help=
        'Max load shedding: do not store/index transfer, disposition, flow or EMPTY_FRAME data'
    )
    p.add_argument(
        '--skip-detail',
        '-sd',
        action='store_true',
        help='Load shedding: do not produce Connection Details tables')
    p.add_argument(
        '--skip-msg-progress',
        '-sm',
        action='store_true',
        help='Load shedding: do not produce Message Progress tables')
    p.add_argument('--split',
                   '-sp',
                   action='store_true',
                   help='A single file is split into per-connection data.')
    p.add_argument(
        '--time-start',
        '-ts',
        help=
        'Ignore log records earlier than this. Format: "2018-08-13 13:15:00.123456"'
    )
    p.add_argument(
        '--time-end',
        '-te',
        help=
        'Ignore log records later than this. Format: "2018-08-13 13:15:15.123456"'
    )
    p.add_argument('--files', '-f', nargs="+")

    del argv[0]
    comn.args = p.parse_args(argv)

    if not comn.args.time_start is None:
        try:
            comn.args.time_start = datetime.datetime.strptime(
                comn.args.time_start, "%Y-%m-%d %H:%M:%S.%f")
        except:
            sys.exit(
                "ERROR: Failed to parse time_start '%s'. Use format 'YYYY-MM-DD HH:MM:SS.n_uS'"
                % comn.args.time_start)

    if not comn.args.time_end is None:
        try:
            comn.args.time_end = datetime.datetime.strptime(
                comn.args.time_end, "%Y-%m-%d %H:%M:%S.%f")
        except:
            sys.exit(
                "ERROR: Failed to parse time_end '%s'. Use format 'YYYY-MM-DD HH:MM:SS.n_uS'"
                % comn.args.time_end)

    # process split function
    if comn.args.split:
        # Split processes only a single file
        if len(comn.args.files) > 1:
            sys.exit('--split mode takes only one file name')
        return splitter_main(comn.args.files[0])

    # process the log files and add the results to router_array
    for log_i in range(len(comn.args.files)):
        arg_log_file = comn.args.files[log_i]
        comn.log_fns.append(arg_log_file)
        comn.n_logs += 1

        if not os.path.exists(arg_log_file):
            sys.exit('ERROR: log file %s was not found!' % arg_log_file)

        # parse the log file
        rtrs = parser.parse_log_file(arg_log_file, log_i, comn)
        comn.routers.append(rtrs)

    # Create lists of various things sorted by time
    tree = []  # log line
    ls_tree = []  # link state lines
    rr_tree = []  # restart records
    for rtrlist in comn.routers:
        for rtr in rtrlist:
            tree += rtr.lines
            ls_tree += rtr.router_ls
            rr_tree.append(rtr.restart_rec)
    tree = sorted(tree, key=lambda lfl: lfl.datetime)
    ls_tree = sorted(ls_tree, key=lambda lfl: lfl.datetime)
    rr_tree = sorted(rr_tree, key=lambda lfl: lfl.datetime)

    # post_extract the shortened names
    comn.shorteners.short_link_names.sort_main()
    comn.shorteners.short_data_names.sort_main()
    for plf in tree:
        plf.post_extract_names()

    # marshall connection facts
    for rtr_list in comn.routers:
        for rtr in rtr_list:
            rtr.discover_connection_facts(comn)

    # Back-propagate a router name/version/mode to each list's router0.
    # Complain if container name or version changes between instances.
    # Fill in container_id and shortened display_name tables
    for fi in range(comn.n_logs):
        rtrlist = comn.routers[fi]
        if len(rtrlist) > 1:
            if rtrlist[0].container_name is None:
                rtrlist[0].container_name = rtrlist[1].container_name
            if rtrlist[0].version is None:
                rtrlist[0].version = rtrlist[1].version
            if rtrlist[0].mode is None:
                rtrlist[0].mode = rtrlist[1].mode
            for i in range(0, len(rtrlist) - 1):
                namei = rtrlist[i].container_name
                namej = rtrlist[i + 1].container_name
                if namei != namej:
                    sys.exit(
                        'Inconsistent container names, log file %s, instance %d:%s but instance %d:%s'
                        % (comn.log_fns[fi], i, namei, i + 1, namej))
                namei = rtrlist[i].version
                namej = rtrlist[i + 1].version
                if namei != namej:
                    sys.exit(
                        'Inconsistent router versions, log file %s, instance %d:%s but instance %d:%s'
                        % (comn.log_fns[fi], i, namei, i + 1, namej))
                namei = rtrlist[i].mode
                namej = rtrlist[i + 1].mode
                if namei != namej:
                    sys.exit(
                        'Inconsistent router modes, log file %s, instance %d:%s but instance %d:%s'
                        % (comn.log_fns[fi], i, namei, i + 1, namej))
        name = rtrlist[0].container_name if len(
            rtrlist) > 0 and rtrlist[0].container_name is not None else (
                "Unknown_%d" % fi)
        mode = rtrlist[0].mode if len(
            rtrlist) > 0 and rtrlist[0].mode is not None else "standalone"
        comn.router_ids.append(name)
        comn.router_display_names.append(
            comn.shorteners.short_rtr_names.translate(name))
        comn.router_modes.append(mode)

    # aggregate connection-to-frame maps into big map
    for rtrlist in comn.routers:
        for rtr in rtrlist:
            comn.conn_to_frame_map.update(rtr.conn_to_frame_map)

    # generate router-to-router connection peer relationships
    peer_list = []
    for plf in tree:
        if plf.data.name == "open" and plf.data.direction_is_in():
            cid = plf.data.conn_id  # the router that generated this log file
            if "properties" in plf.data.described_type.dict:
                peer_conn = plf.data.described_type.dict["properties"].get(
                    ':"qd.conn-id"', "")  # router that sent the open
                if peer_conn != "" and plf.data.conn_peer != "":
                    pid_peer = plf.data.conn_peer.strip('\"')
                    rtr, rtridx = router.which_router_id_tod(
                        comn.routers, pid_peer, plf.datetime)
                    if rtr is not None:
                        pid = rtr.conn_id(peer_conn)
                        hit = sorted((cid, pid))
                        if hit not in peer_list:
                            peer_list.append(hit)

    for (key, val) in peer_list:
        if key in comn.conn_peers_connid:
            sys.exit('key val messed up')
        if val in comn.conn_peers_connid:
            sys.exit('key val messed up')
        comn.conn_peers_connid[key] = val
        comn.conn_peers_connid[val] = key
        cn_k = comn.router_ids[common.index_of_log_letter(key)]
        cn_v = comn.router_ids[common.index_of_log_letter(val)]
        comn.conn_peers_display[
            key] = comn.shorteners.short_rtr_names.translate(cn_v)
        comn.conn_peers_display[
            val] = comn.shorteners.short_rtr_names.translate(cn_k)

    # sort transfer short name customer lists
    comn.shorteners.short_data_names.sort_customers()
    comn.shorteners.short_link_names.sort_customers()

    # compute settlement and index AMQP addresses
    if not comn.args.skip_detail:
        for rtrlist in comn.routers:
            for rtr in rtrlist:
                rtr.details.compute_settlement()
                rtr.details.index_addresses()
                rtr.details.evaluate_credit()

    #
    # Start producing the output stream
    #
    print(text.web_page_head())

    #
    # Generate javascript
    #
    # output the frame show/hide functions into the header
    for conn_id, plfs in common.dict_iteritems(comn.conn_to_frame_map):
        print("function show_%s() {" % conn_id)
        for plf in plfs:
            print("  javascript:show_node(\'%s\');" % plf.fid)
        print("}")
        print("function hide_%s() {" % conn_id)
        for plf in plfs:
            print("  javascript:hide_node(\'%s\');" % plf.fid)
        print("}")
        # manipulate checkboxes
        print("function show_if_cb_sel_%s() {" % conn_id)
        print("  if (document.getElementById(\"cb_sel_%s\").checked) {" %
              conn_id)
        print("    javascript:show_%s();" % conn_id)
        print("  } else {")
        print("    javascript:hide_%s();" % conn_id)
        print("  }")
        print("}")
        print("function select_cb_sel_%s() {" % conn_id)
        print("  document.getElementById(\"cb_sel_%s\").checked = true;" %
              conn_id)
        print("  javascript:show_%s();" % conn_id)
        print("}")
        print("function deselect_cb_sel_%s() {" % conn_id)
        print("  document.getElementById(\"cb_sel_%s\").checked = false;" %
              conn_id)
        print("  javascript:hide_%s();" % conn_id)
        print("}")
        print("function toggle_cb_sel_%s() {" % conn_id)
        print("  if (document.getElementById(\"cb_sel_%s\").checked) {" %
              conn_id)
        print("    document.getElementById(\"cb_sel_%s\").checked = false;" %
              conn_id)
        print("  } else {")
        print("    document.getElementById(\"cb_sel_%s\").checked = true;" %
              conn_id)
        print("  }")
        print("  javascript:show_if_cb_sel_%s();" % conn_id)
        print("}")

    # Select/Deselect/Toggle All Connections functions
    print("function select_all() {")
    for conn_id, frames_ids in common.dict_iteritems(comn.conn_to_frame_map):
        print("  javascript:select_cb_sel_%s();" % conn_id)
    print("}")
    print("function deselect_all() {")
    for conn_id, frames_ids in common.dict_iteritems(comn.conn_to_frame_map):
        print("  javascript:deselect_cb_sel_%s();" % conn_id)
    print("}")
    print("function toggle_all() {")
    for conn_id, frames_ids in common.dict_iteritems(comn.conn_to_frame_map):
        print("  javascript:toggle_cb_sel_%s();" % conn_id)
    print("}")

    #
    print("</script>")
    print("</head>")
    print("<body>")
    #

    # Table of contents
    print(text.web_page_toc())

    # Report how much data was skipped if --no-data switch in effect
    if comn.args.skip_all_data:
        print("--skip-all-data switch is in effect. %d log lines skipped" %
              comn.data_skipped)
        print("<p><hr>")

    # file(s) included in this doc
    print("<a name=\"c_logfiles\"></a>")
    print("<h3>Log files</h3>")
    print(
        "<table><tr><th>Log</th> <th>Container name</th> <th>Version</th> <th>Mode</th>"
        "<th>Instances</th> <th>Log file path</th></tr>")
    for i in range(comn.n_logs):
        rtrlist = comn.routers[i]
        if len(rtrlist) > 0:
            print(
                "<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>"
                % (common.log_letter_of(i), rtrlist[0].container_name,
                   rtrlist[0].version, rtrlist[0].mode, str(
                       len(rtrlist)), os.path.abspath(comn.log_fns[i])))
        else:
            print(
                "<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>"
                % (common.log_letter_of(i), text.nbsp(), text.nbsp(),
                   str(len(rtrlist)), os.path.abspath(comn.log_fns[i])))
    print("</table>")
    print("<hr>")

    # reboot chronology
    print("<a name=\"c_rtrinstances\"></a>")
    print("<h3>Router Reboot Chronology</h3>")
    print("<table><tr><th>Log</th> <th>Time</th> <th>Container name</th> ")
    for i in range(len(comn.routers)):
        print("<td>%s</td>" % common.log_letter_of(i))
    print("</tr>")
    for rr in rr_tree:
        print("<tr><td>%s</td><td>%s</td><td>%s</td>" %
              (rr.router.iname, rr.datetime, rr.router.container_name))
        for i in range(len(comn.routers)):
            print(
                "<td>%s</td> " %
                (rr.router.iname if i == rr.router.log_index else text.nbsp()))
        print("</tr>")
    print("</table>")
    print("<hr>")

    # print the connection peer tables
    #
    # +------+--------------------+-----+--------------------+-------+-------+----------+--------+-------+
    # | 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>")

    print("<p>")
    print("<button onclick=\"javascript:select_all()\">Select All</button>")
    print(
        "<button onclick=\"javascript:deselect_all()\">Deselect All</button>")
    print("<button onclick=\"javascript:toggle_all()\">Toggle All</button>")
    print("</p>")

    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> %s </tr>"
        % amqp_detail.Counts.show_table_heads1())
    print(
        "<tr> <th>container</th> <th>connid</th> <th>connid</th> <th>container</th> %s </tr>"
        % amqp_detail.Counts.show_table_heads2())

    tConn = 0
    tLines = 0
    tBytes = 0
    tErrs = 0
    tLinks = 0
    for rtrlist in comn.routers:
        for rtr in rtrlist:
            rid = rtr.container_name
            for conn in rtr.conn_list:
                tConn += 1
                id = rtr.conn_id(conn)  # this router's full connid 'A0_3'
                peer = rtr.conn_peer_display.get(id, "")  # peer container id
                peerconnid = comn.conn_peers_connid.get(id, "")
                n_links = rtr.details.links_in_connection(id)
                tLinks += n_links
                conn_details = rtr.details.conn_details[id]
                tErrs += conn_details.counts.errors
                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> %s </tr>" %
                    (rid, id, id, rtr.conn_dir[id], peerconnid, peer,
                     rtr.conn_log_lines[id], n_links, rtr.conn_xfer_bytes[id],
                     conn_details.counts.show_table_data()))
                tLines += rtr.conn_log_lines[id]
                tBytes += rtr.conn_xfer_bytes[id]
    print(
        "<td>Total</td><td>%d</td><td> </td><td> </td><td> </td><td> </td><td>%d</td><td>%d</td><td>%d</td><td>%d</td></tr>"
        % (tConn, tLines, tLinks, tBytes, tErrs))
    print("</table>")

    print("<a name=\"c_connectchrono\"></a>")
    print("<h3>Router Restart and Connection chronology</h3>")

    cl = []
    for rtrlist in comn.routers:
        for rtr in rtrlist:
            rid = rtr.container_name
            cl.append(
                common.RestartRec(rtr.iname, rtr, "restart",
                                  rtr.restart_rec.datetime))
            for conn in rtr.conn_list:
                id = rtr.conn_id(conn)
                if id in rtr.conn_open_time:
                    cl.append(
                        common.RestartRec(id, rtr, "open",
                                          rtr.conn_open_time[id].datetime))
                if id in rtr.conn_close_time:
                    cl.append(
                        common.RestartRec(id, rtr, "close",
                                          rtr.conn_close_time[id].datetime))
    cl = sorted(cl, key=lambda lfl: lfl.datetime)

    print(
        "<table><tr> <th>Time</th> <th>Id</th> <th>Event</th> <th>container</th> <th>connid</th> "
        "<th>Dir</th> <th>connid</th> <th>container</th>")
    for i in range(len(comn.routers)):
        print("<td>%s</td>" % common.log_letter_of(i))
    print("</tr>")
    for c in cl:
        if c.event == "restart":
            rid = c.router.container_name
            print(
                "<tr><td>%s</td> <td>%s</td> <td><span style=\"background-color:yellow\">%s</span></td><td>%s</td> "
                "<td>%s</td> <td>%s</td><td>%s</td> <td>%s</td>" %
                (c.datetime, c.id, c.event, rid, "", "", "", ""))
            for i in range(len(comn.routers)):
                print("<td>%s</td> " %
                      (c.id if i == c.router.log_index else text.nbsp()))
            print("</tr>")
        else:
            rid = c.router.container_name
            cdir = c.router.conn_dir[c.id]
            peer = c.router.conn_peer_display.get(c.id,
                                                  "")  # peer container id
            peerconnid = comn.conn_peers_connid.get(c.id, "")
            print(
                "<tr><td>%s</td> <td>%s</td> <td>%s</td><td>%s</td> <td>%s</td> <td>%s</td><td>%s</td> <td>%s</td>"
                %
                (c.datetime, c.id, c.event, rid, c.id, cdir, peerconnid, peer))
            for i in range(len(comn.routers)):
                print("<td>%s</td> " % (text.nbsp()))
            print("</tr>")
    print("</table>")
    print("<hr>")

    # address overview
    print("<a name=\"c_addresses\"></a>")
    print("<h3>AMQP Addresses Overview</h3>")
    # compute with and without data lists
    w_data = []
    wo_data = []
    for i in range(0, comn.shorteners.short_addr_names.len()):
        sname = comn.shorteners.short_addr_names.shortname(i)
        lname = comn.shorteners.short_addr_names.longnames[i]
        links = comn.shorteners.short_addr_names.customers(sname)
        showthis = ("<a href=\"javascript:toggle_node('@@addr_%d')\">%s</a>" %
                    (i, text.lozenge()))
        visitthis = ("<a href=\"#@@addr_%d_data\">%s</a>" % (i, lname))
        n_frames = sum(len(linkd.frame_list) for linkd in links)
        n_transfers = 0
        for linkd in links:
            n_transfers += sum(1 for plf in linkd.frame_list
                               if plf.data.transfer)
        n_unsettled = sum(linkd.counts.unsettled for linkd in links)
        line = (
            "<tr><td>%s %s</td> <td>%d</td> <td>%d</td> <td>%d</td> <td>%d</td></tr>"
            % (showthis, visitthis, len(links), n_frames, n_transfers,
               n_unsettled))
        if n_transfers == 0:
            wo_data.append(line)
        else:
            w_data.append(line)

    # loop to print table with no expanded data
    print("<h4>With transfer data (N=%d)</h4>" % len(w_data))
    print(
        "<table><tr><th>Address</th> <th>N Links</th> <th>Frames</th> <th>Transfers</th> <th>Unsettled</th> </tr>"
    )
    for line in w_data:
        print(line)
    print("</table>")

    print("<h4>With no transfer data (N=%d)</h4>" % len(wo_data))
    print(
        "<table><tr><th>Address</th> <th>N Links</th> <th>Frames</th> <th>Transfers</th> <th>Unsettled</th> </tr>"
    )
    for line in wo_data:
        print(line)
    print("</table>")

    # loop to print expandable sub tables
    print("<h3>AMQP Addresses Details</h3>")
    for i in range(0, comn.shorteners.short_addr_names.len()):
        sname = comn.shorteners.short_addr_names.shortname(i)
        lname = comn.shorteners.short_addr_names.longnames[i]
        links = comn.shorteners.short_addr_names.customers(sname)
        print(
            "<div id=\"@@addr_%d\" style=\"display:none; margin-top: 2px; margin-bottom: 2px; margin-left: 10px\">"
            % (i))
        print("<a name=\"@@addr_%d_data\"></a>" % (i))
        print("<h4>Address %s - %s</h4>" % (sname, lname))
        print(
            "<table><tr> <th colspan=\"2\">Router</th> <th rowspan=\"2\">Dir</th> <th colspan=\"2\">Peer</th> <th rowspan=\"2\">Role</th> "
            "<th rowspan=\"2\">Link</th> <th rowspan=\"2\">Frames</th>  <th rowspan=\"2\">Transfers</th> <th rowspan=\"2\">Unsettled</th></tr>"
        )
        print(
            "<tr> <th>container</th> <th>connid</th> <th>connid</th> <th>container</th></tr>"
        )
        for linkd in links:
            # linkd                         # LinkDetail
            sessd = linkd.session_detail  # SessionDetail
            connd = sessd.conn_detail  # ConnectionDetail
            rtr = connd.router  # Router
            conn = connd.conn  # connection number type int
            rid = rtr.container_name
            id = rtr.conn_id(conn)
            peer = rtr.conn_peer_display.get(id, "")  # peer container id
            peerconnid = comn.conn_peers_connid.get(id, "")
            role = "receiver" if linkd.is_receiver else "sender"
            transfers = sum(1 for plf in linkd.frame_list if plf.data.transfer)
            showall = (
                "<a href=\"javascript:void(0)\" onclick=\"show_node(%s_data); show_node(%s_sess_%s); show_node(%s_sess_%s_link_%s)\">%s</a>"
                % (id, id, sessd.conn_epoch, id, sessd.conn_epoch,
                   linkd.session_seq, text.lozenge()))
            visitthis = (
                "<a href=\"#%s_sess_%s_link_%s_data\">%s</a>" %
                (id, sessd.conn_epoch, linkd.session_seq, linkd.display_name))
            print(
                "<tr> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s %s</td> <td>%d</td> <td>%d</td> <td>%d</td> </tr>"
                % (rid, id, rtr.conn_dir[id], peerconnid, peer, role, showall,
                   visitthis, len(
                       linkd.frame_list), transfers, linkd.counts.unsettled))
        print("</table>")
        print("</div>")
    print("<hr>")

    # connection details
    print("<a name=\"c_conndetails\"></a>")
    print("<h3>Connection Details</h3>")
    if not comn.args.skip_detail:
        for rtrlist in comn.routers:
            for rtr in rtrlist:
                rtr.details.show_html()
    else:
        print("details suppressed<br>")
    print("<hr>")

    # noteworthy log lines: highlight errors and stuff
    print("<a name=\"c_noteworthy\"></a>")
    print("<h3>Noteworthy</h3>")
    n_errors = 0
    n_settled = 0
    n_more = 0
    n_resume = 0
    n_aborted = 0
    n_drain = 0
    n_unsettled = 0
    n_unsettled_no_parent = 0  # without link/session can't match xfers with dispositions
    for plf in tree:
        if plf.data.amqp_error:
            n_errors += 1
        if plf.data.transfer_settled:
            n_settled += 1
        if plf.data.transfer_more:
            n_more += 1
        if plf.data.transfer_resume:
            n_resume += 1
        if plf.data.transfer_aborted:
            n_aborted += 1
        if plf.data.flow_drain:
            n_drain += 1
        if common.transfer_is_possibly_unsettled(plf):
            if plf.data.no_parent_link:
                n_unsettled_no_parent += 1  # possibly unsettled
            else:
                n_unsettled += 1  # probably unsettled
    # amqp errors
    print(
        "<a href=\"javascript:toggle_node('noteworthy_errors')\">%s%s</a> AMQP errors: %d<br>"
        % (text.lozenge(), text.nbsp(), n_errors))
    print(
        " <div width=\"100%%\"; "
        "style=\"display:none; font-weight: normal; margin-bottom: 2px; margin-left: 10px\" "
        "id=\"noteworthy_errors\">")
    for plf in tree:
        if plf.data.amqp_error:
            show_noteworthy_line(plf, comn)
    print("</div>")
    # transfers with settled=true
    print(
        "<a href=\"javascript:toggle_node('noteworthy_settled')\">%s%s</a> Presettled transfers: %d<br>"
        % (text.lozenge(), text.nbsp(), n_settled))
    print(
        " <div width=\"100%%\"; "
        "style=\"display:none; font-weight: normal; margin-bottom: 2px; margin-left: 10px\" "
        "id=\"noteworthy_settled\">")
    for plf in tree:
        if plf.data.transfer_settled:
            show_noteworthy_line(plf, comn)
    print("</div>")
    # transfers with more=true
    print(
        "<a href=\"javascript:toggle_node('noteworthy_more')\">%s%s</a> Partial transfers with 'more' set: %d<br>"
        % (text.lozenge(), text.nbsp(), n_more))
    print(
        " <div width=\"100%%\"; "
        "style=\"display:none; font-weight: normal; margin-bottom: 2px; margin-left: 10px\" "
        "id=\"noteworthy_more\">")
    for plf in tree:
        if plf.data.transfer_more:
            show_noteworthy_line(plf, comn)
    print("</div>")
    # transfers with resume=true, whatever that is
    print(
        "<a href=\"javascript:toggle_node('noteworthy_resume')\">%s%s</a> Resumed transfers: %d<br>"
        % (text.lozenge(), text.nbsp(), n_resume))
    print(
        " <div width=\"100%%\"; "
        "style=\"display:none; font-weight: normal; margin-bottom: 2px; margin-left: 10px\" "
        "id=\"noteworthy_resume\">")
    for plf in tree:
        if plf.data.transfer_resume:
            show_noteworthy_line(plf, comn)
    print("</div>")
    # transfers with abort=true
    print(
        "<a href=\"javascript:toggle_node('noteworthy_aborts')\">%s%s</a> Aborted transfers: %d<br>"
        % (text.lozenge(), text.nbsp(), n_aborted))
    print(
        " <div width=\"100%%\"; "
        "style=\"display:none; font-weight: normal; margin-bottom: 2px; margin-left: 10px\" "
        "id=\"noteworthy_aborts\">")
    for plf in tree:
        if plf.data.transfer_aborted:
            show_noteworthy_line(plf, comn)
    print("</div>")
    # flow with drain=true
    print(
        "<a href=\"javascript:toggle_node('noteworthy_drain')\">%s%s</a> Flow with 'drain' set: %d<br>"
        % (text.lozenge(), text.nbsp(), n_drain))
    print(
        " <div width=\"100%%\"; "
        "style=\"display:none; font-weight: normal; margin-bottom: 2px; margin-left: 10px\" "
        "id=\"noteworthy_drain\">")
    for plf in tree:
        if plf.data.flow_drain:
            show_noteworthy_line(plf, comn)
    print("</div>")
    # probable unsettled transfers
    print(
        "<a href=\"javascript:toggle_node('noteworthy_unsettled')\">%s%s</a> Probable unsettled transfers: %d<br>"
        % (text.lozenge(), text.nbsp(), n_unsettled))
    print(
        " <div width=\"100%%\"; "
        "style=\"display:none; font-weight: normal; margin-bottom: 2px; margin-left: 10px\" "
        "id=\"noteworthy_unsettled\">")
    for plf in tree:
        if common.transfer_is_possibly_unsettled(
                plf) and not plf.data.no_parent_link:
            show_noteworthy_line(plf, comn)
    print("</div>")
    # possible unsettled transfers
    print(
        "<a href=\"javascript:toggle_node('noteworthy_unsettled_qm')\">%s%s</a> Possible unsettled transfers: %d<br>"
        % (text.lozenge(), text.nbsp(), n_unsettled_no_parent))
    print(
        " <div width=\"100%%\"; "
        "style=\"display:none; font-weight: normal; margin-bottom: 2px; margin-left: 10px\" "
        "id=\"noteworthy_unsettled_qm\">")
    for plf in tree:
        if common.transfer_is_possibly_unsettled(
                plf) and plf.data.no_parent_link:
            show_noteworthy_line(plf, comn)
    print("</div>")
    print("<hr>")

    # the proton log lines
    # log lines in         f_A_116
    # log line details in  f_A_116_d
    print("<a name=\"c_logdata\"></a>")
    print("<h3>Log data</h3>")
    for plf in tree:
        l_dict = plf.data.described_type.dict
        print(
            "<div width=\"100%%\" style=\"display:block  margin-bottom: 2px\" id=\"%s\">"
            % plf.fid)
        print("<a name=\"%s\"></a>" % plf.fid)
        detailname = plf.fid + "_d"  # type: str
        loz = "<a href=\"javascript:toggle_node('%s')\">%s%s</a>" % (
            detailname, text.lozenge(), text.nbsp())
        rtr = plf.router
        rid = comn.router_display_names[rtr.log_index]

        peerconnid = "%s" % comn.conn_peers_connid.get(plf.data.conn_id, "")
        peer = rtr.conn_peer_display.get(plf.data.conn_id,
                                         "")  # peer container id
        print(loz, plf.datetime, ("%s#%d" % (plf.prefixi, plf.lineno)), rid,
              ("[%s]" % plf.data.conn_id), plf.data.direction,
              ("[%s]" % peerconnid), peer, plf.data.web_show_str,
              plf.data.disposition_display, "<br>")
        print(
            " <div width=\"100%%\"; "
            "style=\"display:none; font-weight: normal; margin-bottom: 2px; margin-left: 10px\" "
            "id=\"%s\">" % detailname)
        for key in sorted(common.dict_iterkeys(l_dict)):
            val = l_dict[key]
            print("%s : %s <br>" % (key, common.html_escape(str(val))))
        if plf.data.name == "transfer":
            print("Header and annotations : %s <br>" %
                  plf.data.transfer_hdr_annos)
        print("</div>")
        print("</div>")
    print("<hr>")

    # data traversing network
    print("<a name=\"c_messageprogress\"></a>")
    print("<h3>Message progress</h3>")
    if not comn.args.skip_msg_progress:
        for i in range(0, comn.shorteners.short_data_names.len()):
            sname = comn.shorteners.short_data_names.shortname(i)
            size = 0
            for plf in comn.shorteners.short_data_names.customers(sname):
                size = plf.data.transfer_size
                break
            print("<a name=\"%s\"></a> <h4>%s (%s)" % (sname, sname, size))
            print(" <span> <a href=\"javascript:toggle_node('%s')\"> %s</a>" %
                  ("data_" + sname, text.lozenge()))
            print(
                " <div width=\"100%%\"; style=\"display:none; font-weight: normal; margin-bottom: 2px\" id=\"%s\">"
                % ("data_" + sname))
            print(" ", comn.shorteners.short_data_names.longname(i, True))
            print("</div> </span>")
            print("</h4>")
            print("<table>")
            print(
                "<tr><th>Src</th> <th>Time</th> <th>Router</th> <th>ConnId</th> <th>Dir</th> <th>ConnId</th> <th>Peer</th> "
                "<th>T delta</th> <th>T elapsed</th><th>Settlement</th><th>S elapsed</th></tr>"
            )
            t0 = None
            tlast = None
            for plf in comn.shorteners.short_data_names.customers(sname):
                if t0 is None:
                    t0 = plf.datetime
                    tlast = plf.datetime
                    delta = "0.000000"
                    epsed = "0.000000"
                else:
                    delta = time_offset(plf.datetime, tlast)
                    epsed = time_offset(plf.datetime, t0)
                    tlast = plf.datetime
                sepsed = ""
                if plf.data.final_disposition is not None:
                    sepsed = time_offset(plf.data.final_disposition.datetime,
                                         t0)
                rid = plf.router.iname
                peerconnid = "%s" % comn.conn_peers_connid.get(
                    plf.data.conn_id, "")
                peer = plf.router.conn_peer_display.get(
                    plf.data.conn_id, "")  # peer container id
                print(
                    "<tr><td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> "
                    "<td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> </tr>"
                    % (plf.adverbl_link_to(), plf.datetime, rid,
                       plf.data.conn_id, plf.data.direction, peerconnid, peer,
                       delta, epsed, plf.data.disposition_display, sepsed))
            print("</table>")

    print("<hr>")

    # link names traversing network
    print("<a name=\"c_linkprogress\"></a>")
    print("<h3>Link name propagation</h3>")
    for i in range(0, comn.shorteners.short_link_names.len()):
        if comn.shorteners.short_link_names.len() == 0:
            break
        sname = comn.shorteners.short_link_names.prefixname(i)
        print("<a name=\"%s\"></a> <h4>%s" % (sname, sname))
        print(
            " <span> <div width=\"100%%\"; style=\"display:block; font-weight: normal; margin-bottom: 2px\" >"
        )
        print(comn.shorteners.short_link_names.longname(i, True))
        print("</div> </span>")
        print("</h4>")
        print("<table>")
        print(
            "<tr><th>src</th> <th>Time</th> <th>Router</th> <th>ConnId</th> <th>Dir</th> <th>ConnId> <th>Peer</th> "
            "<th>T delta</th> <th>T elapsed</th></tr>")
        t0 = None
        tlast = None
        for plf in comn.shorteners.short_link_names.customers(sname):
            if t0 is None:
                t0 = plf.datetime
                delta = "0.000000"
                epsed = "0.000000"
            else:
                delta = time_offset(plf.datetime, tlast)
                epsed = time_offset(plf.datetime, t0)
            tlast = plf.datetime
            rid = plf.router.iname
            peerconnid = "%s" % comn.conn_peers_connid.get(
                plf.data.conn_id, "")
            peer = plf.router.conn_peer_display.get(plf.data.conn_id,
                                                    "")  # peer container id
            print(
                "<tr><td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> "
                "<td>%s</td> <td>%s</td> <td>%s</td></tr>" %
                (plf.adverbl_link_to(), plf.datetime, rid, plf.data.conn_id,
                 plf.data.direction, peerconnid, peer, delta, epsed))
        print("</table>")

    print("<hr>")

    # short data index
    print("<a name=\"c_rtrdump\"></a>")
    comn.shorteners.short_rtr_names.htmlDump(False)
    print("<hr>")

    print("<a name=\"c_peerdump\"></a>")
    comn.shorteners.short_peer_names.htmlDump(False)
    print("<hr>")

    print("<a name=\"c_linkdump\"></a>")
    comn.shorteners.short_link_names.htmlDump(True)
    print("<hr>")

    print("<a name=\"c_msgdump\"></a>")
    comn.shorteners.short_data_names.htmlDump(with_link=True, log_strings=True)
    print("<hr>")

    # link state info
    # merge link state and restart records into single time based list
    cl = []
    for rtrlist in comn.routers:
        for rtr in rtrlist:
            rid = rtr.container_name
            cl.append(
                common.RestartRec(rtr.iname, rtr, "restart",
                                  rtr.restart_rec.datetime))
    for plf in ls_tree:
        if "costs" in plf.line:
            cl.append(common.RestartRec("ls", plf, "ls", plf.datetime))
    cl = sorted(cl, key=lambda lfl: lfl.datetime)

    # create a map of lists for each router
    # the list holds the name of other routers for which the router publishes a cost
    costs_pub = {}
    for i in range(0, comn.n_logs):
        costs_pub[comn.router_ids[i]] = []

    # cur_costs is a 2D array of costs used to tell when cost calcs have stabilized
    # Each incoming LS cost line replaces a row in this table
    # cur_costs tracks only interior routers
    interior_rtrs = []
    for rtrs in comn.routers:
        if rtrs[0].is_interior():
            interior_rtrs.append(rtrs[0].container_name)

    PEER_COST_REBOOT = -1
    PEER_COST_ABSENT = 0

    def new_costs_row(val):
        """
        return a costs row.
        :param val: -1 when router reboots, 0 when router log line processed
        :return:
        """
        res = {}
        for rtr in interior_rtrs:
            res[rtr] = val
        return res

    cur_costs = {}
    for rtr in interior_rtrs:
        cur_costs[rtr] = new_costs_row(PEER_COST_REBOOT)

    print("<a name=\"c_ls\"></a>")
    print("<h3>Routing link state</h3>")
    print("<h4>Link state costs</h4>")
    print("<table>")
    print("<tr><th>Time</th> <th>Router</th>")
    for i in range(0, comn.n_logs):
        print("<th>%s</th>" % common.log_letter_of(i))
    print("</tr>")
    for c in cl:
        if c.event == "ls":
            # link state computed costs and router reachability
            plf = c.router  # cruel overload here: router is a parsed line not a router
            # Processing: Computed costs: {u'A': 1, u'C': 51L, u'B': 101L}
            print("<tr><td>%s</td> <td>%s</td>" %
                  (plf.datetime, ("%s#%d" % (plf.router.iname, plf.lineno))))
            try:
                line = plf.line
                sti = line.find("{")
                line = line[sti:]
                try:
                    l_dict = common.ls_eval(line)
                except:
                    traceback.print_exc()
                    sys.stderr.write(
                        "Failed to parse router %s, line %d : %s. Analysis continuing...\n"
                        % (plf.router.iname, plf.lineno, plf.line))
                    l_dict = {}
                costs_row = new_costs_row(PEER_COST_ABSENT)
                for i in range(0, comn.n_logs):
                    if len(comn.routers[i]) > 0:
                        tst_name = comn.routers[i][0].container_name
                        if tst_name in l_dict:
                            val = l_dict[tst_name]
                            costs_row[tst_name] = val
                        elif i == plf.router.log_index:
                            val = text.nbsp()
                        else:
                            val = "<span style=\"background-color:orange\">%s</span>" % (
                                text.nbsp() * 2)
                    else:
                        val = "<span style=\"background-color:orange\">%s</span>" % (
                            text.nbsp() * 2)
                    print("<td>%s</td>" % val)
                # track costs published when there is no column to put the number
                tgts = costs_pub[c.router.router.container_name]
                for k, v in common.dict_iteritems(l_dict):
                    if k not in comn.router_ids:
                        if k not in tgts:
                            tgts.append(k)  # this cost went unreported
                # update this router's cost view in running table
                if plf.router.is_interior():
                    cur_costs[plf.router.container_name] = costs_row
            except:
                raise
            print("</tr>")
            # if the costs are stable across all routers then put an indicator in table
            costs_stable = True
            for c_rtr in interior_rtrs:
                for r_rtr in interior_rtrs:
                    if r_rtr != c_rtr \
                            and (cur_costs[r_rtr][c_rtr] != cur_costs[c_rtr][r_rtr] \
                            or cur_costs[c_rtr][r_rtr] <= PEER_COST_ABSENT):
                        costs_stable = False
                        break
                if not costs_stable:
                    break
            if costs_stable:
                print(
                    "<tr><td><span style=\"background-color:green\">stable</span></td></tr>"
                )
        else:
            # restart
            print("<tr><td>%s</td> <td>%s</td>" %
                  (c.datetime, ("%s restart" % (c.router.iname))))
            for i in range(0, comn.n_logs):
                color = "green" if i == c.router.log_index else "orange"
                print(
                    "<td><span style=\"background-color:%s\">%s</span></td>" %
                    (color, text.nbsp() * 2))
            print("</tr>")
            if c.router.is_interior():
                cur_costs[c.router.container_name] = new_costs_row(
                    PEER_COST_REBOOT)
    print("</table>")
    print("<br>")

    # maybe display cost declarations that were not displayed
    costs_clean = True
    for k, v in common.dict_iteritems(costs_pub):
        if len(v) > 0:
            costs_clean = False
            break
    if not costs_clean:
        print(
            "<h4>Router costs declared in logs but not displayed in Link state cost table</h4>"
        )
        print("<table>")
        print("<tr><th>Router</th><Peers whose logs are absent</th></tr>")
        for k, v in common.dict_iteritems(costs_pub):
            if len(v) > 0:
                print("<tr><td>%s</td><td>%s</td></tr>" % (k, str(v)))
        print("</table>")
        print("<br>")

    print(
        "<a href=\"javascript:toggle_node('ls_costs')\">%s%s</a> Link state costs data<br>"
        % (text.lozenge(), text.nbsp()))
    print(
        " <div width=\"100%%\"; "
        "style=\"display:none; font-weight: normal; margin-bottom: 2px; margin-left: 10px\" "
        "id=\"ls_costs\">")
    print("<table>")
    print("<tr><th>Time</th> <th>Router</th> <th>Name</th> <th>Log</th></tr>")
    for plf in ls_tree:
        if "costs" in plf.line:
            print("<tr><td>%s</td> <td>%s</td>" %
                  (plf.datetime, ("%s#%d" % (plf.router.iname, plf.lineno))))
            print("<td>%s</td>" % plf.router.container_name)
            print("<td>%s</td></tr>" % plf.line)
    print("</table>")
    print("</div>")

    print("<hr>")

    print("</body>")
コード例 #12
0
ファイル: scraper.py プロジェクト: apache/qpid-dispatch
def main_except(argv):
    # Instantiate a common block
    comn = common.Common()

    # optparse - look for data-inhibit and program mode control
    p = argparse.ArgumentParser()
    p.add_argument('--skip-all-data', '-sa',
                   action='store_true',
                   help='Max load shedding: do not store/index transfer, disposition, flow or EMPTY_FRAME data')
    p.add_argument('--skip-detail', '-sd',
                   action='store_true',
                   help='Load shedding: do not produce Connection Details tables')
    p.add_argument('--skip-msg-progress', '-sm',
                   action='store_true',
                   help='Load shedding: do not produce Message Progress tables')
    p.add_argument('--split', '-sp',
                   action='store_true',
                   help='A single file is split into per-connection data.')
    p.add_argument('--time-start', '-ts',
                   help='Ignore log records earlier than this. Format: "2018-08-13 13:15:00.123456"')
    p.add_argument('--time-end', '-te',
                   help='Ignore log records later than this. Format: "2018-08-13 13:15:15.123456"')
    p.add_argument('--files', '-f', nargs="+")

    del argv[0]
    comn.args = p.parse_args(argv)

    if not comn.args.time_start is None:
        try:
            comn.args.time_start = datetime.datetime.strptime(comn.args.time_start, "%Y-%m-%d %H:%M:%S.%f")
        except:
            sys.exit("ERROR: Failed to parse time_start '%s'. Use format 'YYYY-MM-DD HH:MM:SS.n_uS'" % comn.args.time_start)

    if not comn.args.time_end is None:
        try:
            comn.args.time_end = datetime.datetime.strptime(comn.args.time_end, "%Y-%m-%d %H:%M:%S.%f")
        except:
            sys.exit("ERROR: Failed to parse time_end '%s'. Use format 'YYYY-MM-DD HH:MM:SS.n_uS'" % comn.args.time_end)

    # process split function
    if comn.args.split:
        # Split processes only a single file
        if len(comn.args.files) > 1:
            sys.exit('--split mode takes only one file name')
        return splitter_main(comn.args.files[0])

    # process the log files and add the results to router_array
    for log_i in range(len(comn.args.files)):
        arg_log_file = comn.args.files[log_i]
        comn.log_fns.append(arg_log_file)
        comn.n_logs += 1

        if not os.path.exists(arg_log_file):
            sys.exit('ERROR: log file %s was not found!' % arg_log_file)

        # parse the log file
        rtrs = parser.parse_log_file(arg_log_file, log_i, comn)
        comn.routers.append(rtrs)

        # marshall facts about the run
        for rtr in rtrs:
            rtr.discover_connection_facts(comn)

    # Create lists of various things sorted by time
    tree = []  # log line
    ls_tree = []  # link state lines
    rr_tree = []  # restart records
    for rtrlist in comn.routers:
        for rtr in rtrlist:
            tree += rtr.lines
            ls_tree += rtr.router_ls
            rr_tree.append(rtr.restart_rec)
    tree = sorted(tree, key=lambda lfl: lfl.datetime)
    ls_tree = sorted(ls_tree, key=lambda lfl: lfl.datetime)
    rr_tree = sorted(rr_tree, key=lambda lfl: lfl.datetime)

    # Back-propagate a router name/version/mode to each list's router0.
    # Complain if container name or version changes between instances.
    # Fill in container_id and shortened display_name tables
    for fi in range(comn.n_logs):
        rtrlist = comn.routers[fi]
        if len(rtrlist) > 1:
            if rtrlist[0].container_name is None:
                rtrlist[0].container_name = rtrlist[1].container_name
            if rtrlist[0].version is None:
                rtrlist[0].version = rtrlist[1].version
            if rtrlist[0].mode is None:
                rtrlist[0].mode = rtrlist[1].mode
            for i in range(0, len(rtrlist) - 1):
                namei = rtrlist[i].container_name
                namej = rtrlist[i + 1].container_name
                if namei != namej:
                    sys.exit('Inconsistent container names, log file %s, instance %d:%s but instance %d:%s' %
                             (comn.log_fns[fi], i, namei, i + 1, namej))
                namei = rtrlist[i].version
                namej = rtrlist[i + 1].version
                if namei != namej:
                    sys.exit('Inconsistent router versions, log file %s, instance %d:%s but instance %d:%s' %
                             (comn.log_fns[fi], i, namei, i + 1, namej))
                namei = rtrlist[i].mode
                namej = rtrlist[i + 1].mode
                if namei != namej:
                    sys.exit('Inconsistent router modes, log file %s, instance %d:%s but instance %d:%s' %
                             (comn.log_fns[fi], i, namei, i + 1, namej))
        name = rtrlist[0].container_name if len(rtrlist) > 0 and rtrlist[0].container_name is not None else ("Unknown_%d" % fi)
        mode = rtrlist[0].mode if len(rtrlist) > 0 and rtrlist[0].mode is not None else "standalone"
        comn.router_ids.append(name)
        comn.router_display_names.append(comn.shorteners.short_rtr_names.translate(name))
        comn.router_modes.append(mode)

    # aggregate connection-to-frame maps into big map
    for rtrlist in comn.routers:
        for rtr in rtrlist:
            comn.conn_to_frame_map.update(rtr.conn_to_frame_map)

    # generate router-to-router connection peer relationships
    peer_list = []
    for plf in tree:
        if plf.data.name == "open" and plf.data.direction_is_in():
            cid = plf.data.conn_id  # the router that generated this log file
            if "properties" in plf.data.described_type.dict:
                peer_conn = plf.data.described_type.dict["properties"].get(':"qd.conn-id"',
                                                                           "")  # router that sent the open
                if peer_conn != "" and plf.data.conn_peer != "":
                    pid_peer = plf.data.conn_peer.strip('\"')
                    rtr, rtridx = router.which_router_id_tod(comn.routers, pid_peer, plf.datetime)
                    if rtr is not None:
                        pid = rtr.conn_id(peer_conn)
                        hit = sorted((cid, pid))
                        if hit not in peer_list:
                            peer_list.append(hit)

    for (key, val) in peer_list:
        if key in comn.conn_peers_connid:
            sys.exit('key val messed up')
        if val in comn.conn_peers_connid:
            sys.exit('key val messed up')
        comn.conn_peers_connid[key] = val
        comn.conn_peers_connid[val] = key
        cn_k = comn.router_ids[common.index_of_log_letter(key)]
        cn_v = comn.router_ids[common.index_of_log_letter(val)]
        comn.conn_peers_display[key] = comn.shorteners.short_rtr_names.translate(cn_v)
        comn.conn_peers_display[val] = comn.shorteners.short_rtr_names.translate(cn_k)

    # sort transfer short name customer lists
    comn.shorteners.short_data_names.sort_customers()
    comn.shorteners.short_link_names.sort_customers()

    # compute settlement and index AMQP addresses
    if not comn.args.skip_detail:
        for rtrlist in comn.routers:
            for rtr in rtrlist:
                rtr.details.compute_settlement()
                rtr.details.index_addresses()
                rtr.details.evaluate_credit()

    #
    # Start producing the output stream
    #
    print(text.web_page_head())

    #
    # Generate javascript
    #
    # output the frame show/hide functions into the header
    for conn_id, plfs in common.dict_iteritems(comn.conn_to_frame_map):
        print("function show_%s() {" % conn_id)
        for plf in plfs:
            print("  javascript:show_node(\'%s\');" % plf.fid)
        print("}")
        print("function hide_%s() {" % conn_id)
        for plf in plfs:
            print("  javascript:hide_node(\'%s\');" % plf.fid)
        print("}")
        # manipulate checkboxes
        print("function show_if_cb_sel_%s() {" % conn_id)
        print("  if (document.getElementById(\"cb_sel_%s\").checked) {" % conn_id)
        print("    javascript:show_%s();" % conn_id)
        print("  } else {")
        print("    javascript:hide_%s();" % conn_id)
        print("  }")
        print("}")
        print("function select_cb_sel_%s() {" % conn_id)
        print("  document.getElementById(\"cb_sel_%s\").checked = true;" % conn_id)
        print("  javascript:show_%s();" % conn_id)
        print("}")
        print("function deselect_cb_sel_%s() {" % conn_id)
        print("  document.getElementById(\"cb_sel_%s\").checked = false;" % conn_id)
        print("  javascript:hide_%s();" % conn_id)
        print("}")
        print("function toggle_cb_sel_%s() {" % conn_id)
        print("  if (document.getElementById(\"cb_sel_%s\").checked) {" % conn_id)
        print("    document.getElementById(\"cb_sel_%s\").checked = false;" % conn_id)
        print("  } else {")
        print("    document.getElementById(\"cb_sel_%s\").checked = true;" % conn_id)
        print("  }")
        print("  javascript:show_if_cb_sel_%s();" % conn_id)
        print("}")

    # Select/Deselect/Toggle All Connections functions
    print("function select_all() {")
    for conn_id, frames_ids in common.dict_iteritems(comn.conn_to_frame_map):
        print("  javascript:select_cb_sel_%s();" % conn_id)
    print("}")
    print("function deselect_all() {")
    for conn_id, frames_ids in common.dict_iteritems(comn.conn_to_frame_map):
        print("  javascript:deselect_cb_sel_%s();" % conn_id)
    print("}")
    print("function toggle_all() {")
    for conn_id, frames_ids in common.dict_iteritems(comn.conn_to_frame_map):
        print("  javascript:toggle_cb_sel_%s();" % conn_id)
    print("}")

    #
    print("</script>")
    print("</head>")
    print("<body>")
    #

    # Table of contents
    print(text.web_page_toc())

    # Report how much data was skipped if --no-data switch in effect
    if comn.args.skip_all_data:
        print("--skip-all-data switch is in effect. %d log lines skipped" % comn.data_skipped)
        print("<p><hr>")

    # file(s) included in this doc
    print("<a name=\"c_logfiles\"></a>")
    print("<h3>Log files</h3>")
    print("<table><tr><th>Log</th> <th>Container name</th> <th>Version</th> <th>Mode</th>"
          "<th>Instances</th> <th>Log file path</th></tr>")
    for i in range(comn.n_logs):
        rtrlist = comn.routers[i]
        if len(rtrlist) > 0:
            print("<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>" %
                  (common.log_letter_of(i), rtrlist[0].container_name, rtrlist[0].version, rtrlist[0].mode,
                   str(len(rtrlist)), os.path.abspath(comn.log_fns[i])))
        else:
            print("<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>" %
                  (common.log_letter_of(i), text.nbsp(), text.nbsp(),
                   str(len(rtrlist)), os.path.abspath(comn.log_fns[i])))
    print("</table>")
    print("<hr>")

    # reboot chronology
    print("<a name=\"c_rtrinstances\"></a>")
    print("<h3>Router Reboot Chronology</h3>")
    print("<table><tr><th>Log</th> <th>Time</th> <th>Container name</th> ")
    for i in range(len(comn.routers)):
        print("<td>%s</td>" % common.log_letter_of(i))
    print("</tr>")
    for rr in rr_tree:
        print("<tr><td>%s</td><td>%s</td><td>%s</td>" %
              (rr.router.iname, rr.datetime, rr.router.container_name))
        for i in range(len(comn.routers)):
            print("<td>%s</td> " % (rr.router.iname if i == rr.router.log_index else text.nbsp()))
        print("</tr>")
    print("</table>")
    print("<hr>")

    # print the connection peer tables
    #
    # +------+--------------------+-----+--------------------+-------+-------+----------+--------+-------+
    # | 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>")

    print("<p>")
    print("<button onclick=\"javascript:select_all()\">Select All</button>")
    print("<button onclick=\"javascript:deselect_all()\">Deselect All</button>")
    print("<button onclick=\"javascript:toggle_all()\">Toggle All</button>")
    print("</p>")

    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> %s </tr>" % amqp_detail.Counts.show_table_heads1())
    print("<tr> <th>container</th> <th>connid</th> <th>connid</th> <th>container</th> %s </tr>" %
          amqp_detail.Counts.show_table_heads2())

    tConn = 0
    tLines = 0
    tBytes = 0
    tErrs = 0
    tLinks = 0
    for rtrlist in comn.routers:
        for rtr in rtrlist:
            rid = rtr.container_name
            for conn in rtr.conn_list:
                tConn += 1
                id = rtr.conn_id(conn)  # this router's full connid 'A0_3'
                peer = rtr.conn_peer_display.get(id, "")  # peer container id
                peerconnid = comn.conn_peers_connid.get(id, "")
                n_links = rtr.details.links_in_connection(id)
                tLinks += n_links
                conn_details = rtr.details.conn_details[id]
                tErrs += conn_details.counts.errors
                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> %s </tr>" %
                      (rid, id, id, rtr.conn_dir[id], peerconnid, peer, rtr.conn_log_lines[id], n_links,
                       rtr.conn_xfer_bytes[id], conn_details.counts.show_table_data() ))
                tLines += rtr.conn_log_lines[id]
                tBytes += rtr.conn_xfer_bytes[id]
    print(
        "<td>Total</td><td>%d</td><td> </td><td> </td><td> </td><td> </td><td>%d</td><td>%d</td><td>%d</td><td>%d</td></tr>" %
        (tConn, tLines, tLinks, tBytes, tErrs))
    print("</table>")

    print("<a name=\"c_connectchrono\"></a>")
    print("<h3>Router Restart and Connection chronology</h3>")

    cl = []
    for rtrlist in comn.routers:
        for rtr in rtrlist:
            rid = rtr.container_name
            cl.append(common.RestartRec(rtr.iname, rtr, "restart", rtr.restart_rec.datetime))
            for conn in rtr.conn_list:
                id = rtr.conn_id(conn)
                if id in rtr.conn_open_time:
                    cl.append(common.RestartRec(id, rtr, "open", rtr.conn_open_time[id].datetime))
                if id in rtr.conn_close_time:
                    cl.append(common.RestartRec(id, rtr, "close", rtr.conn_close_time[id].datetime))
    cl = sorted(cl, key=lambda lfl: lfl.datetime)

    print("<table><tr> <th>Time</th> <th>Id</th> <th>Event</th> <th>container</th> <th>connid</th> "
          "<th>Dir</th> <th>connid</th> <th>container</th>")
    for i in range(len(comn.routers)):
        print("<td>%s</td>" % common.log_letter_of(i))
    print("</tr>")
    for c in cl:
        if c.event == "restart":
            rid = c.router.container_name
            print("<tr><td>%s</td> <td>%s</td> <td><span style=\"background-color:yellow\">%s</span></td><td>%s</td> "
                  "<td>%s</td> <td>%s</td><td>%s</td> <td>%s</td>" %
                  (c.datetime, c.id, c.event, rid, "", "", "", ""))
            for i in range(len(comn.routers)):
                print("<td>%s</td> " % (c.id if i == c.router.log_index else text.nbsp()))
            print("</tr>")
        else:
            rid = c.router.container_name
            cdir = c.router.conn_dir[c.id]
            peer = c.router.conn_peer_display.get(c.id, "")  # peer container id
            peerconnid = comn.conn_peers_connid.get(c.id, "")
            print("<tr><td>%s</td> <td>%s</td> <td>%s</td><td>%s</td> <td>%s</td> <td>%s</td><td>%s</td> <td>%s</td>" %
                  (c.datetime, c.id, c.event, rid, c.id, cdir, peerconnid, peer))
            for i in range(len(comn.routers)):
                print("<td>%s</td> " % (text.nbsp()))
            print("</tr>")
    print("</table>")
    print("<hr>")

    # address overview
    print("<a name=\"c_addresses\"></a>")
    print("<h3>AMQP Addresses Overview</h3>")
    # compute with and without data lists
    w_data = []
    wo_data = []
    for i in range(0, comn.shorteners.short_addr_names.len()):
        sname = comn.shorteners.short_addr_names.shortname(i)
        lname = comn.shorteners.short_addr_names.longnames[i]
        links = comn.shorteners.short_addr_names.customers(sname)
        showthis = ("<a href=\"javascript:toggle_node('@@addr_%d')\">%s</a>" %
                    (i, text.lozenge()))
        visitthis = ("<a href=\"#@@addr_%d_data\">%s</a>" %
                     (i, lname))
        n_frames = sum(len(linkd.frame_list) for linkd in links)
        n_transfers = 0
        for linkd in links:
            n_transfers += sum(1 for plf in linkd.frame_list if plf.data.transfer)
        n_unsettled = sum(linkd.counts.unsettled for linkd in links)
        line = ("<tr><td>%s %s</td> <td>%d</td> <td>%d</td> <td>%d</td> <td>%d</td></tr>" %
                (showthis, visitthis, len(links), n_frames, n_transfers, n_unsettled))
        if n_transfers == 0:
            wo_data.append(line)
        else:
            w_data.append(line)

    # loop to print table with no expanded data
    print("<h4>With transfer data (N=%d)</h4>" % len(w_data))
    print("<table><tr><th>Address</th> <th>N Links</th> <th>Frames</th> <th>Transfers</th> <th>Unsettled</th> </tr>")
    for line in w_data: print(line)
    print("</table>")

    print("<h4>With no transfer data (N=%d)</h4>" % len(wo_data))
    print("<table><tr><th>Address</th> <th>N Links</th> <th>Frames</th> <th>Transfers</th> <th>Unsettled</th> </tr>")
    for line in wo_data: print(line)
    print("</table>")

    # loop to print expandable sub tables
    print("<h3>AMQP Addresses Details</h3>")
    for i in range(0, comn.shorteners.short_addr_names.len()):
        sname = comn.shorteners.short_addr_names.shortname(i)
        lname = comn.shorteners.short_addr_names.longnames[i]
        links = comn.shorteners.short_addr_names.customers(sname)
        print("<div id=\"@@addr_%d\" style=\"display:none; margin-top: 2px; margin-bottom: 2px; margin-left: 10px\">" %
              (i))
        print("<a name=\"@@addr_%d_data\"></a>" % (i))
        print("<h4>Address %s - %s</h4>" % (sname, lname))
        print("<table><tr> <th colspan=\"2\">Router</th> <th rowspan=\"2\">Dir</th> <th colspan=\"2\">Peer</th> <th rowspan=\"2\">Role</th> "
              "<th rowspan=\"2\">Link</th> <th rowspan=\"2\">Frames</th>  <th rowspan=\"2\">Transfers</th> <th rowspan=\"2\">Unsettled</th></tr>")
        print("<tr> <th>container</th> <th>connid</th> <th>connid</th> <th>container</th></tr>")
        for linkd in links:
            # linkd                         # LinkDetail
            sessd = linkd.session_detail    # SessionDetail
            connd = sessd.conn_detail       # ConnectionDetail
            rtr = connd.router              # Router
            conn = connd.conn               # connection number type int
            rid = rtr.container_name
            id = rtr.conn_id(conn)
            peer = rtr.conn_peer_display.get(id, "")  # peer container id
            peerconnid = comn.conn_peers_connid.get(id, "")
            role = "receiver" if linkd.is_receiver else "sender"
            transfers = sum(1 for plf in linkd.frame_list if plf.data.transfer)
            showall = ("<a href=\"javascript:void(0)\" onclick=\"show_node(%s_data); show_node(%s_sess_%s); show_node(%s_sess_%s_link_%s)\">%s</a>" %
                       (id, id, sessd.conn_epoch, id, sessd.conn_epoch, linkd.session_seq, text.lozenge()))
            visitthis = ("<a href=\"#%s_sess_%s_link_%s_data\">%s</a>" %
                         (id, sessd.conn_epoch, linkd.session_seq, linkd.display_name))
            print("<tr> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s %s</td> <td>%d</td> <td>%d</td> <td>%d</td> </tr>" %
                  (rid, id, rtr.conn_dir[id], peerconnid, peer, role, showall, visitthis, len(linkd.frame_list), transfers, linkd.counts.unsettled))
        print("</table>")
        print("</div>")
    print("<hr>")

    # connection details
    print("<a name=\"c_conndetails\"></a>")
    print("<h3>Connection Details</h3>")
    if not comn.args.skip_detail:
        for rtrlist in comn.routers:
            for rtr in rtrlist:
                rtr.details.show_html()
    else:
        print ("details suppressed<br>")
    print("<hr>")

    # noteworthy log lines: highlight errors and stuff
    print("<a name=\"c_noteworthy\"></a>")
    print("<h3>Noteworthy</h3>")
    n_errors = 0
    n_settled = 0
    n_more = 0
    n_resume = 0
    n_aborted = 0
    n_drain = 0
    n_unsettled = 0
    n_unsettled_no_parent = 0 # without link/session can't match xfers with dispositions
    for plf in tree:
        if plf.data.amqp_error:
            n_errors += 1
        if plf.data.transfer_settled:
            n_settled += 1
        if plf.data.transfer_more:
            n_more += 1
        if plf.data.transfer_resume:
            n_resume += 1
        if plf.data.transfer_aborted:
            n_aborted += 1
        if plf.data.flow_drain:
            n_drain += 1
        if common.transfer_is_possibly_unsettled(plf):
            if plf.data.no_parent_link:
                n_unsettled_no_parent += 1 # possibly unsettled
            else:
                n_unsettled += 1 # probably unsettled
    # amqp errors
    print("<a href=\"javascript:toggle_node('noteworthy_errors')\">%s%s</a> AMQP errors: %d<br>" %
          (text.lozenge(), text.nbsp(), n_errors))
    print(" <div width=\"100%%\"; "
          "style=\"display:none; font-weight: normal; margin-bottom: 2px; margin-left: 10px\" "
          "id=\"noteworthy_errors\">")
    for plf in tree:
        if plf.data.amqp_error:
            show_noteworthy_line(plf, comn)
    print("</div>")
    # transfers with settled=true
    print("<a href=\"javascript:toggle_node('noteworthy_settled')\">%s%s</a> Presettled transfers: %d<br>" %
          (text.lozenge(), text.nbsp(), n_settled))
    print(" <div width=\"100%%\"; "
          "style=\"display:none; font-weight: normal; margin-bottom: 2px; margin-left: 10px\" "
          "id=\"noteworthy_settled\">")
    for plf in tree:
        if plf.data.transfer_settled:
            show_noteworthy_line(plf, comn)
    print("</div>")
    # transfers with more=true
    print("<a href=\"javascript:toggle_node('noteworthy_more')\">%s%s</a> Partial transfers with 'more' set: %d<br>" %
          (text.lozenge(), text.nbsp(), n_more))
    print(" <div width=\"100%%\"; "
          "style=\"display:none; font-weight: normal; margin-bottom: 2px; margin-left: 10px\" "
          "id=\"noteworthy_more\">")
    for plf in tree:
        if plf.data.transfer_more:
            show_noteworthy_line(plf, comn)
    print("</div>")
    # transfers with resume=true, whatever that is
    print("<a href=\"javascript:toggle_node('noteworthy_resume')\">%s%s</a> Resumed transfers: %d<br>" %
          (text.lozenge(), text.nbsp(), n_resume))
    print(" <div width=\"100%%\"; "
          "style=\"display:none; font-weight: normal; margin-bottom: 2px; margin-left: 10px\" "
          "id=\"noteworthy_resume\">")
    for plf in tree:
        if plf.data.transfer_resume:
            show_noteworthy_line(plf, comn)
    print("</div>")
    # transfers with abort=true
    print("<a href=\"javascript:toggle_node('noteworthy_aborts')\">%s%s</a> Aborted transfers: %d<br>" %
          (text.lozenge(), text.nbsp(), n_aborted))
    print(" <div width=\"100%%\"; "
          "style=\"display:none; font-weight: normal; margin-bottom: 2px; margin-left: 10px\" "
          "id=\"noteworthy_aborts\">")
    for plf in tree:
        if plf.data.transfer_aborted:
            show_noteworthy_line(plf, comn)
    print("</div>")
    # flow with drain=true
    print("<a href=\"javascript:toggle_node('noteworthy_drain')\">%s%s</a> Flow with 'drain' set: %d<br>" %
          (text.lozenge(), text.nbsp(), n_drain))
    print(" <div width=\"100%%\"; "
          "style=\"display:none; font-weight: normal; margin-bottom: 2px; margin-left: 10px\" "
          "id=\"noteworthy_drain\">")
    for plf in tree:
        if plf.data.flow_drain:
            show_noteworthy_line(plf, comn)
    print("</div>")
    # probable unsettled transfers
    print("<a href=\"javascript:toggle_node('noteworthy_unsettled')\">%s%s</a> Probable unsettled transfers: %d<br>" %
          (text.lozenge(), text.nbsp(), n_unsettled))
    print(" <div width=\"100%%\"; "
          "style=\"display:none; font-weight: normal; margin-bottom: 2px; margin-left: 10px\" "
          "id=\"noteworthy_unsettled\">")
    for plf in tree:
        if common.transfer_is_possibly_unsettled(plf) and not plf.data.no_parent_link:
            show_noteworthy_line(plf, comn)
    print("</div>")
    # possible unsettled transfers
    print("<a href=\"javascript:toggle_node('noteworthy_unsettled_qm')\">%s%s</a> Possible unsettled transfers: %d<br>" %
          (text.lozenge(), text.nbsp(), n_unsettled_no_parent))
    print(" <div width=\"100%%\"; "
          "style=\"display:none; font-weight: normal; margin-bottom: 2px; margin-left: 10px\" "
          "id=\"noteworthy_unsettled_qm\">")
    for plf in tree:
        if common.transfer_is_possibly_unsettled(plf) and plf.data.no_parent_link:
            show_noteworthy_line(plf, comn)
    print("</div>")
    print("<hr>")

    # the proton log lines
    # log lines in         f_A_116
    # log line details in  f_A_116_d
    print("<a name=\"c_logdata\"></a>")
    print("<h3>Log data</h3>")
    for plf in tree:
        l_dict = plf.data.described_type.dict
        print("<div width=\"100%%\" style=\"display:block  margin-bottom: 2px\" id=\"%s\">" % plf.fid)
        print("<a name=\"%s\"></a>" % plf.fid)
        detailname = plf.fid + "_d"  # type: str
        loz = "<a href=\"javascript:toggle_node('%s')\">%s%s</a>" % (detailname, text.lozenge(), text.nbsp())
        rtr = plf.router
        rid = comn.router_display_names[rtr.log_index]

        peerconnid = "%s" % comn.conn_peers_connid.get(plf.data.conn_id, "")
        peer = rtr.conn_peer_display.get(plf.data.conn_id, "")  # peer container id
        print(loz, plf.datetime, ("%s#%d" % (plf.prefixi, plf.lineno)), rid, ("[%s]" % plf.data.conn_id),
              plf.data.direction, ("[%s]" % peerconnid), peer,
              plf.data.web_show_str, plf.data.disposition_display, "<br>")
        print(" <div width=\"100%%\"; "
              "style=\"display:none; font-weight: normal; margin-bottom: 2px; margin-left: 10px\" "
              "id=\"%s\">" %
              detailname)
        for key in sorted(common.dict_iterkeys(l_dict)):
            val = l_dict[key]
            print("%s : %s <br>" % (key, common.html_escape(str(val))))
        if plf.data.name == "transfer":
            print("Header and annotations : %s <br>" % plf.data.transfer_hdr_annos)
        print("</div>")
        print("</div>")
    print("<hr>")

    # data traversing network
    print("<a name=\"c_messageprogress\"></a>")
    print("<h3>Message progress</h3>")
    if not comn.args.skip_msg_progress:
      for i in range(0, comn.shorteners.short_data_names.len()):
        sname = comn.shorteners.short_data_names.shortname(i)
        size = 0
        for plf in comn.shorteners.short_data_names.customers(sname):
            size = plf.data.transfer_size
            break
        print("<a name=\"%s\"></a> <h4>%s (%s)" % (sname, sname, size))
        print(" <span> <a href=\"javascript:toggle_node('%s')\"> %s</a>" % ("data_" + sname, text.lozenge()))
        print(" <div width=\"100%%\"; style=\"display:none; font-weight: normal; margin-bottom: 2px\" id=\"%s\">" %
              ("data_" + sname))
        print(" ", comn.shorteners.short_data_names.longname(i, True))
        print("</div> </span>")
        print("</h4>")
        print("<table>")
        print(
            "<tr><th>Src</th> <th>Time</th> <th>Router</th> <th>ConnId</th> <th>Dir</th> <th>ConnId</th> <th>Peer</th> "
            "<th>T delta</th> <th>T elapsed</th><th>Settlement</th><th>S elapsed</th></tr>")
        t0 = None
        tlast = None
        for plf in comn.shorteners.short_data_names.customers(sname):
            if t0 is None:
                t0 = plf.datetime
                tlast = plf.datetime
                delta = "0.000000"
                epsed = "0.000000"
            else:
                delta = time_offset(plf.datetime, tlast)
                epsed = time_offset(plf.datetime, t0)
                tlast = plf.datetime
            sepsed = ""
            if plf.data.final_disposition is not None:
                sepsed = time_offset(plf.data.final_disposition.datetime, t0)
            rid = plf.router.iname
            peerconnid = "%s" % comn.conn_peers_connid.get(plf.data.conn_id, "")
            peer = plf.router.conn_peer_display.get(plf.data.conn_id, "")  # peer container id
            print("<tr><td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> "
                  "<td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> </tr>" %
                  (plf.adverbl_link_to(), plf.datetime, rid, plf.data.conn_id, plf.data.direction,
                   peerconnid, peer, delta, epsed,
                   plf.data.disposition_display, sepsed))
        print("</table>")

    print("<hr>")

    # link names traversing network
    print("<a name=\"c_linkprogress\"></a>")
    print("<h3>Link name propagation</h3>")
    for i in range(0, comn.shorteners.short_link_names.len()):
        if comn.shorteners.short_link_names.len() == 0:
            break
        sname = comn.shorteners.short_link_names.prefixname(i)
        print("<a name=\"%s\"></a> <h4>%s" % (sname, sname))
        print(" <span> <div width=\"100%%\"; style=\"display:block; font-weight: normal; margin-bottom: 2px\" >")
        print(comn.shorteners.short_link_names.longname(i, True))
        print("</div> </span>")
        print("</h4>")
        print("<table>")
        print("<tr><th>src</th> <th>Time</th> <th>Router</th> <th>ConnId</th> <th>Dir</th> <th>ConnId> <th>Peer</th> "
              "<th>T delta</th> <th>T elapsed</th></tr>")
        t0 = None
        tlast = None
        for plf in comn.shorteners.short_link_names.customers(sname):
            if t0 is None:
                t0 = plf.datetime
                delta = "0.000000"
                epsed = "0.000000"
            else:
                delta = time_offset(plf.datetime, tlast)
                epsed = time_offset(plf.datetime, t0)
            tlast = plf.datetime
            rid = plf.router.iname
            peerconnid = "%s" % comn.conn_peers_connid.get(plf.data.conn_id, "")
            peer = plf.router.conn_peer_display.get(plf.data.conn_id, "")  # peer container id
            print("<tr><td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> "
                  "<td>%s</td> <td>%s</td> <td>%s</td></tr>" %
                  (plf.adverbl_link_to(), plf.datetime, rid, plf.data.conn_id, plf.data.direction, peerconnid, peer,
                   delta, epsed))
        print("</table>")

    print("<hr>")

    # short data index
    print("<a name=\"c_rtrdump\"></a>")
    comn.shorteners.short_rtr_names.htmlDump(False)
    print("<hr>")

    print("<a name=\"c_peerdump\"></a>")
    comn.shorteners.short_peer_names.htmlDump(False)
    print("<hr>")

    print("<a name=\"c_linkdump\"></a>")
    comn.shorteners.short_link_names.htmlDump(True)
    print("<hr>")

    print("<a name=\"c_msgdump\"></a>")
    comn.shorteners.short_data_names.htmlDump(True)
    print("<hr>")

    # link state info
    # merge link state and restart records into single time based list
    cl = []
    for rtrlist in comn.routers:
        for rtr in rtrlist:
            rid = rtr.container_name
            cl.append(common.RestartRec(rtr.iname, rtr, "restart", rtr.restart_rec.datetime))
    for plf in ls_tree:
        if "costs" in plf.line:
            cl.append(common.RestartRec("ls", plf, "ls", plf.datetime))
    cl = sorted(cl, key=lambda lfl: lfl.datetime)

    # create a map of lists for each router
    # the list holds the name of other routers for which the router publishes a cost
    costs_pub = {}
    for i in range(0, comn.n_logs):
        costs_pub[comn.router_ids[i]] = []

    # cur_costs is a 2D array of costs used to tell when cost calcs have stabilized
    # Each incoming LS cost line replaces a row in this table
    # cur_costs tracks only interior routers
    interior_rtrs = []
    for rtrs in comn.routers:
        if rtrs[0].is_interior():
            interior_rtrs.append(rtrs[0].container_name)

    PEER_COST_REBOOT = -1
    PEER_COST_ABSENT = 0
    def new_costs_row(val):
        """
        return a costs row.
        :param val: -1 when router reboots, 0 when router log line processed
        :return:
        """
        res = {}
        for rtr in interior_rtrs:
            res[rtr] = val
        return res

    cur_costs = {}
    for rtr in interior_rtrs:
        cur_costs[rtr] = new_costs_row(PEER_COST_REBOOT)

    print("<a name=\"c_ls\"></a>")
    print("<h3>Routing link state</h3>")
    print("<h4>Link state costs</h4>")
    print("<table>")
    print("<tr><th>Time</th> <th>Router</th>")
    for i in range(0, comn.n_logs):
        print("<th>%s</th>" % common.log_letter_of(i))
    print("</tr>")
    for c in cl:
        if c.event == "ls":
            # link state computed costs and router reachability
            plf = c.router # cruel overload here: router is a parsed line not a router
            # Processing: Computed costs: {u'A': 1, u'C': 51L, u'B': 101L}
            print("<tr><td>%s</td> <td>%s</td>" % (plf.datetime, ("%s#%d" % (plf.router.iname, plf.lineno))))
            try:
                line = plf.line
                sti = line.find("{")
                line = line[sti:]
                l_dict = ast.literal_eval(line)
                costs_row = new_costs_row(PEER_COST_ABSENT)
                for i in range(0, comn.n_logs):
                    if len(comn.routers[i]) > 0:
                        tst_name = comn.routers[i][0].container_name
                        if tst_name in l_dict:
                            val = l_dict[tst_name]
                            costs_row[tst_name] = val
                        elif i == plf.router.log_index:
                            val = text.nbsp()
                        else:
                            val = "<span style=\"background-color:orange\">%s</span>" % (text.nbsp() * 2)
                    else:
                        val = "<span style=\"background-color:orange\">%s</span>" % (text.nbsp() * 2)
                    print("<td>%s</td>" % val)
                # track costs published when there is no column to put the number
                tgts = costs_pub[c.router.router.container_name]
                for k, v in common.dict_iteritems(l_dict):
                    if k not in comn.router_ids:
                        if k not in tgts:
                            tgts.append(k)  # this cost went unreported
                # update this router's cost view in running table
                if plf.router.is_interior():
                    cur_costs[plf.router.container_name] = costs_row
            except:
                pass
            print("</tr>")
            # if the costs are stable across all routers then put an indicator in table
            costs_stable = True
            for c_rtr in interior_rtrs:
                for r_rtr in interior_rtrs:
                    if r_rtr != c_rtr \
                            and (cur_costs[r_rtr][c_rtr] != cur_costs[c_rtr][r_rtr] \
                            or cur_costs[c_rtr][r_rtr] <= PEER_COST_ABSENT):
                        costs_stable = False
                        break
                if not costs_stable:
                    break
            if costs_stable:
                print("<tr><td><span style=\"background-color:green\">stable</span></td></tr>")
        else:
            # restart
            print("<tr><td>%s</td> <td>%s</td>" % (c.datetime, ("%s restart" % (c.router.iname))))
            for i in range(0, comn.n_logs):
                color = "green" if i == c.router.log_index else "orange"
                print("<td><span style=\"background-color:%s\">%s</span></td>" % (color, text.nbsp() * 2))
            print("</tr>")
            if c.router.is_interior():
                cur_costs[c.router.container_name] = new_costs_row(PEER_COST_REBOOT)
    print("</table>")
    print("<br>")

    # maybe display cost declarations that were not displayed
    costs_clean = True
    for k, v in common.dict_iteritems(costs_pub):
        if len(v) > 0:
            costs_clean = False
            break
    if not costs_clean:
        print("<h4>Router costs declared in logs but not displayed in Link state cost table</h4>")
        print("<table>")
        print("<tr><th>Router</th><Peers whose logs are absent</th></tr>")
        for k, v in common.dict_iteritems(costs_pub):
            if len(v) > 0:
                print("<tr><td>%s</td><td>%s</td></tr>" % (k, str(v)))
        print("</table>")
        print("<br>")

    print("<a href=\"javascript:toggle_node('ls_costs')\">%s%s</a> Link state costs data<br>" %
          (text.lozenge(), text.nbsp()))
    print(" <div width=\"100%%\"; "
          "style=\"display:none; font-weight: normal; margin-bottom: 2px; margin-left: 10px\" "
          "id=\"ls_costs\">")
    print("<table>")
    print("<tr><th>Time</th> <th>Router</th> <th>Name</th> <th>Log</th></tr>")
    for plf in ls_tree:
        if "costs" in plf.line:
            print("<tr><td>%s</td> <td>%s</td>" % (plf.datetime, ("%s#%d" % (plf.router.iname, plf.lineno))))
            print("<td>%s</td>" % plf.router.container_name)
            print("<td>%s</td></tr>" % plf.line)
    print("</table>")
    print("</div>")

    print("<hr>")

    print("</body>")
コード例 #13
0
ファイル: log_splitter.py プロジェクト: apache/qpid-dispatch
    def write_subfiles(self):
        # Q: Where to put the generated files? A: odir
        odir = self.odir()
        odirs = ['dummy'] # dirs indexed by log of n-lines

        os.makedirs(odir)
        for i in range(1, self.hist_max):
            nrange = ("10e%d" % (i))
            ndir = os.path.join(odir, nrange)
            os.makedirs(ndir)
            odirs.append(ndir)

        for k, c in dict_iteritems(self.connections):
            cdir = odirs[self.log_of(len(c.lines))]
            opath = os.path.join(cdir, (c.disp_name() + ".log"))
            with open(opath, 'w') as f:
                for l in c.lines:
                    f.write(l)

        xfer0 = 0
        for rc in self.conns_by_size_transfer:
            if rc.transfers == 0:
                xfer0 += 1
        print("<a name=\"c_conn_xfersize\"></a>")
        print("<h3>Connections by transfer count (N=%d)</h3>" % (len(self.conns_by_size_transfer) - xfer0))
        print("<table>")
        n = 1
        print("<tr><th>N</th><th>Connection</th> <th>Transfers</th> <th>Log lines</th> <th>Type</th> <th>AMQP detail<th></tr>")
        for rc in self.conns_by_size_transfer:
            if rc.transfers > 0:
                print("<tr><td>%d</td><td><a href=\"%s/%s\">%s</a></td> <td>%d</td> <td>%d</td> <td>%s</td> <td>%s</td></tr>" %
                      (n, rc.logfile.odir(), rc.path_name, rc.disp_name(), rc.transfers, len(rc.lines),
                       rc.peer_type, common.html_escape(rc.peer_open)))
                n += 1
        print("</table>")
        print("<hr>")

        print("<a name=\"c_conn_xfer0\"></a>")
        print("<h3>Connections with no AMQP transfers (N=%d)</h3>" % (xfer0))
        print("<table>")
        n = 1
        print("<tr><th>N</th><th>Connection</th> <th>Transfers</th> <th>Log lines</th> <th>Type</th> <th>AMQP detail<th></tr>")
        for rc in self.conns_by_size_transfer:
            if rc.transfers == 0:
                print("<tr><td>%d</td><td><a href=\"%s/%s\">%s</a></td> <td>%d</td> <td>%d</td> <td>%s</td> <td>%s</td></tr>" %
                      (n, rc.logfile.odir(), rc.path_name, rc.disp_name(), rc.transfers, len(rc.lines),
                       rc.peer_type, common.html_escape(rc.peer_open)))
                n += 1
        print("</table>")
        print("<hr>")

        print("<a name=\"c_conn_logsize\"></a>")
        print("<h3>Connections by total log line count (N=%d)</h3>" % (len(self.conns_by_size_loglines)))
        print("<table>")
        n = 1
        print("<tr><th>N</th><th>Connection</th> <th>Transfers</th> <th>Log lines</th> <th>Type</th> <th>AMQP detail<th></tr>")
        for rc in self.conns_by_size_loglines:
            print("<tr><td>%d</td><td><a href=\"%s/%s\">%s</a></td> <td>%d</td> <td>%d</td> <td>%s</td> <td>%s</td></tr>" %
                  (n, rc.logfile.odir(), rc.path_name, rc.disp_name(), rc.transfers, len(rc.lines),
                   rc.peer_type, common.html_escape(rc.peer_open)))
            n += 1
        print("</table>")
        print("<hr>")
コード例 #14
0
ファイル: log_splitter.py プロジェクト: apache/qpid-dispatch
    def summarize_connections(self):
        # sort connections based on transfer count and on n log lines
        self.conns_by_size_transfer = self.sort_sizes(lambda x: x.transfers, lambda x: len(x.lines))
        self.conns_by_size_loglines = self.sort_sizes(lambda x: len(x.lines), lambda x: x.transfers)

        # compute log_n and file name facts for all connections
        for k, v in dict_iteritems(self.connections):
            v.log_n_lines = self.log_of(len(v.lines))
            v.generate_paths()

        # Write the web doc to stdout
        print ("""<!DOCTYPE html>
<html>
<head>
<title>%s qpid-dispatch log split</title>

<style>
    * { 
    font-family: sans-serif; 
}
table {
    border-collapse: collapse;
}
table, td, th {
    border: 1px solid black;
    padding: 3px;
}
</style>
<script src="http://ajax.googleapis.com/ajax/libs/dojo/1.4/dojo/dojo.xd.js" type="text/javascript"></script>
<!-- <script src="http://ajax.googleapis.com/ajax/libs/dojo/1.4/dojo/dojo.xd.js" type="text/javascript"></script> -->
<script type="text/javascript">
function node_is_visible(node)
{
  if(dojo.isString(node))
    node = dojo.byId(node);
  if(!node) 
    return false;
  return node.style.display == "block";
}
function set_node(node, str)
{
  if(dojo.isString(node))
    node = dojo.byId(node);
  if(!node) return;
  node.style.display = str;
}
function toggle_node(node)
{
  if(dojo.isString(node))
    node = dojo.byId(node);
  if(!node) return;
  set_node(node, (node_is_visible(node)) ? 'none' : 'block');
}
function hide_node(node)
{
  set_node(node, 'none');
}
function show_node(node)
{
  set_node(node, 'block');
}

""" % self.log_fn)

        print("</script>")
        print("</head>")
        print("<body>")
        print("""
<h3>Contents</h3>
<table>
<tr> <th>Section</th>                                                     <th>Description</th> </tr>
<tr><td><a href=\"#c_summary\"        >Summary</a></td>                   <td>Summary</td></tr>
<tr><td><a href=\"#c_restarts\"       >Router restarts</a></td>           <td>Router reboot records</td></tr>
<tr><td><a href=\"#c_router_conn\"    >Interrouter connections</a></td>   <td>Probable interrouter connections</td></tr>
<tr><td><a href=\"#c_broker_conn\"    >Broker connections</a></td>        <td>Probable broker connections</td></tr>
<tr><td><a href=\"#c_errors\"         >AMQP errors</a></td>               <td>AMQP errors</td></tr>
<tr><td><a href=\"#c_conn_xfersize\"  >Conn by N transfers</a></td>       <td>Connections sorted by transfer log count</td></tr>
<tr><td><a href=\"#c_conn_xfer0\"     >Conn with no transfers</a></td>    <td>Connections with no transfers</td></tr>
<tr><td><a href=\"#c_conn_logsize\"   >Conn by N log lines</a></td>       <td>Connections sorted by total log line count</td></tr>
<tr><td><a href=\"#c_addresses\"      >Addresses</a></td>                 <td>AMQP address usage</td></tr>
</table>
<hr>
""")
        print("<a name=\"c_summary\"></a>")
        print("<table>")
        print("<tr><th>Statistic</th>          <th>Value</th></tr>")
        print("<tr><td>File</td>               <td>%s</td></tr>" % self.log_fn)
        print("<tr><td>Router starts</td>      <td>%s</td></tr>" % str(self.instance))
        print("<tr><td>Connections</td>        <td>%s</td></tr>" % str(len(self.connections)))
        print("<tr><td>Router connections</td> <td>%s</td></tr>" % str(len(self.router_connections)))
        print("<tr><td>AMQP log lines</td>     <td>%s</td></tr>" % str(self.amqp_lines))
        print("<tr><td>AMQP errors</td>        <td>%s</td></tr>" % str(len(self.errors)))
        print("<tr><td>AMQP transfers</td>     <td>%s</td></tr>" % str(self.transfers))
        print("<tr><td>AMQP attaches</td>     <td>%s</td></tr>" % str(self.attaches))
        print("</table>")
        print("<hr>")

        # Restarts
        print("<a name=\"c_restarts\"></a>")
        print("<h3>Restarts</h3>")
        for i in range(1, (self.instance + 1)):
            rr = self.restarts[i-1]
            print("(%d) - %s<br>" % (i, rr), end='')
        print("<hr>")

        # interrouter connections
        print("<a name=\"c_router_conn\"></a>")
        print("<h3>Probable inter-router connections (N=%d)</h3>" % (len(self.router_connections)))
        print("<table>")
        print("<tr><th>Connection</th> <th>Transfers</th> <th>Log lines</th> <th>AMQP Open<th></tr>")
        for rc in self.router_connections:
            print("<tr><td><a href=\"%s/%s\">%s</a></td><td>%d</td><td>%d</td><td>%s</td></tr>" %
                  (rc.logfile.odir(), rc.path_name, rc.disp_name(), rc.transfers, len(rc.lines),
                   common.html_escape(rc.peer_open)))
        print("</table>")
        print("<hr>")

        # broker connections
        print("<a name=\"c_broker_conn\"></a>")
        print("<h3>Probable broker connections (N=%d)</h3>" % (len(self.broker_connections)))
        print("<table>")
        print("<tr><th>Connection</th> <th>Transfers</th> <th>Log lines</th> <th>AMQP Open<th></tr>")
        for rc in self.broker_connections:
            print("<tr><td><a href=\"%s/%s\">%s</a></td><td>%d</td><td>%d</td><td>%s</td></tr>" %
                  (rc.logfile.odir(), rc.path_name, rc.disp_name(), rc.transfers, len(rc.lines),
                   common.html_escape(rc.peer_open)))
        print("</table>")
        print("<hr>")

        ## histogram
        #for cursize in self.sizelist:
        #    self.histogram[self.log_of(cursize)] += len(self.sizemap[str(cursize)])
        #print()
        #print("Log lines per connection distribution")
        #for i in range(1, self.hist_max):
        #    print("N <  10e%d : %d" %(i, self.histogram[i]))
        #print("N >= 10e%d : %d" % ((self.hist_max - 1), self.histogram[self.hist_max]))

        # errors
        print("<a name=\"c_errors\"></a>")
        print("<h3>AMQP errors (N=%d)</h3>" % (len(self.errors)))
        print("<table>")
        print("<tr><th>N</th> <th>AMQP error</th></tr>")
        for i in range(len(self.errors)):
            print("<tr><td>%d</td> <td>%s</td></tr>" % (i, common.html_escape(self.errors[i].strip())))
        print("</table>")
        print("<hr>")
コード例 #15
0
ファイル: rst2post.py プロジェクト: koder-ua/rst2blogger
 def write(self, text, esc_all=False):
     self.write_raw(html_escape(text))
コード例 #16
0
ファイル: parser.py プロジェクト: ctron/qpid-dispatch
    def __init__(self, _log_index, _instance, _lineno, _line, _comn, _router, opaque=None):
        """
        Process a naked qpid-dispatch log line
        A log line looks like this:
          2018-07-20 10:58:40.179187 -0400 SERVER (trace) [2]:0 -> @begin(17) [next-outgoing-id=0, incoming-window=2147483647, outgoing-window=2147483647] (/home/chug/git/qpid-dispatch/src/server.c:106)
        The process is:
         1. If the line ends with a filename:fileline then strip that away
         2. Peel off the leading time of day and put that into data.datetime.
            Lines with no datetime are presumed start-of-epoch.
         3. Find (SERVER) or (POLICY). If absent then raise to reject message.
         4. If connection number in square brackets '[2]' is missing then raise.
         5. Extract connection number; save in data.conn_num
         6. Create decorated data.conn_id "A0_2"
         7. Extract data.channel if present. Raise if malformed.
         8. Create a web_show_str for lines that may not parse any further. Like policy lines.
         9. Extract the direction arrows

        The log line is now reduced to a described type:
          @describedtypename(num) [key=val [, key=val ...]]
            except for transfers that have the funky transfer data at end.

        :param _log_index:   The router prefix index 0 for A, 1 for B, ...
        :param _instance     The router instance
        :param _lineno:
        :param _line:
        :param _comn:
        :param _router:
        """
        if not (ParsedLogLine.server_trace_key in _line or
                ParsedLogLine.protocol_trace_key in _line or
                (ParsedLogLine.policy_trace_key in _line and "lookup_user:"******"Line is not a candidate for parsing")
        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
        self.comn = _comn
        self.router = _router
        self.opaque = opaque
        self.prefixi = common.log_letter_of(self.index) + str(self.instance)  # prefix+instance A0
        self.fid = "f_" + self.prefixi + "_" + str(self.lineno)  # frame id A0_100
        self.shorteners = _comn.shorteners  # name shorteners

        self.line = _line  # working line chopped, trimmed

        self.data = LogLineData()  # parsed line fact store

        # strip optional trailing file:line field
        self.line = self.line.rstrip()
        hasFileLine = False
        if self.line.endswith(')'):
            idxOP = self.line.rfind('(')
            idxColon = self.line.rfind(':')
            if idxOP != -1 and idxColon != -1:
                if idxColon > idxOP:
                    lNumStr = self.line[(idxColon + 1): (-1)]
                    try:
                        lnum = int(lNumStr)
                        hasFileLine = True
                    except:
                        pass
        if hasFileLine:
            self.line = self.line[:self.line.rfind('(')].rstrip()

        # Handle optional timestamp
        # This whole project is brain dead without a timestamp. Just sayin'.
        self.datetime = None
        try:
            self.datetime = datetime.strptime(self.line[:26], '%Y-%m-%d %H:%M:%S.%f')
        except:
            # old routers flub the timestamp and don't print leading zero in uS time
            # 2018-11-18 11:31:08.269 should be 2018-11-18 11:31:08.000269
            td = self.line[:26]
            parts = td.split('.')
            us = parts[1]
            parts_us = us.split(' ')
            if len(parts_us[0]) < 6:
                parts_us[0] = '0' * (6 - len(parts_us[0])) + parts_us[0]
            parts[1] = ' '.join(parts_us)
            td = '.'.join(parts)
            try:
                self.datetime = datetime.strptime(td[:26], '%Y-%m-%d %H:%M:%S.%f')
            except:
                self.datetime = datetime(1970, 1, 1)

        # Apply time-of-day filters
        if self.datetime is not None:
            if self.comn.args.time_start is not None:
                if self.datetime < self.comn.args.time_start:
                    raise ValueError("Line too early outside time-of-day limits")
            if self.comn.args.time_end is not None:
                if self.datetime > self.comn.args.time_end:
                    raise ValueError("Line too late outside time-of-day limits")

        # Pull out scraper literal logs
        sti = self.line.find(self.scraper_key)
        if sti > 0:
            # strip datetime and show literal string
            sti += len("SCRAPER")
            self.data.is_scraper = True
            self.data.web_show_str = ("<strong>SCRAPER</strong> %s" % common.html_escape(self.line[sti:]))
            stcp = self.line[sti:].find(')') # close paren after log level
            if stcp <  0:
                stcp = 0
            self.data.sdorg_str = self.line[sti + stcp + 1:]
            return

        # extract connection number
        sti = self.line.find(self.server_trace_key)
        if sti < 0:
            sti = self.line.find(self.protocol_trace_key)
            if sti < 0:
                sti = self.line.find(self.policy_trace_key)
                if sti < 0:
                    sti = self.line.find(self.server_info_key)
                    if sti < 0:
                        sti = self.line.find(self.router_ls_key)
                        if sti < 0:
                            raise ValueError("Log keyword/level not found in line %s" % (self.line))
                        else:
                            self.line = self.line[sti + len(self.router_ls_key):]
                            self.data.is_router_ls = True
                            # this has no relationship to AMQP log lines
                            return
                    else:
                        self.line = self.line[sti + len(self.server_info_key):]
                        self.data.is_server_info = True
                else:
                    self.line = self.line[sti + len(self.policy_trace_key):]
                    self.data.is_policy_trace = True
            else:
                self.line = self.line[sti + len(self.protocol_trace_key):]
        else:
            self.line = self.line[sti + len(self.server_trace_key):]
        ste = self.line.find(']')
        if ste < 0:
            print("Failed to parse line ", _lineno, " : ", _line)
            traceback.print_exc()
            raise ValueError("'%s' not found in line %s" % ("]", self.line))
        self.data.conn_num = self.line[:ste]
        if self.data.conn_num.startswith("C"):
            self.data.conn_num = self.data.conn_num[1:]
        self.line = self.line[ste + 1:]

        # create decorated connection id
        self.data.conn_id = self.prefixi + "_" + self.data.conn_num

        # get the session (channel) number
        if self.line.startswith(':'):
            self.line = self.line[1:]
        if self.line.startswith(self.proton_frame_key):
            self.line = self.line[len(self.proton_frame_key):]

        sti = self.line.find(' ')
        if sti < 0:
            raise ValueError("space not found after channel number at head of line %s" % (self.line))
        if sti > 0:
            self.data.channel = self.line[:sti]
        self.line = self.line[sti + 1:]
        self.line = self.line.lstrip()

        # cover for traces that don't get any better
        self.data.web_show_str = ("<strong>%s</strong>" % self.line)

        # policy lines have no direction and described type fields
        if self.data.is_policy_trace or self.data.is_server_info:
            return

        # direction
        if self.line.startswith('<') or self.line.startswith('-'):
            self.data.direction = self.line[:2]
            self.line = self.line[3:]
            self.data.web_show_str = ("<strong>%s</strong>" % self.line)

        # The log line is now reduced to a described type:
        #  @describedtypename(num) [key=val [, key=val ...]]
        # extract descriptor name
        dname = self.line.split()[0]
        self.line = self.line[(len(dname) + 1):]

        # Dispose of the transfer data
        if dname == self.transfer_key:
            # Look for the '] (NNN) "' that separates the described type fields
            # from the '(size) "data"'. Stick the required '(size) data' into
            # data.transfer_data and delete it from the line.
            rz = re.compile(r'\] \(\d+\) \"').search(self.line)
            # aborted transfers may or may not have size/data in the log line
            if rz is not None and len(rz.regs) > 0:
                splitSt, splitTo = rz.regs[0]
                self.data.transfer_size = self.line[splitSt + 3: splitTo - 3]
                self.data.transfer_data = self.line[splitTo - 1:]  # discard (NNN) size field
                self.line = self.line[: splitSt + 1]
                # try to isolate the bare message
                sti = self.data.transfer_data.find(r"\x00Ss")
                if sti > 0:
                    self.data.transfer_hdr_annos = self.data.transfer_data[:sti]
                    self.data.transfer_bare = self.data.transfer_data[sti:]
                else:
                    self.data.transfer_hdr_annos = ''
                    self.data.transfer_bare = self.data.transfer_data
            else:
                self.data.transfer_size = "0"
                self.data.transfer_data = "(none)"

        if DescribedType.is_dtype_name(dname):
            self.data.described_type.parse_dtype_line(dname, self.line)
            # data fron incoming line is now parsed out into facts in .data
            # Now cook the data to get useful displays
            self.extract_facts()