Skip to content

Commit 20b361a

Browse files
authored
Merge pull request #7 from AATools/0.3
Update to v.0.3
2 parents 233af69 + aaac577 commit 20b361a

14 files changed

+564
-125
lines changed

README.md

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ The collected metrics can be explored in Prometheus or Grafana.
77

88
The metrics are collected using [mqsilist](https://www.ibm.com/support/knowledgecenter/en/SSMKHH_9.0.0/com.ibm.etools.mft.doc/an07250_.htm) command. So, you need to install `IBM Integration Bus`.
99

10-
Tested for IBM IB v9 and Python 2.6, 2.7, 3.6 on Linux.
10+
Tested for IBM IB v9 and v10 and Python 2.7, 3.6 on Linux.
1111

1212
## Collected metrics
1313

@@ -48,6 +48,31 @@ nohup python3 iib_metrics_client.py &
4848

4949
After that, you should set up your Prometheus server to collect metrics from Pushgateway (`http://<hostname>:9091/metrics`).
5050

51+
You can specify `host` and `port` for pushgateway and Integration Bus version via command-line arguments.
52+
53+
```bash
54+
python3 iib_metrics_client.py -h
55+
56+
usage: iib_metrics_client.py [-h] [--pghost [pushgatewayHost]] [--pgport [pushgatewayPort]] [--iibver [iibVersion]]
57+
58+
optional arguments:
59+
-h, --help show this help message and exit
60+
--pghost [pushgatewayHost]
61+
pushgateway host
62+
--pgport [pushgatewayPort]
63+
pushgateway port
64+
--iibver [iibVersion]
65+
IIB version: 9 or 10
66+
```
67+
68+
If argument is not set the default value is used.
69+
70+
| Command-line argument | Description | Default value |
71+
|:---|:---|:---|
72+
| `pghost` | Pushgateway host | Hostname on which client is started.<br> Value define via `platform.node()`. |
73+
| `pgport` | Pushgateway port | `9091` |
74+
| `iibver` | IIB version | `9`<br> Valid value: **9** or **10**.<br> If argument is omitted or invalid value is passed, the client will try to determine version via environment variable `MQSI_VERSION_V`. If it can't determine the version using the environment variable, the default value will be used. |
75+
5176
## Grafana dashboard
5277
5378
The Grafana dashboard visualizes collected metrics. This is an example of a dashboard. You can create your own dashboards to analyze metrics.

iib_metrics_client.py

Lines changed: 71 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
# -*- coding: utf-8 -*-
22
"""Python client for collecting IBM Integration Bus metrics and exporting to Prometheus pushgateway."""
33
import sys
4+
import os
45
import time
56
import traceback
67
import platform
78
import requests
9+
import argparse
810
from requests import ConnectionError
911
from urllib3.exceptions import ResponseError
1012
from modules.iib_brokers import (
@@ -15,7 +17,9 @@
1517
from modules.iib_applications import format_applications
1618
from modules.iib_message_flows import format_message_flows
1719
from log.logger_client import set_logger
18-
from modules.iib_api import run_iib_command
20+
from modules.iib_api import (
21+
run_iib_command,
22+
get_platform_params_for_commands)
1923

2024

2125
logger = set_logger()
@@ -28,15 +32,39 @@ class PrometheusBadResponse(Exception):
2832
def static_content():
2933
"""Client name and version."""
3034
name = "ib-metrics-pyclient"
31-
version = "0.2"
35+
version = "0.3"
3236
return '{0} v.{1}'.format(name, version)
3337

3438

35-
def put_metric_to_gateway(metric_data, job):
39+
def get_version_from_env():
40+
"""Get Integration Bus version from env variable."""
41+
iib_version = os.getenv("MQSI_VERSION_V")
42+
if iib_version:
43+
logger.info("Integration Bus version is defined via MQSI_VERSION_V environment variable.")
44+
else:
45+
logger.info("Integration Bus default version is used.")
46+
iib_version = "9"
47+
return iib_version
48+
49+
50+
def parse_commandline_args():
51+
"""Parse command-line arguments."""
52+
parser = argparse.ArgumentParser(prog='iib_metrics_client.py')
53+
parser.add_argument('--pghost', metavar='pushgatewayHost', nargs='?', default=platform.node(), dest='pushgateway_host', help='pushgateway host')
54+
parser.add_argument('--pgport', metavar='pushgatewayPort', nargs='?', default='9091', dest='pushgateway_port', help='pushgateway port')
55+
parser.add_argument('--iibver', metavar='iibVersion', nargs='?', default=None, dest='iib_cmd_ver', help='IIB version: 9 or 10')
56+
args = parser.parse_args()
57+
if (args.iib_cmd_ver is None) or ((args.iib_cmd_ver != '9') and (args.iib_cmd_ver != '10')):
58+
logger.info("Trying to determine Integration Bus version from environment variable MQSI_VERSION_V.")
59+
iib_cmd_ver = get_version_from_env()
60+
else:
61+
iib_cmd_ver = args.iib_cmd_ver
62+
return args.pushgateway_host, args.pushgateway_port, iib_cmd_ver
63+
64+
65+
def put_metric_to_gateway(metric_data, job, pushgateway_host, pushgateway_port):
3666
"""Sends data to Prometheus pushgateway."""
37-
hostname = platform.node()
38-
port = 9091
39-
src_url = "http://{0}:{1}".format(hostname, port)
67+
src_url = "http://{0}:{1}".format(pushgateway_host, pushgateway_port)
4068
headers = {"Content-Type": "text/plain; version=0.0.4"}
4169
dest_url = "{0}/metrics/job/{1}".format(src_url, job)
4270
logger.info("Destination url: {0}".format(dest_url))
@@ -51,35 +79,53 @@ def put_metric_to_gateway(metric_data, job):
5179
raise PrometheusBadResponse("{0} is not available!".format(dest_url))
5280

5381

54-
def main():
82+
def get_iib_metrics(pushgateway_host, pushgateway_port, mqsilist_command, bip_codes_brokers, bip_codes_components):
5583
start_time = time.time()
5684
logger.info("Starting metrics collecting for Integration Bus!")
5785
try:
58-
brokers_data = run_iib_command(task='get_brokers_status')
59-
brokers = get_brokers_status(brokers_data=brokers_data)
86+
brokers_data = run_iib_command(task=mqsilist_command)
87+
brokers = get_brokers_status(brokers_data=brokers_data, bip_codes=bip_codes_brokers)
6088
for broker in brokers:
6189
broker_name, status, qm_name = broker
6290
broker_data = format_broker(
6391
broker_name=broker_name,
6492
status=status,
6593
qm_name=qm_name)
66-
if status == 'running.':
94+
if status == 'running':
6795
broker_row_data = run_iib_command(
6896
task='get_broker_objects',
6997
broker_name=broker_name)
70-
exec_groups, applications, message_flows = get_broker_items(broker_row_data=broker_row_data)
71-
exec_groups_data = format_exec_groups(exec_groups=exec_groups)
72-
applications_data = format_applications(applications=applications, broker_name=broker_name)
73-
message_flows_data = format_message_flows(message_flows=message_flows, broker_name=broker_name)
98+
exec_groups, applications, message_flows = get_broker_items(
99+
broker_row_data=broker_row_data,
100+
bip_codes=bip_codes_components)
101+
exec_groups_data = format_exec_groups(
102+
exec_groups=exec_groups,
103+
bip_codes=bip_codes_components)
104+
applications_data = format_applications(
105+
applications=applications,
106+
broker_name=broker_name,
107+
bip_codes=bip_codes_components)
108+
message_flows_data = format_message_flows(
109+
message_flows=message_flows,
110+
broker_name=broker_name,
111+
bip_codes=bip_codes_components)
74112
metric_data = "{0}{1}{2}{3}".format(
75113
broker_data,
76114
exec_groups_data,
77115
applications_data,
78116
message_flows_data)
79-
put_metric_to_gateway(metric_data=metric_data, job=broker_name)
117+
put_metric_to_gateway(
118+
metric_data=metric_data,
119+
job=broker_name,
120+
pushgateway_host=pushgateway_host,
121+
pushgateway_port=pushgateway_port)
80122
logger.info("All metrics pushed successfully!")
81123
else:
82-
put_metric_to_gateway(metric_data=broker_data, job=broker_name)
124+
put_metric_to_gateway(
125+
metric_data=broker_data,
126+
job=broker_name,
127+
pushgateway_host=pushgateway_host,
128+
pushgateway_port=pushgateway_port)
83129
logger.warning("The status of broker is {0}\nOther metrics will not be collected!".format(status))
84130
logger.info("Script finished in - {0} seconds -".format(time.time() - start_time))
85131
except PrometheusBadResponse as error:
@@ -92,6 +138,14 @@ def main():
92138

93139
if __name__ == "__main__":
94140
logger.info("Run {0}".format(static_content()))
141+
pushgateway_host, pushgateway_port, iib_ver = parse_commandline_args()
142+
logger.info("Integration Bus version: {0}".format(iib_ver))
143+
mqsilist_command, bip_codes_brokers, bip_codes_components = get_platform_params_for_commands(iib_ver=iib_ver)
95144
while True:
96-
main()
145+
get_iib_metrics(
146+
pushgateway_host=pushgateway_host,
147+
pushgateway_port=pushgateway_port,
148+
mqsilist_command=mqsilist_command,
149+
bip_codes_brokers=bip_codes_brokers,
150+
bip_codes_components=bip_codes_components)
97151
time.sleep(60)

modules/iib_api.py

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ def run_iib_command(**kwargs):
77
"""Calls predefined commands and returns their result."""
88
command_mapping = {
99
'get_brokers_status': 'mqsilist | grep Broker',
10+
'get_integration_nodes_status': 'mqsilist | grep "Integration node"',
1011
'get_broker_objects': 'mqsilist {0} -r',
1112
}
1213
broker = str()
@@ -37,6 +38,63 @@ def execute_command(command):
3738
def get_status(status):
3839
"""Returns a numeric status value."""
3940
status_map = {
40-
'running.': 1,
41-
'stopped.': 0}
41+
'running': 1,
42+
'stopped': 0}
4243
return status_map[status]
44+
45+
46+
def get_platform_params_for_commands(iib_ver):
47+
"""Returns parameters for internal functions depending on Integration Bus version."""
48+
mqsilist_brokers = "get_brokers_status"
49+
mqsilist_integration_nodes = "get_integration_nodes_status"
50+
# See IBM diagnostic messages:
51+
# https://www.ibm.com/support/knowledgecenter/en/SSMKHH_9.0.0/com.ibm.etools.mft.bipmsgs.doc/ay_bip1.htm
52+
# Also you can use command: mqsiexplain <bip_code>
53+
bip_codes_broker = {
54+
# BIPCode: [broker_name_position, qm_name_position, status_position, trim_last_dot_in_qm_name]
55+
'BIP1284I': [2, 6, 8, 'false'],
56+
'BIP1285I': [2, 6, 8, 'false'],
57+
'BIP1293I': [2, 14 ,7, 'true'],
58+
'BIP1294I': [2, 14 ,7, 'true'],
59+
'BIP1295I': [2, 17, 13, 'true'],
60+
'BIP1296I': [2, 22, 4, 'true'],
61+
'BIP1297I': [2, 14, 7, 'true'],
62+
'BIP1298I': [2, 17, 4, 'true']
63+
}
64+
# https://www.ibm.com/support/knowledgecenter/en/SSMKHH_10.0.0/com.ibm.etools.mft.bipmsgs.doc/ay_bip1.htm
65+
bip_codes_integration_nodes = {
66+
# BIPCode: [broker_name_position, qm_name_position, status_position, trim_last_dot_in_qm_name]
67+
'BIP1284I': [3, 8, 14, 'false'],
68+
'BIP1285I': [3, 7, 9, 'false'],
69+
'BIP1295I': [3, 19, 15, 'true'],
70+
'BIP1296I': [3, 24 ,5, 'true'],
71+
'BIP1298I': [3, 18, 5, 'true'],
72+
'BIP1325I': [3, None, 9, 'false'],
73+
'BIP1326I': [3, None, 5, 'false'],
74+
'BIP1340I': [3, None, 5, 'false'],
75+
'BIP1353I': [3, 8, 10, 'false'],
76+
'BIP1366I': [3, 19, 15, 'true'],
77+
'BIP1376I': [3, 19, 15, 'true'],
78+
'BIP1377I': [3, 24, 5, 'true']
79+
}
80+
bip_codes_broker_components = {
81+
# BIPCode: [component_type, positions: broker_name, egname, status]
82+
'BIP1286I': ['exec_groups', 6, 3, 8],
83+
'BIP1287I': ['exec_groups', 6, 3, 8],
84+
# BIPCode: [component_type, positions: egname, appname, status]
85+
'BIP1275I': ['applications', 6, 2, 8],
86+
'BIP1276I': ['applications', 6, 2, 8],
87+
# BIPCode: [component_type, positions: egname, appname, msgflowname, status]
88+
'BIP1277I': ['message_flows', 7, 11, 3, 9],
89+
'BIP1278I': ['message_flows', 7, 11, 3, 9]}
90+
bip_codes_integration_nodes_components = {
91+
'BIP1286I': ['exec_groups', 7, 3, 9],
92+
'BIP1287I': ['exec_groups', 7, 3, 9],
93+
'BIP1275I': ['applications', 6, 2, 8],
94+
'BIP1276I': ['applications', 6, 2, 8],
95+
'BIP1277I': ['message_flows', 7, 11, 3, 9],
96+
'BIP1278I': ['message_flows', 7, 11, 3, 9]}
97+
if iib_ver == "9":
98+
return mqsilist_brokers, bip_codes_broker, bip_codes_broker_components
99+
if iib_ver == "10":
100+
return mqsilist_integration_nodes, bip_codes_integration_nodes, bip_codes_integration_nodes_components

modules/iib_applications.py

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,28 @@ def get_metric_annotation():
1616
return annotations
1717

1818

19-
def format_applications(applications, broker_name):
19+
def format_applications(applications, broker_name, bip_codes):
2020
"""Returns string with all metrics for all applications which ready to push to pushgateway."""
2121
metrics_annotation = get_metric_annotation()
2222
app_metric_data = str()
2323
for app in applications:
2424
app_list = app.split()
25-
egname, app_name, status = app_list[6], app_list[2], app_list[8]
26-
template_string = 'egname="{0}", brokername="{1}", appname="{2}"'.format(
27-
egname.replace("'", ""),
28-
broker_name,
29-
app_name.replace("'", ""))
30-
app_metric = '{0}{{{1}}} {2}\n'.format(
31-
get_metric_name(metric_label='status'),
32-
template_string,
33-
get_status(status=status))
34-
app_metric_data += app_metric
35-
app_metric_data = '{0}{1}'.format(
36-
metrics_annotation['status'],
37-
app_metric_data)
25+
bip_code = app_list[0].replace(':', '')
26+
if bip_code in bip_codes.keys():
27+
egname = app_list[bip_codes[bip_code][1]]
28+
app_name = app_list[bip_codes[bip_code][2]]
29+
status = app_list[bip_codes[bip_code][3]].replace(".", "")
30+
template_string = 'egname="{0}", brokername="{1}", appname="{2}"'.format(
31+
egname.replace("'", ""),
32+
broker_name,
33+
app_name.replace("'", ""))
34+
app_metric = '{0}{{{1}}} {2}\n'.format(
35+
get_metric_name(metric_label='status'),
36+
template_string,
37+
get_status(status=status))
38+
app_metric_data += app_metric
39+
if app_metric_data:
40+
app_metric_data = '{0}{1}'.format(
41+
metrics_annotation['status'],
42+
app_metric_data)
3843
return app_metric_data

modules/iib_brokers.py

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,40 +16,42 @@ def get_metric_annotation():
1616
return annotations
1717

1818

19-
def get_brokers_status(brokers_data):
19+
def get_brokers_status(brokers_data, bip_codes):
2020
"""Returns list with statuses for brokers."""
2121
output_list = brokers_data.split('\n')
2222
brokers = list()
2323
for record in filter(None, output_list):
2424
record_list = record.split()
25-
broker_name = record_list[2].replace("'", "")
26-
qm_name = record_list[6].replace("'", "")
27-
status = record_list[8].replace("'", "")
28-
brokers.append([broker_name, status, qm_name])
25+
bip_code = record_list[0].replace(':', '')
26+
if bip_code in bip_codes.keys():
27+
qm_name = str()
28+
broker_name = record_list[bip_codes[bip_code][0]].replace("'", "")
29+
trim_last_dot = bip_codes[bip_code][3]
30+
if bip_codes[bip_code][1] is not None:
31+
qm_name = record_list[bip_codes[bip_code][1]].replace("'", "")
32+
if trim_last_dot == 'true':
33+
qm_name = qm_name[:-1]
34+
status = record_list[bip_codes[bip_code][2]].replace("'", "").replace(".", "")
35+
brokers.append([broker_name, status, qm_name])
2936
return brokers
3037

3138

32-
def get_broker_items(broker_row_data):
39+
def get_broker_items(broker_row_data, bip_codes):
3340
"""Returns lists with data for broker items: execution groups, applications, message flows."""
3441
output_list = broker_row_data.split('\n')
3542
exec_groups = list()
3643
applications = list()
3744
message_flows = list()
38-
# See IBM diagnostic messages:
39-
# https://www.ibm.com/support/knowledgecenter/en/SSMKHH_9.0.0/com.ibm.etools.mft.bipmsgs.doc/ay_bip1.htm
40-
# Also you can use command: mqsiexplain <bip_code>
41-
bip_codes = {
42-
'BIP1286I': exec_groups,
43-
'BIP1287I': exec_groups,
44-
'BIP1275I': applications,
45-
'BIP1276I': applications,
46-
'BIP1277I': message_flows,
47-
'BIP1278I': message_flows}
4845
for record in output_list:
4946
if record:
5047
bip_code = record.split()[0].replace(':', '')
5148
if bip_code in bip_codes.keys():
52-
bip_codes[bip_code].append(record)
49+
if bip_codes[bip_code][0] == 'exec_groups':
50+
exec_groups.append(record)
51+
if bip_codes[bip_code][0] == 'applications':
52+
applications.append(record)
53+
if bip_codes[bip_code][0] == 'message_flows':
54+
message_flows.append(record)
5355
return exec_groups, applications, message_flows
5456

5557

0 commit comments

Comments
 (0)