Saya sedang mengerjakan api sisanya dengan spring boot. Saya perlu mencatat semua permintaan dengan params input (dengan metode, mis. GET, POST, dll), jalur permintaan, string kueri, metode kelas yang sesuai dari permintaan ini, juga respons dari tindakan ini, baik keberhasilan maupun kesalahan.
Sebagai contoh:
permintaan yang berhasil:
http://example.com/api/users/1
Log harus terlihat seperti ini:
{
HttpStatus: 200,
path: "api/users/1",
method: "GET",
clientIp: "0.0.0.0",
accessToken: "XHGu6as5dajshdgau6i6asdjhgjhg",
method: "UsersController.getUser",
arguments: {
id: 1
},
response: {
user: {
id: 1,
username: "user123",
email: "[email protected]"
}
},
exceptions: []
}
Atau permintaan dengan kesalahan:
http://example.com/api/users/9999
Log harus seperti ini:
{
HttpStatus: 404,
errorCode: 101,
path: "api/users/9999",
method: "GET",
clientIp: "0.0.0.0",
accessToken: "XHGu6as5dajshdgau6i6asdjhgjhg",
method: "UsersController.getUser",
arguments: {
id: 9999
},
returns: {
},
exceptions: [
{
exception: "UserNotFoundException",
message: "User with id 9999 not found",
exceptionId: "adhaskldjaso98d7324kjh989",
stacktrace: ...................
]
}
Saya ingin Permintaan / Respons menjadi entitas tunggal, dengan informasi khusus yang terkait dengan entitas ini, baik dalam kasus yang berhasil maupun yang salah.
Apa praktik terbaik di musim semi untuk mencapai ini, mungkin dengan filter? jika ya, dapatkah Anda memberikan contoh nyata?
(Saya sudah bermain dengan @ControllerAdvice dan @ExceptionHandler, tetapi seperti yang saya sebutkan, saya perlu menangani semua permintaan kesalahan dan keberhasilan di satu tempat (dan satu log)).
sumber
HandlerInterceptor
tetapi yang mungkin tidak bekerja dengan baik dengan logging respon seperti yang disebutkan dalam jawaban: concretepage.com/spring/spring-mvc/... - HandlerInterceptor memiliki akses ke metode (metode: "UsersController.getUser") sekalipun. Itu tidak dikenal dalam filter servlet.LogClass{ getRequestAndSaveIt()} Gson.toJson(LogClass)
as pseudocodeJawaban:
Jangan menulis Pencegat, Filter, Komponen, Aspek, dll., Ini adalah masalah yang sangat umum dan telah dipecahkan berulang kali.
Spring Boot memiliki modul yang disebut Actuator , yang menyediakan permintaan HTTP untuk keluar dari kotak. Ada titik akhir yang dipetakan ke
/trace
(SB1.x) atau/actuator/httptrace
(SB2.0 +) yang akan menunjukkan kepada Anda 100 permintaan HTTP terakhir. Anda dapat menyesuaikannya untuk mencatat setiap permintaan, atau menulis ke DB.Untuk mendapatkan titik akhir yang Anda inginkan, Anda memerlukan dependensi spring-boot-starter-actuator, dan juga untuk "memasukkan daftar putih" titik akhir yang Anda cari, dan mungkin mengatur atau menonaktifkan keamanan untuk itu.
Juga, di mana aplikasi ini berjalan? Apakah Anda akan menggunakan PaaS? Penyedia hosting, Heroku misalnya, memberikan permintaan logging sebagai bagian dari layanan mereka dan Anda tidak perlu melakukan apa pun coding apapun itu.
sumber
Spring sudah menyediakan filter yang melakukan pekerjaan ini. Tambahkan kacang berikut ke konfigurasi Anda
Jangan lupa untuk mengubah level log
org.springframework.web.filter.CommonsRequestLoggingFilter
menjadiDEBUG
.sumber
Anda dapat menggunakan
javax.servlet.Filter
jika tidak ada persyaratan untuk login metode java yang telah dijalankan.Tapi dengan persyaratan ini Anda harus mengakses informasi yang tersimpan dalam
handlerMapping
dariDispatcherServlet
. Karena itu, Anda dapat menggantiDispatcherServlet
untuk menyelesaikan pembuatan log pasangan permintaan / respons.Di bawah ini adalah contoh ide yang dapat lebih ditingkatkan dan diadaptasi untuk kebutuhan Anda.
HandlerExecutionChain
- Berisi informasi tentang penangan permintaan.Anda kemudian dapat mendaftarkan dispatcher ini sebagai berikut:
Dan inilah contoh log:
MEMPERBARUI
Dalam hal kesalahan Spring melakukan penanganan kesalahan otomatis. Oleh karena itu,
BasicErrorController#error
ditampilkan sebagai penangan permintaan. Jika Anda ingin mempertahankan penangan permintaan asli, maka Anda dapat menimpa perilaku inispring-webmvc-4.2.5.RELEASE-sources.jar!/org/springframework/web/servlet/DispatcherServlet.java:971
sebelum#processDispatchResult
dipanggil, untuk men-cache penangan asli.sumber
The buku catatan perpustakaan khusus dibuat untuk permintaan HTTP logging dan tanggapan. Ini mendukung Spring Boot menggunakan perpustakaan pemula khusus.
Untuk mengaktifkan login di Boot Spring yang perlu Anda lakukan adalah menambahkan perpustakaan ke dependensi proyek Anda. Misalnya dengan asumsi Anda menggunakan Maven:
Secara default output logging terlihat seperti ini:
Namun itu tidak menampilkan nama kelas yang menangani permintaan. Perpustakaan memang memiliki beberapa antarmuka untuk menulis logger kustom.
sumber
logging.level.org.zalando.logbook=TRACE
ke Andaapplication.properties
(seperti yang dinyatakan dalamReadme
)Saya telah menetapkan level login
application.properties
untuk mencetak permintaan / tanggapan, url metode dalam file logSaya telah menggunakan Spring Boot.
sumber
Inilah cara saya melakukannya di pegas data rest dengan menggunakan
org.springframework.web.util.ContentCachingRequestWrapper
danorg.springframework.web.util.ContentCachingResponseWrapper
sumber
Jika Anda tidak keberatan mencoba Spring AOP, ini adalah sesuatu yang telah saya jelajahi untuk tujuan logging dan ini bekerja cukup baik untuk saya. Itu tidak akan mencatat permintaan yang belum ditentukan dan gagal upaya permintaan.
Tambahkan tiga dependensi ini
Tambahkan ini ke file konfigurasi xml Anda
<aop:aspectj-autoproxy/>
Buat anotasi yang dapat digunakan sebagai titik potong
Sekarang beri catatan semua metode API lainnya yang ingin Anda catat
Sekarang ke Aspek. memindai komponen yang ada di kelas ini.
Jika Anda ingin membaca secara detail bacalah ini. http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html
sumber
Setelah menambahkan Aktuator ke aplikasi bass boot spring, Anda memiliki
/trace
titik akhir yang tersedia dengan informasi permintaan terbaru. Titik akhir ini berfungsi berdasarkan TraceRepository dan implementasi default adalah InMemoryTraceRepository yang menyimpan 100 panggilan terakhir. Anda dapat mengubah ini dengan mengimplementasikan antarmuka ini sendiri dan menjadikannya tersedia sebagai Spring bean. Sebagai contoh untuk mencatat semua permintaan untuk log (dan masih menggunakan implementasi default sebagai penyimpanan dasar untuk melayani info pada/trace
titik akhir) Saya menggunakan implementasi semacam ini:Ini
traceInfo
peta berisi informasi dasar tentang permintaan dan respon dalam jenis bentuk:{method=GET, path=/api/hello/John, headers={request={host=localhost:8080, user-agent=curl/7.51.0, accept=*/*}, response={X-Application-Context=application, Content-Type=text/plain;charset=UTF-8, Content-Length=10, Date=Wed, 29 Mar 2017 20:41:21 GMT, status=200}}}
. Tidak ada konten tanggapan di sini.SEDANG! Mencatat data POST
Anda dapat mengakses data POST dengan mengganti WebRequestTraceFilter , tetapi jangan berpikir itu adalah ide yang bagus (mis. Semua konten file yang diunggah akan masuk ke log) Berikut adalah contoh kode, tetapi jangan menggunakannya:
sumber
TraceRepository
, bagaimana kita bisa mengaksesnya?protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
tetapi saya tidak yakin kapan filter ini dijalankan - mungkin pada tahap permintaan, jadi badan tanggapan tidak akan siap di sana.Kode ini berfungsi untuk saya dalam aplikasi Boot Musim Semi - cukup daftarkan sebagai filter
sumber
Saat ini Spring Boot memiliki fitur Actuator untuk mendapatkan log permintaan dan tanggapan.
Tetapi Anda juga bisa mendapatkan log menggunakan Aspect (AOP).
Aspek menyediakan Anda dengan penjelasan seperti:
@Before
,@AfterReturning
,@AfterThrowing
dll@Before
mencatat permintaan,@AfterReturning
mencatat respons dan@AfterThrowing
mencatat pesan kesalahan, Anda mungkin tidak memerlukan semua log titik akhir, sehingga Anda dapat menerapkan beberapa filter pada paket.Berikut ini beberapa contohnya :
Untuk Permintaan:
Di sini
@Before("within(your.package.where.endpoints.are..*)")
ada jalur paket. Semua titik akhir dalam paket ini akan menghasilkan log.Untuk Respon:
Di sini
@AfterReturning("within(your.package.where.endpoints.are..*)")
ada jalur paket. Semua titik akhir dalam paket ini akan menghasilkan log. JugaObject returnValue
berisi respons.Untuk Pengecualian:
Di sini
@AfterThrowing(pointcut = ("within(your.package.where.endpoints.are..*)"), throwing = "e")
ada jalur paket. Semua titik akhir dalam paket ini akan menghasilkan log. JugaException e
mengandung respons kesalahan.Ini kode lengkapnya:
Di sini, menggunakan
@ConditionalOnExpression("${endpoint.aspect.enabled:true}")
Anda dapat mengaktifkan / menonaktifkan log. tambahkan sajaendpoint.aspect.enabled:true
keapplication.property
dan kontrol logInfo lebih lanjut tentang kunjungan AOP di sini:
Spring dok tentang AOP
Contoh artikel tentang AOP
sumber
new ObjectMapper()
mahal, lebih baik bagikan satu mapper untuk semuaDi sini solusi saya (Spring 2.0.x)
Tambahkan ketergantungan maven:
Edit application.properties dan tambahkan baris berikut:
Setelah aplikasi booting musim semi dimulai, Anda dapat melacak permintaan 100 http terbaru dengan memanggil url ini: http: // localhost: 8070 / actuator / httptrace
sumber
Anda juga dapat mengonfigurasi interseptor Spring khusus
HandlerInterceptorAdapter
untuk implementasi yang disederhanakan dari interceptors pre-only / post-only:Kemudian, Anda mendaftarkan pencegat sebanyak yang Anda inginkan:
Catatan: sama seperti yang dinyatakan oleh @Robert , Anda perlu memperhatikan implementasi spesifik dan aplikasi Anda menggunakan.
HttpServletRequest
HttpServletResponse
Misalnya, untuk aplikasi yang menggunakan
ShallowEtagHeaderFilter
, implementasi respons akan menjadiContentCachingResponseWrapper
, jadi Anda harus:sumber
@ hahn menjawab diperlukan sedikit modifikasi agar bisa bekerja untuk saya, tetapi sejauh ini adalah hal yang paling dapat disesuaikan yang bisa saya dapatkan.
Itu tidak bekerja untuk saya, mungkin karena saya juga memiliki HandlerInterceptorAdapter [??] tapi saya terus mendapat respons buruk dari server dalam versi itu. Ini modifikasi saya.
sumber
Jika seseorang masih membutuhkannya di sini adalah implementasi sederhana dengan Spring HttpTrace Actuator. Tetapi seperti yang mereka katakan di atas, ia tidak mencatat tubuh.
sumber
Silakan merujuk ke tautan di bawah ini untuk jawaban aktual https://gist.github.com/int128/e47217bebdb4c402b2ffa7cc199307ba
Membuat beberapa perubahan dari solusi yang disebutkan di atas, permintaan dan tanggapan akan masuk konsol dan file juga jika tingkat logger adalah info. kita dapat mencetak di konsol atau file.
Output dalam File:
sumber
Jika Anda hanya melihat sebagian dari payload permintaan Anda, Anda perlu memanggil
setMaxPayloadLength
fungsi karena defaultnya hanya menampilkan 50 karakter di badan permintaan Anda. Juga, menetapkansetIncludeHeaders
ke false adalah ide yang bagus jika Anda tidak ingin mencatat tajuk auth!sumber
jika Anda menggunakan Tomcat di aplikasi boot Anda di sini ada
org.apache.catalina.filters.RequestDumperFilter
di jalur kelas untuk Anda. (tapi itu tidak akan memberi Anda "pengecualian di satu tempat").sumber
kode yang ditempelkan di bawah berfungsi dengan pengujian saya dan dapat diunduh dari [proyek github] saya [1], dibagikan setelah menerapkan solusi berdasarkan pada itu pada proyek produksi.
sumber
Untuk mencatat semua permintaan dengan parameter input dan isi, kita dapat menggunakan filter dan interseptor . Tetapi saat menggunakan filter atau interseptor, kami tidak dapat mencetak badan permintaan beberapa kali. Cara yang lebih baik adalah kita bisa menggunakan spring-AOP. Dengan menggunakan ini kita dapat memisahkan mekanisme logging dari aplikasi. AOP dapat digunakan untuk mencatat Input dan output masing - masing metode dalam aplikasi.
Solusi saya adalah:
}
sumber
Jika Anda telah mengonfigurasi server Spring boot Config, cukup aktifkan Debug logger untuk kelas:
Http11InputBuffer.Http11InputBuffer.java
Debug akan mencatat semua permintaan dan respons untuk setiap permintaan
sumber
Untuk mencatat permintaan yang menghasilkan hanya 400:
sumber