大众点评 链路监控cat源码的几个片段分析(初始化 messageId的传递)

版权声明:微信公众号 java架构狮 欢迎转载 请注明出处 https://blog.csdn.net/AlbertFly/article/details/89955184

关注的几个点:

a tcp连接netty的使用 TODO

b 服务间调用messageId rootId parentId的传递如何实现  第4点有提到

c mybatis如何作为一个transation类似的消息也加入 messageTree的 因为之前记录都是的都是url 使用拦截器 参考第5点  

几个片段

1 D:\work\git\taimei\cat\cat-client\src\main\java\com\dianping\cat\Cat.java

初始化cat

// this should be called during application initialization time

public static void initialize(File configFile) {

try {

if (!s_init) {

synchronized (s_instance) {

if (!s_init) {

PlexusContainer container = ContainerLoader.getDefaultContainer();

ModuleContext ctx = new DefaultModuleContext(container);

Module module = ctx.lookup(Module.class, CatClientModule.ID);

if (!module.isInitialized()) {

ModuleInitializer initializer = ctx.lookup(ModuleInitializer.class);

ctx.setAttribute("cat-client-config-file", configFile);

initializer.execute(ctx, module);

}

log("INFO", "Cat is lazy initialized!");

s_init = true;

}

}

}

} catch (Exception e) {

errorHandler(e);

}

}

加载client.xml地方

2 MessageTree 的一个主要实现

public class DefaultMessageTree implements MessageTree {

private ByteBuf m_buf;

private String m_domain;

private String m_hostName;

private String m_ipAddress;

private Message m_message;

private String m_messageId;

private String m_parentMessageId;

private String m_rootMessageId;

private String m_sessionToken;

private String m_threadGroupName;

private String m_threadId;

private String m_threadName;

private MessageId m_formatMessageId;

private boolean m_discard = true;

private boolean m_processLoss = false;

private boolean m_hitSample = false;

private List<Event> events = new ArrayList<Event>(); // by flyer messageTree主要存储的信息 主要就是这些message

private List<Transaction> transactions = new ArrayList<Transaction>();

private List<Heartbeat> heartbeats = new ArrayList<Heartbeat>();

private List<Metric> metrics = new ArrayList<Metric>();

3 有很多context类

主要看这个上下文

@Named(type = MessageManager.class)

public class DefaultMessageManager extends ContainerHolder implements MessageManager, Initializable, LogEnabled {

还有这个

4 catFilter写入rootId parentId messageId 信息到header传递给下一个请求.

代码路径

package com.dianping.cat.servlet;


public class CatFilter implements Filter {

ID_SETUP {
			private String m_servers;

			private String getCatServer() {
				if (m_servers == null) {
					DefaultMessageManager manager = (DefaultMessageManager) Cat.getManager();
					List<Server> servers = manager.getConfigManager().getServers();

					m_servers = Joiners.by(',').join(servers, new IBuilder<Server>() {
						@Override
						public String asString(Server server) {
							String ip = server.getIp();
							Integer httpPort = server.getHttpPort();

							if ("127.0.0.1".equals(ip)) {
								ip = NetworkInterfaceManager.INSTANCE.getLocalHostAddress();
							}

							return ip + ":" + httpPort;
						}
					});
				}

				return m_servers;
			}

			@Override
			public void handle(Context ctx) throws IOException, ServletException {
				boolean isTraceMode = Cat.getManager().isTraceMode();

				HttpServletRequest req = ctx.getRequest();
				HttpServletResponse res = ctx.getResponse();
				MessageProducer producer = Cat.getProducer();
				int mode = ctx.getMode();

				switch (mode) {
				case 0:
					ctx.setId(producer.createMessageId());
					break;
				case 1:
					ctx.setRootId(req.getHeader("X-CAT-ROOT-ID"));
					ctx.setParentId(req.getHeader("X-CAT-PARENT-ID"));
					ctx.setId(req.getHeader("X-CAT-ID"));
					break;
				case 2:
					ctx.setRootId(producer.createMessageId());
					ctx.setParentId(ctx.getRootId());
					ctx.setId(producer.createMessageId());
					break;
				default:
					throw new RuntimeException(String.format("Internal Error: unsupported mode(%s)!", mode));
				}

				if (isTraceMode) {
					MessageTree tree = Cat.getManager().getThreadLocalMessageTree();

					tree.setMessageId(ctx.getId());
					tree.setParentMessageId(ctx.getParentId());
					tree.setRootMessageId(ctx.getRootId());

					res.setHeader("X-CAT-SERVER", getCatServer());

					switch (mode) {
					case 0:
						res.setHeader("X-CAT-ROOT-ID", ctx.getId());
						break;
					case 1:
						res.setHeader("X-CAT-ROOT-ID", ctx.getRootId());
						res.setHeader("X-CAT-PARENT-ID", ctx.getParentId());
						res.setHeader("X-CAT-ID", ctx.getId());
						break;
					case 2:
						res.setHeader("X-CAT-ROOT-ID", ctx.getRootId());
						res.setHeader("X-CAT-PARENT-ID", ctx.getParentId());
						res.setHeader("X-CAT-ID", ctx.getId());
						break;
					}
				}

				ctx.handle();
			}
		},

5 mybatis信息采集的问题

官方整理了一个mybatis的拦截器

https://github.com/dianping/cat/blob/master/integration/mybatis/CatMybatisPlugin.java

主要代码如下

@Override
  public Object intercept(Invocation invocation) throws Throwable {
  MappedStatement mappedStatement = this.getStatement(invocation);
  String methodName = this.getMethodName(mappedStatement);
  Transaction t = Cat.newTransaction("SQL", methodName);
   
  String sql = this.getSql(invocation,mappedStatement);
  SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
  Cat.logEvent("SQL.Method", sqlCommandType.name().toLowerCase(), Message.SUCCESS, sql);
   
  String url = this.getSQLDatabaseUrlByStatement(mappedStatement);
  Cat.logEvent("SQL.Database", url);
   
  return doFinish(invocation,t);
  }

 可看到是主动写入一个Transaction (就是一个message) 到当前的messageTree里面 然后就采集到了,可以跟一下里面代码 

下面是关闭的过程

猜你喜欢

转载自blog.csdn.net/AlbertFly/article/details/89955184
今日推荐