LogRock: Menguji melalui Logging

Logrock

LogRock: Menguji melalui Logging


Selama lebih dari 2 tahun kami telah mengerjakan proyek Cleverbrush kami. Ini adalah perangkat lunak untuk bekerja dengan grafik vektor. Bekerja dengan editor grafis menyiratkan sejumlah besar kasus penggunaan aplikasi. Kami berusaha menghemat uang dan waktu, jadi kami mengoptimalkan semuanya, termasuk pengujian. Menutupi kasus uji dengan setiap opsi terlalu mahal dan tidak rasional, terutama karena tidak mungkin untuk menutup semua opsi.

Selama pengembangan, modul untuk aplikasi React JS telah dibuat - LogRock (github) .

Modul ini memungkinkan Anda untuk mengatur aplikasi logging modern. Berdasarkan log, kami melakukan pengujian. Pada artikel ini saya akan memberi tahu Anda tentang seluk-beluk penggunaan modul ini dan cara mengatur pengujian melalui pencatatan.

Apa masalahnya?


Jika Anda membandingkan program dengan organisme hidup, maka bug di dalamnya adalah penyakit. Penyebab "penyakit" ini mungkin sejumlah faktor, termasuk lingkungan pengguna tertentu. Ini terutama benar jika kita mempertimbangkan platform web. Terkadang hubungan sebab akibat sangat kompleks, dan bug yang ditemukan selama pengujian adalah hasil dari sejumlah peristiwa.

Seperti halnya penyakit manusia, tidak ada yang akan menjelaskan gejalanya lebih baik daripada pasien, tidak ada penguji yang dapat mengetahui apa yang terjadi, lebih baik daripada program itu sendiri.

Apa yang harus dilakukan


Untuk memahami apa yang terjadi, kita perlu daftar tindakan yang dilakukan pengguna dalam aplikasi kita.

Agar program kami sendiri dapat memberi tahu kami apa yang โ€œmenyakitkanโ€, kami akan mengambil modul LogRock (github) dan menghubungkannya dengan ElasticSearch, LogStash, dan Kibana.

gambar

ElasticSearch adalah mesin pencari teks lengkap yang kuat. Anda dapat menonton tutorial ElasticSearch di sini .
LogStash adalah sistem untuk mengumpulkan log dari berbagai sumber, yang dapat mengirim log, termasuk ke ElasticSearch.
Kibana adalah antarmuka web ke ElasticSearch dengan banyak add-on.

Bagaimana cara kerjanya?


gambar

Jika terjadi kesalahan (atau hanya sesuai permintaan), aplikasi mengirimkan log ke server tempat mereka disimpan ke file. Logstash secara bertahap menyimpan data dalam ElasticSearch - ke basis data. Pengguna login ke Kibana dan melihat log yang disimpan.

gambar

Sepertinya Kibana yang telah disetel dengan baik. Ini menampilkan data dari ElasticSearch. Kibana dapat menampilkan data dalam bentuk tabel, grafik, peta, dll., Yang sangat nyaman untuk menganalisis dan memahami apa yang terjadi dengan aplikasi kita.

Pada artikel ini, saya TIDAK akan membahas pengaturan ElasticStack!

Menciptakan sistem logging


Sebagai contoh, kami akan mengintegrasikan sistem logging dalam aplikasi JS satu halaman yang ditulis dalam Bereaksi. Tidak masalah kerangka mana aplikasi Anda akan ditulis. Saya akan mencoba menggambarkan pendekatan membangun sistem log itu sendiri.

1. Pelanggan


1.0 LogRock. Instalasi


Tautan ke LogRock

Untuk menginstal, Anda harus melakukan:

npm install logrock  yarn add logrock 

1.1 LogRock. Pengaturan aplikasi


Untuk memulai, bungkus aplikasi kami dalam sebuah komponen

 import { LoggerContainer } from "logrock"; <LoggerContainer> <App /> </LoggerContainer> 

LoggerContainer adalah komponen yang merespons kesalahan aplikasi Anda dan membentuk tumpukan.

Tumpukan adalah objek dengan informasi tentang sistem operasi pengguna, browser, yang ditekan tombol mouse atau keyboard dan, tentu saja, tindakan subarray, di mana semua tindakan pengguna yang ia lakukan dalam sistem kami direkam.

LoggerContainer memiliki sejumlah pengaturan, pertimbangkan beberapa di antaranya

 <LoggerContainer active={true|false} limit={20} onError={stack => { sendToServer(stack); }} > <App /> </LoggerContainer> 

aktif - aktifkan atau nonaktifkan logger

limit - menetapkan batas jumlah tindakan terbaru yang disimpan oleh pengguna. Jika pengguna melakukan 21 tindakan, yang pertama dalam larik ini akan secara otomatis dihapus. Dengan demikian, kita akan memiliki 20 tindakan terakhir yang mendahului kesalahan.

onError - panggilan balik yang dipanggil saat terjadi kesalahan. Objek Stack masuk ke dalamnya, di mana semua informasi tentang lingkungan, tindakan pengguna, dll disimpan. Dari callback inilah kita perlu mengirim data ini ke ElasticSearch atau backend, atau menyimpannya ke file untuk analisis dan pemantauan lebih lanjut.

1.2 LogRock. Penebangan


Untuk membuat pencatatan tindakan pengguna yang berkualitas tinggi, kita harus menutup kode kita dengan panggilan log.

Modul LogRock dilengkapi dengan logger yang dikaitkan dengan LoggerContainer

Misalkan kita memiliki komponen

 import React, { useState } from "react"; export default function Toggle(props) { const [toggleState, setToggleState] = useState("off"); function toggle() { setToggleState(toggleState === "off" ? "on" : "off"); } return <div className={`switch ${toggleState}`} onClick={toggle} />; } 

Untuk menutupnya dengan log, kita perlu memodifikasi metode sakelar

 function toggle() { let state = toggleState === "off" ? "on" : "off"; logger.info(`React.Toggle|Toggle component changed state ${state}`); setToggleState(state); } 

Kami telah menambahkan logger di mana informasi dibagi menjadi 2 bagian. React.Toggle menunjukkan kepada kita bahwa tindakan ini terjadi pada tingkat Bereaksi, komponen Toggle, dan kemudian kita memiliki penjelasan verbal tentang tindakan dan keadaan saat ini yang masuk ke komponen ini. Pemisahan seperti itu ke level tidak perlu, tetapi dengan pendekatan ini akan lebih jelas di mana tepatnya kode kita dieksekusi.

Kita juga bisa menggunakan metode "componentDidCatch", yang diperkenalkan di React versi 16, jika terjadi kesalahan.

2. Interaksi server


Perhatikan contoh berikut.

Misalkan kita memiliki metode yang mengumpulkan data pengguna dari backend. Metode ini tidak sinkron, bagian dari logika disembunyikan di backend. Bagaimana cara mencatat kode ini dengan benar?

Pertama, karena kami memiliki aplikasi klien, semua permintaan pergi ke server akan melalui sesi pengguna tunggal, tanpa memuat ulang halaman. Untuk mengaitkan tindakan pada klien dengan tindakan di server, kita harus membuat SessionID global dan menambahkannya ke header untuk setiap permintaan ke server. Di server, kita bisa menggunakan logger apa pun yang akan mencakup logika kita seperti contoh dari frontend, dan jika terjadi kesalahan kirim data ini dengan sessionID terlampir di Elastic ke pelat Backend.

1. Kami menghasilkan SessionID pada klien

 window.SESSION_ID = `sessionid-${Math.random().toString(36).substr(3, 9)}`; 

2. Kita harus mengatur SessionID untuk semua permintaan ke server. Jika kami menggunakan pustaka untuk kueri, ini sangat sederhana dengan mendeklarasikan SessionID untuk semua kueri.

 let fetch = axios.create({...}); fetch.defaults.headers.common.sessionId = window.SESSION_ID; 

3. Di LoggerContainer ada bidang khusus untuk SessionID

 <LoggerContainer active={true|false} sessionID={window.SESSION_ID} limit={20} onError={stack => { sendToServer(stack); }} > <App /> </LoggerContainer> 

4. Permintaan itu sendiri (pada klien) akan terlihat seperti ini:

 logger.info(`store.getData|User is ready for loading... User ID is ${id}`); getData('/api/v1/user', { id }) .then(userData => { logger.info(`store.getData|User have already loaded. User count is ${JSON.stringify(userData)}`); }) .catch(err => { logger.error(`store.getData|User loaded fail ${err.message}`); }); 

Bagaimana cara kerjanya: kita mencatat log, sebelum permintaan pada klien. Menurut kode kami, kami melihat bahwa memuat data dari server sekarang akan dimulai. Kami telah melampirkan SessionID ke permintaan. Jika backend kami ditutupi dengan log dengan penambahan SessionID ini dan permintaan gagal, maka kita dapat melihat apa yang terjadi di backend.

Dengan demikian, kami memantau seluruh siklus aplikasi kami, tidak hanya pada klien, tetapi juga pada backend.

3. Penguji


Bekerja dengan tester layak mendapatkan deskripsi terpisah dari proses tersebut.

Karena kami memiliki startup, kami tidak memiliki persyaratan formal dan terkadang semuanya tidak logis dalam pekerjaan.

Jika penguji tidak memahami perilaku, ini adalah kasus yang setidaknya perlu dipertimbangkan. Juga, seringkali, seorang tester tidak dapat mengulangi satu situasi dua kali. Karena langkah-langkah yang mengarah ke perilaku yang salah bisa banyak dan tidak sepele. Selain itu, tidak semua kesalahan mengarah pada konsekuensi kritis, seperti Pengecualian. Beberapa dari mereka hanya dapat mengubah perilaku aplikasi, tetapi tidak dapat ditafsirkan oleh sistem sebagai kesalahan. Untuk keperluan ini, pada pementasan, Anda dapat menambahkan tombol di header aplikasi untuk memaksa pengiriman log. Penguji melihat bahwa ada sesuatu yang tidak berfungsi dengan benar, mengklik tombol dan mengirim tumpukan dengan tindakan ke ElasticSearch.

gambar


Namun, jika kesalahan kritis telah terjadi, kita harus memblokir antarmuka sehingga tester tidak mengklik lebih lanjut dan tidak menemui jalan buntu.

Untuk tujuan ini, kami menampilkan layar biru kematian.

Kita melihat di bagian atas teks dengan tumpukan kesalahan kritis ini, dan di bawah ini - tindakan yang mendahuluinya. Kami juga mendapatkan ID kesalahan, itu cukup bagi tester untuk memilihnya dan melampirkannya pada tiket. Nantinya kesalahan ini dapat dengan mudah ditemukan di Kibana oleh ID ini.

gambar

Untuk tujuan ini, LoggerContainer memiliki propertinya sendiri.

 <LoggerContainer active={true|false} limit={20} bsodActive={true} bsod={BSOD} onError={stack => { sendToServer(stack); }} > <App /> </LoggerContainer> 

bsodActive - mengaktifkan / menonaktifkan BSOD (menonaktifkan BSOD berlaku untuk kode produksi)

bsod adalah komponen. Secara default, sepertinya screenshot di atas.

Untuk menampilkan tombol di UI LoggerContainer, kita dapat menggunakannya dalam konteks

 context.logger.onError(context.logger.getStackData()); 

4. LogRock. Interaksi pengguna


Anda dapat menampilkan log ke konsol atau menunjukkannya kepada pengguna, untuk ini Anda perlu menggunakan metode stdout:

 <LoggerContainer active={true|false} limit={20} bsodActive={true} bsod={BSOD} onError={stack => { sendToServer(stack); }} stdout={(level, message, important) => { console[level](message); if (important) { alert(message); } }} > <App /> </LoggerContainer> 

stdout adalah metode yang bertanggung jawab untuk menampilkan pesan.

Agar pesan menjadi penting, cukup untuk mengirimkan parameter kedua true ke logger. Dengan demikian, pesan ini dapat ditampilkan kepada pengguna di jendela sembulan, misalnya, jika pemuatan data gagal, kami dapat menampilkan pesan kesalahan.

 logger.log('Something was wrong', true); 

Pencatatan tingkat lanjut


Jika Anda menggunakan Redux, atau solusi serupa dengan satu Store, Anda dapat menempatkan logger di Middleware yang memproses Tindakan Anda, dengan demikian, semua tindakan signifikan akan dilakukan melalui sistem kami.

Untuk pencatatan yang efektif, Anda bisa membungkus data Anda dalam objek proxy, dan menempatkan penebang pada semua tindakan dengan objek.

Untuk mencakup metode pihak ketiga dengan pendataan (metode pustaka, metode kode lama), Anda dapat menggunakan dekorator - โ€œ@โ€.

Kiat


Log aplikasi, termasuk pada produksi, karena lebih baik daripada pengguna nyata, tidak ada tester yang akan menemukan hambatan.

Jangan lupa untuk menunjukkan pengumpulan log dalam perjanjian lisensi.

JANGAN mencatat kata sandi, detail bank, dan informasi pribadi lainnya!

Redundansi log juga buruk, buat tanda tangan sejelas mungkin.

Alternatif


Sebagai pendekatan alternatif, saya menyoroti:

  • Rollbar sangat dapat disesuaikan. Memungkinkan Anda mencatat 500 ribu kesalahan dengan $ 150 per bulan. Saya sarankan menggunakannya jika Anda sedang mengembangkan aplikasi dari awal.
  • Sentry lebih mudah diintegrasikan, tetapi kurang dapat disesuaikan. Memungkinkan Anda mencatat 1 juta peristiwa dengan $ 200 per bulan.

Kedua layanan memungkinkan Anda untuk melakukan hal yang hampir sama dan berintegrasi ke dalam backend.

Apa selanjutnya


Logging tidak hanya mencari kesalahan, tetapi juga memonitor tindakan pengguna, pengumpulan data. Logging bisa menjadi pelengkap yang baik untuk pengujian Google Analytics dan Pengalaman Pengguna.

Kesimpulan


Ketika Anda merilis aplikasi, hidup baru saja dimulai untuknya. Bertanggung jawab atas gagasan Anda, dapatkan umpan balik, pantau log, dan perbaiki. Menulis perangkat lunak berkualitas tinggi dan makmur :)

PS Jika Anda ingin membantu pengembangan modul untuk Angular, Vue, dll. Saya akan dengan senang hati menarik permintaan - di sini .

Source: https://habr.com/ru/post/id453652/


All Articles