multiprocess.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. "use strict";
  2. var log4js = require('../log4js')
  3. , net = require('net')
  4. , END_MSG = '__LOG4JS__';
  5. /**
  6. * Creates a server, listening on config.loggerPort, config.loggerHost.
  7. * Output goes to config.actualAppender (config.appender is used to
  8. * set up that appender).
  9. */
  10. function logServer(config) {
  11. /**
  12. * Takes a utf-8 string, returns an object with
  13. * the correct log properties.
  14. */
  15. function deserializeLoggingEvent(clientSocket, msg) {
  16. var loggingEvent;
  17. try {
  18. loggingEvent = JSON.parse(msg);
  19. loggingEvent.startTime = new Date(loggingEvent.startTime);
  20. loggingEvent.level = log4js.levels.toLevel(loggingEvent.level.levelStr);
  21. } catch (e) {
  22. // JSON.parse failed, just log the contents probably a naughty.
  23. loggingEvent = {
  24. startTime: new Date(),
  25. categoryName: 'log4js',
  26. level: log4js.levels.ERROR,
  27. data: [ 'Unable to parse log:', msg ]
  28. };
  29. }
  30. loggingEvent.remoteAddress = clientSocket.remoteAddress;
  31. loggingEvent.remotePort = clientSocket.remotePort;
  32. return loggingEvent;
  33. }
  34. var actualAppender = config.actualAppender,
  35. server = net.createServer(function serverCreated(clientSocket) {
  36. clientSocket.setEncoding('utf8');
  37. var logMessage = '';
  38. function logTheMessage(msg) {
  39. if (logMessage.length > 0) {
  40. actualAppender(deserializeLoggingEvent(clientSocket, msg));
  41. }
  42. }
  43. function chunkReceived(chunk) {
  44. var event;
  45. logMessage += chunk || '';
  46. if (logMessage.indexOf(END_MSG) > -1) {
  47. event = logMessage.substring(0, logMessage.indexOf(END_MSG));
  48. logTheMessage(event);
  49. logMessage = logMessage.substring(event.length + END_MSG.length) || '';
  50. //check for more, maybe it was a big chunk
  51. chunkReceived();
  52. }
  53. }
  54. clientSocket.on('data', chunkReceived);
  55. clientSocket.on('end', chunkReceived);
  56. });
  57. server.listen(config.loggerPort || 5000, config.loggerHost || 'localhost');
  58. return actualAppender;
  59. }
  60. function workerAppender(config) {
  61. var canWrite = false,
  62. buffer = [],
  63. socket;
  64. createSocket();
  65. function createSocket() {
  66. socket = net.createConnection(config.loggerPort || 5000, config.loggerHost || 'localhost');
  67. socket.on('connect', function() {
  68. emptyBuffer();
  69. canWrite = true;
  70. });
  71. socket.on('timeout', socket.end.bind(socket));
  72. //don't bother listening for 'error', 'close' gets called after that anyway
  73. socket.on('close', createSocket);
  74. }
  75. function emptyBuffer() {
  76. var evt;
  77. while ((evt = buffer.shift())) {
  78. write(evt);
  79. }
  80. }
  81. function write(loggingEvent) {
  82. socket.write(JSON.stringify(loggingEvent), 'utf8');
  83. socket.write(END_MSG, 'utf8');
  84. }
  85. return function log(loggingEvent) {
  86. if (canWrite) {
  87. write(loggingEvent);
  88. } else {
  89. buffer.push(loggingEvent);
  90. }
  91. };
  92. }
  93. function createAppender(config) {
  94. if (config.mode === 'master') {
  95. return logServer(config);
  96. } else {
  97. return workerAppender(config);
  98. }
  99. }
  100. function configure(config, options) {
  101. var actualAppender;
  102. if (config.appender && config.mode === 'master') {
  103. log4js.loadAppender(config.appender.type);
  104. actualAppender = log4js.appenderMakers[config.appender.type](config.appender, options);
  105. config.actualAppender = actualAppender;
  106. }
  107. return createAppender(config);
  108. }
  109. exports.appender = createAppender;
  110. exports.configure = configure;