Saya menulis perpustakaan yang memiliki banyak informasi yang dapat digunakan dalam log di program yang menggunakannya, tapi saya tidak tahu cara terbaik untuk mengeksposnya sedemikian rupa sehingga program yang menggunakan perpustakaan saya bisa mengintegrasikan log perpustakaan saya dengan lognya sendiri tanpa terlihat (jika diinginkan).
Memilih perpustakaan logging khusus untuk perpustakaan saya menambah daftar dependensi untuk menggunakan perpustakaan saya serta mengikat program utama ke perpustakaan itu - dan jika beberapa perpustakaan yang digunakan oleh program utama melakukan ini, masing-masing bisa memilih perpustakaan yang berbeda .
Meskipun saya sudah punya program mendaftarkan objek aliran C ++ dengan perpustakaan untuk menggunakannya. Sepertinya itu akan menjadi tujuan yang relatif umum, tetapi saya juga berpikir tentang hanya memiliki program utama mendaftarkan fungsi callback yang akan dipanggil dengan konten dan metadata ketika data dicatat. Opsi lain hanya akan menyimpan data log di perpustakaan dalam semacam daftar untuk program utama untuk mengambil setiap kali ingin menangani data itu, membiarkan program utama memutuskan kapan waktu untuk menangani data.
Saya mencari saran dan kelebihan pendekatan yang berbeda sehingga saya dapat memutuskan apa yang terbaik dalam situasi saya.
Jawaban:
Anda dapat mengekspos beberapa metode untuk menerima penebangan dari perpustakaan Anda, dan membungkus semua kecuali satu di adapter ke yang "asli" yang digunakan di perpustakaan.
Misalnya Anda memutuskan untuk secara internal memiliki
std::function<void(std::string)>
koleksi yang setiap panggilan balik logger. Anda memberikan:dan juga
dan juga
dan variasi jenis "terima string dari suatu tempat" lagi yang ingin Anda terapkan untuk adaptor.
sumber
Cara paling sederhana untuk memungkinkan aplikasi untuk dapat masuk ke fungsionalitas logging adalah memungkinkannya untuk mendaftarkan kelas / fungsi untuk menerima pesan log. Apa yang mereka lakukan dengan pesan itu sepenuhnya tergantung pada aplikasi.
Menggunakan C / C ++, Anda bisa menggunakan yang berikut di perpustakaan Anda:
Aplikasi dapat mendaftarkan suatu fungsi dengan menelepon
registerLogMessageReceiver
. dengan tepatuser_data
. Di bagian logging basis kode Anda, Anda harus memastikan untuk memanggil fungsi itu dengan pesan yang sesuai dan terdaftaruser_data
.Jika Anda tidak perlu khawatir tentang C, Anda bisa menggunakan kelas sebagai penerima pesan.
dan menambahkan fungsi di perpustakaan untuk memungkinkan aplikasi mendaftarkan penerima pesan log.
Aplikasi dapat mendaftar
LogMessageReceiver
dengan memanggil fungsi di atas. Anda harus membuat beberapa keputusan kebijakan mengenai kepemilikan yang terdaftarLogMessageReceiver
. Jika perpustakaan mengambil kepemilikan penerima, itu harusdelete
pointer. Jika perpustakaan tidak mengambil kepemilikan penerima, aplikasi harus mengurusdelete
penerima.Menggunakan kelas sebagai penerima pesan log memungkinkan
user_data
bit dihilangkanregisterLogMessageReceiver
karena sub-jenisLogMessageReceiver
bebas untuk menyimpan data apa pun yang berguna agar berfungsi. Tidak perlu mengirimkan data pengguna tambahan apa pun dalamreceive
fungsinya.Dari sana, ini bisa menjadi lebih kompleks tergantung pada seberapa canggih mekanisme logging Anda.
Misalnya, Anda bisa memiliki berbagai level logging: Ringkas, Normal, Verbose, atau LoggingLevel1, LoggingLevel2, ..., LoggingLevelN.
Dalam hal ini, Anda harus mengizinkan aplikasi mengontrol tingkat pencatatan yang ingin mereka gunakan.
Ada serangkaian pilihan tanpa akhir begitu Anda memutuskan untuk bergerak melampaui mekanisme logging yang disederhanakan. Tidak masuk akal untuk menyelidiki mereka di sini.
sumber
Saya akan menegaskan bahwa Anda harus memikirkan kembali perlunya logging ditambah dengan perpustakaan Anda; Khusus untuk C ++ di mana tidak ada antarmuka logger standar.
Aplikasi yang berbeda memiliki kebijakan yang berbeda tentang pencatatan. Perpustakaan harus agnostik kebijakan.
Tujuan perpustakaan adalah untuk menyediakan layanan, dan lebih disukai, menunjukkan apakah permintaan untuk layanan itu berhasil atau gagal; idealnya dengan indikasi mengapa [gagal] melalui errno, kembalikan kode, pengecualian ... Jika keinginan Anda untuk login adalah karena fungsi yang disediakan dapat gagal di banyak tempat, Anda mungkin mencoba melakukan terlalu banyak dalam satu fungsi. Mungkin tidak , tetapi pertimbangkan kemungkinannya.
sumber
[...] answer can be “don’t do that" [...]
.Menulis pustaka yang mudah berinteraksi dengan sistem log aplikasi host adalah mudah, asalkan Anda tahu apa sistem itu. Ketika ada banyak kemungkinan untuk itu, itu lebih sulit, dan Anda dibatasi oleh tirani penyebut umum terendah. Anda bisa memiliki lapisan kompatibilitas yang mengadaptasi pustaka Anda dengan berbagai sistem log, tetapi sekarang Anda tidak dapat bergantung pada beberapa fitur unik dan bermanfaat yang hanya dimiliki oleh satu sistem. Jika pengguna akhir memiliki sistem lain, fitur unik yang bermanfaat itu tidak ada.
Di dunia .Net, ada (setidaknya) dua sistem log yang umum digunakan, log4net dan NLog. Keduanya serupa, tetapi tidak identik. Saya sudah menggunakan log4net, dan kemudian mulai menggunakan NHibernate (perpustakaan ORM). Untungnya, ia menggunakan log4net secara internal, jadi mudah untuk menambahkannya ke proyek. (Dan di sini saya tidak setuju dengan jawaban @ Daniel: Terkadang sangat berguna bagi NHibernate untuk mencatat aktivitasnya dengan detail halus dalam sistem yang sama yang saya gunakan di tempat lain, tanpa kerja tambahan.) Jika saya sudah berinvestasi di NLog, itu berarti baik Saya beralih, atau memiliki proyek yang menggunakan keduanya.
Setidaknya dengan pencatatan, biasanya ada opsi untuk membuat append pesan khusus yang dapat Anda konfigurasikan untuk meneruskan pesan yang masuk dalam satu sistem ke sistem pencatatan yang lain. Jadi, jika sudah menggunakan NLog, dan benar-benar ingin melanjutkannya, tetapi juga menggunakan NHibernate, saya dapat menggeretakkan giginya dengan menulis log4net appender yang meneruskan setiap pesan ke NLog. Akan mudah dilakukan jika API serupa.
Alternatifnya adalah benar-benar memilih sistem terbaik untuk kebutuhan Anda yang tersedia dan menggunakannya tanpa syarat, atau memiliki semacam lapisan adaptor, yang tunduk pada masalah penyebut umum terendah. Itu bukan jawaban yang sangat memuaskan.
sumber