`
nbtlxx
  • 浏览: 253159 次
  • 性别: Icon_minigender_1
  • 来自: 宁波
社区版块
存档分类
最新评论

log4j的真实项目使用经验

阅读更多
项目需要将以下需求进行处理,通过log4j组建输出到log文件进行保存,方便今后运营维护中的分析和问题解决。

项目基本的基本流程包括:
    1. 生成若干个独立线程
    2. 启动线程进行工作
      2.1 根据消息工程生产消息
      2.2 将消息转成二进制方式放入输出队列
      2.3 启动发送功能,将消息进行加密后发生到服务器端
      2.4 等待并读取来自服务器端的消息

需要进行输出的内容主要包括:
     1. 发送登陆时间
     2. 接收完成登陆时间
     3. 发送查询考题时间
     4. 接收查询结果的时间
     5. 单次登陆操作的花费时间
     6. 单次查询考题操作的花费时间
    
    输出到文件output.log
log4j.properties:
log4j.rootLogger=DEBUG,stdout

log4j.appender.stdout=org.apache.log4j.RollingFileAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss}  %p %c{1}.%M(%L) | %m%n
log4j.appender.stdout.MaxFileSize=30MB
log4j.appender.stdout.MaxBackupIndex=1  
log4j.appender.stdout.file=E:\\output.log 



/**
 * 
 */
package net.tuolian.test;

/**
 * @author sean
 * 
 * 1. 启动类
 * 2. 循环产生100个独立线程
 * 3. 启动线程执行任务
 *
 */
public class MainTest {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		for(int i=0; i<500; i++){
			UserThread user = new UserThread(i);
			new Thread(user).start();			
		}
	}

}



/**
 * 
 */
package net.tuolian.test;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Date;

import org.apache.log4j.Logger;

/**
 * @author sean 
 *  1. 建立连接
 *  2. 填充数据:login, query 
 *  3. 发生数据 
 *  4. 接收数据
 * 
 */
public class UserThread implements Runnable {

	Logger logger = null;
	
	Socket socket = null;
	private String ip = "192.168.1.2";
//	private String ip = "tuolian.gicp.net";
//	private String ip = "127.0.0.1";
	private int port = 9999;

	DataInputStream dis;
	DataOutputStream dos;

	boolean isRunning = false;

	private byte[] outData;

	private int id;
	private int counter = 0;
	
	Log4jUtil log;

	private long startTime;

	private long endTime;

	public UserThread(int id) {
		outData = new byte[512];
		this.id = id;
		System.out.println(id + " thread is created");
		
		logger = Logger.getLogger(UserThread.class);
		
		log = new Log4jUtil();
	}

	public void run() {
		// TODO Auto-generated method stub
		if (!connect()) {
//			System.out.println("没有连接");
			logger.error("网络没有连接成功");
		}

		while (isRunning) {
			// System.out.println(id + " thread is running");
			if (!fillData()) {
//				System.out.println("没有添加数据");
				logger.error("没有添加数据 ");
			}

			sendData();

			recvData();
			
			if (counter == 1) {
				recvData();
			}
			
			try {
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	/**
	 * 建立网络连接
	 * 
	 * @return
	 */
	private boolean connect() {
		// TODO Auto-generated method stub
		boolean flag = false;

		try {
			socket = new Socket(ip, port);

			dis = new DataInputStream(socket.getInputStream());
			dos = new DataOutputStream(socket.getOutputStream());

			isRunning = true;
			flag = true;
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return flag;
	}

	/**
	 * 添加测试数据
	 * 1. 登陆消息 
	 * 2. 查少询数据库消息 
	 * 
	 * 
	 * @return
	 */
	private boolean fillData() {
		// TODO Auto-generated method stub
		boolean flag = false;
		outData = null;

		counter++;
//		System.out.println("counter: " + counter);

		//记录操作的开始时间
		startTime = System.currentTimeMillis();
		if (counter == 1) {
			outData = MessageFactory.createMessage(MessageFactory.LOGIN);
		} else {
			outData = MessageFactory.createMessage(MessageFactory.GETCONTENT);
		}

//		System.out.println("outdata length: before decrypt " + outData.length);

		// 如果内容长度不为空,则设置返回值true
		if (outData.length > 0) {
			flag = true;
		}
		return flag;
	}

	/**
	 * 发送数据到服务器端 数据从发生队列中读取
	 */
	private void sendData() {
		if (outData.length == 0) {
//			System.out.println("发生数据位空,发送出错" + new Date());
			log.debug("发生数据位空,发送出错" + new Date());
			return;
		}

		startTime = System.currentTimeMillis();
		try {
			// 1. tea加密数组 2. 长度数组 3. 发送长度 4. 发生加密后数据 5. flush
			// 第二個步骤(长度数组)可以不要
			byte[] tempData = Tea.encryptByTea(outData);
//			System.out.println(" tempdata after decrypt: " + tempData.length);
			dos.write((byte) ((tempData.length & 0xFF)));
			
//			logger.info("temp data length: "
//					+ ((byte) (tempData.length & 0xFF)));
//			System.out.println("temp data length: "
//					+ ((byte) (tempData.length & 0xFF)));
			dos.write((byte) ((tempData.length >> 8 & 0xFF)));
//			logger.info("temp data length: "
//					+ ((byte) (tempData.length >> 8 & 0xFF)));
//			System.out.println("temp data length: "
//					+ ((byte) (tempData.length >> 8 & 0xFF)));
			dos.write(tempData);
			dos.flush();
//			logger.info("outdata length: " + tempData.length);

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		outData = null;
	}

	/**
	 * 发生数据
	 */
	private void recvData() {
		// TODO Auto-generated method stub
		if (dis == null) {
			return;
		}

		try {
			if (dis.available() < -1) {
				return;
			}

			// 1. 长度数组2位,读取, 2. 读取加密数据 3. 解密成正常数组 4. 读取包头12个字节
			// 5.
			// byte[] len = new byte[2];
			// dis.read(len);
			// //长度2位短整型表示
			// int size = Util.BytetoInt2(len,0);
			//			
			// byte[] data = new byte[size];
			// dis.read(data);
			//			
			// byte[] finalData = Tea.decryptByTea(data);
			//			
			// //复制包头部分
			// byte[] head = new byte[12];
			// System.arraycopy(finalData, 0, head, 0, head.length);
			//			
			// char[] tags = new char[2];
			// tags[0] = (char) head[0];
			// tags[0] = (char) head[1];
			//			
			// //包体长度
			// int bodyLen = Util.BytetoInt2(head,2);
			//			
			// //命令头
			// int cmdType = Util.BytetoInt2(head,4);
			//			
			// //playerId
			// int playerId = Util.BytetoInt4(head, 8);
			//			
			// byte[] body = new byte[bodyLen];
			// System.arraycopy(finalData, 12, body, 0, bodyLen);
			//			
			// //进行数据解析和逻辑处理
			// parseInputData(cmdType, body , head);
			// //通过包头属性,获得包体数据的长度
			// //复制包体部分

			byte[] datas = new byte[2];
			dis.read(datas);
//			logger.info("收到消息长度为" + Util.toHexString1(datas));

			// short lens=(short) (((datas[0] & 0xFF) << 8) + ((datas[1] & 0xFF)
			// << 0));
			int len = Util.BytetoInt2(datas, 0);// (short) (((datas[0] & 0xff)
												// << 8) + ((datas[1] & 0xff) <<
												// 0));
//			logger.info("收到消息长度为" + len);

			// 读取通信流中的数据
			datas = new byte[len];
			dis.read(datas);
			datas = Tea.decryptByTea(datas);
			byte[] headdata = new byte[12];
			System.arraycopy(datas, 0, headdata, 0, 12);

			// dis.read(headdata);

			// headdata=Tea.encryptByTea(headdata);
			char[] tags = new char[2];
			tags[0] = (char) headdata[0];
			tags[1] = (char) headdata[1];
//			logger.info("收到body len " + headdata[0]);
			
			int bodyLen = Util.BytetoInt2(headdata, 2);// (short) (((headdata[2]
														// & 0xff) << 8) +
														// ((headdata[3] & 0xff)
														// << 0));
//			logger.info("收到body len " + bodyLen);
			// headdata[4]
			int cmdtype = Util.BytetoInt2(headdata, 4);// (short) (((headdata[4]
														// & 0xff) << 8) +
														// ((headdata[5] & 0xff)
														// << 0));
			// headdata[7]
			int playerid = Util.BytetoInt4(headdata, 8);
			
//			logger.info("收到player id is " + playerid + " cmd=" + cmdtype);

			byte[] bodydata = new byte[bodyLen];
			System.arraycopy(datas, 12, bodydata, 0, bodyLen);

			// 进行数据解析和逻辑处理
			parseInputData(cmdtype, bodydata, headdata);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * 解析读取的数据,进行现场处理,打印结果
	 * 
	 * @param cmdType
	 * @param body
	 */
	private void parseInputData(int cmdType, byte[] body, byte[] head) {
		// TODO Auto-generated method stub

		switch (cmdType) {
		case MessageFactory.RE_LOGIN:
			int playerId = Util.BytetoInt4(head, 8);
//			logger.info("playerId: " + playerId);
			
			endTime = System.currentTimeMillis();
			
			Log4jUtil.logTime("login", startTime, endTime);
//			System.out.println("playerId: " + playerId);
			break;

		case MessageFactory.R_GETTYPE:
//			handleGetContent(body);
			break;
			
		case MessageFactory.R_GETCONTENT:
			handleGetContent(body);
			break;

		default:
			break;
		}
	}

	/**
	 * 
	 * @param body
	 */
	private void handleGetContent(byte[] body) {
		// TODO Auto-generated method stub
		ByteArrayInputStream bis = new ByteArrayInputStream(body);
		DataInputStream dis = new DataInputStream(bis);

		try {
			int id = dis.read();

			int style = dis.read();
			int sub_style = dis.read();

			byte[] data = new byte[2];
			dis.read(data);
			int len = Util.BytetoInt2(data, 0);

			data = new byte[len];
			dis.read(data);
			String title = new String(data, "utf-8");
//			logger.info("question title: " + title);
//			System.out.println("question title: " + title);

			int slen = dis.read();
//			System.out.println(" success in dealing with handleGetContent");
			dis.close();
//			String[] selects = new String[slen];

//			for (int i = 0; i < slen; i++) {
//				data = new byte[2];
//				dis.read(data);
//				int strlen = Util.BytetoInt2(data, 0);
//				data = new byte[strlen];
//				dis.read(data);
//				selects[i] = new String(data, "utf-8");
//				dis.close();
//			}
			
//			int result = dis.read();
			
			endTime = System.currentTimeMillis();
			
			Log4jUtil.logTime("query", startTime, endTime);
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			logger.error("read question error ");
//			e.printStackTrace();
		}
	}
}



package net.tuolian.test;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;


/**
 * 消息工厂 
 * 1. 产生登陆消息 
 * 2. 产生数据查询消息
 * 
 * 上述消息都直接写成二进制方式
 * 包体+包头
 * 放入outData数据队列
 *
 * @author sean
 * 
 */
public class MessageFactory {

	public static final int LOGIN = 3005;	
	public static final int GETCONTENT = 2003;

	/** ******收到的命令******** */
	public static final int RE_LOGIN = 3006;
	public static final int R_GETTYPE = 2002;
	public static final int R_GETCONTENT = 2004;
	

	
	private static final String TAG = "tl";
	
	
	

	public static byte[] createMessage(int cmdType) {
		// TODO Auto-generated method stub
		ByteArrayOutputStream writeBos = new ByteArrayOutputStream();
		DataOutputStream writeDos = new DataOutputStream(writeBos);

		switch (cmdType) {
		case LOGIN:
			loginWrite(writeDos);
			break;

		case GETCONTENT:
			getContent(writeDos);
			break;
		default:
			break;
		}
		// 返回加入包头的消息二进制数组
		return addMessageHead(writeBos.toByteArray(),cmdType);
		
//		return writeBos.toByteArray();
	}


	/**
	 * 添加消息包头,根据具体情况定义包头

	 * @param body
	 * @param cmdType
	 * @return
	 */
	private static byte[] addMessageHead(byte[] body, int cmdType) {
		
		
		return data;
		// TODO Auto-generated method stub
		
	}

	/**
	 * 编写登陆口命令体 
	 * username 
	 * password 
	 * note: 
	 * log4j记录时间
	 * 
	 * @param dos
	 */
	private static void loginWrite(DataOutputStream dos) {
		// TODO Auto-generated method stub
		int userid = 1000;
		String name = "username";
		String password = "password";
		try {
			dos.writeInt(1000);
			byte data[] = name.getBytes("UTF-8");
			dos.write(data.length & 0xff);
			dos.write(data.length >> 8 & 0xff);
			dos.write(data);
			data = password.getBytes("UTF-8");
			dos.write(data.length & 0xff);
			dos.write(data.length >> 8 & 0xff);
			dos.write(data);
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	/**
	 * 打印获得考试内容的时间
	 * @param dos
	 */
	private static void getContent(DataOutputStream dos) {
		// TODO Auto-generated method stub
		int examTypeId = 2;
		try {
			dos.write(examTypeId);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}


package net.tuolian.test;

import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.Properties;

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.apache.log4j.spi.Configurator;

/**
 * log4j初始化配置
 * 
 * @author Administrator 1. Property 对象 2.读取配置文件 inputstream 3.
 *         property.load(is) 4. configure(file); 5.
 * 
 *         错误及解决: 1. log4j.properties文件,需要和代码放在同一级,也就是放在同一个包内
 *         2. logger =
 *         Logger.getLogger(Log4jUtil.class); 否则使用logger对象,报空指针错误
 */
public class Log4jUtil {

	private static String fileName = "log4j.properties";

	static Logger logger = null;

	public Log4jUtil() {
		Properties properties = new Properties();
		InputStream is = getClass().getResourceAsStream(fileName);
		try {
			properties.load(is);
			PropertyConfigurator.configure(properties);

			logger = Logger.getLogger(Log4jUtil.class);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		long startTime = System.currentTimeMillis();
		long endTime;

		new Log4jUtil();

		for (int i = 0; i < 1000; i++) {
			System.out.println(" println :" + i);
		}

		endTime = System.currentTimeMillis();

		long takeTime = (endTime - startTime);
		logger.info("hello: " + takeTime);
		
		logTime("query time", startTime, endTime);

	}

	public static void logTime(String logicName, long startTime, long endTime){
		logger.info(logicName + "操作使用的时间为" + (endTime - startTime));
	}

	public void debug(String string) {
		// TODO Auto-generated method stub
		logger.debug(string);
	}
}


还有几个小问题:
1. log4j.properties默认是在代码的同一级目录(package)下,比如当前package是net.tuolian.test, 则配置文件放在这个package下就可以被成功加载
2. 根据自己的需要封装方法
   比如:封装一个方法来打印业务名称、花费时间
   logTime(name, starttime, endTime)
3. 另外log4j的配置文件读取的方法如代码所示:
   Properties properties = new Properties();
InputStream is = getClass().getResourceAsStream(fileName);
try {
properties.load(is);
PropertyConfigurator.configure(properties);

logger = Logger.getLogger(Log4jUtil.class);
    读取配置文件、设置配置文件,getLogger(类名)
4.将日志输出到数据库,需要对配置文件进行如下设置
   输出到数据库
    log4j.appender.DATABASE=org.apache.log4j.jdbc.JDBCAppender
   log4j.appender.DATABASE.URL=jdbc:mysql://localhost:3306/test
log4j.appender.DATABASE.driver=com.mysql.jdbc.Driver
log4j.appender.DATABASE.user=root
log4j.appender.DATABASE.password= root
log4j.appender.DATABASE.sql=INSERT INTO LOG4J (Message) VALUES ('[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n')
log4j.appender.DATABASE.layout=org.apache.log4j.PatternLayout
log4j.appender.DATABASE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
   成功与否,笔者还没进行测试

其他方法,还包括输出地格式设定、输出的目标地址设定等等
1
0
分享到:
评论

相关推荐

    log4j2 demo 性能测试

    《深入理解Log4j2 Demo性能测试:探索异步日志的魅力》 ...通过深入理解和实践"Log4j2 Demo性能测试",开发者可以更好地掌握这一技术,从而在实际项目中发挥出Log4j2的潜力,优化系统的日志处理能力。

    C3P0 fastjson log4j POI3.7+3.8 jar包资源

    3. **Log4j**:Log4j是Apache软件基金会的一个项目,它是一个广泛使用的日志记录框架。`log4j1.2.17.jar`这个版本提供了灵活的日志配置,可以定制日志输出级别,格式,目标等,有助于开发者调试代码,监控系统运行...

    Log4j日志体系结构

    我们在写日志的时候首先要获取logger,在每一个使用log4j的项目都有很多个地方要获取logger,这些logger是真实的被实例化的Logger对象,他们有可能被分散在无数不同的类中,日志体系结构讲的是这些logger对象是如何...

    raven-log4j-5.0.zip

    首先,我们来看一下"raven-log4j-5.0.zip",这个名字可能意味着它与Log4j框架的一个特定版本相关,Log4j是Java领域广泛应用的日志记录框架,而“raven”可能是用来集成错误追踪服务如Sentry的一个组件。在5.0版本中...

    公司真实项目源码(java)

    【标题】"公司真实项目源码(java)"揭示了一个基于Java编程语言的企业级实际开发项目。这样的项目源码对于学习者来说具有很高的价值,因为它提供了真实世界中的应用实例,帮助开发者了解如何在实践中运用Java技术。...

    毕业设计:资料管理系统-springboot整合ssm,shiro,log4j.zip

    用Java写的项目,项目真实可靠,能正常运行,欢迎下载使用。用Java写的项目,项目真实可靠,能正常运行,欢迎下载使用。用Java写的项目,项目真实可靠,能正常运行,欢迎下载使用。用Java写的项目,项目真实可靠,能...

    真实的项目源码!

    此外,商业项目源码还可能涉及到权限控制(如Spring Security)、用户认证(OAuth2)、日志记录(Log4j或Logback)、单元测试(JUnit或TestNG)、任务调度(Quartz或Spring Task)等常见的企业级功能。这些组件和...

    李腾飞CMS 文档资料

    《李腾飞CMS文档资料》中可能详细讲解了如何在实际项目中集成和配置Log4j,以实现有效和高效的日志管理。同时,它可能也涵盖了htmlprase的使用教程,包括基本的元素操作、选择器语法以及常见问题的解决方法。这些...

    SpringBoot前后端分离 - 预约挂号系统

    选材来自生活,项目真实感强,可用学习使用和就业面试使用,适合作为面试中提高实际项目经验...该项目前后端分离,满足前沿技术点..项目技术: - 数据库:MySQL8.0 - 后端技术:SpringBoot,MyBatisPlus,JWT 等 - ...

    应用分析监控平台 闪电狗.zip

    闪电狗监控(flash-dog)起源于杭州斯凯网络科技有限公司一个真实项目,主要优点是轻巧快捷,非侵入式,不影响业务代码,只需加入几个jar包和修改log4j配置文件,就能监控任意指标,如CPU,内存、线程,游戏收入,...

    Java测试项目.zip

    Java有内置的日志API,如java.util.logging,也可以使用Log4j或SLF4J等第三方库。调试工具如Eclipse或IntelliJ IDEA的调试器可以帮助开发者定位问题。 11. **版本控制**:项目通常使用Git进行版本控制,确保代码的...

    使用selenium进行web测试项目框架

    我们可以使用try-catch语句来捕获异常,并使用如Log4j或SLF4J等日志框架记录测试过程中的重要信息。 **九、并行测试** 为了提高测试效率,我们可以利用TestNG的并行测试功能,同时运行多个测试用例或测试套件。这在...

    北大青鸟S2结业项目

    7. **日志配置**:如`log4j.properties`,用于记录应用运行时的日志信息。 8. **启动脚本**:如`run.sh`或`start.bat`,用于启动应用程序。 通过这个项目,学员将有机会实践以下Java Web开发的重要知识点: 1. **...

    机器学习实战项目教你逻辑回归项目

    3. 更新权重:\( \theta_j := \theta_j - \alpha \cdot \frac{\partial L}{\partial \theta_j} \),其中 \( \theta_j \) 是第j个参数,\( \alpha \) 是学习率。 4. 重复步骤2和3,直到损失函数收敛或达到预设的最大...

    logistic_lj_逻辑回归_

    在本案例中,“logistic_lj”可能是一个项目或教程,旨在教授如何使用逻辑回归来识别数字字符串。 逻辑回归的核心在于构建一个线性模型,然后通过Sigmoid函数将线性组合转换为概率。线性模型的公式为: \[ \hat{y}...

    Spring2.56Mvc

    本文将详细介绍Spring2.56版本中Spring MVC的配置与使用,包括基础配置、方法调用、定时器配置、Log4J配置、C3p0数据库连接池配置以及事务配置等多个方面。学习这些知识点后,开发者可以迅速上手进行真实项目的开发...

    测试项目测试项目测试项目测试项目

    8. **异常处理与日志**:理解和测试异常处理逻辑,同时分析日志来定位问题,如使用Logback或Log4j进行日志记录。 9. **单元测试的最佳实践**:编写可读性强、易于维护的测试用例,遵循 Arrange-Act-Assert (AAA) ...

    Java代码测试IP是否为真实IP

    7. **日志记录**:为了调试和监控,可以使用Log4j、SLF4J等日志框架记录程序运行中的信息、警告和错误。 8. **单元测试**:使用JUnit或其他测试框架编写单元测试,确保代码的正确性。对于测试IP是否可达的功能,...

    电子宠物系统epet项目案例完整代码

    而`log4j-1.2.15.jar`是一个流行的日志记录框架,帮助开发者记录程序运行时的事件和错误信息,便于调试和问题追踪。 至于`epet`文件,它可能是项目的源代码压缩包,包含`.java`文件和其他资源。开发者可以通过解压...

    JAVA项目

    另外,日志框架如Log4j用于记录应用程序的运行信息,便于调试和问题排查。 总之,这个【JAVA项目】全面展示了Java在实际开发中的各种应用场景,包括基础语法、数据库操作、并发编程以及框架的使用。通过学习和理解...

Global site tag (gtag.js) - Google Analytics