Tại sao không sử dụng java.util.logging?


351

Lần đầu tiên trong đời tôi thấy mình ở một vị trí mà tôi đang viết một API Java sẽ được mở nguồn. Hy vọng sẽ được đưa vào nhiều dự án khác.

Để đăng nhập tôi (và thực sự những người tôi làm việc cùng) đã luôn sử dụng JUL (java.util.logging) và không bao giờ có bất kỳ vấn đề nào với nó. Tuy nhiên bây giờ tôi cần hiểu chi tiết hơn những gì tôi nên làm để phát triển API. Tôi đã thực hiện một số nghiên cứu về điều này và với thông tin tôi có được, tôi càng bối rối hơn. Do đó bài này.

Vì tôi đến từ JUL nên tôi thiên vị về điều đó. Kiến thức của tôi về phần còn lại không phải là lớn.

Từ nghiên cứu tôi đã thực hiện, tôi đã đưa ra những lý do tại sao mọi người không thích JUL:

  1. "Tôi đã bắt đầu phát triển Java từ lâu trước khi Sun phát hành JUL và việc tiếp tục với log-framework-X dễ dàng hơn là học một cái gì đó mới" . Hừm. Tôi không đùa, đây thực sự là những gì mọi người nói. Với lập luận này, tất cả chúng ta có thể thực hiện COBOL. (tuy nhiên tôi chắc chắn có thể liên quan đến việc đây là một anh chàng lười biếng)

  2. "Tôi không thích tên của các cấp ghi nhật ký trong JUL" . Ok, nghiêm túc, điều này không đủ lý do để giới thiệu một phụ thuộc mới.

  3. "Tôi không thích định dạng chuẩn của đầu ra từ JUL" . Hừm. Đây chỉ là cấu hình. Bạn thậm chí không phải làm bất cứ điều gì khôn ngoan. (đúng, trở lại ngày xưa, bạn có thể phải tạo lớp Formatter của riêng mình để làm cho đúng).

  4. "Tôi sử dụng các thư viện khác cũng sử dụng log-framework-X vì vậy tôi nghĩ việc sử dụng thư viện đó dễ dàng hơn" . Đây là một đối số tròn, phải không? Tại sao 'mọi người' sử dụng log-framework-X mà không phải JUL?

  5. "Mọi người khác đang sử dụng log-framework-X" . Điều này với tôi chỉ là một trường hợp đặc biệt ở trên. Đa số không phải lúc nào cũng đúng.

Vì vậy, câu hỏi lớn thực sự là tại sao không JUL? . Tôi đã bỏ lỡ điều gì? Cơ sở cho việc ghi nhật ký (SLF4J, JCL) là nhiều triển khai khai thác đã tồn tại trong lịch sử và lý do cho điều đó thực sự quay trở lại thời đại trước JUL như tôi thấy. Nếu JUL hoàn hảo thì mặt tiền đăng nhập sẽ không tồn tại, hay sao? Để làm cho vấn đề trở nên khó hiểu hơn JUL là ở một mức độ nào đó, chính mặt tiền, cho phép Người xử lý, Trình định dạng và thậm chí Trình quản lý Log được hoán đổi.

Thay vì chấp nhận nhiều cách để làm cùng một việc (ghi nhật ký), chúng ta không nên đặt câu hỏi tại sao chúng lại cần thiết ngay từ đầu? (và xem nếu những lý do đó vẫn còn tồn tại)

Ok, nghiên cứu của tôi cho đến nay đã dẫn đến một vài điều mà tôi có thể thấy có thể là vấn đề thực sự với JUL:

  1. Hiệu suất . Một số người nói rằng hiệu suất trong SLF4J là vượt trội so với phần còn lại. Đây dường như là một trường hợp tối ưu hóa sớm. Nếu bạn cần đăng nhập hàng trăm megabyte mỗi giây thì tôi không chắc bạn đang đi đúng hướng. JUL cũng đã phát triển và các thử nghiệm bạn đã thực hiện trên Java 1.4 có thể không còn đúng nữa. Bạn có thể đọc về nó ở đây và cách khắc phục này đã biến nó thành Java 7. Nhiều người cũng nói về chi phí của việc nối chuỗi trong các phương thức ghi nhật ký. Tuy nhiên, việc ghi nhật ký dựa trên mẫu sẽ tránh được chi phí này và nó cũng tồn tại trong JUL. Cá nhân tôi không bao giờ thực sự viết mẫu dựa trên đăng nhập. Quá lười biếng cho điều đó. Ví dụ: nếu tôi làm điều này với JUL:

    log.finest("Lookup request from username=" + username 
       + ", valueX=" + valueX
       + ", valueY=" + valueY));

    IDE của tôi sẽ cảnh báo tôi và xin phép rằng nó sẽ thay đổi nó thành:

    log.log(Level.FINEST, "Lookup request from username={0}, valueX={1}, valueY={2}", 
       new Object[]{username, valueX, valueY});

    .. mà tôi tất nhiên sẽ chấp nhận. Đã được cho phép ! Cảm ơn sự giúp đỡ của bạn.

    Vì vậy, tôi thực sự không viết những tuyên bố như vậy, được thực hiện bởi IDE.

    Để kết luận về vấn đề hiệu suất, tôi không tìm thấy bất cứ điều gì cho thấy hiệu suất của JUL không ổn so với đối thủ.

  2. Cấu hình từ classpath . JUL ngoài hộp không thể tải tệp cấu hình từ đường dẫn lớp. Đó là một vài dòng mã để làm cho nó làm như vậy. Tôi có thể thấy tại sao điều này có thể gây phiền nhiễu nhưng giải pháp ngắn và đơn giản.

  3. Sẵn có của xử lý đầu ra . JUL đi kèm với 5 trình xử lý đầu ra bên ngoài: bảng điều khiển, luồng tệp, ổ cắm và bộ nhớ. Đây có thể được mở rộng hoặc những cái mới có thể được viết. Ví dụ, điều này có thể được ghi vào UNIX / Linux Syslog và Windows Event Log. Cá nhân tôi chưa bao giờ có yêu cầu này và tôi chưa thấy nó được sử dụng nhưng tôi chắc chắn có thể liên quan đến lý do tại sao nó có thể là một tính năng hữu ích. Logback đi kèm với một ứng dụng cho Syslog chẳng hạn. Tôi vẫn sẽ tranh luận rằng

    1. 99,5% nhu cầu cho các điểm đến đầu ra được bảo đảm bởi những gì có sẵn trong JUL.
    2. Nhu cầu đặc biệt có thể được phục vụ cho những người xử lý tùy chỉnh trên đầu JUL chứ không phải trên một thứ khác. Không có gì với tôi cho thấy rằng cần nhiều thời gian hơn để viết trình xử lý đầu ra Syslog cho JUL so với khung công tác ghi nhật ký khác.

Tôi thực sự lo ngại rằng có một cái gì đó tôi đã bỏ qua. Việc sử dụng các mặt tiền ghi nhật ký và triển khai ghi nhật ký khác với JUL rất phổ biến đến nỗi tôi phải đi đến kết luận rằng đó là tôi, người không hiểu. Đó không phải là lần đầu tiên, tôi sợ. :-)

Vậy tôi nên làm gì với API của mình? Tôi muốn nó trở nên thành công. Tất nhiên tôi có thể chỉ "đi theo dòng chảy" và thực hiện SLF4J (có vẻ phổ biến nhất hiện nay) nhưng vì lợi ích của riêng tôi, tôi vẫn cần hiểu chính xác những gì sai với JUL của ngày hôm nay để đảm bảo tất cả các fuzz? Tôi sẽ phá hoại bản thân mình bằng cách chọn JUL cho thư viện của mình chứ?

Kiểm tra hiệu suất

(phần được thêm bởi nolan600 vào ngày 07 tháng 7 năm 2012)

Có một tài liệu tham khảo dưới đây từ Ceki về tham số của SLF4J nhanh hơn 10 lần so với JUL. Vì vậy, tôi đã bắt đầu làm một số thử nghiệm đơn giản. Thoạt nhìn yêu sách chắc chắn là đúng. Dưới đây là kết quả sơ bộ (nhưng đọc tiếp!):

  • Thời gian thực hiện SLF4J, phụ trợ Đăng nhập lại: 1515
  • Thời gian thực hiện SLF4J, phụ trợ JUL: 12938
  • Thời gian thực hiện JUL: 16911

Những con số trên là msecs nên ít hơn là tốt hơn. Vì vậy, 10 lần khác biệt hiệu suất là lần đầu tiên thực sự khá gần. Phản ứng ban đầu của tôi: Đó là rất nhiều!

Đây là cốt lõi của bài kiểm tra. Như có thể thấy một số nguyên và một chuỗi được hiểu trong một vòng lặp sau đó được sử dụng trong câu lệnh log:

    for (int i = 0; i < noOfExecutions; i++) {
        for (char x=32; x<88; x++) {
            String someString = Character.toString(x);
            // here we log 
        }
    }

(Tôi muốn câu lệnh log có cả kiểu dữ liệu nguyên thủy (trong trường hợp này là int) và kiểu dữ liệu phức tạp hơn (trong trường hợp này là String). Không chắc nó có vấn đề nhưng bạn có nó.)

Báo cáo nhật ký cho SLF4J:

logger.info("Logging {} and {} ", i, someString);

Báo cáo nhật ký cho JUL:

logger.log(Level.INFO, "Logging {0} and {1}", new Object[]{i, someString});

JVM đã được 'làm nóng' với cùng một thử nghiệm được thực hiện một lần trước khi thực hiện phép đo thực tế. Java 1.7.03 đã được sử dụng trên Windows 7. Phiên bản mới nhất của SLF4J (v1.6.6) và Logback (v1.0.6) đã được sử dụng. Stdout và stderr đã được chuyển hướng đến thiết bị null.

Tuy nhiên, bây giờ hãy cẩn thận, hóa ra JUL đang dành phần lớn thời gian của mình getSourceClassName()vì JUL mặc định in tên lớp nguồn trong đầu ra, trong khi Logback thì không. Vì vậy, chúng tôi đang so sánh táo và cam. Tôi phải làm lại bài kiểm tra và cấu hình các cài đặt ghi nhật ký theo cách tương tự để chúng thực sự xuất ra cùng một thứ. Tuy nhiên, tôi nghi ngờ rằng SLF4J + Logback vẫn sẽ đứng đầu nhưng khác xa với những con số ban đầu như đã nêu ở trên. Giữ nguyên.

Btw: Thử nghiệm là lần đầu tiên tôi thực sự làm việc với SLF4J hoặc Logback. Một trải nghiệm thú vị. JUL chắc chắn là ít chào đón hơn khi bạn bắt đầu.

Hiệu suất thử nghiệm (phần 2)

(phần được thêm bởi nolan600 vào ngày 08 tháng 8 năm 2012)

Vì hóa ra nó không thực sự quan trọng đối với hiệu suất như thế nào khi bạn định cấu hình mẫu của mình trong JUL, tức là nó có bao gồm tên nguồn hay không. Tôi đã thử với một mẫu rất đơn giản:

java.util.logging.SimpleFormatter.format="%4$s: %5$s [%1$tc]%n"

và điều đó đã không thay đổi thời gian trên. Trình hồ sơ của tôi tiết lộ rằng trình ghi nhật ký vẫn dành nhiều thời gian cho các cuộc gọi đến getSourceClassName()ngay cả khi đây không phải là một phần trong mẫu của tôi. Các mô hình không quan trọng.

Do đó, tôi kết luận về vấn đề hiệu suất rằng ít nhất là đối với câu lệnh nhật ký dựa trên mẫu được kiểm tra dường như có khoảng 10 yếu tố khác biệt về hiệu suất thực giữa JUL (chậm) và SLF4J + Logback (nhanh). Đúng như Ceki nói.

Tôi cũng có thể thấy một điều khác là getLogger()cuộc gọi của SLF4J đắt hơn rất nhiều so với cuộc gọi của JUL. (95 ms so với 0,3 ms nếu hồ sơ của tôi là chính xác). Điều này thật ý nghĩa. SLF4J phải thực hiện một số thời gian để ràng buộc việc thực hiện ghi nhật ký cơ bản. Điều này không làm tôi sợ. Các cuộc gọi này sẽ hơi hiếm trong vòng đời của một ứng dụng. Độ bền phải có trong các cuộc gọi nhật ký thực tế.

Kết luận cuối cùng

(phần được thêm bởi nolan600 vào ngày 08 tháng 8 năm 2012)

Cảm ơn bạn cho tất cả các câu trả lời của bạn. Trái với những gì tôi nghĩ ban đầu tôi đã quyết định sử dụng SLF4J cho API của mình. Điều này dựa trên một số điều và đầu vào của bạn:

  1. Nó cho phép linh hoạt để chọn thực hiện nhật ký tại thời điểm triển khai.

  2. Các vấn đề thiếu linh hoạt về cấu hình của JUL khi chạy bên trong máy chủ ứng dụng.

  3. SLF4J chắc chắn nhanh hơn rất nhiều như chi tiết ở trên, đặc biệt nếu bạn kết hợp nó với Logback. Ngay cả khi đây chỉ là một thử nghiệm sơ bộ, tôi vẫn có lý do để tin rằng đã có nhiều nỗ lực hơn để tối ưu hóa trên SLF4J + Logback so với JUL.

  4. Tài liệu. Tài liệu về SLF4J đơn giản là toàn diện và chính xác hơn rất nhiều.

  5. Hoa văn linh hoạt. Khi tôi thực hiện các bài kiểm tra, tôi đã đặt ra để JUL bắt chước mẫu mặc định từ Logback. Mẫu này bao gồm tên của chủ đề. Hóa ra JUL không thể làm điều này ra khỏi hộp. Ok, tôi đã không bỏ lỡ nó cho đến bây giờ, nhưng tôi không nghĩ rằng đó là một điều nên thiếu trong khung đăng nhập. Giai đoạn = Stage!

  6. Hầu hết (hoặc nhiều) các dự án Java ngày nay sử dụng Maven, vì vậy việc thêm một phụ thuộc không phải là vấn đề lớn đặc biệt là nếu sự phụ thuộc đó khá ổn định, tức là không liên tục thay đổi API của nó. Điều này dường như đúng với SLF4J. Ngoài ra bình SLF4J và bạn bè có kích thước nhỏ.

Vì vậy, điều kỳ lạ đã xảy ra là tôi thực sự cảm thấy khó chịu với JUL sau khi đã làm việc một chút với SLF4J. Tôi vẫn hối tiếc rằng nó phải theo cách này với JUL. JUL là xa hoàn hảo nhưng loại công việc. Chỉ là không đủ tốt. Điều tương tự cũng có thể nói về Propertiesmột ví dụ nhưng chúng tôi không nghĩ về việc trừu tượng hóa để mọi người có thể cắm vào thư viện cấu hình của riêng họ và những gì có bạn. Tôi nghĩ lý do là Propertiesở ngay phía trên quán bar trong khi điều ngược lại là đúng với JUL của ngày hôm nay ... và trong quá khứ, nó ở mức 0 vì nó không tồn tại.


8
Tôi sẽ không hỏi kết thúc, vì câu hỏi được trình bày tốt này rất thú vị, nhưng nó là ranh giới nếu bạn đọc Câu hỏi thường gặp: sẽ khó tìm được câu trả lời độc đáo dứt khoát không dựa trên ý kiến.
Denys Séguret

Những gì bạn có thể đã bỏ lỡ là nhiều tác giả khung đã từ bỏ việc cố gắng sử dụng JUL và do đó thường khó sử dụng hơn nếu bạn không đơn giản tạo vanilla java.
Denys Séguret

3
Việc sử dụng thuật ngữ chung "log-framework-X" là sai lầm khi đề cập đến (các) khung ghi nhật ký phổ biến trước jul. Bạn nên sử dụng "log4j" trong trường hợp này. Các khung phổ biến khác như SLF4J và logback đã hoạt động tốt sau khi jul được phát hành.
Ceki

1
@Acuariano. Dự án Netty chỉ đơn giản là sử dụng Reflection để kiểm tra khung đăng nhập nào có sẵn trên classpath. Xem ở đây để có nguồn. Xem InternalLoggerFactory.java.
peterh

1
@xenoterracide thậm chí còn quan trọng hơn sẽ là một bản cập nhật cho Java 9, như đã giới thiệu java.lang.System.Logger, đó là một giao diện , có thể được chuyển hướng đến bất kỳ khung ghi nhật ký thực tế nào bạn muốn, miễn là khung đó bắt kịp và cung cấp triển khai giao diện đó. Kết hợp với mô đun hóa, bạn thậm chí có thể triển khai một ứng dụng với JRE đi kèm không chứa java.util.logging, nếu bạn thích một khung khác.
Holger

Câu trả lời:


207

Tuyên bố miễn trừ trách nhiệm : Tôi là người sáng lập các dự án log4j, SLF4J và logback.

Có những lý do khách quan để thích SLF4J. Đối với một, SLF4J cho phép người dùng cuối tự do lựa chọn khung ghi nhật ký cơ bản . Ngoài ra, người dùng thông thái có xu hướng thích logback, cung cấp các khả năng ngoài log4j , với jul tụt lại phía sau. Tính năng khôn ngoan có thể đủ cho một số người dùng nhưng đối với nhiều người khác thì không. Tóm lại, nếu đăng nhập là quan trọng đối với bạn, bạn sẽ muốn sử dụng SLF4J với logback làm triển khai cơ bản. Nếu đăng nhập là không quan trọng, jul là tốt.

Tuy nhiên, là một nhà phát triển oss, bạn cần tính đến sở thích của người dùng chứ không chỉ của riêng bạn. Theo đó, bạn nên chấp nhận SLF4J không phải vì bạn tin rằng SLF4J tốt hơn jul mà vì hầu hết các nhà phát triển Java hiện tại (tháng 7 năm 2012) thích SLF4J làm API ghi nhật ký của họ. Nếu cuối cùng bạn quyết định không quan tâm đến ý kiến ​​phổ biến, hãy xem xét các sự kiện sau:

  1. những người thích jul làm điều đó vì sự tiện lợi vì jul được gói cùng với JDK. Theo hiểu biết của tôi, không có tranh luận khách quan nào khác ủng hộ jul
  2. sở thích riêng của bạn cho jul chỉ là, một sở thích .

Do đó, việc nắm giữ "sự thật phũ phàng" trên dư luận, trong khi có vẻ dũng cảm, là một ngụy biện logic trong trường hợp này.

Nếu vẫn không bị thuyết phục, JB Nizet đưa ra một lập luận bổ sung và mạnh mẽ:

Ngoại trừ người dùng cuối có thể đã thực hiện tùy chỉnh này cho mã riêng của mình hoặc thư viện khác sử dụng log4j hoặc logback. jul có thể mở rộng, nhưng phải mở rộng logback, jul, log4j và God chỉ biết khung đăng nhập nào khác bởi vì anh ta sử dụng bốn thư viện sử dụng bốn khung ghi nhật ký khác nhau là cồng kềnh. Bằng cách sử dụng SLF4J, bạn cho phép anh ta định cấu hình khung đăng nhập mà anh ta muốn, không phải khung bạn đã chọn. Hãy nhớ rằng một dự án điển hình sử dụng vô số thư viện chứ không chỉ của bạn .

Nếu vì bất kỳ lý do gì bạn ghét API SLF4J và sử dụng nó sẽ làm mất đi niềm vui trong công việc của bạn, thì bằng mọi cách, hãy tìm jul Sau tất cả, có những cách để chuyển hướng jul sang SLF4J .

Nhân tiện, jul parametrization chậm hơn ít nhất 10 lần so với SLF4J, kết thúc tạo ra sự khác biệt đáng chú ý.


2
@Ceki bạn có thể muốn giải thích một chút về từ chối trách nhiệm của mình để nó đề cập đến vai trò hiện tại của bạn trong các dự án log4j, slf4j và logback. Lý do là tự nhiên để giải thích sự thiên vị của bạn.
Thorbjørn Ravn Andersen

2
Có một số hỗ trợ cho tuyên bố rằng hầu hết các nhà phát triển Java thích SLF4J làm API ghi nhật ký của họ không?
Olivier Cailloux

3
Bản chất của bài viết của tôi là các nhà phát triển khác nhau có sở thích khác nhau dường như vượt quá tranh chấp. Đúng?
Ceki

1
mặc dù thành thật mà nói, tôi rất thích xem các điểm chuẩn năm 2018 trên Java 11 (hoặc bất cứ điều gì kết thúc) và chống lại log4j2 ở chế độ không đồng bộ.
xenoterracide

5
Tôi đang ở đây, sử dụng SLF4J và tôi vẫn phải xử lý tất cả các khung ghi nhật ký khác mà các thư viện khác sử dụng. Sử dụng SLF4J không giải quyết được vấn đề của logger không đồng nhất, nó chỉ làm cho nó tồi tệ hơn. xkcd.com/927
Charlie

34
  1. java.util.loggingđã được giới thiệu trong Java 1.4. Đã có những cách sử dụng để ghi nhật ký trước đó, đó là lý do tại sao nhiều API ghi nhật ký khác tồn tại. Các API đó được sử dụng nhiều trước Java 1.4 và do đó có một thị trường tuyệt vời không giảm xuống 0 khi 1.4 được phát hành.

  2. JUL đã không bắt đầu tất cả những điều tuyệt vời đó, nhiều điều bạn đã đề cập ở mức tệ hơn rất nhiều trong 1.4 và chỉ trở nên tốt hơn trong 1.5 (và tôi đoán là 6 cũng vậy, nhưng tôi không chắc lắm).

  3. JUL không phù hợp cho nhiều ứng dụng có cấu hình khác nhau trong cùng một JVM (nghĩ rằng nhiều ứng dụng web không nên tương tác). Tomcat cần phải nhảy qua một số vòng để hoạt động (thực hiện lại JUL một cách hiệu quả nếu tôi hiểu điều đó một cách chính xác).

  4. Bạn không thể luôn ảnh hưởng đến khung đăng nhập mà thư viện của bạn sử dụng. Do đó, sử dụng SLF4J (thực tế chỉ là một lớp API rất mỏng so với các thư viện khác) giúp giữ một bức tranh nhất quán về toàn bộ thế giới ghi nhật ký (để bạn có thể quyết định khung ghi nhật ký cơ bản trong khi vẫn có nhật ký thư viện trong cùng hệ thống).

  5. Thư viện không thể dễ dàng thay đổi. Nếu một phiên bản trước của thư viện được sử dụng để sử dụng log-library-X, nó không thể dễ dàng chuyển sang log-library-Y (ví dụ JUL), ngay cả khi cái sau rõ ràng là siêu cấp: bất kỳ người dùng nào của thư viện đó đều cần học khung ghi nhật ký mới và (ít nhất) cấu hình lại việc ghi nhật ký của họ. Đó là một điều không nên, đặc biệt là khi nó không mang lại lợi ích rõ ràng cho hầu hết mọi người.

Đã nói tất cả những gì tôi nghĩ rằng JUL ít nhất là một sự thay thế hợp lệ cho các khung đăng nhập khác hiện nay.


1
Cảm ơn Joachim, tôi đánh giá cao bài viết của bạn. (1) và (2) của bạn đối với tôi chỉ là lịch sử. Lâu lắm rồi. (4) của bạn là hậu quả của điều đó và sau đó trở thành cái mà tôi gọi là đối số tuần hoàn. (3) của bạn tuy nhiên thực sự thú vị. Có lẽ bạn đang ở một cái gì đó? Nhưng điều này sẽ chỉ ảnh hưởng đến những người đang xây dựng các thùng chứa ứng dụng mà vào cuối ngày là rất ít người. Hay cái gì?
peterh

3
Chà, ai bỏ qua lịch sử thì cam chịu lặp lại nó ;-) Lịch sử rất phù hợp trong việc phát triển phần mềm. Mọi người không di chuyển quá nhanh và thay thế các thư viện của bên thứ ba hiện tại bằng các API tiêu chuẩn chỉ hoạt động tốt nếu các API tiêu chuẩn hoạt động ít nhất là tốt như các thư viện của bên thứ ba. Và họ đã không ban đầu (và được cho là vẫn không làm trong một số trường hợp).
Joachim Sauer

Joachim, tôi quan tâm đến những người "được cho là vẫn không trong một số trường hợp" mà bạn đề cập. Đó là thịt phải có. Thay thế một thư viện logger trong mã hiện tại của bạn là khá nhỏ và có thể được tự động hóa những ngày này. SLF4J có một công cụ để chứng minh quan điểm của tôi. Vì vậy, tôi nghĩ rằng một thư viện đồ sộ được viết vào năm 2002 với log4j có thể được chuyển đổi thành JUL chỉ trong vài phút với một công cụ tự động. (Tôi không biết nếu một người tồn tại, mặc dù). Vậy tại sao nó không xảy ra?
peterh

3
@ nolan6000: Tôi không biết đủ về các chi tiết cụ thể để đi sâu vào chi tiết về cụm từ đó và nó không thực sự là điểm tôi đang thực hiện. Ngay cả khi JUL bây giờ ngang bằng với khuôn khổ của bên thứ ba, quán tính và cơ sở hạ tầng hiện tại vẫn là một lý do mạnh mẽ để không chuyển đổi. Ví dụ: nếu thư viện X sử dụng slf4j trong Phiên bản 1.1, thì việc chuyển sang JUL trong 1.2 (hoặc thậm chí 2.0) sẽ là một vấn đề lớn đối với nhiều người dùng (đã cấu hình chính xác hệ thống cũ và sẽ phải làm lại điều đó để không đạt được lợi ích rõ ràng) .
Joachim Sauer

@ nolan6000 ngay cả khi bạn không quan tâm đến lịch sử, các thư viện bạn sử dụng trong ứng dụng của bạn chắc chắn sẽ làm được. Không có gì thú vị khi phải loại bỏ một thư viện đơn giản chỉ vì nó sử dụng một khung ghi nhật ký khác với bạn.
Thorbjørn Ravn Andersen

29

IMHO, lợi thế chính trong việc sử dụng mặt tiền ghi nhật ký như slf4j là bạn cho phép người dùng cuối của thư viện chọn thực hiện ghi nhật ký cụ thể mà anh ta muốn, thay vì áp đặt lựa chọn của bạn cho người dùng cuối.

Có thể anh ta đã đầu tư thời gian và tiền bạc vào Log4j hoặc LogBack (trình định dạng đặc biệt, trình bổ sung, v.v.) và thích tiếp tục sử dụng Log4j hoặc LogBack, thay vì định cấu hình jul. Không có vấn đề: slf4j cho phép điều đó. Có phải là một lựa chọn khôn ngoan để sử dụng Log4j hơn jul? Co le không. Nhưng bạn không quan tâm. Hãy để người dùng cuối chọn những gì anh ta thích.


Cảm ơn JB. Câu hỏi của tôi là nếu tôi thực sự áp đặt nhiều cho người dùng / người thực hiện thư viện của mình bằng cách buộc JUL vào anh ta? Nếu anh ta không hài lòng với các trình xử lý đầu ra tiêu chuẩn của JUL, anh ta có thể trao đổi chúng cho riêng mình tại thời điểm triển khai như tôi thấy. Tôi không thực sự xem JUL như một cái vợt. Dường như với tôi là linh hoạt và có thể mở rộng như phần còn lại của họ.
peterh

12
Ngoại trừ người dùng cuối có thể đã thực hiện tùy chỉnh này cho mã riêng của mình hoặc thư viện khác sử dụng log4j hoặc LogBack. jul có thể mở rộng, nhưng phải mở rộng LogBack, jul, log4j và God chỉ biết khung đăng nhập nào khác bởi vì anh ta sử dụng 4 thư viện sử dụng 4 khung ghi nhật ký khác nhau là cồng kềnh. Bằng cách sử dụng slf4j, bạn cho phép anh ta định cấu hình các khung đăng nhập mà anh ta muốn. không phải là người bạn đã chọn. Hãy nhớ rằng các dự án điển hình sử dụng vô số thư viện, và không chỉ của bạn.
JB Nizet

6

Tôi bắt đầu, giống như bạn, tôi nghi ngờ, sử dụng JUL vì đó là cách dễ nhất để đi ngay lập tức. Tuy nhiên, trong nhiều năm qua, tôi đã ước rằng mình đã dành thêm một chút thời gian để lựa chọn.

Vấn đề chính của tôi bây giờ là chúng tôi có một lượng đáng kể mã 'thư viện' được sử dụng trong nhiều ứng dụng và tất cả chúng đều sử dụng JUL. Bất cứ khi nào tôi sử dụng các công cụ này trong một ứng dụng loại dịch vụ web, việc ghi nhật ký sẽ biến mất hoặc đi đến một nơi không thể đoán trước hoặc lạ.

Giải pháp của chúng tôi là thêm một mặt tiền vào mã thư viện có nghĩa là các cuộc gọi nhật ký thư viện không thay đổi nhưng được chuyển hướng linh hoạt đến bất kỳ cơ chế ghi nhật ký nào có sẵn. Khi được bao gồm trong một công cụ POJO, chúng được chuyển hướng đến JUL nhưng khi được triển khai dưới dạng một ứng dụng web, chúng được chuyển hướng đến LogBack.

Tất nhiên, điều đáng tiếc của chúng tôi - là mã thư viện không sử dụng ghi nhật ký được tham số hóa nhưng giờ đây có thể được trang bị thêm khi cần thiết.

Chúng tôi đã sử dụng slf4j để xây dựng mặt tiền.


1
Bất kỳ lý do nào bạn không chỉ sử dụng gói "redirect java.util.logging to slf4j" trong bản phân phối slf4j?
Thorbjørn Ravn Andersen

2
Chúng tôi đã làm, nhưng ít giá trị vì lợi ích chính của việc chuyển sang slf4j là ghi nhật ký tham số hiệu quả. Nếu chúng ta đã sử dụng nó từ đầu, chúng ta sẽ không có việc gì phải làm bây giờ.
OldCurmudgeon

1
Tôi đồng ý rằng đây là trái cây treo thấp của slf4j.
Thorbjørn Ravn Andersen

3

Tôi đã chạy jul với slf4j-1.7,21 qua logback-1.1.7, xuất ra ổ SSD, Java 1.8, Win64

jul đã chạy 48449 ms, logback 27185 ms cho một vòng lặp 1M.

Tuy nhiên, API tốc độ cao hơn và đẹp hơn một chút không đáng giá 3 thư viện và 800K đối với tôi.

package log;

import java.util.logging.Level;
import java.util.logging.Logger;

public class LogJUL
{
    final static Logger logger = Logger.getLogger(LogJUL.class.getSimpleName());

    public static void main(String[] args) 
    {
        int N = 1024*1024;

        long l = System.currentTimeMillis();

        for (int i = 0; i < N; i++)
        {
            Long lc = System.currentTimeMillis();

            Object[] o = { lc };

            logger.log(Level.INFO,"Epoch time {0}", o);
        }

        l = System.currentTimeMillis() - l;

        System.out.printf("time (ms) %d%n", l);
    }
}

package log;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LogSLF
{
    static Logger logger = LoggerFactory.getLogger(LogSLF.class);


    public static void main(String[] args) 
    {
        int N = 1024*1024;

        long l = System.currentTimeMillis();

        for (int i = 0; i < N; i++)
        {
            Long lc = System.currentTimeMillis();

            logger.info("Epoch time {}", lc);
        }

        l = System.currentTimeMillis() - l;

        System.out.printf("time (ms) %d%n", l);
    }

}

3
Bạn không so sánh thích cho thích. Tại sao bạn rõ ràng tạo ra một mảng cho jul? Tôi đoán đó là vì slf4j thiếu quá tải một đối số logger.info(). Vì vậy, bạn đang cố tình làm tê liệt hiệu suất của jul để bù đắp cho sự thiếu sót trong giao diện của slf4j. Thay vào đó, bạn nên mã hóa cả hai phương thức theo cách chúng được mã hóa thành ngữ.
Klitos Kyriacou

2
Bạn đã hiểu lầm nó. Bạn không phải sử dụng thêm 800K. Sự đồng thuận là api SLF4J rất mỏng đáng để sử dụng vì sau đó bạn (hoặc những người khác có thể sử dụng lại một ngày mã của bạn!) Có thể chuyển đổi tự do giữa JUL, Logback, Log4j, v.v. SLF4J chỉ ~ 28K. Cầu SLF4J đến JUL (slf4j-jdk ... jar) chỉ ~ 9K.
risop
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.