Skip to content

Commit d0ee2d4

Browse files
authored
Merge pull request #105 from Cinimex-Informatica/develop
Release 0.2.1-rc has been tested. No bugs have been found. Merging into the master branch to release 0.2.1-alfa.
2 parents d070dcd + 0caec3d commit d0ee2d4

19 files changed

+953
-591
lines changed

README.md

Lines changed: 379 additions & 96 deletions
Large diffs are not rendered by default.
64.3 KB
Loading
118 KB
Loading

src/main/java/ru/cinimex/exporter/Config.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import java.util.ArrayList;
1212
import java.util.HashMap;
1313
import java.util.LinkedHashMap;
14+
import java.util.List;
1415

1516
/**
1617
* Class is used for parsing config file.
@@ -81,11 +82,11 @@ public boolean usePCFWildcards() {
8182
return usePCFWildcards;
8283
}
8384

84-
public ArrayList<String> getChannels() {
85+
public List<String> getChannels() {
8586
return channels;
8687
}
8788

88-
public ArrayList<String> getListeners() {
89+
public List<String> getListeners() {
8990
return listeners;
9091
}
9192

@@ -121,7 +122,7 @@ public String getEndpURL() {
121122
return endpURL;
122123
}
123124

124-
public ArrayList<String> getQueues() {
125+
public List<String> getQueues() {
125126
return queues;
126127
}
127128

src/main/java/ru/cinimex/exporter/ExporterLauncher.java

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,15 @@
2222
import java.io.IOException;
2323
import java.net.InetSocketAddress;
2424
import java.util.ArrayList;
25+
import java.util.List;
2526

2627
/**
2728
* Main class of mq exporter tool. Parses config, scans topics, starts subscribers.
2829
*/
2930
public class ExporterLauncher {
3031
private static final Logger logger = LogManager.getLogger(ExporterLauncher.class);
31-
private static final String topicString = "$SYS/MQ/INFO/QMGR/%s/Monitor/METADATA/CLASSES";
32-
private static final int getMsgOpt = MQConstants.MQGMO_WAIT | MQConstants.MQGMO_COMPLETE_MSG | MQConstants.MQGMO_SYNCPOINT;
32+
private static final String TOPIC_STRING = "$SYS/MQ/INFO/QMGR/%s/Monitor/METADATA/CLASSES";
33+
private static final int GMO = MQConstants.MQGMO_WAIT | MQConstants.MQGMO_COMPLETE_MSG | MQConstants.MQGMO_SYNCPOINT;
3334

3435
public static void main(String[] args) {
3536
if (args.length == 0) {
@@ -42,19 +43,19 @@ public static void main(String[] args) {
4243
ArrayList<MQObject.MQType> monitoringTypes = new ArrayList<>();
4344
ArrayList<MQObject> objects = new ArrayList<>();
4445

45-
if (config.getQueues() != null && config.getQueues().size() > 0) {
46+
if (config.getQueues() != null && !config.getQueues().isEmpty()) {
4647
monitoringTypes.add(MQObject.MQType.QUEUE);
4748
for (String queueName : config.getQueues()) {
4849
objects.add(new MQObject(queueName, MQObject.MQType.QUEUE));
4950
}
5051
}
51-
if (config.getChannels() != null && config.getChannels().size() > 0) {
52+
if (config.getChannels() != null && !config.getChannels().isEmpty()) {
5253
monitoringTypes.add(MQObject.MQType.CHANNEL);
5354
for (String channelName : config.getChannels()) {
5455
objects.add(new MQObject(channelName, MQObject.MQType.CHANNEL));
5556
}
5657
}
57-
if (config.getListeners() != null && config.getListeners().size() > 0) {
58+
if (config.getListeners() != null && !config.getListeners().isEmpty()) {
5859
monitoringTypes.add(MQObject.MQType.LISTENER);
5960
for (String listenerName : config.getListeners()) {
6061
objects.add(new MQObject(listenerName, MQObject.MQType.LISTENER));
@@ -80,23 +81,23 @@ public static void main(String[] args) {
8081
private static ArrayList<PCFElement> getAllPublishedMetrics(Config config) {
8182
MQConnection connection = new MQConnection();
8283
MQTopic topic = null;
83-
ArrayList<PCFElement> elements = new ArrayList<PCFElement>();
84+
ArrayList<PCFElement> elements = new ArrayList<>();
8485
MQGetMessageOptions gmo = new MQGetMessageOptions();
85-
gmo.options = getMsgOpt;
86+
gmo.options = GMO;
8687
gmo.waitInterval = 30000;
8788
try {
8889
connection.establish(config.getQmgrHost(), config.getQmgrPort(), config.getQmgrChannel(), config.getQmgrName(), config.getUser(), config.getPassword(), config.useMqscp());
89-
topic = connection.createTopic(String.format(topicString, config.getQmgrName()));
90+
topic = connection.createTopic(String.format(TOPIC_STRING, config.getQmgrName()));
9091
MQMessage msg = getEmptyMessage();
9192
topic.get(msg, gmo);
9293
PCFMessage pcfResponse = new PCFMessage(msg);
93-
ArrayList<PCFClass> classes = PCFDataParser.getPCFClasses(pcfResponse);
94+
List<PCFClass> classes = PCFDataParser.getPCFClasses(pcfResponse);
9495
for (PCFClass pcfClass : classes) {
9596
topic = connection.createTopic(pcfClass.getTopicString());
9697
msg = getEmptyMessage();
9798
topic.get(msg, gmo);
9899
pcfResponse = new PCFMessage(msg);
99-
ArrayList<PCFType> types = PCFDataParser.getPCFTypes(pcfResponse);
100+
List<PCFType> types = PCFDataParser.getPCFTypes(pcfResponse);
100101
for (PCFType type : types) {
101102
topic = connection.createTopic(type.getTopicString());
102103
msg = getEmptyMessage();

src/main/java/ru/cinimex/exporter/mq/MQConnection.java

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,8 @@
1515
*/
1616
public class MQConnection {
1717
private static final Logger logger = LogManager.getLogger(MQConnection.class);
18-
private Hashtable<String, Object> connectionProperties;
1918
private MQQueueManager queueManager;
2019

21-
/**
22-
* Default constructor.
23-
*/
24-
public MQConnection() {
25-
26-
}
27-
2820
/**
2921
* Method creates connection properties Hashtable from connection parameters.
3022
*
@@ -37,7 +29,7 @@ public MQConnection() {
3729
* @return - returns prepared structure with all parameters transformed into queue manager's format.
3830
*/
3931
protected static Hashtable<String, Object> createMQConnectionParams(String host, int port, String channel, String user, String password, boolean useMQCSP) {
40-
Hashtable<String, Object> properties = new Hashtable<String, Object>();
32+
Hashtable<String, Object> properties = new Hashtable<>();
4133
properties.put(MQConstants.TRANSPORT_PROPERTY, host == null ? MQConstants.TRANSPORT_MQSERIES_BINDINGS : MQConstants.TRANSPORT_MQSERIES_CLIENT);
4234
if (host != null) properties.put(MQConstants.HOST_NAME_PROPERTY, host);
4335
if (port != 0) properties.put(MQConstants.PORT_PROPERTY, port);
@@ -62,11 +54,10 @@ protected static Hashtable<String, Object> createMQConnectionParams(String host,
6254
* @param useMQCSP - flag, which indicates, if MQCSP auth should be used.
6355
*/
6456
public void establish(String host, int port, String channel, String qmName, String user, String password, boolean useMQCSP) throws MQException {
65-
connectionProperties = createMQConnectionParams(host, port, channel, user, password, useMQCSP);
57+
Hashtable<String, Object> connectionProperties = createMQConnectionParams(host, port, channel, user, password, useMQCSP);
6658
queueManager = new MQQueueManager(qmName, connectionProperties);
6759
}
6860

69-
7061
/**
7162
* Method establishes connection with queue manager.
7263
*

src/main/java/ru/cinimex/exporter/mq/MQObject.java

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ public class MQObject {
1212
private static final Logger logger = LogManager.getLogger(MQObject.class);
1313
private String name;
1414
private MQType type;
15-
private PCFMessage PCFCmd;
16-
private int PCFHeader;
15+
private PCFMessage pcfCmd;
16+
private int pcfHeader;
1717

1818
/**
1919
* MQObject constructor.
@@ -29,26 +29,24 @@ public MQObject(String name, MQType type) {
2929
*/
3030
switch (type) {
3131
case QUEUE:
32-
PCFCmd = new PCFMessage(MQConstants.MQCMD_INQUIRE_Q); //if object type is queue, exporter would inquire it.
33-
PCFCmd.addParameter(MQConstants.MQCA_Q_NAME, name); //PCF command would try to retrieve statistics about queue with specific name
34-
PCFCmd.addParameter(MQConstants.MQIA_Q_TYPE, MQConstants.MQQT_LOCAL); // and specific type
35-
PCFHeader = MQConstants.MQIA_MAX_Q_DEPTH; //the only statistics we want to know about queue is it's max depth.
32+
pcfCmd = new PCFMessage(MQConstants.MQCMD_INQUIRE_Q); //if object type is queue, exporter would inquire it.
33+
pcfCmd.addParameter(MQConstants.MQCA_Q_NAME, name); //PCF command would try to retrieve statistics about queue with specific name
34+
pcfCmd.addParameter(MQConstants.MQIA_Q_TYPE, MQConstants.MQQT_LOCAL); // and specific type
35+
pcfHeader = MQConstants.MQIA_MAX_Q_DEPTH; //the only statistics we want to know about queue is it's max depth.
3636
break;
3737
case LISTENER:
38-
PCFCmd = new PCFMessage(MQConstants.MQCMD_INQUIRE_LISTENER_STATUS); //if object type is listener, exporter would inquire it.
39-
PCFCmd.addParameter(MQConstants.MQCACH_LISTENER_NAME, name);//PCF command would try to retrieve statistics about listener with specific name
40-
PCFHeader = MQConstants.MQIACH_LISTENER_STATUS;//the only statistics we want to know about listener is it's status.
38+
pcfCmd = new PCFMessage(MQConstants.MQCMD_INQUIRE_LISTENER_STATUS); //if object type is listener, exporter would inquire it.
39+
pcfCmd.addParameter(MQConstants.MQCACH_LISTENER_NAME, name);//PCF command would try to retrieve statistics about listener with specific name
40+
pcfHeader = MQConstants.MQIACH_LISTENER_STATUS;//the only statistics we want to know about listener is it's status.
4141
break;
4242
case CHANNEL:
43-
PCFCmd = new PCFMessage(MQConstants.MQCMD_INQUIRE_CHANNEL_STATUS); //if object type is channel, exporter would inquire it.
44-
PCFCmd.addParameter(MQConstants.MQCACH_CHANNEL_NAME, name); //PCF command would try to retrieve statistics about channel with specific name
45-
PCFHeader = MQConstants.MQIACH_CHANNEL_STATUS;//the only statistics we want to know about channel is it's status.
43+
pcfCmd = new PCFMessage(MQConstants.MQCMD_INQUIRE_CHANNEL_STATUS); //if object type is channel, exporter would inquire it.
44+
pcfCmd.addParameter(MQConstants.MQCACH_CHANNEL_NAME, name); //PCF command would try to retrieve statistics about channel with specific name
45+
pcfHeader = MQConstants.MQIACH_CHANNEL_STATUS;//the only statistics we want to know about channel is it's status.
4646
break;
47-
default: {
47+
default:
4848
logger.error("Unknown type for MQObject: {}", type.name());
4949
throw new RuntimeException("Unable to create new MQObject. Received unexpected MQObject type: " + type.name());
50-
}
51-
5250
}
5351
}
5452

@@ -90,7 +88,7 @@ public String getName() {
9088
* @return - MQConstant integer code.
9189
*/
9290
public int getPCFHeader() {
93-
return PCFHeader;
91+
return pcfHeader;
9492
}
9593

9694
/**
@@ -107,8 +105,8 @@ public MQType getType() {
107105
*
108106
* @return - prepared PCF command object.
109107
*/
110-
public PCFMessage getPCFCmd() {
111-
return PCFCmd;
108+
public PCFMessage getPcfCmd() {
109+
return pcfCmd;
112110
}
113111

114112
/**

src/main/java/ru/cinimex/exporter/mq/MQPCFSubscriber.java

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import java.io.IOException;
1414
import java.util.ArrayList;
1515
import java.util.Hashtable;
16+
import java.util.List;
1617

1718
/**
1819
* MQPCFSubscriber is technically not a subscriber, but a runnable object, which sends PCFCommands every n seconds to
@@ -24,7 +25,7 @@ public class MQPCFSubscriber implements Runnable {
2425
private String queueManagerName;
2526
private MQObject object;
2627
private PCFMessageAgent agent;
27-
private ArrayList<MQObject> objects;
28+
private List<MQObject> objects;
2829

2930
/**
3031
* MQPCFSubscriber constructor which is used, when exporter is configured to use 1 MQPCFSubscriber per 1 MQObject.
@@ -43,9 +44,9 @@ public MQPCFSubscriber(String queueManagerName, Hashtable<String, Object> connec
4344
*
4445
* @param queueManagerName - queue manager name.
4546
* @param connectionProperties - connection properties.
46-
* @param objects - Array with all MQObjects.
47+
* @param objects - List with all MQObjects.
4748
*/
48-
public MQPCFSubscriber(String queueManagerName, Hashtable<String, Object> connectionProperties, ArrayList<MQObject> objects) {
49+
public MQPCFSubscriber(String queueManagerName, Hashtable<String, Object> connectionProperties, List<MQObject> objects) {
4950
establishMQConnection(queueManagerName, connectionProperties);
5051
this.objects = objects;
5152
this.object = new MQObject("*", objects.get(0).getType());
@@ -90,39 +91,45 @@ private void updateMetricWithoutWildcards(PCFMessage response, String objectName
9091
private void updateMetricsWithWildcards(PCFMessage[] pcfResponse) {
9192
ArrayList<String> objectNames = new ArrayList<>();
9293
//copy all objects names to temporary array
93-
for (MQObject object : objects) {
94-
objectNames.add(object.getName());
94+
for (MQObject monitoredObject : objects) {
95+
objectNames.add(monitoredObject.getName());
9596
}
9697
for (PCFMessage response : pcfResponse) {
9798
String objectName = (String) response.getParameterValue(MQObject.objectNameCode(object.getType()));
9899
objectName = objectName.trim();
99100
//if temporary array contains metric, then remove it from temporary array and update metric
100101
if (objectNames.contains(objectName)) {
101102
objectNames.remove(objectName);
102-
Object result = response.getParameterValue(object.getPCFHeader());
103-
double prometheusValue = MetricsReference.getMetricValue(object.getType(), (Integer) result);
104-
MetricsManager.updateMetric(MetricsReference.getMetricName(object.getType()), prometheusValue, queueManagerName, objectName);
103+
updateMetricWithoutWildcards(response, objectName);
105104
}
106105
}
107-
108-
//There are some objects in temporary array? It means that "*" wildcard didn't return all values.
106+
//Are there any objects left in temporary array? It means that "*" wildcard didn't return all values.
109107
//There are multiple reasons why it could happen. For example, MQ channel has status "inactive".
110108
//Then we send direct PCF command for specific object. If some error occurs, we have custom processing for it.
111-
if (objectNames.size() > 0) {
112-
for (String objectName : objectNames) {
113-
MQObject directObject = new MQObject(objectName, object.getType());
114-
try {
115-
PCFMessage[] directPCFResponse = agent.send(directObject.getPCFCmd());
116-
updateMetricWithoutWildcards(directPCFResponse[0], objectName);
117-
} catch (PCFException e) {
118-
//This error means, that channel has status "inactive".
109+
updateWithDirectPCFCommand(objectNames);
110+
}
111+
112+
/**
113+
* Retrieves info about all objects from input array via direct pcf commands.
114+
*
115+
* @param objectNames - input array with objects.
116+
*/
117+
private void updateWithDirectPCFCommand(ArrayList<String> objectNames) {
118+
for (String objectName : objectNames) {
119+
MQObject directObject = new MQObject(objectName, object.getType());
120+
try {
121+
PCFMessage[] directPCFResponse = agent.send(directObject.getPcfCmd());
122+
updateMetricWithoutWildcards(directPCFResponse[0], objectName);
123+
} catch (PCFException e) {
124+
//This error means, that channel has status "inactive".
125+
if (e.reasonCode == MQConstants.MQRCCF_CHL_STATUS_NOT_FOUND) {
119126
logger.warn("Channel {} is possibly inactive.", objectName);
120-
if (e.reasonCode == MQConstants.MQRCCF_CHL_STATUS_NOT_FOUND) {
121-
MetricsManager.updateMetric(MetricsReference.getMetricName(object.getType()), MetricsReference.getMetricValue(object.getType(), MQConstants.MQCHS_INACTIVE), queueManagerName, objectName);
122-
}
123-
} catch (IOException | MQException e) {
127+
MetricsManager.updateMetric(MetricsReference.getMetricName(object.getType()), MetricsReference.getMetricValue(object.getType(), MQConstants.MQCHS_INACTIVE), queueManagerName, objectName);
128+
} else {
124129
logger.error("Error occurred during sending PCF command: ", e);
125130
}
131+
} catch (IOException | MQException e) {
132+
logger.error("Error occurred during sending PCF command: ", e);
126133
}
127134
}
128135
}
@@ -131,7 +138,7 @@ private void updateMetricsWithWildcards(PCFMessage[] pcfResponse) {
131138
public void run() {
132139
try {
133140
logger.debug("Sending PCF command for object type {} with name {}...", object.getType(), object.getName());
134-
PCFMessage[] pcfResponse = agent.send(object.getPCFCmd());
141+
PCFMessage[] pcfResponse = agent.send(object.getPcfCmd());
135142
if (!objects.isEmpty()) {
136143
updateMetricsWithWildcards(pcfResponse);
137144
} else {
@@ -145,6 +152,10 @@ public void run() {
145152
logger.warn("Channel {} is possibly inactive.", object.getName());
146153
MetricsManager.updateMetric(MetricsReference.getMetricName(object.getType()), MetricsReference.getMetricValue(object.getType(), MQConstants.MQCHS_INACTIVE), queueManagerName, object.getName());
147154
}
155+
if (object.getType() == MQObject.MQType.LISTENER && e.reasonCode == MQConstants.MQRC_UNKNOWN_OBJECT_NAME) {
156+
MetricsManager.updateMetric(MetricsReference.getMetricName(object.getType()), MetricsReference.getMetricValue(object.getType(), MQConstants.MQSVC_STATUS_STOPPED), queueManagerName, object.getName());
157+
logger.warn("Listener {} is possibly stopped.", object.getName());
158+
}
148159
} catch (MQException | IOException e) {
149160
logger.error("Error occurred during sending PCF command: ", e);
150161
}

0 commit comments

Comments
 (0)