2012-11-02 31 views
8

Dưới đây là hai câu mà dường như thường được chấp nhận, nhưng mà tôi có thể không thực sự vượt qua:Ghi lại tham số trong slf4j - nó so sánh như thế nào với các tham số bằng tên của scala?

1) Scala bằng tên params duyên dáng thay thế luôn cái khó chịu sử dụng log4j mẫu:

if (l.isDebugEnabled()) { 
     logger.debug("expensive string representation, eg: godObject.toString()") 
    } 

vì tham số theo tên (một tính năng ngôn ngữ cụ thể theo Scala) không được đánh giá trước khi gọi phương thức.

2) Tuy nhiên, vấn đề này được giải quyết bằng cách khai thác gỗ parametrized trong slf4f:

logger.debug("expensive string representation, eg {}:", godObject[.toString()]); 

Vì vậy, làm thế nào để làm việc này? Có một số phép thuật cấp thấp liên quan đến thư viện slf4j ngăn cản việc đánh giá tham số trước khi thực hiện phương thức "gỡ lỗi" không? (thậm chí có thể không? Có thể một thư viện tác động đến một khía cạnh cơ bản của ngôn ngữ?)

Hoặc thực tế đơn giản là một đối tượng được chuyển sang phương thức - chứ không phải là một chuỗi? (và có thể toString() của đối tượng đó được gọi trong chính phương thức debug(), nếu có).

Nhưng sau đó, điều đó cũng không đúng đối với log4j? (nó có các phương thức với các tham số Object). Và điều này có nghĩa là nếu bạn truyền một chuỗi - như trong đoạn mã trên, nó sẽ hoạt động giống hệt log4j?

Tôi thực sự muốn có chút ánh sáng nào đó về vấn đề này.

Cảm ơn!

Trả lời

24

Không có phép thuật nào trong slf4j. Vấn đề với khai thác gỗ từng là rằng nếu bạn muốn đăng nhập giả

logger.debug("expensive string representation: " + godObject) 

thì không có vấn đề nếu mức debug được kích hoạt trong logger hay không, bạn luôn được đánh giá godObject.toString() mà có thể là một hoạt động tốn kém, và sau đó cũng nối chuỗi. Điều này xuất phát từ thực tế là trong các đối số Java (và hầu hết các ngôn ngữ) được đánh giá trước khi chúng được truyền vào một hàm.

Đó là lý do tại sao slf4j giới thiệu logger.debug(String msg, Object arg) (và các biến thể khác cho nhiều đối số hơn). Toàn bộ ý tưởng là bạn vượt qua các đối số giá rẻ cho hàm debug và nó gọi toString trên chúng và kết hợp chúng thành một thông báo chỉ khi mức gỡ lỗi được bật.

Lưu ý rằng bằng cách gọi

logger.debug("expensive string representation, eg: {}", godObject.toString()); 

bạn giảm đáng kể lợi thế này, như cách này bạn chuyển đổi godObject tất cả các thời gian, trước khi bạn vượt qua nó để debug, không có vấn đề gì debug mức trên. Bạn chỉ nên sử dụng

logger.debug("expensive string representation, eg: {}", godObject); 

Tuy nhiên, đây vẫn không phải là lý tưởng. Nó chỉ spares gọi toString và chuỗi nối. Nhưng nếu thông điệp đăng nhập của bạn yêu cầu một số xử lý tốn kém khác để tạo thông báo, nó sẽ không giúp ích gì.Giống như nếu bạn cần phải gọi một số expensiveMethod để tạo ra thông điệp:

logger.debug("expensive method, eg: {}", 
    godObject.expensiveMethod()); 

sau đó expensiveMethod luôn được đánh giá trước khi được truyền cho logger. Để thực hiện công việc này một cách hiệu quả với slf4j, bạn vẫn phải nghỉ mát trở lại

if (logger.isDebugEnabled()) 
    logger.debug("expensive method, eg: {}", 
     godObject.expensiveMethod()); 

Scala của cuộc gọi theo tên sẽ giúp rất nhiều trong vấn đề này, bởi vì nó cho phép bạn quấn mảnh tùy ý các mã vào một đối tượng chức năng và chỉ đánh giá mã đó khi cần. Đây chính xác là những gì chúng ta cần. Hãy xem ví dụ slf4s. Thư viện này cho thấy phương pháp như

def debug(msg: => String) { ... } 

Tại sao không có đối số như trong slf4j của Logger? Bởi vì chúng ta không cần chúng nữa. Chúng tôi có thể viết chỉ

logger.debug("expensive representation, eg: " + 
    godObject.expensiveMethod()) 

Chúng tôi không chuyển một thông điệp và các đối số của nó, chúng tôi chuyển trực tiếp một đoạn mã được đánh giá vào thư. Nhưng chỉ khi logger quyết định làm như vậy. Nếu mức độ gỡ lỗi không được bật, thì không có gì trong phạm vi logger.debug(...) được đánh giá bao giờ, toàn bộ mọi thứ chỉ bị bỏ qua. Không phải expensiveMethod được gọi hay bất kỳ cuộc gọi nào hoặc chuỗi nối kết xảy ra. Vì vậy, cách tiếp cận này là chung nhất và linh hoạt nhất. Bạn có thể chuyển bất kỳ biểu thức nào đánh giá đến một số String đến debug, bất kể phức tạp đến mức nào.

+1

Tinh thể rõ ràng, cảm ơn bạn rất nhiều. Tôi đoán giải thích kỹ lưỡng của bạn bù đắp cho phép thuật mà tôi đã hy vọng và không nhận được. :) – teo

Các vấn đề liên quan