You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by gm...@apache.org on 2019/11/08 17:53:17 UTC
[qpid-dispatch] branch master updated: DISPATCH-1439 - Added two
attributes to connection and one to router. 1. connection uptime - The
number of seconds the connection has been up 2. connection last delivery
seconds - The number of seconds since a delivery was sent on a connection
3. router uptime - the number of seconds since the router started
This is an automated email from the ASF dual-hosted git repository.
gmurthy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/qpid-dispatch.git
The following commit(s) were added to refs/heads/master by this push:
new bf6592f DISPATCH-1439 - Added two attributes to connection and one to router. 1. connection uptime - The number of seconds the connection has been up 2. connection last delivery seconds - The number of seconds since a delivery was sent on a connection 3. router uptime - the number of seconds since the router started
bf6592f is described below
commit bf6592ffbbe742ce52c8c780baf1c07299e62dec
Author: Ganesh Murthy <gm...@apache.org>
AuthorDate: Wed Nov 6 16:13:44 2019 -0500
DISPATCH-1439 - Added two attributes to connection and one to router.
1. connection uptime - The number of seconds the connection has been up
2. connection last delivery seconds - The number of seconds since a delivery was sent on a connection
3. router uptime - the number of seconds since the router started
---
docs/man/qdstat.8.adoc | 7 ++
python/qpid_dispatch/management/qdrouter.json | 19 ++++-
python/qpid_dispatch_internal/tools/display.py | 9 ++-
src/router_core/agent_connection.c | 16 ++++
src/router_core/agent_connection.h | 2 +-
src/router_core/agent_router.c | 6 ++
src/router_core/agent_router.h | 2 +-
src/router_core/connections.c | 1 +
src/router_core/core_link_endpoint.c | 3 +
src/router_core/forwarder.c | 2 +
src/router_core/router_core_private.h | 2 +
src/router_core/transfer.c | 2 +
tests/system_tests_one_router.py | 101 +++++++++++++++++++++++++
tests/system_tests_qdstat.py | 18 +++++
tools/qdstat.in | 33 ++++++++
15 files changed, 218 insertions(+), 5 deletions(-)
diff --git a/docs/man/qdstat.8.adoc b/docs/man/qdstat.8.adoc
index caaed43..9f9b57a 100644
--- a/docs/man/qdstat.8.adoc
+++ b/docs/man/qdstat.8.adoc
@@ -73,6 +73,13 @@ The authentication method and user ID of the connection's authenticated user.
tenant::
If the connection is to a listener using multi-tenancy, this column displays the tenant namespace for the connection.
+last dlv::
+Time since the last delivery arrived on this connection. Displayed in the days:hours:minutes:seconds format.
+
+uptime::
+Time this connection has been up. Displayed in the days:hours:minutes:seconds format.
+
+
qdstat -l
~~~~~~~~~
type::
diff --git a/python/qpid_dispatch/management/qdrouter.json b/python/qpid_dispatch/management/qdrouter.json
index c862d8b..79c98cf 100644
--- a/python/qpid_dispatch/management/qdrouter.json
+++ b/python/qpid_dispatch/management/qdrouter.json
@@ -609,7 +609,12 @@
"type": "integer",
"description": "Number of deliveries that were sent to the fallback destination due to the primary destination being unreachable.",
"graph": true
- }
+ },
+ "uptimeSeconds": {
+ "type": "integer",
+ "graph": true,
+ "description": "The number of seconds since the router was started."
+ }
}
},
"sslProfile": {
@@ -1772,10 +1777,20 @@
"description": "If multi-tenancy is on for this connection, the tenant space in effect",
"type": "string"
},
+ "uptimeSeconds": {
+ "type": "integer",
+ "graph": true,
+ "description": "The number of seconds since the connection was created."
+ },
"properties": {
"description": "Connection properties supplied by the peer.",
"type": "map"
- }
+ },
+ "lastDlvSeconds": {
+ "type": "integer",
+ "graph": true,
+ "description": "The number of seconds since a delivery was sent on this connection. Will display a - (dash) if no deliveries have been sent on the connection."
+ }
}
},
diff --git a/python/qpid_dispatch_internal/tools/display.py b/python/qpid_dispatch_internal/tools/display.py
index ead8077..2acb8b7 100644
--- a/python/qpid_dispatch_internal/tools/display.py
+++ b/python/qpid_dispatch_internal/tools/display.py
@@ -45,7 +45,14 @@ def Commas(value):
sval = left
def TimeLong(value):
- return strftime("%c", gmtime(value / 1000000000))
+ day = value // (24 * 3600)
+ time = value % (24 * 3600)
+ hour = time // 3600
+ time %= 3600
+ minutes = time // 60
+ time %= 60
+ seconds = time
+ return "%03d:%02d:%02d:%02d" % (day, hour, minutes, seconds)
def TimeShort(value):
return strftime("%X", gmtime(value / 1000000000))
diff --git a/src/router_core/agent_connection.c b/src/router_core/agent_connection.c
index 488e450..dc26768 100644
--- a/src/router_core/agent_connection.c
+++ b/src/router_core/agent_connection.c
@@ -43,6 +43,8 @@
#define QDR_CONNECTION_ACTIVE 18
#define QDR_CONNECTION_ADMIN_STATUS 19
#define QDR_CONNECTION_OPER_STATUS 20
+#define QDR_CONNECTION_UPTIME_SECONDS 21
+#define QDR_CONNECTION_LAST_DLV_SECONDS 22
const char * const QDR_CONNECTION_DIR_IN = "in";
const char * const QDR_CONNECTION_DIR_OUT = "out";
@@ -83,6 +85,9 @@ const char *qdr_connection_columns[] =
"active",
"adminStatus",
"operStatus",
+ "uptimeSeconds",
+ "lastDlvSeconds",
+
0};
const char *CONNECTION_TYPE = "org.apache.qpid.dispatch.connection";
@@ -240,6 +245,17 @@ static void qdr_connection_insert_column_CT(qdr_core_t *core, qdr_connection_t *
qd_compose_insert_string(body, text);
break;
+ case QDR_CONNECTION_UPTIME_SECONDS:
+ qd_compose_insert_uint(body, core->uptime_ticks - conn->conn_uptime);
+ break;
+
+ case QDR_CONNECTION_LAST_DLV_SECONDS:
+ if (conn->last_delivery_time==0)
+ qd_compose_insert_null(body);
+ else
+ qd_compose_insert_uint(body, core->uptime_ticks - conn->last_delivery_time);
+ break;
+
case QDR_CONNECTION_PROPERTIES: {
pn_data_t *data = conn->connection_info->connection_properties;
qd_compose_start_map(body);
diff --git a/src/router_core/agent_connection.h b/src/router_core/agent_connection.h
index 0b764b1..247aaf5 100644
--- a/src/router_core/agent_connection.h
+++ b/src/router_core/agent_connection.h
@@ -35,7 +35,7 @@ void qdra_connection_update_CT(qdr_core_t *core,
qdr_query_t *query,
qd_parsed_field_t *in_body);
-#define QDR_CONNECTION_COLUMN_COUNT 21
+#define QDR_CONNECTION_COLUMN_COUNT 23
const char *qdr_connection_columns[QDR_CONNECTION_COLUMN_COUNT + 1];
#endif
diff --git a/src/router_core/agent_router.c b/src/router_core/agent_router.c
index b726686..15c7720 100644
--- a/src/router_core/agent_router.c
+++ b/src/router_core/agent_router.c
@@ -54,6 +54,7 @@
#define QDR_ROUTER_DELIVERIES_EGRESS_ROUTE_CONTAINER 27
#define QDR_ROUTER_DELIVERIES_REDIRECTED 28
#define QDR_ROUTER_LINKS_BLOCKED 29
+#define QDR_ROUTER_UPTIME_SECONDS 30
const char *qdr_router_columns[] =
@@ -87,6 +88,7 @@ const char *qdr_router_columns[] =
"deliveriesEgressRouteContainer",
"deliveriesRedirectedToFallback",
"linksBlocked",
+ "uptimeSeconds",
0};
@@ -233,6 +235,10 @@ static void qdr_agent_write_column_CT(qd_composed_field_t *body, int col, qdr_co
qd_compose_insert_uint(body, core->links_blocked);
break;
+ case QDR_ROUTER_UPTIME_SECONDS:
+ qd_compose_insert_uint(body, core->uptime_ticks);
+ break;
+
default:
qd_compose_insert_null(body);
break;
diff --git a/src/router_core/agent_router.h b/src/router_core/agent_router.h
index 97452af..5246187 100644
--- a/src/router_core/agent_router.h
+++ b/src/router_core/agent_router.h
@@ -21,7 +21,7 @@
#include "router_core_private.h"
-#define QDR_ROUTER_COLUMN_COUNT 30
+#define QDR_ROUTER_COLUMN_COUNT 31
const char *qdr_router_columns[QDR_ROUTER_COLUMN_COUNT + 1];
diff --git a/src/router_core/connections.c b/src/router_core/connections.c
index 984a7c2..3594b7e 100644
--- a/src/router_core/connections.c
+++ b/src/router_core/connections.c
@@ -106,6 +106,7 @@ qdr_connection_t *qdr_connection_opened(qdr_core_t *core,
DEQ_INIT(conn->work_list);
conn->connection_info->role = conn->role;
conn->work_lock = sys_mutex();
+ conn->conn_uptime = core->uptime_ticks;
if (vhost) {
conn->tenant_space_len = strlen(vhost) + 1;
diff --git a/src/router_core/core_link_endpoint.c b/src/router_core/core_link_endpoint.c
index 268887d..e48b80e 100644
--- a/src/router_core/core_link_endpoint.c
+++ b/src/router_core/core_link_endpoint.c
@@ -133,6 +133,9 @@ qdr_delivery_t *qdrc_endpoint_delivery_CT(qdr_core_t *core, qdrc_endpoint_t *end
qdr_delivery_t *dlv = new_qdr_delivery_t();
uint64_t *tag = (uint64_t*) dlv->tag;
+ if (endpoint->link->conn)
+ endpoint->link->conn->last_delivery_time = core->uptime_ticks;
+
ZERO(dlv);
set_safe_ptr_qdr_link_t(endpoint->link, &dlv->link_sp);
dlv->msg = message;
diff --git a/src/router_core/forwarder.c b/src/router_core/forwarder.c
index b33772a..04575f3 100644
--- a/src/router_core/forwarder.c
+++ b/src/router_core/forwarder.c
@@ -116,6 +116,8 @@ qdr_delivery_t *qdr_forward_new_delivery_CT(qdr_core_t *core, qdr_delivery_t *in
{
qdr_delivery_t *out_dlv = new_qdr_delivery_t();
uint64_t *tag = (uint64_t*) out_dlv->tag;
+ if (link->conn)
+ link->conn->last_delivery_time = core->uptime_ticks;
ZERO(out_dlv);
set_safe_ptr_qdr_link_t(link, &out_dlv->link_sp);
diff --git a/src/router_core/router_core_private.h b/src/router_core/router_core_private.h
index 17256a5..4106db1 100644
--- a/src/router_core/router_core_private.h
+++ b/src/router_core/router_core_private.h
@@ -659,6 +659,8 @@ struct qdr_connection_t {
qdr_conn_admin_status_t admin_status;
qdr_error_t *error;
bool closed; // This bit is used in the case where a client is trying to force close this connection.
+ uint32_t conn_uptime; // Timestamp which can be used to calculate the number of seconds this connection has been up and running.
+ uint32_t last_delivery_time; // Timestamp which can be used to calculate the number of seconds since the last delivery arrived on this connection.
};
DEQ_DECLARE(qdr_connection_t, qdr_connection_list_t);
diff --git a/src/router_core/transfer.c b/src/router_core/transfer.c
index 175eba2..58ad85e 100644
--- a/src/router_core/transfer.c
+++ b/src/router_core/transfer.c
@@ -639,6 +639,8 @@ static void qdr_link_deliver_CT(qdr_core_t *core, qdr_action_t *action, bool dis
if (!link)
return;
+ if (link->conn)
+ link->conn->last_delivery_time = core->uptime_ticks;
//
// Record the ingress time so we can track the age of this delivery.
diff --git a/tests/system_tests_one_router.py b/tests/system_tests_one_router.py
index 1840229..5578e20 100644
--- a/tests/system_tests_one_router.py
+++ b/tests/system_tests_one_router.py
@@ -502,6 +502,11 @@ class OneRouterTest(TestCase):
test.run()
self.assertEqual(None, test.error)
+ def test_48_connection_uptime_last_dlv(self):
+ test = ConnectionUptimeLastDlvTest(self.address, "test_48")
+ test.run()
+ self.assertEqual(None, test.error)
+
class Entity(object):
def __init__(self, status_code, status_description, attrs):
@@ -2684,6 +2689,102 @@ class MulticastUnsettledNoReceiverTest(MessagingHandler):
Container(self).run()
+class UptimeLastDlvChecker(object):
+ def __init__(self, parent, lastDlv=None, uptime=0):
+ self.parent = parent
+ self.uptime = uptime
+ self.lastDlv = lastDlv
+ self.expected_num_connections = 2
+ self.num_connections = 0
+
+ def on_timer_task(self, event):
+ local_node = Node.connect(self.parent.address, timeout=TIMEOUT)
+ result = local_node.query('org.apache.qpid.dispatch.connection')
+ container_id_index = result.attribute_names.index('container')
+ uptime_seconds_index = result.attribute_names.index('uptimeSeconds')
+ last_dlv_seconds_index = result.attribute_names.index('lastDlvSeconds')
+
+ for res in result.results:
+ container_id = res[container_id_index]
+
+ # We only care if the container_id is "UPTIME-TEST"
+ if container_id == self.parent.container_id:
+ uptime_seconds = res[uptime_seconds_index]
+ if self.uptime != 0 and uptime_seconds < self.uptime:
+ self.parent.error = "The connection uptime should be greater than or equal to %d seconds but instead is %d seconds" % (self.uptime, uptime_seconds)
+ last_dlv_seconds = res[last_dlv_seconds_index]
+ if self.lastDlv == '-':
+ if last_dlv_seconds != self.lastDlv:
+ self.parent.error = "Expected lastDlvSeconds to be empty"
+ else:
+ if not last_dlv_seconds >= self.lastDlv:
+ self.parent.error = "Connection lastDeliverySeconds must be greater than or equal to $d but is %d" % (self.lastDlv, last_dlv_seconds)
+ else:
+ self.parent.success = True
+ self.num_connections += 1
+
+ if self.expected_num_connections != self.num_connections:
+ self.parent.error = "Number of client connections expected=%d, but got %d" % (self.expected_num_connections, self.num_connections)
+
+ self.parent.cancel_custom()
+
+
+class ConnectionUptimeLastDlvTest(MessagingHandler):
+ def __init__(self, address, dest):
+ super(ConnectionUptimeLastDlvTest, self).__init__()
+ self.timer = None
+ self.sender_conn = None
+ self.receiver_conn = None
+ self.address = address
+ self.sender = None
+ self.receiver = None
+ self.error = None
+ self.custom_timer = None
+ self.container_id = "UPTIME-TEST"
+ self.dest = dest
+ self.reactor = None
+ self.success = False
+
+ def cancel_custom(self):
+ self.custom_timer.cancel()
+ if self.error or self.success:
+ self.timer.cancel()
+ self.sender_conn.close()
+ self.receiver_conn.close()
+ else:
+ msg = Message(body=self.container_id)
+ self.sender.send(msg)
+
+ # We have now sent a message that the router must have sent to the
+ # receiver. We will wait for 2 seconds and once again check
+ # uptime and lastDlv
+ self.custom_timer = self.reactor.schedule(2, UptimeLastDlvChecker(self, uptime=7, lastDlv=2))
+
+ def timeout(self):
+ self.error = "Timeout Expired:, Test took too long to execute. "
+ self.sender_conn.close()
+ self.receiver_conn.close()
+
+ def on_start(self, event):
+ self.timer = event.reactor.schedule(TIMEOUT, Timeout(self))
+ self.sender_conn = event.container.connect(self.address)
+ self.receiver_conn = event.container.connect(self.address)
+
+ # Let's create a sender and receiver but not send any messages.
+ self.sender = event.container.create_sender(self.sender_conn, self.dest)
+ self.receiver = event.container.create_receiver(self.receiver_conn, self.dest)
+
+ # Execute a management query for connections after 5 seconds
+ # This will help us check the uptime and lastDlv time
+ # No deliveries were sent on any link yet, so the lastDlv must be "-"
+ self.reactor = event.reactor
+ self.custom_timer = event.reactor.schedule(5, UptimeLastDlvChecker(self, uptime=5, lastDlv=None))
+
+ def run(self):
+ container = Container(self)
+ container.container_id = self.container_id
+ container.run()
+
class AnonymousSenderNoRecvLargeMessagedTest(MessagingHandler):
def __init__(self, address):
super(AnonymousSenderNoRecvLargeMessagedTest, self).__init__(auto_accept=False)
diff --git a/tests/system_tests_qdstat.py b/tests/system_tests_qdstat.py
index 2147263..9bee375 100644
--- a/tests/system_tests_qdstat.py
+++ b/tests/system_tests_qdstat.py
@@ -109,6 +109,7 @@ class QdstatTest(system_test.TestCase):
self.assertTrue("Deliveries to Fallback" in outs)
self.assertTrue("Egress Count" in outs)
self.assertTrue("Ingress Count" in outs)
+ self.assertTrue("Uptime" in outs)
def test_address_priority(self):
out = self.run_qdstat(['--address'])
@@ -256,9 +257,26 @@ class QdstatTest(system_test.TestCase):
self.assertEqual(sender_addresses, COUNT)
self.assertEqual(receiver_addresses, COUNT)
+ # Test if there is a non-zero uptime for the router in the output of
+ # qdstat -g
+ non_zero_seconds = False
+ outs = self.run_qdstat(args=None)
+ parts = outs.split("\n")
+ for part in parts:
+ if "Uptime" in part:
+ uptime_parts = part.split(" ")
+ for uptime_part in uptime_parts:
+ if uptime_part.startswith("000"):
+ time_parts = uptime_part.split(":")
+ if int(time_parts[3]) > 0:
+ non_zero_seconds = True
+ self.assertTrue(non_zero_seconds)
+
c.close()
+
+
class QdstatLinkPriorityTest(system_test.TestCase):
"""Need 2 routers to get inter-router links for the link priority test"""
@classmethod
diff --git a/tools/qdstat.in b/tools/qdstat.in
index 267237f..e9bd2f5 100755
--- a/tools/qdstat.in
+++ b/tools/qdstat.in
@@ -200,6 +200,28 @@ class BusManager(Node):
if show_date_id:
self.display_datetime_router_id()
+ has_uptime = False
+ has_last_dlv = False
+
+ if objects:
+ first_conn = objects[0]
+ try:
+ lastDlvSeconds = first_conn.lastDlvSeconds
+ has_last_dlv = True
+ except:
+ pass
+ try:
+ uptime = first_conn.uptimeSeconds
+ has_uptime = True
+ except:
+ pass
+
+ # This is so that, this qdstat can be used against older routers without Python keyerrors
+ if has_last_dlv:
+ heads.append(Header("last dlv"))
+ if has_uptime:
+ heads.append(Header("uptime"))
+
for conn in objects:
row = []
row.append(conn.identity)
@@ -210,6 +232,13 @@ class BusManager(Node):
row.append(self.connSecurity(conn))
row.append(self.connAuth(conn))
row.append(self.noTrailingSlash(get(conn, 'tenant')))
+ if has_last_dlv:
+ if conn.lastDlvSeconds is None:
+ row.append('-')
+ else:
+ row.append(TimeLong(conn.lastDlvSeconds))
+ if has_uptime:
+ row.append(TimeLong(conn.uptimeSeconds))
rows.append(row)
title = "Connections"
dispRows = rows
@@ -291,6 +320,10 @@ class BusManager(Node):
rows.append(('Version', router.version))
rows.append(('Mode', router.mode))
rows.append(('Router Id', router.id))
+ try:
+ rows.append(('Uptime', TimeLong(router.uptimeSeconds)))
+ except:
+ pass
rows.append(('Area', router.area))
rows.append(('Link Routes', router.linkRouteCount))
rows.append(('Auto Links', router.autoLinkCount))
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org