/*
* Copyright 2014-2015 JKOOL, LLC.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jkoolcloud.tnt4j.tracker;
import java.security.NoSuchAlgorithmException;
import java.util.Collection;
import java.util.Set;
import com.jkoolcloud.tnt4j.core.OpCompCode;
import com.jkoolcloud.tnt4j.core.OpType;
import com.jkoolcloud.tnt4j.source.Source;
import com.jkoolcloud.tnt4j.core.Message;
import com.jkoolcloud.tnt4j.core.OpLevel;
import com.jkoolcloud.tnt4j.core.Operation;
import com.jkoolcloud.tnt4j.core.Relate2;
import com.jkoolcloud.tnt4j.core.Trackable;
import com.jkoolcloud.tnt4j.core.UsecTimestamp;
import com.jkoolcloud.tnt4j.utils.Useconds;
import com.jkoolcloud.tnt4j.utils.Utils;
/**
* <p><code>TrackingEvent</code> implements tracking for a specific application sub-activity. Applications create
* instances of <code>TrackingEvent</code> after initiating an application activity using <code>Tracker</code>
* logger instance or <code>TrackingLogger</code>. Each <code>TrackingEvent</code> can be timed independently using
* start()/stop() method calls and reported and logged using <code>Tracker.reportEvent()</code> method call.</p>
*
* <p>A <code>TrackingEvent</code> can represent a specific tracking event that application creates for
* every discrete activity such as JDBC, JMS, SOAP or any other relevant application activity.
* Source developers must obtain a <code>Tracker</code> instance via <code>DefaultTrackerFactory</code>, create
* instances of <code>TrackingEvent</code> and use <code>TrackingActivity.tnt()</code> to associate and report
* tracking events.
*
* <p>A <code>Tracker</code> start()/end() used to mark application activity boundaries.</p>
*
* <p>Any pair of <code>TrackingEvent</code> instances are related when event correlators match.
* <code>TrackingEvent</code> A is related to <code>TrackingEvent</code> B when {@code A.getCorrelator() == B.getCorrelator()}.
* Developers may use signatures and or correlators to correlate tracking events across application/server boundaries.
* <code>TrackingEvent</code> A is the same as <code>TrackingEvent</code> B if the corresponding event signature are identical: meaning
* {@code A.getSignature() == B.getSignature()}. Currently each <code>TrackingEvent</code> gets assigned a unique event signature using
* <code>TrackingEvent.newUUID()</code> call. Signatures can be changed using {@code TrackingEvent.setSiganture()} method call.
* Signatures and correlators must be set before making {@code TrackingActivity.tnt()} call.
*
* <p>Below is example of how to set <code>TrackingEvent</code> correlator and operation type for a sender application:
* <pre>
* <code>
* TrackingLogger logger = TrackingLogger.getInstance("com.jkoolcloud.appl.name"); // register and obtain Tracker logger instance
* TrackingActivity activity = logger.newActivity(); // create a new application activity timing
* TrackingEvent event = logger.newEvent(OpLevel.INFO, OpType.SEND, "SendOrder", "Sending order"); // create a sender tracking event
* activity.start(); // start application activity timing
* event.start(); // start timing a tracking event
* String order_id = null;
* try {
* ...
* ...
* order_id = request.getOrderId(); // sample code to obtain order id which will be used as a correlator
* event.setCorrelator(order_id); // set event correlator obtained from order_id
* event.stop(); // stop timing tracking event
* } catch (SQLException e) {
* event.stop(e); // stop timing tracking event and associate an exception
* ...
* } finally {
* activity.stop();
* activity.tnt(event); // report a tracking event
* logger.tnt(activity); // end activity timing
* }
* </code>
* </pre>
* <p>Below is example of corresponding receiver application:
* <pre>
* <code>
* TrackingLogger tracker = TrackingLogger.getInstance("com.jkoolcloud.appl.name"); // register and obtain Tracker logger instance
* TrackingActivity activity = tracker.newActivity(); // create a new application activity timing
* TrackingEvent event = tracker.newEvent(OpLevel.INFO, OpType.RECEIVE, "RecvOrder", "Received order"); // create a receiver tracking event
* activity.start(); // start application activity timing
* event.start(); // start timing a tracking event
* String order_id = null;
* try {
* ...
* ...
* order_id = response.getOrderId(); // sample code to obtain order id which will be used as a correlator
* event.setCorrelator(order_id); // set event correlator obtained from the received order_id
* event.stop(); // stop timing tracking event
* } catch (SQLException e) {
* event.stop(e); // stop timing tracking event and associate an exception
* ...
* } finally {
* activity.stop();
* activity.tnt(event); // report a tracking event
* tracker.tnt(activity); // end activity timing
* }
* </code>
* </pre>
* @see Message
* @see OpLevel
* @see DefaultTrackerFactory
* @see OpCompCode
* @see OpType
*
* @version $Revision: 7 $
*
*/
public class TrackingEvent extends Message implements Trackable, Relate2<Source> {
private Source source;
private String parent;
private String sign;
Operation operation;
private TrackerImpl tracker;
private final Source [] relation = new Source[2];
private OpType relationType = OpType.NOOP;
/**
* Create a new NOOP tracking event
* This constructor will assign a unique event signature using newUUID() call
*
* @param tr tracker instance
*/
protected TrackingEvent(TrackerImpl tr) {
this(tr, null, OpLevel.NONE, OpType.NOOP, Operation.NOOP, (String)null, (String)null, (String)null);
}
/**
* Create a new instance of tracking event that can be timed and reported.
* This constructor will assign a unique event signature using newUUID() call
*
* @param tr tracker instance
* @param src event source
* @param severity severity level
* @param opName operation name associated with this event (tracking event name)
* @param correlator associated with this event (could be unique or passed from a correlated activity)
* @param msg text message associated with this event
* @param args argument list passed along side the message
*/
protected TrackingEvent(TrackerImpl tr, Source src, OpLevel severity, String opName, String correlator, String msg, Object...args) {
this(tr, src, severity, OpType.EVENT, opName, correlator, null, msg, args);
}
/**
* Create a new instance of tracking event that can be timed and reported.
* This constructor will assign a unique event signature using newUUID() call
*
* @param tr tracker instance
* @param src event source
* @param severity severity level
* @param opName operation name associated with this event (tracking event name)
* @param correlators associated with this event (could be unique or passed from a correlated activity)
* @param msg text message associated with this event
* @param args argument list passed along side the message
*/
protected TrackingEvent(TrackerImpl tr, Source src, OpLevel severity, String opName, Collection<String> correlators, String msg, Object...args) {
this(tr, src, severity, OpType.EVENT, opName, correlators, null, msg, args);
}
/**
* Create a new instance of tracking event that can be timed and reported.
* This constructor will assign a unique event signature using newUUID() call
*
* @param tr tracker instance
* @param src event source
* @param severity severity level
* @param opName operation name associated with this event (tracking event name)
* @param correlator associated with this event (could be unique or passed from a correlated activity)
* @param msg binary message associated with this event
* @param args argument list passed along side the message
*/
protected TrackingEvent(TrackerImpl tr, Source src, OpLevel severity, String opName, String correlator, byte[] msg, Object...args) {
this(tr, src, severity, OpType.EVENT, opName, correlator, null, msg, args);
}
/**
* Create a new instance of tracking event that can be timed and reported.
* This constructor will assign a unique event signature using newUUID() call
*
* @param tr tracker instance
* @param src event source
* @param severity severity level
* @param opName operation name associated with this event (tracking event name)
* @param correlators associated with this event (could be unique or passed from a correlated activity)
* @param msg binary message associated with this event
* @param args argument list passed along side the message
*/
protected TrackingEvent(TrackerImpl tr, Source src, OpLevel severity, String opName, Collection<String> correlators, byte[] msg, Object...args) {
this(tr, src, severity, OpType.EVENT, opName, correlators, null, msg, args);
}
/**
* Create a new instance of tracking event that can be timed and reported.
*
* @param tr tracker instance
* @param src event source
* @param severity severity level
* @param opType operation type
* @param opName operation name associated with this event (tracking event name)
* @param correlator associated with this event (could be unique or passed from a correlated activity)
* @param tag associated with this event
* @param msg text message associated with this event
* @param args argument list passed along side the message
* @see OpLevel
* @see OpType
*/
protected TrackingEvent(TrackerImpl tr, Source src, OpLevel severity, OpType opType, String opName, String correlator, String tag, String msg, Object...args) {
super(null, msg, args);
tracker = tr;
operation = new Operation(opName, opType);
operation.setSeverity(severity);
operation.setCorrelator(correlator);
operation.setException(Utils.getThrowable(args));
setSource(src);
setLocation(src);
setTag(tag);
}
/**
* Create a new instance of tracking event that can be timed and reported.
*
* @param tr tracker instance
* @param src event source
* @param severity severity level
* @param opType operation type
* @param opName operation name associated with this event (tracking event name)
* @param correlators associated with this event (could be unique or passed from a correlated activity)
* @param tags associated with this event
* @param msg text message associated with this event
* @param args argument list passed along side the message
* @see OpLevel
* @see OpType
*/
protected TrackingEvent(TrackerImpl tr, Source src, OpLevel severity, OpType opType, String opName, Collection<String> correlators, Collection<String> tags, String msg, Object...args) {
super(null, msg, args);
tracker = tr;
operation = new Operation(opName, opType);
operation.setSeverity(severity);
operation.setCorrelator(correlators);
operation.setException(Utils.getThrowable(args));
setSource(src);
setLocation(src);
setTag(tags);
}
/**
* Create a new instance of tracking event that can be timed and reported.
*
* @param tr tracker instance
* @param src event source
* @param severity severity level
* @param opType operation type
* @param opName operation name associated with this event (tracking event name)
* @param correlators associated with this event (could be unique or passed from a correlated activity)
* @param tags associated with this event
* @param msg binary message associated with this event
* @param args argument list passed along side the message
* @see OpLevel
* @see OpType
*/
protected TrackingEvent(TrackerImpl tr, Source src, OpLevel severity, OpType opType, String opName, Collection<String> correlators, Collection<String> tags, byte[] msg, Object...args) {
super(null, msg, args);
tracker = tr;
operation = new Operation(opName, opType);
operation.setSeverity(severity);
operation.setCorrelator(correlators);
operation.setException(Utils.getThrowable(args));
setSource(src);
setLocation(src);
setTag(tags);
}
/**
* Create a new instance of tracking event that can be timed and reported.
*
* @param tr tracker instance
* @param src event source
* @param severity severity level
* @param opType operation type
* @param opName operation name associated with this event (tracking event name)
* @param correlator associated with this event (could be unique or passed from a correlated activity)
* @param tag associated with this event
* @param msg binary message associated with this event
* @param args argument list passed along side the message
* @see OpLevel
* @see OpType
*/
protected TrackingEvent(TrackerImpl tr, Source src, OpLevel severity, OpType opType, String opName, String correlator, String tag, byte[] msg, Object...args) {
super(null, msg, args);
tracker = tr;
operation = new Operation(opName, opType);
operation.setSeverity(severity);
operation.setCorrelator(correlator);
operation.setException(Utils.getThrowable(args));
setSource(src);
setLocation(src);
setTag(tag);
}
/**
* Return string representation of this tracking event
*
* @return string representation of the tracking event
*/
@Override
public String toString() {
return "{" + operation.getSeverity()
+ ",[" + getMessage() + "],"
+ "[" + operation.getName() + "],"
+ super.toString()
+ "," + operation + "}";
}
/**
* Returns true of operation is a NOOP
*
* @return true if operation is a NOOP, false otherwise
*/
public boolean isNoop() {
return operation.isNoop();
}
/**
* Determine if operation was ever started
*
* @return true if operation was started, false otherwise
*/
public boolean isStarted() {
return operation.isStarted();
}
/**
* Determine if operation was ever stopped
*
* @return true if operation was stopped, false otherwise
*/
public boolean isStopped() {
return operation.isStopped();
}
/**
* Return current severity level associated with this event
*
* @return severity level
*/
public OpLevel getSeverity() {
return operation.getSeverity();
}
@Override
public void setParentId(Trackable parentObject) {
parent = parentObject.getTrackingId();
if (source == null)
source = parentObject.getSource();
}
@Override
public void setParentId(String parentId) {
parent = parentId;
}
@Override
public String getParentId() {
return parent;
}
@Override
public Source getSource() {
return source;
}
@Override
public void setCorrelator(String...cids) {
operation.setCorrelator(cids);
}
@Override
public void setCorrelator(Collection<String> cids) {
operation.setCorrelator(cids);
}
@Override
public Set<String> getCorrelator() {
return operation.getCorrelator();
}
/**
* Gets the location string associated with the tracking event such as GPS locator.
*
* @return location string for tracking event
*/
public String getLocation() {
return operation.getLocation();
}
/**
* Sets the location associated with the tracking event such as GPS locator.
*
* @param location location string for tracking event
*/
public void setLocation(String location) {
operation.setLocation(location);
}
/**
* Sets the location associated with the tracking event such as GPS locator.
*
* @param location location string for tracking event
*/
public void setLocation(Source location) {
operation.setLocation(location);
}
/**
* Indicates that application tracking event has started at the specified startTime
*
* @param startTimeUsc start time of the tracking event (usec)
*/
public void start(long startTimeUsc) {
operation.start(startTimeUsc);
}
/**
* Indicates that application tracking event has started.
*
*/
public void start() {
operation.start();
}
/**
* Indicates that application tracking event has started given a
* specific time stamp.
*
* @param time when operation started
*/
public void start(UsecTimestamp time) {
operation.start(time);
}
/**
* Indicates that application tracking event has ended.
*
*/
public void stop() {
operation.stop();
}
/**
* Indicates that application tracking event has ended.
*
* @param time when operation stopped
* @param elapsedUsec elapsed time of the event in microseconds
*/
public void stop(UsecTimestamp time, long elapsedUsec) {
operation.stop(time, elapsedUsec);
}
/**
* Indicates that application tracking event has ended.
*
* @param elaspedTime elapsed time of this event in (usec)
*/
public void stop(long elaspedTime) {
operation.stop(Useconds.CURRENT.get(), elaspedTime);
}
/**
* Indicates that application tracking event has ended.
*
* @param endTimeUsec ending time associated with the event (usec)
* @param elapsedUsec elapsed time in (usec)
*/
public void stop(long endTimeUsec, long elapsedUsec) {
operation.stop(endTimeUsec, elapsedUsec);
}
/**
* Indicates that application tracking event has ended.
* Event completion code is set to <code>OpCompCode.WARNING</code>
*
* @param opEx exception associated with this tracking event
*/
public void stop(Throwable opEx) {
operation.setException(opEx);
operation.stop();
operation.setCompCode(opEx != null? OpCompCode.WARNING: OpCompCode.SUCCESS);
}
/**
* Indicates that application tracking event has ended.
* Event completion code is set to <code>OpCompCode.WARNING</code>
*
* @param opEx exception associated with this tracking event
* @param elapsedUsec elapsed time in (usec)
*/
public void stop(Throwable opEx, long elapsedUsec) {
operation.setException(opEx);
operation.setCompCode(opEx != null? OpCompCode.WARNING: OpCompCode.SUCCESS);
operation.stop(Useconds.CURRENT.get(), elapsedUsec);
}
/**
* Indicates that application tracking event has ended.
*
* @param ccode completion code of the tracking event
* @param rcode reason code associated with this tracking event
* @see OpCompCode
*/
public void stop(OpCompCode ccode, int rcode) {
operation.stop();
operation.setCompCode(ccode);
operation.setReasonCode(rcode);
}
/**
* Indicates that application tracking event has ended.
*
* @param ccode completion code of the tracking event
* @param opEx exception associated with this tracking event
* @see OpCompCode
*/
public void stop(OpCompCode ccode, Throwable opEx) {
operation.stop();
operation.setException(opEx);
operation.setCompCode(ccode);
}
/**
* Indicates that application tracking event has ended.
*
* @param ccode completion code of the tracking event
* @param rcode reason code associated with this tracking event
* @param opEx exception associated with this tracking event
* @see OpCompCode
*/
public void stop(OpCompCode ccode, int rcode, Throwable opEx) {
operation.setException(opEx);
operation.setCompCode(ccode);
operation.setReasonCode(rcode);
operation.stop();
}
/**
* Indicates that application tracking event has ended.
*
* @param ccode completion code of the tracking event
* @param rcode reason code associated with this tracking event
* @param opEx exception associated with this tracking event
* @param endTimeUsec time when the tracking event has ended (usec)
* @see OpCompCode
*/
public void stop(OpCompCode ccode, int rcode, Throwable opEx, long endTimeUsec) {
operation.setException(opEx);
operation.setCompCode(ccode);
operation.setReasonCode(rcode);
operation.stop(endTimeUsec);
}
/**
* Indicates that application tracking event has ended.
*
* @param ccode completion code of the tracking event
* @param rcode reason code associated with this tracking event
* @param opEx exception associated with this tracking event
* @param endTimeUsec time when the tracking event has ended (usec)
* @param elpasedUsec elapsed time in (usec)
* @see OpCompCode
*/
public void stop(OpCompCode ccode, int rcode, Throwable opEx, long endTimeUsec, long elpasedUsec) {
operation.setException(opEx);
operation.setCompCode(ccode);
operation.setReasonCode(rcode);
operation.stop(endTimeUsec, elpasedUsec);
}
/**
* Indicates that application tracking event has ended.
*
* @param ccode completion code of the tracking event
* @param rcode reason code associated with this tracking event
* @param opEx exception associated with this tracking event
* @param endTime time when the tracking event has ended (usec)
* @param elpasedUsec elapsed time in (usec)
* @see OpCompCode
*/
public void stop(OpCompCode ccode, int rcode, Throwable opEx, UsecTimestamp endTime, long elpasedUsec) {
operation.setException(opEx);
operation.setCompCode(ccode);
operation.setReasonCode(rcode);
operation.stop(endTime, elpasedUsec);
}
/**
* Obtain a handle to the {@link Operation} associated with this tracking event
*
*@return operation handle associated with this event
*/
public Operation getOperation() {
return operation;
}
/**
* Sign current event with hash/signature based on trackers
* configured signature factory.
*
* @return signed self
* @throws NoSuchAlgorithmException
*
*/
public TrackingEvent sign() throws NoSuchAlgorithmException {
if (tracker != null) {
setSignature(tracker.getConfiguration().getSignFactory().sign(this));
}
return this;
}
@Override
public OpType getType() {
return operation.getType();
}
@Override
public void setSource(Source src) {
source = src;
}
@Override
public long getTTL() {
return operation.getTTL();
}
@Override
public void setTTL(long ttl) {
operation.setTTL(ttl);
}
@Override
public Relate2<Source> relate2(Source srcA, Source srcB, OpType type) {
relation[OBJ_ONE] = srcA;
relation[OBJ_TWO] = srcB;
relationType = type;
return this;
}
@Override
public Relate2<Source> relate2(Source srcB, OpType type) {
return relate2(getSource(), srcB, type);
}
@Override
public OpType get2Type() {
return relationType;
}
@Override
public Source get2(int index) {
return relation[index];
}
@Override
public Relate2<Source> clear2() {
relation[OBJ_ONE] = null;
relation[OBJ_TWO] = null;
relationType = OpType.NOOP;
return this;
}
@Override
public String getSignature() {
return sign;
}
@Override
public void setSignature(String sign) {
this.sign = sign;
}
}