This sample shows how to stream ActiveMQ Artemis intercepted packets and connection data to jKool/XRay.
Quick Setup Steps
Broker
Consider your broker with the default directory layout, where:
- Configuration is stored in
etcdirectory - Run scripts are in
bindirectory - Custom broker libraries go to the
libdirectory
- Copy
tnt4j-streams-jms-<VERSION>-artemis-broker-interceptor.jarto your broker lib directory<broker>/lib. - Create
<broker>/etc/tnt4jdirectory to store TNT4J-Streams dedicated configuration:- For the whole config directory, copy the tnt4j*.properties content into that directory.
- Files one-by-one:
- Copy interceptors.properties file into that directory.
- Copy logging.properties file into that directory.
- Copy interceptor_parsers.xml file into that directory.
- Copy msg_parsers.xml file into that directory.
- Copy tntj4*.properties files into that directory.
- Copy tnt-data-source.xml file into that directory.
- Alter
<broker>/etc/tnt4j/tnt4j-streams.propertiesfile by setting your jKool token in lineevent.sink.factory.EventSinkFactory.prod.Token: replace valueprod-access-tokenwith your token. -
Alter
<broker>/etc/broker.xmlby changing sectionsremoting-incoming-interceptorsandremoting-outgoing-interceptors:<remoting-incoming-interceptors> <class-name>com.jkoolcloud.tnt4j.streams.custom.interceptors.jms.artemis.PacketInterceptor</class-name> </remoting-incoming-interceptors> <remoting-outgoing-interceptors> <class-name>com.jkoolcloud.tnt4j.streams.custom.interceptors.jms.artemis.PacketInterceptor</class-name> </remoting-outgoing-interceptors> - Alter
<broker>/bin/artemis.cmd(or.sh) by setting:- Change the logger configuration path by changing the
ARTEMIS_LOGGING_CONFvariable definition to:-
MS Windows
set ARTEMIS_LOGGING_CONF=%ARTEMIS_INSTANCE_ETC_URI%\tnt4j\logging.properties
-
*nix
ARTEMIS_LOGGING_CONF="$ARTEMIS_INSTANCE_ETC_URI/tnt4j/logging.properties"
-
- Set the TNT4J configuration system property by appending the
JVM_ARGSvariable definition:-
MS Windows
set JVM_ARGS=%JVM_ARGS% -Dtnt4j.config=%ARTEMIS_INSTANCE_ETC%\tnt4j\tnt4j.properties
-
*nix
JVM_ARGS="$JVM_ARGS -Dtnt4j.config=$ARTEMIS_INSTANCE_ETC/tnt4j/tnt4j.properties"
-
- Change the logger configuration path by changing the
TL;DR
Interceptor Types
Now TNT4J-Streams provides an individual interceptor for every ActiveMQ Artemis supported protocol:
-
Core-com.jkoolcloud.tnt4j.streams.custom.interceptors.jms.artemis.PacketInterceptor -
Amqp-com.jkoolcloud.tnt4j.streams.custom.interceptors.jms.artemis.AmqpInterceptor -
Mqtt-com.jkoolcloud.tnt4j.streams.custom.interceptors.jms.artemis.MQTTInterceptor -
OpenWire-com.jkoolcloud.tnt4j.streams.custom.interceptors.jms.artemis.OpenWireInterceptor -
Stomp-com.jkoolcloud.tnt4j.streams.custom.interceptors.jms.artemis.StompInterceptor
Configuration
TNT4J-Streams interceptors are configured over interceptors.properties configuration file.
Note: This is just interceptor instance configuration - a complete solution also requires TNT4J, loggers, data source, and parsers configuration.
Now the interceptor configuration allows you to configure:
- Produced intercepted data map layout. Default is
FLAT. - Interceptions include a packet class name regex pattern. See Artemis API documentation for available packet implementation classes per communication protocol. Default is
Session(Send|Receive)Messageto intercept packets transporting produced or consumed message. Change to.*to intercept any available packet. - Interceptions exclude a packet class name regex pattern. See Artemis API documentation for available packet implementation classes per communication protocol. Default is none.
Interceptors can be configured by scope (protocol). The first configuration property name token defines the scope: amqp, mqtt, owire, core, stomp. the prefix any defines configuration for any (all) scope of interceptors.
Intercepted Data
Every TNT4J-Streams ActiveMQ Artemis interceptor produces a map with attributes for these scopes:
-
packet- packet implementation provided attributes -
conn- connection implementation provided attributes -
ictx- interceptor context provided attributes
Interceptors can produce such map layouts:
-
FLAT- produces a single-depth-level map (kind of a properties list) where the entry key is made (using the:delimiter) by appending the complex type property name's path. This is the default layout. -
DEEP- produces map constructed by making dedicated entry value map for complex type properties.
Parsing Message Payload
Core Protocol
If there is a need to parse intercepted message payload, you can bind your parser to Message field like this:
-
Define your message payload parser in
msg_parsers.xmlfile like this:<!-- Sample Message XML payload parser --> <parser name="XML_Data_Parser" class="com.jkoolcloud.tnt4j.streams.parsers.ActivityXmlParser"> <field name="EventType" value="NOOP"/> <field name="HostName" locator="/tracking_event/HostName" locator-type="Label"/> </parser> -
Bind parser reference to
Messagefield ininterceptor_parsers.xmlfile like this:<field name="Message" locator="packet:message:stringBody" locator-type="Label"> <!-- To parse message payload, put your parser reference here --> <parser-ref name="XML_Data_Parser" aggregation="Merge"/> </field>
Message Properties
Core Protocol
Intercepted message properties are parsed by PropertiesParser parser:
<!-- Message properties parser -->
<parser name="PropertiesParser" class="com.jkoolcloud.tnt4j.streams.parsers.ActivityMapParser">
<field name="EventType" value="NOOP"/>
<field name="AllProps" locator="#" locator-type="Label"/>
</parser>By default, it performs simple direct properties mapping into produced TNT4J event.
But if there is known set of properties used in messages, here you can define additional mapping logic by defining meaningful property names, transforming values or aggregating multiple properties values.
Binding Interceptors
Same interceptors can be used for both ActiveMQ Artemis client (producer/consumer) and server (broker) side API interceptions. Naturally interceptor classes shall be in your client/server classpath.
Client Side API
Put tnt4j-streams-jms-<VERSION>-artemis-client-interceptor.jar into your client classpath.
To bind TNT4J-Streams ActiveMQ Artemis interceptors for client side API:
System.setProperty(TrackerConfigStore.TNT4J_PROPERTIES_KEY,
"./samples/artemis-interceptors/mybroker0/etc/tnt4j/tnt4j.properties");
ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory( //
"tcp://localhost:61616?" //
+ "incomingInterceptorList=" + PacketInterceptor.class.getName() + "&" //
+ "outgoingInterceptorList=" + PacketInterceptor.class.getName() //
);
try (Connection connection = cf.createConnection()) {
//DO YOUR ARTEMIS MESSAGES PRODUCTION/CONSUMPTION
} finally {
StreamsAgent.waitForStreamsToComplete();
}See ClientInterceptorTest.java for more details.
- Define system property
tnt4j.config(through command line-Dor over API callSystem.setProperty) to define where to look for TNT4J configuration. All the rest of configuration (interceptors, logger, stream/parsers) shall be placed on the same path as TNT4J configuration to be picked automatically. Logger configuration though can be defined individually by setting logger configuration path system properties. - Bind ActiveMQ Artemis interceptor classes over connection factory URL.
incomingInterceptorListdefines interceptor classes for consumer andoutgoingInterceptorListfor producer APIs. These lists can have multiple classes defined using delimiter,. - Finally, the block statement
StreamsAgent.waitForStreamsToComplete()ensures the JVM stays alive until all intercepted packets are processed and sent to jKool/XRay.
Server Side (Broker)
Put tnt4j-streams-jms-<VERSION>-artemis-broker-interceptor.jar into your broker classpath bound directory. e.g., mybroker0/lib.
-
To bind TNT4J-Streams ActiveMQ Artemis interceptors for server side (broker) API edit your broker configuration file
broker.xmlby changingremoting-incoming-interceptorsandremoting-outgoing-interceptorssections:<configuration xmlns="urn:activemq" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xi="http://www.w3.org/2001/XInclude" xsi:schemaLocation="urn:activemq /schema/artemis-configuration.xsd"> <core xmlns="urn:activemq:core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:activemq:core "> <!--...--> <remoting-incoming-interceptors> <class-name>com.jkoolcloud.tnt4j.streams.custom.interceptors.jms.artemis.PacketInterceptor</class-name> <class-name>com.jkoolcloud.tnt4j.streams.custom.interceptors.jms.artemis.AmqpInterceptor</class-name> <class-name>com.jkoolcloud.tnt4j.streams.custom.interceptors.jms.artemis.MQTTInterceptor</class-name> <class-name>com.jkoolcloud.tnt4j.streams.custom.interceptors.jms.artemis.OpenWireInterceptor</class-name> <class-name>com.jkoolcloud.tnt4j.streams.custom.interceptors.jms.artemis.StompInterceptor</class-name> </remoting-incoming-interceptors> <remoting-outgoing-interceptors> <class-name>com.jkoolcloud.tnt4j.streams.custom.interceptors.jms.artemis.PacketInterceptor</class-name> <class-name>com.jkoolcloud.tnt4j.streams.custom.interceptors.jms.artemis.AmqpInterceptor</class-name> <class-name>com.jkoolcloud.tnt4j.streams.custom.interceptors.jms.artemis.MQTTInterceptor</class-name> <class-name>com.jkoolcloud.tnt4j.streams.custom.interceptors.jms.artemis.OpenWireInterceptor</class-name> <class-name>com.jkoolcloud.tnt4j.streams.custom.interceptors.jms.artemis.StompInterceptor</class-name> </remoting-outgoing-interceptors> </core> </configuration>Here we bind all available TNT4J-Streams interceptors, but you can pick just the ones matching your broker-enabled acceptor protocols.
- To define system property
tnt4j.configpointing where to look for TNT4J configuration edit your broker run script fileartemis.cmd(orartemis.sh) by appendingJVM_ARGSvariable definition:-
MS Windows
set JVM_ARGS=%JVM_ARGS% -Dtnt4j.config=%ARTEMIS_INSTANCE_ETC%\tnt4j\tnt4j.properties
-
*nix
JVM_ARGS="$JVM_ARGS -Dtnt4j.config=$ARTEMIS_INSTANCE_ETC/tnt4j/tnt4j.properties"
-
-
Since TNT4J-Streams ActiveMQ Artemis interceptors use their own logging, it is recommended to use a dedicated logging configuration, like the one defined in logging.properties:
############################################################## ### TNT4J Streams configuration section ### ############################################################## # Add additional streams loggers loggers=${loggers},com.jkoolcloud.tnt4j.streams,com.jkoolcloud.tnt4j.streams.activities_prod_log # Streams logging into common log file logger.com.jkoolcloud.tnt4j.streams.level=INFO # Streams logging into dedicated file logger.com.jkoolcloud.tnt4j.streams.handlers=STREAMS_FILE logger.com.jkoolcloud.tnt4j.streams.useParentHandlers=false #### streamed activity entities logger #### logger.com.jkoolcloud.tnt4j.streams.activities_prod_log.level=INFO logger.com.jkoolcloud.tnt4j.streams.activities_prod_log.handlers=ACTIVITIES_PROD logger.com.jkoolcloud.tnt4j.streams.activities_prod_log.useParentHandlers=false # Streams file logger handler.STREAMS_FILE=org.jboss.logmanager.handlers.PeriodicSizeRotatingFileHandler handler.STREAMS_FILE.level=INFO handler.STREAMS_FILE.properties=rotateSize,rotateOnBoot,maxBackupIndex,suffix,append,autoFlush,fileName handler.STREAMS_FILE.rotateSize=10485760 handler.STREAMS_FILE.rotateOnBoot=false handler.STREAMS_FILE.maxBackupIndex=20 handler.STREAMS_FILE.suffix=.yyyyMMdd.gz handler.STREAMS_FILE.append=true handler.STREAMS_FILE.autoFlush=true handler.STREAMS_FILE.fileName=${artemis.instance}/log/tnt4j-streams.log handler.STREAMS_FILE.formatter=STREAMS_PATTERN # Streams file logger pattern formatter.STREAMS_PATTERN=org.jboss.logmanager.formatters.PatternFormatter formatter.STREAMS_PATTERN.properties=pattern formatter.STREAMS_PATTERN.pattern=%d %-5p [%t!%c{1}] - %m%n # Streams file logger handler.ACTIVITIES_PROD=org.jboss.logmanager.handlers.PeriodicSizeRotatingFileHandler handler.ACTIVITIES_PROD.level=INFO handler.ACTIVITIES_PROD.properties=rotateSize,rotateOnBoot,maxBackupIndex,suffix,append,autoFlush,fileName handler.ACTIVITIES_PROD.rotateSize=10485760 handler.ACTIVITIES_PROD.rotateOnBoot=false handler.ACTIVITIES_PROD.maxBackupIndex=20 handler.ACTIVITIES_PROD.suffix=.yyyyMMdd.gz handler.ACTIVITIES_PROD.append=true handler.ACTIVITIES_PROD.autoFlush=true handler.ACTIVITIES_PROD.fileName=${artemis.instance}/log/tnt4j-streams-prod-activities.log handler.ACTIVITIES_PROD.formatter=ACTIVITIES_PATTERN # Streams activities logger pattern formatter.ACTIVITIES_PATTERN=org.jboss.logmanager.formatters.PatternFormatter formatter.ACTIVITIES_PATTERN.properties=pattern formatter.ACTIVITIES_PATTERN.pattern=%m%n ##############################################################If you decide to use a dedicated logging configuration file instead of appending the above section to the default one
<broker>/etc/logging.properties, then do not forget to alter your broker run script fileartemis.cmd(orartemis.sh) by changing theARTEMIS_LOGGING_CONFvariable definition to:-
MS Windows
set ARTEMIS_LOGGING_CONF=%ARTEMIS_INSTANCE_ETC_URI%\tnt4j\logging.properties
-
*nix
ARTEMIS_LOGGING_CONF="$ARTEMIS_INSTANCE_ETC_URI/tnt4j/logging.properties"
-
Full Configuration Preset
See the mybroker0 directory content for the complete interceptor solution configuration. To have all TNT4J in one place you can put it in your broker configuration directory (default is etc) sub-directory like tnt4j.
Logs
TNT4J-Streams ActiveMQ Artemis interceptors produce logs that, by default can be found in <broker>/log directory.