log4js icon indicating copy to clipboard operation
log4js copied to clipboard

POST by using fetch appender

Open padoauk opened this issue 6 years ago • 0 comments

Hi.

log4js is a nice framework. I'd like to propose simpler ajax appender by using fetch API. In the following, data to be POSTed are kept as an object just before it is fetched. Therefore ObjectLayout is used.

If you like, include such capability in log4js. Thanks.

/**
 *  ajax by fetch appender
 */
 Log4js.ObjectLayout = function(){
 };

 Log4js.ObjectLayout.prototype = Log4js.extend(new Log4js.Layout(), {
  format: function(loggingEvent){
    let useragent = "unknown";
    try {
      useragent = navigator.userAgent;
    } catch(e){
      useragent = "unknown";
    }

    let referer = "unknown";
    try {
      referer = location.href;
    } catch(e){
      referer = "unknown";
    }

    const obj = {};
    obj.logger = loggingEvent.categoryName;
    obj.level = loggingEvent.level.toString();
    obj.message = `${loggingEvent.message}`;
    obj.referer = referer;
    obj.useragent = useragent;
    obj.timestamp = new Date();
    obj.exception = loggingEvent.exception;

    return obj;
  }
});

Log4js.FetchAppender = function(url){
  this.isInProgress = false;
  this.loggingUrl = url || "logging.log4js";
  this.threshold = 1;
  this.timeout = 2000;
  this.loggingEventMap = new Log4js.FifoBuffer();
  this.layout = new Log4js.ObjectLayout();
  this.httpRequest = null;
};

Log4js.FetchAppender.prototype = Log4js.extend( new Log4js.Appender(),{
  doAppend: function(loggingEvent){
    log4jsLogger && log4jsLogger.trace("> FetchAppender.append");

    if (this.loggingEventMap.length() <= this.threshold || this.isInProgress === true) {
      this.loggingEventMap.push(loggingEvent);
    }

    if (this.loggingEventMap.length() >= this.threshold && this.isInProgress === false) {
      //if threshold is reached send the events and reset current threshold
      this.send();
    }

    log4jsLogger && log4jsLogger.trace("< FetchAppender.append");
  },

  doClear: function () {
    log4jsLogger && log4jsLogger.trace("> FetchAppender.doClear");
    if (this.loggingEventMap.length() > 0) {
      this.send();
    }
    log4jsLogger && log4jsLogger.trace("< FetchAppender.doClear");
  },

  setThreshold: function (threshold) {
    log4jsLogger && log4jsLogger.trace("> FetchAppender.setThreshold: " + threshold);
    this.threshold = threshold;
    log4jsLogger && log4jsLogger.trace("< FetchAppender.setThreshold");
  },

  setTimeout: function (milliseconds) {
    this.timeout = milliseconds;
  },

  send: function(){
    if (0 < this.loggingEventMap.length()) {
      this.isInProgress = true;
      const a = [];
      for (var i = 0; i < this.loggingEventMap.length() && i < this.threshold; i++) {
        a.push(this.layout.format(this.loggingEventMap.pull()));
      }
      postData(this.loggingUrl, a)
        .then(data => console.log(JSON.stringify(data))) // JSON-string from `response.json()` call
        .catch(error => console.error(error));
    }
    this.isInProgress = false;
    
    function postData(url = ``, data = {}) {
      return fetch(url, {
        method:      "POST",
        mode:        "cors", // no-cors, cors, *same-origin
        cache:       "no-cache", // *default, no-cache, reload, force-cache, only-if-cached
        credentials: "same-origin", // include, same-origin, *omit
        headers: {
          "Content-Type": "application/json; charset=utf-8",
        },
        redirect: "follow",
        referrer: "no-referrer",
        body: JSON.stringify(data),
      })
        .then(response => response.json());
    }
  }
});

padoauk avatar Feb 11 '19 05:02 padoauk