1. 生产消息newTransaction,检查上下文ThreadLocal<Context>是否已经初始化,没有则通过m_manager.setup()初始化。初始化消息DefaultTransaction,转交给默认消息管理开始消息处理,m_manager.start(transaction, false);如果是该线程的第一个消息则保存在MessageTree
public void start(Transaction transaction, boolean forked) {
if (!m_stack.isEmpty()) {
// Do NOT make strong reference from parent transaction to forked transaction.
// Instead, we create a "soft" reference to forked transaction later, via linkAsRunAway()
// By doing so, there is no need for synchronization between parent and child threads.
// Both threads can complete() anytime despite the other thread.
Transaction parent = m_stack.peek();
addTransactionChild(transaction, parent);
} else {
m_tree.setMessage(transaction);
}
if (!forked) {
m_stack.push(transaction);
}
}
否则就和Stack中的栈顶消息比较生成时间,超过本时段结束时间10s即到达下一时段或者子消息的数量超过配置的最大值,这时深度复制最初的消息以及它的子消息,添加事件消息消息DefaultEvent,最后设置ctx.m_totalDurationInMicros为对应的生成时间,也就表示该值大于0。
public void truncateAndFlush(Context ctx, long timestamp) {
MessageTree tree = ctx.m_tree;
Stack<Transaction> stack = ctx.m_stack;
Message message = tree.getMessage();
if (message instanceof DefaultTransaction) {
String id = tree.getMessageId();
if (id == null) {
id = nextMessageId();
tree.setMessageId(id);
}
String rootId = tree.getRootMessageId();
String childId = nextMessageId();
DefaultTransaction source = (DefaultTransaction) message;
DefaultTransaction target = new DefaultTransaction(source.getType(), source.getName(),
DefaultMessageManager.this);
target.setTimestamp(source.getTimestamp());
target.setDurationInMicros(source.getDurationInMicros());
target.addData(source.getData().toString());
target.setStatus(Message.SUCCESS);
migrateMessage(stack, source, target, 1);
for (int i = stack.size() - 1; i >= 0; i--) {
DefaultTransaction t = (DefaultTransaction) stack.get(i);
t.setTimestamp(timestamp);
t.setDurationStart(System.nanoTime());
}
DefaultEvent next = new DefaultEvent("RemoteCall", "Next");
next.addData(childId);
next.setStatus(Message.SUCCESS);
target.addChild(next);
// tree is the parent, and m_tree is the child.
MessageTree t = tree.copy();
t.setMessage(target);
ctx.m_tree.setMessageId(childId);
ctx.m_tree.setParentMessageId(id);
ctx.m_tree.setRootMessageId(rootId != null ? rootId : id);
ctx.m_length = stack.size();
ctx.m_totalDurationInMicros = ctx.m_totalDurationInMicros + target.getDurationInMicros();
flush(t);
}
}
最后通过TcpSocketSender#send把他放入不同的队列中,原子队列或者普通消息队列,m_queue.offer(tree, m_manager.getSample()),这里可以设置采样sampleRatio,发送完后执行reset();这时只清除异常信息。最后把当前的消息添加到栈顶消息的子集中,同时记录消息总长度m_length,该值的初始值为1。最后把消息压入栈中。
private void addTransactionChild(Message message, Transaction transaction) {
long treePeriod = trimToHour(m_tree.getMessage().getTimestamp());
long messagePeriod = trimToHour(message.getTimestamp() - 10 * 1000L); // 10 seconds extra time allowed
if (treePeriod < messagePeriod || m_length >= m_configManager.getMaxMessageLength()) {
m_validator.truncateAndFlush(this, message.getTimestamp());
}
transaction.addChild(message);
m_length++;
}
2. 设置对应的成功状态h.setStatus(Message.SUCCESS);最后结束消息的构造t.complete();设置完成状态setCompleted(true);结束消息的传送后清除m_context.remove();弹出栈顶的消息,m_validator.validate判断消息有没有正常结尾,也就是设置完成状态,否则增加子事件消息DefaultEvent event = new DefaultEvent("cat", "BadInstrument");设置完成状态
public boolean end(DefaultMessageManager manager, Transaction transaction) {
if (!m_stack.isEmpty()) {
Transaction current = m_stack.pop();
if (transaction == current) {
m_validator.validate(m_stack.isEmpty() ? null : m_stack.peek(), current);
} else {
while (transaction != current && !m_stack.empty()) {
m_validator.validate(m_stack.peek(), current);
current = m_stack.pop();
}
}
if (m_stack.isEmpty()) {
MessageTree tree = m_tree.copy();
m_tree.setMessageId(null);
m_tree.setMessage(null);
if (m_totalDurationInMicros > 0) {
adjustForTruncatedTransaction((Transaction) tree.getMessage());
}
manager.flush(tree);
return true;
}
}
return false;
}
那什么时候才会进入下面这个else呢?开始transactionA,开始transactionB,但是完成的时候是transactionA,transactionB。正确的做法是transactionB,transactionA。否则这个时候就会给强制给transactionB设置完成状态。
public void validate(Transaction parent, Transaction transaction) {
if (transaction.isStandalone()) {
List<Message> children = transaction.getChildren();
int len = children.size();
for (int i = 0; i < len; i++) {
Message message = children.get(i);
if (message instanceof Transaction) {
validate(transaction, (Transaction) message);
}
}
if (!transaction.isCompleted() && transaction instanceof DefaultTransaction) {
// missing transaction end, log a BadInstrument event so that
// developer can fix the code
markAsNotCompleted((DefaultTransaction) transaction);
}
}
}
private void markAsNotCompleted(DefaultTransaction transaction) {
DefaultEvent event = new DefaultEvent("cat", "BadInstrument");
event.setStatus("TransactionNotCompleted");
event.setCompleted(true);
transaction.addChild(event);
transaction.setCompleted(true);
}
这个m_stack.isEmpty()又是怎么起作用的?如果是上面这个错误情况的话,这个条件可以满足,还有就是正常情况下,当transactionB设置完成状态时,这个条件不会满足,也就不会给发送消息,进而也能保证整个流程的顺利执行,当transactionA设置完成状态之后,m_stack.isEmpty()就会满足,然后发送消息。检验完栈中所有的元素后,深拷贝最初的消息MessageTree,释放最初的消息,最后把消息通过TcpSocketSender发送到消息队列中。
如果之前生成消息的时候超过了时间或者数量限制的话,就会产生截断信息,也就是m_totalDurationInMicros会大于0,这是就会给根消息增加子事件消息,并且设置m_totalDurationInMicros = 0
private void adjustForTruncatedTransaction(Transaction root) {
DefaultEvent next = new DefaultEvent("TruncatedTransaction", "TotalDuration");
long actualDurationInMicros = m_totalDurationInMicros + root.getDurationInMicros();
next.addData(String.valueOf(actualDurationInMicros));
next.setStatus(Message.SUCCESS);
root.addChild(next);
m_totalDurationInMicros = 0;
}
发送完后调用reset();清理栈,移除线程上下文等。那ctx.m_totalDurationInMicros == 0该条件什么时候满足呢,一个就是整个线程中的消息没有超过时间或者数量限制,这时m_totalDurationInMicros的默认值就是0,另一个情况就是超过限制,如上,在截断后给该值设置为0,保证该线程结束后能清理掉该清理的线程上下文,栈变量等。
public void reset() {
// destroy current thread local data
Context ctx = m_context.get();
if (ctx != null) {
if (ctx.m_totalDurationInMicros == 0) {
ctx.m_stack.clear();
ctx.m_knownExceptions.clear();
m_context.remove();
} else {
ctx.m_knownExceptions.clear();
}
}
}