Repository: qpid-dispatch Updated Branches: refs/heads/master bb4769aec -> cf2431622
DISPATCH-553 - From Mick Goulish - Added counters for log source X level. This closes #115. Project: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/repo Commit: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/commit/cf243162 Tree: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/tree/cf243162 Diff: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/diff/cf243162 Branch: refs/heads/master Commit: cf2431622ac1acf44f22b7c01f2168274e211d2a Parents: bb4769a Author: Ted Ross <[email protected]> Authored: Wed Nov 23 11:58:28 2016 -0500 Committer: Ted Ross <[email protected]> Committed: Wed Nov 23 11:58:28 2016 -0500 ---------------------------------------------------------------------- python/qpid_dispatch/management/qdrouter.json | 35 +++++++++++ .../qpid_dispatch_internal/management/agent.py | 8 +++ src/log.c | 61 +++++++++++++++++++- tests/system_tests_qdmanage.py | 34 ++++++++++- 4 files changed, 136 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/cf243162/python/qpid_dispatch/management/qdrouter.json ---------------------------------------------------------------------- diff --git a/python/qpid_dispatch/management/qdrouter.json b/python/qpid_dispatch/management/qdrouter.json index 2bd21ac..53b171d 100644 --- a/python/qpid_dispatch/management/qdrouter.json +++ b/python/qpid_dispatch/management/qdrouter.json @@ -845,6 +845,41 @@ } }, + "logStats": { + "description": "histogram of the different severity-levels of events on the given log.", + "extends": "operationalEntity", + "attributes": { + "traceCount": { + "description": "How many trace-level events have happened on this log.", + "type": "integer" + } , + "debugCount": { + "description": "How many debug-level events have happened on this log.", + "type": "integer" + } , + "infoCount": { + "description": "How many info-level events have happened on this log.", + "type": "integer" + } , + "noticeCount": { + "description": "How many notice-level events have happened on this log.", + "type": "integer" + } , + "warningCount": { + "description": "How many warning-level events have happened on this log.", + "type": "integer" + } , + "errorCount": { + "description": "How many error-level events have happened on this log.", + "type": "integer" + } , + "criticalCount": { + "description": "How many critical-level events have happened on this log.", + "type": "integer" + } + } + }, + "router.config.address": { "description": "Entity type for address configuration. This is used to configure the treatment of message-routed deliveries within a particular address-space. The configuration controls distribution and address phasing.", "extends": "configurationEntity", http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/cf243162/python/qpid_dispatch_internal/management/agent.py ---------------------------------------------------------------------- diff --git a/python/qpid_dispatch_internal/management/agent.py b/python/qpid_dispatch_internal/management/agent.py index 370dc36..7f50cb8 100644 --- a/python/qpid_dispatch_internal/management/agent.py +++ b/python/qpid_dispatch_internal/management/agent.py @@ -515,6 +515,14 @@ class ConnectionEntity(EntityAdapter): return super(ConnectionEntity, self).__str__().replace("Entity(", "ConnectionEntity(") +class LogStatsEntity(EntityAdapter): + def _identifier(self): + return self.attributes.get('identity') + + def __str__(self): + return super(LogStatsEntity, self).__str__().replace("Entity(", "LogStatsEntity(") + + class AllocatorEntity(EntityAdapter): def _identifier(self): return self.attributes.get('typeName') http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/cf243162/src/log.c ---------------------------------------------------------------------- diff --git a/src/log.c b/src/log.c index 3e5aca6..434115f 100644 --- a/src/log.c +++ b/src/log.c @@ -21,6 +21,7 @@ #include "log_private.h" #include "entity.h" +#include "entity_cache.h" #include "aprintf.h" #include <qpid/dispatch/ctools.h> #include <qpid/dispatch/dispatch.h> @@ -37,6 +38,8 @@ #define LOG_MAX (QD_LOG_TEXT_MAX+128) #define LIST_MAX 1000 +const char *QD_LOG_STATS_TYPE = "logStats"; + static qd_log_source_t *default_log_source=0; static qd_log_source_t *logging_log_source=0; @@ -149,6 +152,12 @@ static log_sink_t* log_sink_lh(const char* name) { } +typedef enum {DEFAULT, NONE, TRACE, DEBUG, INFO, NOTICE, WARNING, ERROR, CRITICAL, N_LEVELS} level_index_t; +#define MIN_VALID_LEVEL_INDEX TRACE +#define MAX_VALID_LEVEL_INDEX CRITICAL +#define N_LEVEL_INDICES (MAX_VALID_LEVEL_INDEX - MIN_VALID_LEVEL_INDEX + 1) +#define LEVEL_INDEX(LEVEL) ((LEVEL) - TRACE) + struct qd_log_source_t { DEQ_LINKS(qd_log_source_t); char *module; @@ -157,6 +166,7 @@ struct qd_log_source_t { int source; /* boolean or -1 means not set */ bool syslog; log_sink_t *sink; + uint64_t severity_histogram[N_LEVEL_INDICES]; }; DEQ_DECLARE(qd_log_source_t, qd_log_source_list_t); @@ -165,7 +175,6 @@ static sys_mutex_t *log_lock = 0; static sys_mutex_t *log_source_lock = 0; static qd_log_source_list_t source_list = {0}; -typedef enum {DEFAULT, NONE, TRACE, DEBUG, INFO, NOTICE, WARNING, ERROR, CRITICAL, N_LEVELS} level_index_t; typedef struct level_t { const char* name; @@ -215,6 +224,22 @@ static const level_t* level_for_name(const char *name, int len) { return &levels[i]; } +/* + Return -1 and set qd_error if not a valid bit. + Translate so that the min valid level index is 0. +*/ +static int level_index_for_bit(int bit) { + level_index_t i = MIN_VALID_LEVEL_INDEX; + while ( i <= MAX_VALID_LEVEL_INDEX ) { + if ( levels[i].bit == bit ) + return (int) (i - MIN_VALID_LEVEL_INDEX); + ++ i; + } + + qd_error(QD_ERROR_CONFIG, "'%d' is not a valid log level bit.", bit); + return -1; +} + /// Return the name of log level or 0 if not found. static const char* level_name(int level) { return (0 <= level && level < N_LEVELS) ? levels[level].name : NULL; @@ -304,6 +329,7 @@ static void qd_log_source_defaults(qd_log_source_t *log_source) { log_source->timestamp = -1; log_source->source = -1; log_source->sink = 0; + memset ( log_source->severity_histogram, 0, sizeof(uint64_t) * (N_LEVEL_INDICES) ); } /// Caller must hold the log_source_lock @@ -319,6 +345,7 @@ static qd_log_source_t *qd_log_source_lh(const char *module) strcpy(log_source->module, module); qd_log_source_defaults(log_source); DEQ_INSERT_TAIL(source_list, log_source); + qd_entity_cache_add(QD_LOG_STATS_TYPE, log_source); } return log_source; } @@ -355,6 +382,18 @@ bool qd_log_enabled(qd_log_source_t *source, qd_log_level_t level) { void qd_log_impl(qd_log_source_t *source, qd_log_level_t level, const char *file, int line, const char *fmt, ...) { + /*----------------------------------------------- + Count this log-event in this log's histogram + whether or not this log is currently enabled. + We can always decide not to look at it later, + based on its used/unused status. + -----------------------------------------------*/ + level_index_t level_index = level_index_for_bit(level); + if (level_index < 0) + qd_error_clear(); + else + source->severity_histogram[level_index]++; + if (!qd_log_enabled(source, level)) return; qd_log_entry_t *entry = new_qd_log_entry_t(); @@ -508,3 +547,23 @@ qd_error_t qd_log_entity(qd_entity_t *entity) { return qd_error_code(); } + + +qd_error_t qd_entity_refresh_logStats(qd_entity_t* entity, void *impl) +{ + qd_log_source_t *log = (qd_log_source_t*)impl; + char identity_str[TEXT_MAX]; + snprintf(identity_str, TEXT_MAX - 1,"logStats/%s", log->module); + + qd_entity_set_long(entity, "traceCount", log->severity_histogram[LEVEL_INDEX(TRACE)]); + qd_entity_set_long(entity, "debugCount", log->severity_histogram[LEVEL_INDEX(DEBUG)]); + qd_entity_set_long(entity, "infoCount", log->severity_histogram[LEVEL_INDEX(INFO)]); + qd_entity_set_long(entity, "noticeCount", log->severity_histogram[LEVEL_INDEX(NOTICE)]); + qd_entity_set_long(entity, "warningCount", log->severity_histogram[LEVEL_INDEX(WARNING)]); + qd_entity_set_long(entity, "errorCount", log->severity_histogram[LEVEL_INDEX(ERROR)]); + qd_entity_set_long(entity, "criticalCount", log->severity_histogram[LEVEL_INDEX(CRITICAL)]); + qd_entity_set_string(entity, "name", log->module); + qd_entity_set_string(entity, "identity", identity_str); + + return QD_ERROR_NONE; +} http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/cf243162/tests/system_tests_qdmanage.py ---------------------------------------------------------------------- diff --git a/tests/system_tests_qdmanage.py b/tests/system_tests_qdmanage.py index 346bd72..0c70e66 100644 --- a/tests/system_tests_qdmanage.py +++ b/tests/system_tests_qdmanage.py @@ -178,13 +178,45 @@ class QdmanageTest(TestCase): def test_get_types(self): out = json.loads(self.run_qdmanage("get-types")) - self.assertEqual(len(out), 27) + self.assertEqual(len(out), 28) def test_get_log(self): log = json.loads(self.run_qdmanage("get-log limit=1"))[0] self.assertEquals(['AGENT', 'trace'], log[0:2]) self.assertRegexpMatches(log[2], 'get-log') + def test_get_logstats(self): + query_command = 'QUERY --type=logStats' + logs = json.loads(self.run_qdmanage(query_command)) + # Each value returned by the above query should be + # a log, and each log should contain an entry for each + # log level. + log_levels = [ 'criticalCount', + 'debugCount', + 'errorCount', + 'infoCount', + 'noticeCount', + 'traceCount', + 'warningCount' + ] + n_log_levels = len ( log_levels ) + + good_logs = 0 + + for log_dict in logs: + log_levels_present = 0 + log_levels_missing = 0 + for log_level in log_levels: + if log_level in log_dict: + log_levels_present += 1 + else: + log_levels_missing += 1 + + if log_levels_present == n_log_levels: + good_logs += 1 + + self.assertEquals ( good_logs, len(logs) ) + def test_ssl(self): """Simple test for SSL connection. Note system_tests_qdstat has a more complete SSL test""" url = Url(self.router_1.addresses[1], scheme="amqps") --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
