PageRenderTime 51ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/src/test/java/org/log4mongo/TestMongoDbPatternLayout.java

https://github.com/akurdyukov/log4mongo-java
Java | 360 lines | 264 code | 57 blank | 39 comment | 1 complexity | 1b6592ce28bbf01c63d57480434ef1c0 MD5 | raw file
  1. /* Copyright (C) 2010 Robert Stewart (robert@wombatnation.com)
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. package org.log4mongo;
  16. import static org.junit.Assert.*;
  17. import java.net.InetAddress;
  18. import java.util.Properties;
  19. import org.apache.log4j.Logger;
  20. import org.apache.log4j.PropertyConfigurator;
  21. import org.junit.After;
  22. import org.junit.AfterClass;
  23. import org.junit.Before;
  24. import org.junit.BeforeClass;
  25. import org.junit.Test;
  26. import com.mongodb.BasicDBList;
  27. import com.mongodb.BasicDBObject;
  28. import com.mongodb.BasicDBObjectBuilder;
  29. import com.mongodb.DBCollection;
  30. import com.mongodb.DBObject;
  31. import com.mongodb.Mongo;
  32. /**
  33. * JUnit unit tests for PatternLayout style logging.
  34. *
  35. * Since tests may depend on different Log4J property settings, each test
  36. * reconfigures an appender using a Properties object.
  37. *
  38. * Note: these tests require that a MongoDB server is running, and (by default)
  39. * assumes that server is listening on the default port (27017) on localhost.
  40. *
  41. * @author Robert Stewart (robert@wombatnation.com)
  42. * @version $Id$
  43. */
  44. public class TestMongoDbPatternLayout {
  45. private final static Logger log = Logger.getLogger(TestMongoDbPatternLayout.class);
  46. public final static String TEST_MONGO_SERVER_HOSTNAME = "localhost";
  47. public final static int TEST_MONGO_SERVER_PORT = 27017;
  48. private final static String TEST_DATABASE_NAME = "log4mongotest";
  49. private final static String TEST_COLLECTION_NAME = "logeventslayout";
  50. private final static String APPENDER_NAME = "MongoDBPatternLayout";
  51. private final Mongo mongo;
  52. private DBCollection collection;
  53. public TestMongoDbPatternLayout() throws Exception {
  54. mongo = new Mongo(TEST_MONGO_SERVER_HOSTNAME, TEST_MONGO_SERVER_PORT);
  55. }
  56. @BeforeClass
  57. public static void setUpBeforeClass() throws Exception {
  58. Mongo mongo = new Mongo(TEST_MONGO_SERVER_HOSTNAME,
  59. TEST_MONGO_SERVER_PORT);
  60. mongo.dropDatabase(TEST_DATABASE_NAME);
  61. }
  62. @AfterClass
  63. public static void tearDownAfterClass() throws Exception {
  64. Mongo mongo = new Mongo(TEST_MONGO_SERVER_HOSTNAME,
  65. TEST_MONGO_SERVER_PORT);
  66. mongo.dropDatabase(TEST_DATABASE_NAME);
  67. }
  68. @Before
  69. public void setUp() throws Exception {
  70. // Ensure both the appender and the JUnit test use the same collection
  71. // object - provides consistency across reads (JUnit) & writes (Log4J)
  72. collection = mongo.getDB(TEST_DATABASE_NAME).getCollection(
  73. TEST_COLLECTION_NAME);
  74. collection.drop();
  75. mongo.getDB(TEST_DATABASE_NAME).requestStart();
  76. }
  77. @After
  78. public void tearDown() throws Exception {
  79. mongo.getDB(TEST_DATABASE_NAME).requestDone();
  80. }
  81. @Test
  82. public void testValidPatternLayout() {
  83. PropertyConfigurator.configure(getValidPatternLayoutProperties());
  84. MongoDbAppender appender = (MongoDbAppender) Logger.getRootLogger()
  85. .getAppender(APPENDER_NAME);
  86. collection = mongo.getDB(TEST_DATABASE_NAME).getCollection(
  87. TEST_COLLECTION_NAME);
  88. appender.setCollection(collection);
  89. assertEquals(0L, countLogEntries());
  90. log.warn("Warn entry");
  91. assertEquals(1L, countLogEntries());
  92. assertEquals(1L, countLogEntriesAtLevel("WARN"));
  93. // verify log entry content
  94. DBObject entry = collection.findOne();
  95. assertNotNull(entry);
  96. assertEquals("WARN", entry.get("level"));
  97. assertEquals("Warn entry", entry.get("message"));
  98. // This is the custom info. In the pattern, the field is named "extra".
  99. assertEquals("useful info", entry.get("extra"));
  100. }
  101. @Test
  102. public void testQuotesInMessage() {
  103. PropertyConfigurator.configure(getValidPatternLayoutProperties());
  104. MongoDbAppender appender = (MongoDbAppender) Logger.getRootLogger()
  105. .getAppender(APPENDER_NAME);
  106. collection = mongo.getDB(TEST_DATABASE_NAME).getCollection(
  107. TEST_COLLECTION_NAME);
  108. appender.setCollection(collection);
  109. assertEquals(0L, countLogEntries());
  110. String msg = "\"Quotes\" ' \"embedded\"";
  111. log.warn(msg);
  112. assertEquals(1L, countLogEntries());
  113. assertEquals(1L, countLogEntriesAtLevel("WARN"));
  114. // verify log entry content
  115. DBObject entry = collection.findOne();
  116. assertNotNull(entry);
  117. assertEquals("WARN", entry.get("level"));
  118. assertEquals(msg, entry.get("message"));
  119. }
  120. @Test
  121. public void testNestedDoc() {
  122. PropertyConfigurator.configure(getNestedDocPatternLayoutProperties());
  123. MongoDbAppender appender = (MongoDbAppender) Logger.getRootLogger()
  124. .getAppender(APPENDER_NAME);
  125. collection = mongo.getDB(TEST_DATABASE_NAME).getCollection(
  126. TEST_COLLECTION_NAME);
  127. appender.setCollection(collection);
  128. assertEquals(0L, countLogEntries());
  129. String msg = "Nested warning";
  130. log.warn(msg);
  131. assertEquals(1L, countLogEntries());
  132. assertEquals(1L, countLogEntriesAtLevel("WARN"));
  133. // verify log entry content
  134. DBObject entry = collection.findOne();
  135. assertNotNull(entry);
  136. assertEquals("WARN", entry.get("level"));
  137. DBObject nestedDoc = (DBObject) entry.get("nested");
  138. assertEquals(msg, nestedDoc.get("message"));
  139. }
  140. /**
  141. * Tests that the document stored in MongoDB has an array as a value if the
  142. * conversion pattern specifies an array as a value.
  143. */
  144. @Test
  145. public void testArrayValue() {
  146. PropertyConfigurator.configure(getArrayPatternLayoutProperties());
  147. MongoDbAppender appender = (MongoDbAppender) Logger.getRootLogger()
  148. .getAppender(APPENDER_NAME);
  149. collection = mongo.getDB(TEST_DATABASE_NAME).getCollection(
  150. TEST_COLLECTION_NAME);
  151. appender.setCollection(collection);
  152. assertEquals(0L, countLogEntries());
  153. String msg = "Message in array";
  154. log.warn(msg);
  155. assertEquals(1L, countLogEntries());
  156. assertEquals(1L, countLogEntriesAtLevel("WARN"));
  157. // verify log entry content
  158. DBObject entry = collection.findOne();
  159. assertNotNull(entry);
  160. assertEquals("WARN", entry.get("level"));
  161. BasicDBList list = (BasicDBList) entry.get("array");
  162. assertEquals(2, list.size());
  163. assertEquals(this.getClass().getSimpleName(), list.get(0));
  164. assertEquals(msg, list.get(1));
  165. }
  166. @Test
  167. public void testHostInfoPatternLayout() throws Exception {
  168. PropertyConfigurator.configure(getHostInfoPatternLayoutProperties());
  169. MongoDbAppender appender = (MongoDbAppender) Logger.getRootLogger()
  170. .getAppender(APPENDER_NAME);
  171. collection = mongo.getDB(TEST_DATABASE_NAME).getCollection(
  172. TEST_COLLECTION_NAME);
  173. appender.setCollection(collection);
  174. assertEquals(0L, countLogEntries());
  175. String msg = "Message in array";
  176. log.warn(msg);
  177. assertEquals(1L, countLogEntries());
  178. assertEquals(1L, countLogEntriesAtLevel("WARN"));
  179. // verify log entry content
  180. DBObject entry = collection.findOne();
  181. assertNotNull(entry);
  182. assertEquals("WARN", entry.get("level"));
  183. assertNotNull(entry.get("host"));
  184. DBObject hostinfo = (DBObject) entry.get("host");
  185. assertNotNull(hostinfo.get("name"));
  186. assertNotNull(hostinfo.get("ip_address"));
  187. assertNotNull(hostinfo.get("process"));
  188. assertEquals(InetAddress.getLocalHost().getHostName(), hostinfo.get("name"));
  189. assertEquals(InetAddress.getLocalHost().getHostAddress(), hostinfo.get("ip_address"));
  190. }
  191. @Test
  192. public void testBackslashInMessage() {
  193. PropertyConfigurator.configure(getValidPatternLayoutProperties());
  194. MongoDbAppender appender = (MongoDbAppender) Logger.getRootLogger()
  195. .getAppender(APPENDER_NAME);
  196. collection = mongo.getDB(TEST_DATABASE_NAME).getCollection(
  197. TEST_COLLECTION_NAME);
  198. appender.setCollection(collection);
  199. assertEquals(0L, countLogEntries());
  200. String msg = "c:\\users\\some_file\\";
  201. log.warn(msg);
  202. assertEquals(1L, countLogEntries());
  203. assertEquals(1L, countLogEntriesAtLevel("WARN"));
  204. String msgDoubleBackslash = "c:\\\\users\\\\some_file\\\\";
  205. log.info(msgDoubleBackslash);
  206. assertEquals(2L, countLogEntries());
  207. assertEquals(1L, countLogEntriesAtLevel("INFO"));
  208. // verify log entry content
  209. DBObject queryObj = new BasicDBObject();
  210. queryObj.put("level", "WARN");
  211. DBObject entry = collection.findOne(queryObj);
  212. assertNotNull(entry);
  213. assertEquals("WARN", entry.get("level"));
  214. assertEquals(msg, entry.get("message"));
  215. queryObj = new BasicDBObject();
  216. queryObj.put("level", "INFO");
  217. entry = collection.findOne(queryObj);
  218. assertNotNull(entry);
  219. assertEquals("INFO", entry.get("level"));
  220. assertEquals(msgDoubleBackslash, entry.get("message"));
  221. }
  222. @Test
  223. public void testPerformance() {
  224. PropertyConfigurator.configure(getValidPatternLayoutProperties());
  225. MongoDbAppender appender = (MongoDbAppender) Logger.getRootLogger()
  226. .getAppender(APPENDER_NAME);
  227. collection = mongo.getDB(TEST_DATABASE_NAME).getCollection(
  228. TEST_COLLECTION_NAME);
  229. appender.setCollection(collection);
  230. int NUM_MESSAGES = 1000;
  231. long now = System.currentTimeMillis();
  232. for (int i = 0; i < NUM_MESSAGES; i++) {
  233. log.warn("Warn entry");
  234. }
  235. long dur = System.currentTimeMillis() - now;
  236. System.out.println("Milliseconds for MongoDbPatternLayoutAppender to log "
  237. + NUM_MESSAGES + " messages:" + dur);
  238. assertEquals(NUM_MESSAGES, countLogEntries());
  239. }
  240. private long countLogEntries() {
  241. return (collection.getCount());
  242. }
  243. private long countLogEntriesAtLevel(final String level) {
  244. return (countLogEntriesWhere(BasicDBObjectBuilder.start().add("level",
  245. level.toUpperCase()).get()));
  246. }
  247. private long countLogEntriesWhere(final DBObject whereClause) {
  248. return collection.getCount(whereClause);
  249. }
  250. private Properties getValidPatternLayoutProperties() {
  251. Properties props = new Properties();
  252. props.put("log4j.rootLogger", "DEBUG, MongoDBPatternLayout");
  253. props.put("log4j.appender.MongoDBPatternLayout",
  254. "org.log4mongo.MongoDbPatternLayoutAppender");
  255. props.put("log4j.appender.MongoDBPatternLayout.databaseName",
  256. "log4mongotest");
  257. props.put("log4j.appender.MongoDBPatternLayout.layout",
  258. "org.log4mongo.CustomPatternLayout");
  259. props.put("log4j.appender.MongoDBPatternLayout.layout.ConversionPattern",
  260. "{\"extra\":\"%e\",\"timestamp\":\"%d{yyyy-MM-dd'T'HH:mm:ss'Z'}\",\"level\":\"%p\",\"class\":\"%c{1}\",\"message\":\"%m\"}");
  261. return props;
  262. }
  263. private Properties getNestedDocPatternLayoutProperties() {
  264. Properties props = new Properties();
  265. props.put("log4j.rootLogger", "DEBUG, MongoDBPatternLayout");
  266. props.put("log4j.appender.MongoDBPatternLayout",
  267. "org.log4mongo.MongoDbPatternLayoutAppender");
  268. props.put("log4j.appender.MongoDBPatternLayout.databaseName",
  269. "log4mongotest");
  270. props.put("log4j.appender.MongoDBPatternLayout.layout",
  271. "org.log4mongo.CustomPatternLayout");
  272. props.put("log4j.appender.MongoDBPatternLayout.layout.ConversionPattern",
  273. "{\"timestamp\":\"%d{yyyy-MM-dd'T'HH:mm:ss'Z'}\",\"level\":\"%p\",\"nested\":{\"class\":\"%c{1}\",\"message\":\"%m\"}}");
  274. return props;
  275. }
  276. private Properties getArrayPatternLayoutProperties() {
  277. Properties props = new Properties();
  278. props.put("log4j.rootLogger", "DEBUG, MongoDBPatternLayout");
  279. props.put("log4j.appender.MongoDBPatternLayout",
  280. "org.log4mongo.MongoDbPatternLayoutAppender");
  281. props.put("log4j.appender.MongoDBPatternLayout.databaseName",
  282. "log4mongotest");
  283. props.put("log4j.appender.MongoDBPatternLayout.layout",
  284. "org.log4mongo.CustomPatternLayout");
  285. props.put("log4j.appender.MongoDBPatternLayout.layout.ConversionPattern",
  286. "{\"timestamp\":\"%d{yyyy-MM-dd'T'HH:mm:ss'Z'}\",\"level\":\"%p\",\"array\":[\"%c{1}\",\"%m\"]}");
  287. return props;
  288. }
  289. private Properties getHostInfoPatternLayoutProperties() {
  290. Properties props = new Properties();
  291. props.put("log4j.rootLogger", "DEBUG, MongoDBPatternLayout");
  292. props.put("log4j.appender.MongoDBPatternLayout",
  293. "org.log4mongo.MongoDbPatternLayoutAppender");
  294. props.put("log4j.appender.MongoDBPatternLayout.databaseName",
  295. "log4mongotest");
  296. props.put("log4j.appender.MongoDBPatternLayout.layout",
  297. "org.log4mongo.contrib.HostInfoPatternLayout");
  298. props.put("log4j.appender.MongoDBPatternLayout.layout.ConversionPattern",
  299. "{\"timestamp\":\"%d{yyyy-MM-dd'T'HH:mm:ss'Z'}\",\"level\":\"%p\",\"array\":[\"%c{1}\",\"%m\"],\"host\":{\"name\":\"%H\", \"process\":\"%V\", \"ip_address\":\"%I\"}}");
  300. return props;
  301. }
  302. }