Skip to content

Commit 5c9931e

Browse files
committed
issue15 Resolves: #15. Log4j logging implemented, readme updated with basic configuration file description.
1 parent 82914f7 commit 5c9931e

17 files changed

+361
-164
lines changed

README.md

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,60 @@ Support [IBM MQ](https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_9.0.0/com
5555
- [IBM MQ](https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_9.0.0/com.ibm.mq.helphome.v90.doc/WelcomePagev9r0.htm)
5656

5757
#### Configuration
58-
All settings have to be set in mq-java-exporter\src\main\resources\exporter_config.yaml.
59-
- MQ connection information. Describes MQ connection information.
60-
- Prometheus connection information. Describes Prometheus connection information.
61-
- Monitoring objects. Sets names of objects, that have to be monitored: queues, channels.
58+
All connection and monitoring settings have to be set in exporter_config.yaml file.
59+
Below is an example of a filled configuration file with all possible fields:
60+
```yaml
61+
# MQ connection information -------------------------------
62+
qmgrConnectionParams:
63+
# Queue manager name.
64+
qmgrName: QM
65+
# Queue manager host.
66+
qmgrHost: hostname
67+
# Queue manager connection port.
68+
qmgrPort: 1414
69+
# Queue manager connection channel.
70+
qmgrChannel: SYSTEM.DEF.SVRCONN
71+
# Username, which will be used for connection (optional).
72+
user: mqm
73+
# Password, which will be used for connection (optional).
74+
password: mqm
75+
# Use MQCSP for connection?
76+
mqscp: false
6277

63-
1. Fill exporter_config.yaml with your enviroments configuration.
78+
# Prometheus connection information -------------------------------
79+
prometheusEndpointParams:
80+
# URL and port which will be used to expose metrics for Prometheus.
81+
url: /metrics
82+
port: 8080
6483

84+
85+
# Monitoring objects ----------------------------------
86+
# This block refers to collecting of additional metrics.
87+
# If there are any queues, channels or listeners in the config file below,
88+
# these metrics may be useful for you. (More info about additional metrics is located
89+
# under "MQ PCF API specific statistics" section.
90+
PCFParameters:
91+
# Collect additional metrics? If false, all settings in this section below are ignored.
92+
sendPCFCommands: true
93+
# Use wildcards? If yes, only one PCF command will be send, matching all objects on queue manager. Otherwise, each
94+
# object will be monitored by separate PCF command.
95+
usePCFWildcards: true
96+
# Interval in seconds between sending PCF commands.
97+
scrapeInterval: 10
98+
99+
# Monitored queues.
100+
queues:
101+
- QUEUE1
102+
- QUEUE2
103+
104+
# Monitored listeners.
105+
listeners:
106+
- LISTENER01
107+
108+
# Monitored channels.
109+
channels:
110+
- MANAGEMENT.CHANNEL
111+
```
65112
#### Build
66113
67114
1. Download current repository.
@@ -79,6 +126,7 @@ mvn package
79126
```shell
80127
java -jar mq_exporter.jar /opt/mq_exporter/exporter_config.yaml
81128
```
129+
The only input parameter is the path to your configuration file.
82130

83131
## Metrics
84132
#### Platform central processing units

pom.xml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
<mq.allclient.version>9.0.0.1</mq.allclient.version>
1212
<snakeyaml.version>1.23</snakeyaml.version>
1313
<prometheus.version>0.6.0</prometheus.version>
14+
<log4j.version>2.11.2</log4j.version>
1415
<mq.allclient.jar.path>/lib/com.ibm.mq.allclient.jar</mq.allclient.jar.path>
1516
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
1617
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
@@ -41,6 +42,16 @@
4142
<artifactId>simpleclient_common</artifactId>
4243
<version>${prometheus.version}</version>
4344
</dependency>
45+
<dependency>
46+
<groupId>org.apache.logging.log4j</groupId>
47+
<artifactId>log4j-api</artifactId>
48+
<version>${log4j.version}</version>
49+
</dependency>
50+
<dependency>
51+
<groupId>org.apache.logging.log4j</groupId>
52+
<artifactId>log4j-core</artifactId>
53+
<version>${log4j.version}</version>
54+
</dependency>
4455
</dependencies>
4556
<build>
4657
<finalName>webspheremq_exporter</finalName>
@@ -61,6 +72,10 @@
6172
<artifactId>maven-jar-plugin</artifactId>
6273
<version>3.1.1</version>
6374
<configuration>
75+
<excludes>
76+
<exclude>**/exporter_config.yaml</exclude>
77+
<exclude>**/log4j.properties</exclude>
78+
</excludes>
6479
<archive>
6580
<manifest>
6681
<!-- Jar file entry point -->

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package ru.cinimex.exporter;
22

3+
import org.apache.logging.log4j.LogManager;
4+
import org.apache.logging.log4j.Logger;
35
import org.yaml.snakeyaml.Yaml;
46

57
import java.io.BufferedReader;
@@ -14,6 +16,7 @@
1416
* Class is used for parsing config file.
1517
*/
1618
public class Config {
19+
private static final Logger logger = LogManager.getLogger(Config.class);
1720
private String qmgrName;
1821
private String qmgrHost;
1922
private int qmgrPort;
@@ -37,7 +40,7 @@ public Config(String path) {
3740
try {
3841
br = new BufferedReader(new FileReader(rawFile));
3942
} catch (FileNotFoundException e) {
40-
System.err.println(String.format("Unable to locate config file. Make sure %s is valid path.", path));
43+
logger.error("Unable to locate config file. Make sure \"{}\" is a valid path.", path);
4144
System.exit(1);
4245
}
4346
LinkedHashMap<String, Object> config = file.load(br);
@@ -59,6 +62,7 @@ public Config(String path) {
5962
this.sendPCFCommands = (boolean) pcfParameters.get("sendPCFCommands");
6063
this.usePCFWildcards = (boolean) pcfParameters.get("usePCFWildcards");
6164
this.scrapeInterval = (Integer) pcfParameters.get("scrapeInterval");
65+
logger.info("Successfully parsed configuration file!");
6266
}
6367

6468
public boolean useMqscp() {

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

Lines changed: 38 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import com.ibm.mq.MQTopic;
77
import com.ibm.mq.constants.MQConstants;
88
import com.ibm.mq.pcf.PCFMessage;
9+
import org.apache.logging.log4j.LogManager;
10+
import org.apache.logging.log4j.Logger;
911
import ru.cinimex.exporter.mq.MQConnection;
1012
import ru.cinimex.exporter.mq.MQObject;
1113
import ru.cinimex.exporter.mq.MQSubscriberManager;
@@ -25,46 +27,51 @@
2527
* Main class of mq exporter tool. Parses config, scans topics, starts subscribers.
2628
*/
2729
public class ExporterLauncher {
30+
private static final Logger logger = LogManager.getLogger(ExporterLauncher.class);
2831
private static final String topicString = "$SYS/MQ/INFO/QMGR/%s/Monitor/METADATA/CLASSES";
2932
private static final int getMsgOpt = MQConstants.MQGMO_WAIT | MQConstants.MQGMO_COMPLETE_MSG | MQConstants.MQGMO_SYNCPOINT;
3033

31-
public static void main(String[] args) throws MQException, IOException {
34+
public static void main(String[] args) {
3235
if (args.length == 0) {
33-
System.err.println("It seems that you forgot to specify the path to the config file.");
36+
logger.error("It seems like you forgot to specify path to the config file.");
3437
System.exit(1);
3538
}
3639
Config config = new Config(args[0]);
37-
try {
38-
ArrayList<PCFElement> elements = getAllPublishedMetrics(config);
39-
ArrayList<MQObject.MQType> monitoringTypes = new ArrayList<>();
40-
ArrayList<MQObject> objects = new ArrayList<>();
4140

42-
if (config.sendPCFCommands()) {
43-
if (config.getQueues() != null && config.getQueues().size() > 0) {
44-
monitoringTypes.add(MQObject.MQType.QUEUE);
45-
for (String queueName : config.getQueues()) {
46-
objects.add(new MQObject(queueName, MQObject.MQType.QUEUE));
47-
}
41+
ArrayList<PCFElement> elements = getAllPublishedMetrics(config);
42+
ArrayList<MQObject.MQType> monitoringTypes = new ArrayList<>();
43+
ArrayList<MQObject> objects = new ArrayList<>();
44+
45+
if (config.sendPCFCommands()) {
46+
if (config.getQueues() != null && config.getQueues().size() > 0) {
47+
monitoringTypes.add(MQObject.MQType.QUEUE);
48+
for (String queueName : config.getQueues()) {
49+
objects.add(new MQObject(queueName, MQObject.MQType.QUEUE));
50+
logger.debug("Queue {} was added for additional monitoring.", queueName);
4851
}
49-
if (config.getChannels() != null && config.getChannels().size() > 0) {
50-
monitoringTypes.add(MQObject.MQType.CHANNEL);
51-
for (String channelName : config.getChannels()) {
52-
objects.add(new MQObject(channelName, MQObject.MQType.CHANNEL));
53-
}
52+
}
53+
if (config.getChannels() != null && config.getChannels().size() > 0) {
54+
monitoringTypes.add(MQObject.MQType.CHANNEL);
55+
for (String channelName : config.getChannels()) {
56+
objects.add(new MQObject(channelName, MQObject.MQType.CHANNEL));
57+
logger.debug("Channel {} was added for additional monitoring.", channelName);
5458
}
55-
if (config.getListeners() != null && config.getListeners().size() > 0) {
56-
monitoringTypes.add(MQObject.MQType.LISTENER);
57-
for (String listenerName : config.getListeners()) {
58-
objects.add(new MQObject(listenerName, MQObject.MQType.LISTENER));
59-
}
59+
}
60+
if (config.getListeners() != null && config.getListeners().size() > 0) {
61+
monitoringTypes.add(MQObject.MQType.LISTENER);
62+
for (String listenerName : config.getListeners()) {
63+
objects.add(new MQObject(listenerName, MQObject.MQType.LISTENER));
64+
logger.debug("Listener {} was added for additional monitoring.", listenerName);
6065
}
6166
}
62-
MetricsManager.initMetrics(elements, monitoringTypes);
63-
MQSubscriberManager manager = new MQSubscriberManager(config.getQmgrHost(), config.getQmgrPort(), config.getQmgrChannel(), config.getQmgrName(), config.getUser(), config.getPassword(), config.useMqscp());
64-
manager.runSubscribers(elements, objects, config.sendPCFCommands(), config.usePCFWildcards(), config.getScrapeInterval());
67+
}
68+
MetricsManager.initMetrics(elements, monitoringTypes);
69+
MQSubscriberManager manager = new MQSubscriberManager(config.getQmgrHost(), config.getQmgrPort(), config.getQmgrChannel(), config.getQmgrName(), config.getUser(), config.getPassword(), config.useMqscp());
70+
manager.runSubscribers(elements, objects, config.sendPCFCommands(), config.usePCFWildcards(), config.getScrapeInterval());
71+
try {
6572
new HTTPServer(new InetSocketAddress("0.0.0.0", config.getEndpPort()), config.getEndpURL(), Registry.getRegistry(), false);
66-
} catch (Exception e) {
67-
System.err.println(e.getMessage());
73+
} catch (IOException e) {
74+
logger.error("Error occurred during expanding endpoint for Prometheus: ", e);
6875
}
6976
}
7077

@@ -81,9 +88,8 @@ private static ArrayList<PCFElement> getAllPublishedMetrics(Config config) {
8188
MQGetMessageOptions gmo = new MQGetMessageOptions();
8289
gmo.options = getMsgOpt;
8390
gmo.waitInterval = 30000;
84-
connection.establish(config.getQmgrHost(), config.getQmgrPort(), config.getQmgrChannel(), config.getQmgrName(), config.getUser(), config.getPassword(), config.useMqscp());
85-
8691
try {
92+
connection.establish(config.getQmgrHost(), config.getQmgrPort(), config.getQmgrChannel(), config.getQmgrName(), config.getUser(), config.getPassword(), config.useMqscp());
8793
topic = connection.createTopic(String.format(topicString, config.getQmgrName()));
8894
MQMessage msg = getEmptyMessage();
8995
topic.get(msg, gmo);
@@ -103,16 +109,16 @@ private static ArrayList<PCFElement> getAllPublishedMetrics(Config config) {
103109
elements.addAll(PCFDataParser.getPCFElements(pcfResponse));
104110
}
105111
}
106-
} catch (Exception e) {
107-
System.err.println(e.getMessage());
112+
} catch (MQException | IOException e) {
113+
logger.error("Failed!", e);
108114
} finally {
109115
try {
110116
if (topic != null && topic.isOpen()) {
111117
topic.close();
112118
}
113119
connection.close();
114120
} catch (MQException e) {
115-
System.err.println(String.format("Error occured during disconnecting from topic %s. Error: %s", topic.toString(), e.getStackTrace()));
121+
logger.error("Error occurred during disconnecting from topic {}. Error: ", topic.toString(), e);
116122
}
117123
}
118124
return elements;

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

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,16 @@
55
import com.ibm.mq.MQTopic;
66
import com.ibm.mq.constants.CMQC;
77
import com.ibm.mq.constants.MQConstants;
8+
import org.apache.logging.log4j.LogManager;
9+
import org.apache.logging.log4j.Logger;
810

911
import java.util.Hashtable;
1012

1113
/**
1214
* Class represents MQ connection.
1315
*/
1416
public class MQConnection {
17+
private static final Logger logger = LogManager.getLogger(MQConnection.class);
1518
private Hashtable<String, Object> connectionProperties;
1619
private MQQueueManager queueManager;
1720

@@ -58,13 +61,9 @@ protected static Hashtable<String, Object> createMQConnectionParams(String host,
5861
* @param password - password, which is required to establish connection with queue manager (optional).
5962
* @param useMQCSP - flag, which indicates, if MQCSP auth should be used.
6063
*/
61-
public void establish(String host, int port, String channel, String qmName, String user, String password, boolean useMQCSP) {
64+
public void establish(String host, int port, String channel, String qmName, String user, String password, boolean useMQCSP) throws MQException {
6265
connectionProperties = createMQConnectionParams(host, port, channel, user, password, useMQCSP);
63-
try {
64-
queueManager = new MQQueueManager(qmName, connectionProperties);
65-
} catch (MQException e) {
66-
System.err.println(e.getMessage());
67-
}
66+
queueManager = new MQQueueManager(qmName, connectionProperties);
6867
}
6968

7069

@@ -74,12 +73,8 @@ public void establish(String host, int port, String channel, String qmName, Stri
7473
* @param qmNqme - queue manager's name.
7574
* @param connectionProperties - prepared structure with all parameters transformed into queue manager's format. See {@link #createMQConnectionParams(String, int, String, String, String, boolean)} for more info.
7675
*/
77-
public void establish(String qmNqme, Hashtable<String, Object> connectionProperties) {
78-
try {
79-
queueManager = new MQQueueManager(qmNqme, connectionProperties);
80-
} catch (MQException e) {
81-
System.err.println(e.getMessage());
82-
}
76+
public void establish(String qmNqme, Hashtable<String, Object> connectionProperties) throws MQException {
77+
queueManager = new MQQueueManager(qmNqme, connectionProperties);
8378
}
8479

8580
/**
@@ -90,7 +85,7 @@ public void close() {
9085
try {
9186
queueManager.disconnect();
9287
} catch (MQException e) {
93-
System.err.println(e.getMessage());
88+
logger.error("Failed!", e);
9489
}
9590
}
9691
}
@@ -108,6 +103,7 @@ public MQTopic createTopic(String topic) throws MQException {
108103

109104
/**
110105
* Returns MQQueueManager object.
106+
*
111107
* @return - MQQueueManager object.
112108
*/
113109
public MQQueueManager getQueueManager() {

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

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@
22

33
import com.ibm.mq.constants.MQConstants;
44
import com.ibm.mq.pcf.PCFMessage;
5+
import org.apache.logging.log4j.LogManager;
6+
import org.apache.logging.log4j.Logger;
57

68
/**
79
* Class represents MQObject (Queue, channel or listener). It stores object type and all PCFParameters, required for correct request.
810
*/
911
public class MQObject {
12+
private static final Logger logger = LogManager.getLogger(MQObject.class);
1013
private String name;
1114
private MQType type;
1215
private PCFMessage PCFCmd;
@@ -41,16 +44,19 @@ public MQObject(String name, MQType type) {
4144
PCFCmd.addParameter(MQConstants.MQCACH_CHANNEL_NAME, name); //PCF command would try to retrieve statistics about channel with specific name
4245
PCFHeader = MQConstants.MQIACH_CHANNEL_STATUS;//the only statistics we want to know about channel is it's status.
4346
break;
44-
default:
45-
//TODO:Exception
47+
default: {
48+
logger.error("Unknown type for MQObject: {}", type.name());
49+
throw new RuntimeException("Unable to create new MQObject. Received unexpected MQObject type: " + type.name());
50+
}
51+
4652
}
4753
}
4854

4955
/**
5056
* This method returns MQConstant int code, which represents name for input object.
5157
*
5258
* @param type - object type.
53-
* @return - integer code.
59+
* @return - integer code. Returns -1 if code wasn't found.
5460
*/
5561
public static int objectNameCode(MQObject.MQType type) {
5662
int code = -1;
@@ -108,7 +114,5 @@ public PCFMessage getPCFCmd() {
108114
/**
109115
* This enum represents all supported MQObject types.
110116
*/
111-
public enum MQType {
112-
QUEUE, CHANNEL, LISTENER
113-
}
117+
public enum MQType {QUEUE, CHANNEL, LISTENER}
114118
}

0 commit comments

Comments
 (0)