2011-04-09 55 views
10

Tôi đã làm việc với một codebase của một công ty có chính sách viết nhiều lần ghi nhật ký. Vì vậy, khá nhiều mỗi phương pháp có một đoạn mã mà bắt đầu như thế này:Sử dụng chú thích để ghi nhật ký theo dõi

String LOG_METHOD = "nameOfMethod(String,List<Long>):void"; 
if(logger.isTraceEnabled()) { 
    Object[] params = new Object[] { string, list }; 
    logger.trace(CompanyMessages.newMethodInstanceMessage(this, LOG_METHOD, params)); 
} 

và kết thúc như thế này (hoặc trong một finally -clause hoặc chỉ ở phần cuối của phương pháp này:

if(logger.isTraceEnabled()) { 
    logger.trace(CompanyMessages.leaveMethodInstanceMessage(this, LOG_METHOD)); 
} 

Có Điều này làm lộn xộn mã và các lập trình viên khác liên tục làm rối tung nó bằng cách giải thích riêng của họ mà không sử dụng lớp CompanyMessages cụ thể cần thiết để định dạng các thông điệp thành được đọc bởi các công cụ giám sát. Vì vậy, tôi đang tìm kiếm một cách để loại bỏ tất cả mã ở trên và chỉ cung cấp tất cả các phương pháp cần ghi nhật ký-ghi nhật ký với chú thích như: @LogBefore('logLevel') & @LogAfter('logLevel').

Lý do tôi chọn giải pháp này là làm cho nó để các nhà phát triển khác không phải học bất cứ điều gì mới nhưng để sử dụng chú thích thay vì mã. Tôi đang làm việc trong một môi trường máy chủ, trong đó chúng tôi triển khai hàng trăm ứng dụng web và hàng tá nhà phát triển. Vì vậy, tôi đã tìm kiếm một cách để thực hiện điều này trong một ứng dụng web mà không cần thêm nhiều mã hóa hoặc các thư viện lớn bổ sung. Điều này có nghĩa là tôi đang tìm một triển khai AOP nhỏ, ổn định bằng cách sử dụng các chú thích tương tự như những gì tôi đã đề xuất, dễ cấu hình trong mỗi ứng dụng web. Hiệu suất cũng rất quan trọng. Ví dụ đơn giản nhất để thực hiện điều này với AOP là gì?

Chỉnh sửa: Tôi đã tìm thấy something very similar với những gì tôi đang tìm kiếm, nhưng điều này có một số vấn đề. Tất cả các lớp cần đăng nhập phải được cấu hình, vốn sẽ tốn nhiều tài nguyên hơn là chỉ sử dụng chú thích. Cấu hình mùa xuân <aop:aspectj-autoproxy/> có khắc phục được điều đó không?

Trả lời

3

Tôi không nghĩ rằng chú thích là giải pháp. Để chú thích một lớp hoặc một cá thể có nghĩa là cung cấp các lớp thông tin bổ sung khi chạy, mỗi lần nó không làm bất cứ điều gì. Bạn sẽ cần một số mã xử lý các lớp có chú thích và thêm mã trước và sau mỗi phương thức dựa trên các chú thích đó trong thời gian chạy.

Vì vậy, không có cách nào để thêm chú thích và sẵn sàng sử dụng, các lớp học của bạn bắt đầu ghi lại các phương thức của chúng.

Giải pháp nên là AOP - chính xác vấn đề này AOP đã được phát minh ngay từ đầu. Xác định các lớp/phương thức/hành động trên mỗi phương thức và bạn đã giải quyết được vấn đề.

Vâng, có lẽ bạn có thể làm cho nó hoạt động với các chú thích và các lớp điều chỉnh trong thời gian chạy nhưng bạn kết thúc với tự làm AOP :-)

+0

Cảm ơn, điều này khiến tôi nhận ra rằng quan điểm của tôi về hoạt động của chú thích là không hoàn thiện. – mahler

5

Hình như Aspect Oriented Programming (AOP) thực sự có thể giúp bạn với điều này. Thật tuyệt vời khi giải quyết các mối quan tâm chéo này như ghi nhật ký và truy tìm và nó hỗ trợ các chú thích giống như những gì bạn cần.

Hãy xem AspectJ hoặc Spring AOP.

Nó sẽ liên quan đến một số học tập về nguyên tắc AOP và API bạn chọn nhưng nó chắc chắn đáng để nỗ lực. Đặc biệt là đăng nhập và truy tìm là một trong những hướng dẫn AOP đầu tiên bạn sẽ gặp phải và nó khá dễ dàng để làm mà không cần phải đi sâu hơn.

4

Chú thích và điểm AOP đều hợp lệ. Sử dụng chú thích để cảnh báo khung AOP về việc ghi nhật ký.

Một điều khác tôi sẽ làm là sửa nhật ký của bạn.

Bạn có:

String LOG_METHOD = "nameOfMethod(String,List<Long>):void" 
if(logger.isTraceEnabled()) { 
    Object[] params = new Object[] { string, list }; 
    logger.trace(CompanyMessages.newMethodInstanceMessage(this, LOG_METHOD, params)); 
} 

Thay vào đó, hãy xem xét một cái gì đó như thế này:

logger.trace(this, LOG_METHOD, string, list); 

và bạn có thể thực hiện nó như thế này:

public void trace(Object obj, Object args...) { 
    if (parentLogger.isTraceEnabled()) { 
     logger.trace(CompanyMessages.newMethodInstanceMessage(obj, LOG_METHOD, args); 
    } 
} 

Hầu hết các tiện ích khai thác gỗ được viết trước khi chúng tôi có varargs trong Java, vì vậy chúng tôi vẫn thấy những thứ như những gì bạn đã viết.

Chúng tôi cũng vẫn muốn bảo vệ để ngăn chặn gọi log khi nó không được kích hoạt, nhưng động lực chính cho điều đó là bởi vì hầu hết mọi người trong quá khứ sẽ làm những gì bạn đã làm, hoặc, thậm chí tệ hơn:

logger.trace("My message: " + string + " with list " + list); 

Mà đã có một biểu hiện đắt tiền cho dù dấu vết được kích hoạt hay không.

Nhưng bằng cách tận dụng các vararg, bạn có thể nhận cả hai. Đơn giản chỉ cần sử dụng một cái gì đó giống như MessageFormat (mà bạn có lẽ làm được), bạn có thể dễ dàng nhận được:

logger.trace("My message: {0} with list {1}", string, list); 

Với dấu vết bị vô hiệu hóa, đây là một phương pháp gọi giá rẻ đi qua 3 con trỏ. Vì vậy, có ít động cơ hơn để bảo vệ nó và làm lộn xộn mã của bạn.

Hầu hết các trình ghi nhật ký hiện đại không ghi đè độc đáo, vì vậy bạn thường phải gói gọn nó thay vì chỉ đơn giản là mở rộng nó.

Nó không trực tiếp giải quyết vấn đề của bạn, tự động tạo thông tin theo dõi. Nhưng đó là một nền tảng trung bình đơn giản mà dễ dàng, và dần dần, làm sạch cơ sở mã hiện tại của bạn.

Ngoài ra, còn có 2 tùy chọn khác.

Một, là sử dụng bộ xử lý bài đăng chạy qua mã của bạn và thêm đăng nhập vào những địa điểm chưa tồn tại. Điều này giúp bạn tiết kiệm gánh nặng của việc gõ là tất cả bằng tay, nhưng nó làm lộn xộn mã (vì nó vẫn tồn tại MỌI NGƯỜI).

Hai, là sử dụng bộ xử lý chú thích tại thời gian biên dịch. Điều này phức tạp hơn. Nhưng những gì nó làm là trong quá trình biên dịch, nó chạy qua và tăng thêm các lớp của bạn vào thời gian biên dịch với thông tin. Điều tốt đẹp là mã của bạn được sạch sẽ (có thể tiết kiệm cho chú thích), nhưng cũng có tất cả các công việc được thực hiện tại biên dịch. Không có thời gian chạy tác động không phải là classloaders ưa thích của các nhà máy Object. Một khi nó được xây dựng, bạn có thể quăng bộ vi xử lý của bạn đi, nó không cần thiết trong thời gian chạy ở tất cả.

Có một dự án, tên của người đó đã trốn thoát tôi, thúc đẩy điều này. Nó tự động thêm setters/getter vào mã của bạn khi biên dịch. Tôi đã nghe những điều tốt đẹp về nó.

Các khung công tác AOP cũng có thể làm điều này cho bạn khi biên dịch, tôi không quen thuộc với họ để nói, nhưng dù bằng cách nào, kỹ thuật cũng đáng để khám phá.

Ít nhất, hãy gói nhật ký của bạn. Đó là gia tăng, an toàn, và dần dần sẽ làm sạch mã của bạn và hỗ trợ đăng nhập của bạn, nơi các chú thích có thể không làm việc cho bạn nói chung.

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