2012-09-25 63 views
7

我正在使用express.js。每當有人試圖記錄消息時,我都需要能夠記錄某些請求數據。爲此我想創建一個像這樣的幫手方法是否有可能獲取由node.js提供服務的當前請求?

function log_message(level, message){ 
    winston.log(level, req.path + "" + message); 
} 

然後我會使用類似的方法。

exports.index = function(req, res){ 
    log_message("info", "I'm here"); 
} 

請注意,我沒有將req對象傳遞給log_message函數。我希望透明地完成這一操作,以便log_message API用戶不需要知道正在記錄的公共數據。

有沒有一種方法可以通過express.js/node.js來實現。請求對象是否可以從某種全局變量中獲得?

回答

1

以下解決方案對我來說是可以接受的。

在這裏我有一箇中間件,它將log_message方法添加到請求對象上。之後,我只需調用req.log_message來記錄消息。雖然這與將req對象傳遞給每個日誌記錄調用非常相似,但它只是稍微更清晰。

function logging_middleware(req, res, next){ 
    req.log_message = function(level, message){ 
     winston.log(level, req.path + ":" + message); 
    } 
    next(); 
} 
2

log_message如何暴露給調用者(一個模塊等),以及你對管道前的管道有什麼控制權?

您可以應用中間件這條路的調用之前和具備的功能來自於閉包內log_message,或者你可以把req EventEmitter設施的優勢,敷呼叫到處理器中winston.log的req.end和只需記錄請求期間發出的所有消息。這將有效地將您的log_message更改爲日誌消息的累加器(可能位於數組中),並在請求結束時將它們全部記錄下來。

這一切都取決於你如何公開這些東西。

許多貓在這裏已經剝皮:)

10

一個有趣的方式來做到這將是新的域功能。 http://nodejs.org/api/domain.html

域雖然提供了出色的錯誤恢復,但可以用作「線程本地存儲」的一種類型 - 基本上存儲每個請求的數據。

創建一些中間件,將每個請求/響應添加到域中。

app.use(function(req, res, next) { 
    var reqd = domain.create(); 
    reqd.add(req); 
    reqd.add(res); 
    reqd._req = req; // Add request object to custom property 
    // TODO: hook error event on reqd (see docs) 
    next(); 
}); 

在日誌功能中,您現在可以獲取當前域並取出請求對象。

function log_message(level, message) { 
    // Pull the request from the current domain. 
    var request = process.domain._req; 

    // TODO: log message 
}; 

域名仍然是實驗性的,但從現在到1.0版本之間聽起來不會有太多變化。

+0

創建域不會自動設置process.domain到該域。所以在log_message中process.domain實際上是未定義的。 –

+0

@MoizRaja那麼,人們如何將該域添加到後來可用的過程中呢? –

+0

@ChristopherWill:'process.domain = reqd;'在中間件中爲我工作。可悲的是找不到描述行爲的文檔: -/ – Timm

3

創建中間件:

app.use(function(req, res, next) { 
     var tid = uuid.v4(); 
    var cls = require('continuation-local-storage'); 
     var namespace = cls.createNamespace('com.storage'); 
     var pre_ip; 
      if(get_ip(req)) 
      { ip_info= get_ip(req).clientIp; 
       pre_ip=ip_info 
      } 
      namespace.bindEmitter(req); 
      namespace.bindEmitter(res); 
     namespace.run(function() { 
       console.log(logobj); 
       namespace.set('tid', tid); 
       namespace.set('ip',ip_info); 
      namespace.set('logobj',logobj); 
       next(); 
      }); 
     }); 

並使用它:

var cls = require('continuation-local-storage'); 
var namespace = cls.getNamespace('com.storage'); 
     namespace.get('ip'); 
相關問題