/*
* 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 com.jkoolcloud.tnt4j.core.ActivityListener;
import com.jkoolcloud.tnt4j.core.ActivityStatus;
import com.jkoolcloud.tnt4j.core.OpCompCode;
import com.jkoolcloud.tnt4j.core.OpType;
import com.jkoolcloud.tnt4j.core.Property;
import com.jkoolcloud.tnt4j.core.Snapshot;
import com.jkoolcloud.tnt4j.TrackingLogger;
import com.jkoolcloud.tnt4j.core.Activity;
import com.jkoolcloud.tnt4j.core.Message;
import com.jkoolcloud.tnt4j.core.OpLevel;
import com.jkoolcloud.tnt4j.core.Operation;
import com.jkoolcloud.tnt4j.utils.Useconds;
import com.jkoolcloud.tnt4j.utils.Utils;
/**
* <p>
* Implements application activity tracking and tracing entity, which keeps track of all related tracking events.
* </p>
*
* <p>
* Represents a collection of related {@link TrackingEvent} instances considered to be an application activity.
* These are generally delimited by START/STOP (or START/STOP(EXCEPTION)) calls. {@link TrackingEvent} instances
* can be created using {@link TrackingLogger} or {@link Tracker}. Source activities should be started and
* stopped before being reported using {@code TrackingLogger.tnt()} or {@code Tracker.tnt()} calls.
* {@link TrackingEvent} instances should be registered with a given activity using
* {@code TrackingActivity.tnt()} call which adds and reports a given {@link TrackingEvent} with the activity.
* </p>
*
* @see Activity
* @see ActivityListener
* @see ActivityStatus
* @see Message
* @see Operation
* @see Property
* @see Tracker
* @see TrackingEvent
* @see TrackingLogger
*
* @version $Revision: 9 $
*/
public class TrackingActivity extends Activity {
private boolean reportStarts = false;
private long lastEventNanos = 0;
private TrackerImpl tracker = null;
/**
* Creates a logical application activity object with the specified signature.
*
* @param level activity severity level
* @param name
* activity name
* @throws NullPointerException
* if the signature is {@code null}
* @throws IllegalArgumentException
* if the signature is empty or is too long
* @see #setTrackingId(String)
*/
protected TrackingActivity(OpLevel level, String name) {
super(null, name);
setSeverity(level);
}
/**
* Creates a logical application activity object with the specified signature.
*
* @param level activity severity level
* @param name
* activity name
* @param trk
* {@link Tracker} instance associated with this activity
* @throws NullPointerException
* if the signature is {@code null}
* @throws IllegalArgumentException
* if the signature is empty or is too long
* @see #setTrackingId(String)
*/
protected TrackingActivity(OpLevel level, String name, TrackerImpl trk) {
super(trk.newUUID(), name, trk.getSource());
tracker = trk;
setSeverity(level);
setLocation(trk.getSource());
}
/**
* Creates a logical application activity object with the specified signature.
*
* @param level activity severity level
* @param name
* activity name
* @param signature
* activity signature
* @param trk
* {@link Tracker} instance associated with this activity
* @throws NullPointerException
* if the signature is {@code null}
* @throws IllegalArgumentException
* if the signature is empty or is too long
* @see #setTrackingId(String)
*/
protected TrackingActivity(OpLevel level, String name, String signature, TrackerImpl trk) {
super(signature, name, trk.getSource());
tracker = trk;
setSeverity(level);
setLocation(trk.getSource());
}
/**
* Obtain {@link Tracker} instance associated with this activity
*
* @return {@link Tracker} instance associated with this activity
*/
public Tracker getTracker() {
return tracker;
}
private long getLastElapsedUsec() {
return lastEventNanos > 0? (System.nanoTime() - lastEventNanos)/1000: 0;
}
/**
* Track and Trace given {@link TrackingEvent} instance correlated with current activity
*
* @param event tracking instance to be tracked
*/
public void tnt(TrackingEvent event) {
if (isStopped()) {
throw new IllegalStateException("Activity already stopped: name=" + getName() + ", id=" + this.getTrackingId());
}
add(event);
lastEventNanos = System.nanoTime();
tracker.tnt(event);
}
/**
* Track and Trace given <code>Snapshot</code> instance correlated with current activity
*
* @param snapshot snapshot instance to be tracked
*/
public void tnt(Snapshot snapshot) {
if (isStopped()) {
throw new IllegalStateException("Activity already stopped: name=" + getName() + ", id=" + this.getTrackingId());
}
add(snapshot);
tracker.tnt(snapshot);
}
/**
* Track and Trace a given event and associate it with this activity
*
* @param severity
* severity level of the reported message
* @param opName
* operation name associated with the event message
* @param msg
* event string message
* @param args
* argument list, exception passed along side given message
* @see OpLevel
*/
public void tnt(OpLevel severity, String opName, byte[] msg, Object...args) {
tnt(severity, OpType.EVENT, opName, null, null, 0, msg, args);
}
/**
* Track and Trace a given event and associate it with this activity
*
* @param severity
* severity level of the reported message
* @param type
* operation type
* @param opName
* operation name associated with the event message
* @param msg
* event string message
* @param args
* argument list, exception passed along side given message
* @see OpLevel
*/
public void tnt(OpLevel severity, OpType type, String opName, byte[] msg, Object...args) {
tnt(severity, type, opName, null, null, 0, msg, args);
}
/**
* Track and Trace a given event and associate it with this activity
*
* @param severity
* severity level of the reported message
* @param type
* operation type
* @param opName
* operation name associated with the event message
* @param cid
* event correlator
* @param elapsed
* elapsed time of the event in microseconds.
* @param msg
* event string message
* @param args
* argument list, exception passed along side given message
* @see OpLevel
*/
public void tnt(OpLevel severity, OpType type, String opName, String cid, long elapsed, byte[] msg, Object...args) {
tnt(severity, type, opName, cid, null, elapsed, msg, args);
}
/**
* Track and Trace a given event and associate it with this activity
*
* @param severity
* severity level of the reported message
* @param type
* operation type
* @param opName
* operation name associated with the event message
* @param cid
* event correlator
* @param tag
* message tag
* @param elapsed
* elapsed time of the event in microseconds.
* @param msg
* event binary message
* @param args
* argument list, exception passed along side given message
* @see OpLevel
*/
public void tnt(OpLevel severity, OpType type, String opName, String cid, String tag, long elapsed, byte[] msg, Object...args) {
TrackingEvent event = tracker.newEvent(severity, type, opName, cid, tag, msg, args);
Throwable ex = Utils.getThrowable(args);
long elapsedUsec = elapsed > 0? elapsed: getLastElapsedUsec();
event.stop(ex != null ? OpCompCode.WARNING : OpCompCode.SUCCESS, 0,
ex, Useconds.CURRENT.get(), elapsedUsec);
tnt(event);
}
/**
* Track and Trace a given event and associate it with this activity
*
* @param severity
* severity level of the reported message
* @param opName
* operation name associated with the event message
* @param msg
* event string message
* @param args
* argument list, exception passed along side given message
* @see OpLevel
*/
public void tnt(OpLevel severity, String opName, String msg, Object...args) {
tnt(severity, OpType.EVENT, opName, null, null, 0, msg, args);
}
/**
* Track and Trace a given event and associate it with this activity
*
* @param severity
* severity level of the reported message
* @param type
* operation type
* @param opName
* operation name associated with the event message
* @param msg
* event string message
* @param args
* argument list, exception passed along side given message
* @see OpLevel
*/
public void tnt(OpLevel severity, OpType type, String opName, String msg, Object...args) {
tnt(severity, type, opName, null, null, 0, msg, args);
}
/**
* Track and Trace a given event and associate it with this activity
*
* @param severity
* severity level of the reported message
* @param type
* operation type
* @param opName
* operation name associated with the event message
* @param cid
* event correlator
* @param elapsed
* elapsed time of the event in microseconds.
* @param msg
* event string message
* @param args
* argument list, exception passed along side given message
* @see OpLevel
*/
public void tnt(OpLevel severity, OpType type, String opName, String cid, long elapsed, String msg, Object...args) {
tnt(severity, type, opName, cid, null, elapsed, msg, args);
}
/**
* Track and Trace a given event and associate it with this activity
*
* @param severity
* severity level of the reported message
* @param type
* operation type
* @param opName
* operation name associated with the event message
* @param cid
* event correlator
* @param tag
* message tag
* @param elapsed
* elapsed time of the event in microseconds.
* @param msg
* event string message
* @param args
* argument list, exception passed along side given message
* @see OpLevel
*/
public void tnt(OpLevel severity, OpType type, String opName, String cid, String tag, long elapsed, String msg, Object...args) {
TrackingEvent event = tracker.newEvent(severity, type, opName, cid, tag, msg, args);
Throwable ex = Utils.getThrowable(args);
long elapsedUsec = elapsed > 0? elapsed: getLastElapsedUsec();
event.stop(ex != null ? OpCompCode.WARNING : OpCompCode.SUCCESS, 0,
ex, Useconds.CURRENT.get(), elapsedUsec);
tnt(event);
}
/**
* Instruct activity to report start activity events into the underlying tracker associated with this activity. An
* tracking event will be logged when <code>start(..)</code> method call is made.
*
* @param flag
* enable reporting on start (default is false).
*/
public void reportStart(boolean flag) {
reportStarts = flag;
}
/**
* Indicates that application activity has ended normally without exception.
*
*/
@Override
public void stop() {
stop(ActivityStatus.END, null, 0);
}
/**
* Indicates that application activity has ended normally without exception.
*
* @param elapsedUsec elapsed time in microseconds
*/
@Override
public void stop(long elapsedUsec) {
stop(ActivityStatus.END, null, elapsedUsec);
}
/**
* Indicates that application activity has ended.
*
* @param ex
* exception associated with the activity or null if none.
* @see ActivityStatus
*/
public void stop(Throwable ex) {
stop((ex != null ? ActivityStatus.EXCEPTION : ActivityStatus.END), (ex != null ? OpCompCode.WARNING
: OpCompCode.SUCCESS), ex, 0);
}
/**
* Indicates that application activity has ended.
*
* @param ex
* exception associated with the activity or null if none.
* @param elapsedUsec elapsed time in microseconds
* @see ActivityStatus
*/
public void stop(Throwable ex, long elapsedUsec) {
stop((ex != null ? ActivityStatus.EXCEPTION : ActivityStatus.END), (ex != null ? OpCompCode.WARNING
: OpCompCode.SUCCESS), ex, elapsedUsec);
}
/**
* Indicates that application activity has ended.
*
* @param status
* status with which activity ended.
* @param ex
* exception associated with the activity or null if none.
* @see ActivityStatus
*/
public void stop(ActivityStatus status, Throwable ex) {
stop(status, (ex != null ? OpCompCode.WARNING : OpCompCode.SUCCESS), ex, 0);
}
/**
* Indicates that application activity has ended.
*
* @param status
* status with which activity ended.
* @param ex
* exception associated with the activity or null if none.
* @param elapsedUsec elapsed time in microseconds
* @see ActivityStatus
*/
public void stop(ActivityStatus status, Throwable ex, long elapsedUsec) {
stop(status, (ex != null ? OpCompCode.WARNING : OpCompCode.SUCCESS), ex, elapsedUsec);
}
/**
* Indicates that application activity has ended.
*
* @param status
* status with which activity ended.
* @param ccode
* completion code of the activity.
* @param ex
* exception associated with the activity or null if none.
* @see ActivityStatus
* @see OpCompCode
*/
public void stop(ActivityStatus status, OpCompCode ccode, Throwable ex) {
stop(status, ccode, ex, 0);
}
/**
* Indicates that application activity has ended.
*
* @param status
* status with which activity ended.
* @param ccode
* completion code of the activity.
* @param ex
* exception associated with the activity or null if none.
* @param elapsedUsec elapsed time in microseconds
* @see ActivityStatus
* @see OpCompCode
*/
public void stop(ActivityStatus status, OpCompCode ccode, Throwable ex, long elapsedUsec) {
setException(ex);
setStatus(status);
setCompCode(ccode);
super.stop(Useconds.CURRENT.get(), elapsedUsec);
}
@Override
protected void onStart(long start) {
tracker.push(this);
if (reportStarts) {
tracker.tnt(this);
}
long delta = (System.nanoTime() - start);
super.onStart(start);
tracker.countOverheadNanos(delta);
}
@Override
protected void onStop(long start) {
tracker.pop(this);
super.onStop(start);
long delta = (System.nanoTime() - start);
tracker.countOverheadNanos(delta);
}
@Override
public String toString() {
if (getSnapshotCount() > 0) {
return super.toString() + "," + getSnapshots();
} else {
return super.toString();
}
}
}