Skip to content

Instantly share code, notes, and snippets.

@wu-sheng
Created December 28, 2016 03:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wu-sheng/0cf0aaa5d532b26b74e973cf80ed594a to your computer and use it in GitHub Desktop.
Save wu-sheng/0cf0aaa5d532b26b74e973cf80ed594a to your computer and use it in GitHub Desktop.
Transaction Trace
/**
* Created by wusheng on 2016/12/21.
*/
public class Transaction {
// 当前线程事务GUID
private java.lang.String traceId;
// 相关性上级GUID
private java.lang.String refTraceId;
// 全局 GUID
private java.lang.String tripId;
private List<Span> finishedSpan = new LinkedList<Span>();
private SpanNodeStack activeSpanStack = new SpanNodeStack();
private int spanIdGenerator = 0;
private TransactionContextHolder contextHolder = new TransactionContextHolder();
Transaction() {
traceId = TransactionGuidFactory.generateGuid();
}
public Span createSpan() {
Span parentSpan = activeSpanStack.peek();
Span span;
if (parentSpan == null) {
span = new Span(this, spanIdGenerator++);
} else {
span = new Span(this, spanIdGenerator++, parentSpan);
}
activeSpanStack.push(span);
return span;
}
public Span activeSpan() {
Span span = activeSpanStack.peek();
if (span == null) {
span = new NoopSpan();
}
return span;
}
public void stopSpan(Span span) {
Span lastSpan = activeSpanStack.peek();
if (lastSpan == span) {
finishedSpan.add(activeSpanStack.pop());
} else {
throw new UnexpectedActiveSpanException(span);
}
if (activeSpanStack.isEmpty()) {
this.finish();
}
}
public void setRefTraceId(java.lang.String refTraceId) {
this.refTraceId = refTraceId;
}
public void setTripId(java.lang.String tripId) {
this.tripId = tripId;
}
public String getTraceId() {
return traceId;
}
public String getRefTraceId() {
return refTraceId;
}
public String getTripId() {
return tripId;
}
public TransactionContextHolder getContextHolder() {
return contextHolder;
}
private void finish() {
ServiceFactory.getServiceManager().getTransactionDisruptorBufferService().finishTransaction(this);
TransactionManager.instance().finish();
}
static class SpanNodeStack {
/**
* 单JVM的单线程,埋点数量一般不会超过20.
* 超过20会影响性能,不推荐使用
*/
private List<Span> spans = new ArrayList<Span>(20);
public Span pop() {
return spans.remove(getTopElementIdx());
}
public void push(Span span) {
spans.add(spans.size(), span);
}
public Span peek() {
if (spans.isEmpty()) {
return null;
}
return spans.get(getTopElementIdx());
}
private int getTopElementIdx() {
return spans.size() - 1;
}
boolean isEmpty() {
return spans.isEmpty();
}
}
static class TransactionContextHolder {
private final Map<Connection, JdbcDataSourceConnectionFactory> connectionToFactory = new ConcurrentHashMap<Connection, JdbcDataSourceConnectionFactory>();
private final Map<Statement, String> statementToSql = new ConcurrentHashMap<Statement, String>();
public void putConnectionFactory(Connection connection, JdbcDataSourceConnectionFactory jdbcDataSourceConnectionFactory) {
connectionToFactory.put(connection, jdbcDataSourceConnectionFactory);
}
public JdbcDataSourceConnectionFactory getConnectionFactory(Connection connection) {
if (connection == null)
return null;
return connectionToFactory.get(connection);
}
public void putSql(Statement statement, String sql) {
statementToSql.put(statement, sql);
}
public String getSql(Statement statement) {
if (statement == null)
return null;
return statementToSql.get(statement);
}
}
public static class TransactionHolder{
private Transaction instance;
public TransactionHolder(){
}
public void setValue(Transaction transaction){
this.instance = transaction;
}
public Transaction getValue(){
return this.instance;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment