JRT提供的是业务脚本化,在Windows下开发时候有问题时候可以借助System.out.prinln输出信息到tomcat的控制台来调试程序。在Linux上发布后看输出就得到catalina.out里,这样虽然也能用xftp连着看日志,但是有个致命问题是:部署环境有很多用户在使用,输出日志的话日志太多了,根本难以辅助跟踪问题(开发环境只有一个人用就好查日志)。
为了简化JRT跟踪问题,设计新的日志跟踪体系:
在业务基类里共提供zw、zwg、zwu、zwk几个写日志的方法。其中zw输出日志到相同IP的调试端,zwg输出到登录相同组的调试端、zwu输出到相同登录用户的调试端、zwk输出到指定key的调试端。最常用的是zw,自己操作网站功能来调试程序、然后是zwk适用于外部接口调用的逻辑、操作地方不在本机、也没有会话和组。zwu和zwg适合有些操作只有用户才能重现的时候写日志。
跟踪日志会话的对象:
package JRT.Core.Debug;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedDeque;
/**
* 调试会话对象
*/
public class DebugSession {
/**
* 前端最后查询时间,长时间没被查询的会话就去除会话
*/
public long LastSelectTime;
/**
* 调试会话唯一键,用IP-用户-组构成
*/
private String SessionKey;
/**
* 按自定义键写日志
*/
public String SelfKey;
/**
* 按IP写日志
*/
public String IpAddr;
/**
* 按GroupID写日志
*/
public String GroupID;
/**
* 按UserID写日志
*/
public String UserID;
/**
* 日志缓存队列
*/
public ConcurrentLinkedDeque<String> LogQueue;
}
日志管理器:
package JRT.Core.Debug;
import java.util.*;
import java.util.concurrent.ConcurrentLinkedDeque;
import JRT.Core.Debug.DebugSession;
/**
* 管理调试信息
*/
public class DebugManager {
/**
* 存储调试会话
*/
private static HashMap<String, DebugSession> SessionMap=new HashMap<>();
/**
* 按IP地址写日志
* @param ipAddr ip
* @param obj 对象
* @param title 标题
* @throws Exception
*/
public static void ZW(String ipAddr,Object obj,String title) throws Exception
{
boolean hasOut=false;
//使用迭代器遍历
Iterator<HashMap.Entry<String, DebugSession>> iterator = SessionMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, DebugSession> entry = iterator.next();
//两分钟不活动的会话就移除
if (JRT.Core.Util.TimeParser.GetTimeInMillis()-entry.getValue().LastSelectTime>120000) {
iterator.remove();
continue;
}
//按IP写日志
DebugSession one=entry.getValue();
if(one.IpAddr.equals(ipAddr))
{
String logStr="[Usr:"+one.UserID+"#Grp:"+one.GroupID+"#"+JRT.Core.Util.TimeParser.GetNowTimeStr()+"]# "+title+"="+ JRT.Core.Util.JsonUtil.Object2Json(obj);
one.LogQueue.addLast(logStr);
System.out.println(logStr);
hasOut=true;
}
}
if(hasOut==false)
{
System.out.println(JRT.Core.Util.TimeParser.GetNowTimeStr()+"]# "+title+"="+ JRT.Core.Util.JsonUtil.Object2Json(obj));
}
}
/**
* 按自定义Key写日志
* @param selfKey 自定义Key
* @param obj 对象
* @param title 标题
* @throws Exception
*/
public static void ZWK(String selfKey,Object obj,String title) throws Exception
{
boolean hasOut=false;
//使用迭代器遍历
Iterator<HashMap.Entry<String, DebugSession>> iterator = SessionMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, DebugSession> entry = iterator.next();
//两分钟不活动的会话就移除
if (JRT.Core.Util.TimeParser.GetTimeInMillis()-entry.getValue().LastSelectTime>120000) {
iterator.remove();
continue;
}
//按IP写日志
DebugSession one=entry.getValue();
if(one.SelfKey.equals(selfKey))
{
String logStr="[Usr:"+one.UserID+"#Grp:"+one.GroupID+"#"+JRT.Core.Util.TimeParser.GetNowTimeStr()+"]# "+title+"="+ JRT.Core.Util.JsonUtil.Object2Json(obj);
one.LogQueue.addLast(logStr);
System.out.println(logStr);
hasOut=true;
}
}
if(hasOut==false)
{
System.out.println(JRT.Core.Util.TimeParser.GetNowTimeStr()+"]# "+title+"="+ JRT.Core.Util.JsonUtil.Object2Json(obj));
}
}
/**
* 按登录组写日志
* @param groupID 组
* @param obj 对象
* @param title 标题
* @throws Exception
*/
public static void ZWG(String groupID,Object obj,String title) throws Exception
{
boolean hasOut=false;
//使用迭代器遍历
Iterator<HashMap.Entry<String, DebugSession>> iterator = SessionMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, DebugSession> entry = iterator.next();
//两分钟不活动的会话就移除
if (JRT.Core.Util.TimeParser.GetTimeInMillis()-entry.getValue().LastSelectTime>120000) {
iterator.remove();
continue;
}
//按组写日志
DebugSession one=entry.getValue();
if(one.GroupID.equals(groupID))
{
String logStr="[Usr:"+one.UserID+"#Grp:"+one.GroupID+"#"+JRT.Core.Util.TimeParser.GetNowTimeStr()+"]# "+title+"="+ JRT.Core.Util.JsonUtil.Object2Json(obj);
one.LogQueue.addLast(logStr);
System.out.println(logStr);
hasOut=true;
}
}
if(hasOut==false)
{
System.out.println(JRT.Core.Util.TimeParser.GetNowTimeStr()+"]# "+title+"="+ JRT.Core.Util.JsonUtil.Object2Json(obj));
}
}
/**
* 按用户写日志
* @param userID 用户
* @param obj 对象
* @param title 标题
* @throws Exception
*/
public static void ZWU(String userID,Object obj,String title) throws Exception
{
boolean hasOut=false;
//使用迭代器遍历
Iterator<HashMap.Entry<String, DebugSession>> iterator = SessionMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, DebugSession> entry = iterator.next();
//两分钟不活动的会话就移除
if (JRT.Core.Util.TimeParser.GetTimeInMillis()-entry.getValue().LastSelectTime>120000) {
iterator.remove();
continue;
}
//按用户写日志
DebugSession one=entry.getValue();
if(one.UserID.equals(userID))
{
String logStr="[Usr:"+one.UserID+"#Grp:"+one.GroupID+"#"+JRT.Core.Util.TimeParser.GetNowTimeStr()+"]# "+title+"="+ JRT.Core.Util.JsonUtil.Object2Json(obj);
one.LogQueue.addLast(logStr);
System.out.println(logStr);
hasOut=true;
}
}
if(hasOut==false)
{
System.out.println(JRT.Core.Util.TimeParser.GetNowTimeStr()+"]# "+title+"="+ JRT.Core.Util.JsonUtil.Object2Json(obj));
}
}
/**
* 开启调试会话
* @param ipAddr ip地址
* @param userID 用户
* @param groupID 组
* @param selfKey 自定义键
*/
public static void StartDebugSession(String ipAddr,String userID,String groupID,String selfKey)
{
//构造会话
String key=ipAddr+"-"+userID+"-"+groupID;
DebugSession session=new DebugSession();
session.SelfKey=selfKey;
session.IpAddr=ipAddr;
session.UserID=userID;
session.GroupID=groupID;
session.LastSelectTime= JRT.Core.Util.TimeParser.GetTimeInMillis();
session.LogQueue=new ConcurrentLinkedDeque<String>();
SessionMap.put(key,session);
//移除不活动会话
CheckOutTimeSession();
}
/**
* 停止调试会话
* @param ipAddr ip地址
* @param userID 用户
* @param groupID 组
*/
public static void StopDebugSession(String ipAddr,String userID,String groupID)
{
//构造会话
String key=ipAddr+"-"+userID+"-"+groupID;
if(SessionMap.containsKey(key))
{
SessionMap.remove(key);
}
//移除不活动会话
CheckOutTimeSession();
}
/**
* 得到日志数据
* @param ipAddr ip地址
* @param userID 用户
* @param groupID 组
* @return 日志数据
* @throws Exception
*/
public static String GetLogs(String ipAddr,String userID,String groupID) throws Exception
{
String key=ipAddr+"-"+userID+"-"+groupID;
HashMap retMap=new HashMap();
List<String> logList=new ArrayList<>();
if(SessionMap.containsKey(key))
{
DebugSession one=SessionMap.get(key);
one.LastSelectTime= JRT.Core.Util.TimeParser.GetTimeInMillis();
while (one.LogQueue.size()>0)
{
logList.add(one.LogQueue.poll());
}
}
retMap.put("Logs",logList);
retMap.put("SessionNum",SessionMap.size());
return JRT.Core.Util.JsonUtil.Object2Json(retMap);
}
/**
* 查询长时间没活动的会话清除
*/
public static void CheckOutTimeSession()
{
try {
//使用迭代器安全地删除元素
Iterator<HashMap.Entry<String, DebugSession>> iterator = SessionMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, DebugSession> entry = iterator.next();
//两分钟不活动的会话就移除
if (JRT.Core.Util.TimeParser.GetTimeInMillis() - entry.getValue().LastSelectTime > 120000) {
iterator.remove();
}
}
}
catch (Exception ex)
{
JRT.Core.Util.LogUtils.WriteExceptionLog("检测超时的调试会话",ex);
}
}
}
业务基类提供的写日志方法:
/**
* 按照客户端IP地址输出日志
* @param obj 对象
* @throws Exception
*/
public void zw(Object obj) throws Exception
{
DebugManager.ZW(JRTContext.GetClientIP(Request),obj,"obj");
}
/**
* 按照客户端IP地址输出日志
* @param obj 对象
* @param title 标题
* @throws Exception
*/
public void zw(Object obj,String title) throws Exception
{
DebugManager.ZW(JRTContext.GetClientIP(Request),obj,title);
}
/**
* 按照自定义键输出日志
* @param selfkey 自定义键
* @param obj 对象
* @param title 标题
* @throws Exception
*/
public void zwk(String selfkey,Object obj,String title) throws Exception
{
if(selfkey==null)
{
return;
}
DebugManager.ZWK(selfkey,obj,title);
}
/**
* 按照自定义键输出日志
* @param selfkey 自定义键
* @param obj 对象
* @throws Exception
*/
public void zwk(String selfkey,Object obj) throws Exception
{
if(selfkey==null)
{
return;
}
DebugManager.ZWK(selfkey,obj,"obj");
}
/**
* 按照登录的GroupID输出日志
* @param obj 对象
* @throws Exception
*/
public void zwg(Object obj) throws Exception
{
DebugManager.ZWG(UserLogin().GroupID,obj,"obj");
}
/**
* 按照登录的GroupID输出日志
* @param obj 对象
* @param title 标题
* @throws Exception
*/
public void zwg(Object obj,String title) throws Exception
{
DebugManager.ZWG(UserLogin().GroupID,obj,title);
}
/**
* 按照登录的UserID输出日志
* @param obj 对象
* @throws Exception
*/
public void zwu(Object obj) throws Exception
{
DebugManager.ZWU(UserLogin().UserID,obj,"obj");
}
/**
* 按照登录的UserID输出日志
* @param obj 对象
* @param title 标题
* @throws Exception
*/
public void zwu(Object obj,String title) throws Exception
{
DebugManager.ZWU(UserLogin().UserID,obj,title);
}