Một bug trong phần mềm có thể disruptive, elusive, maddening, và invasive. Thực sự, một developer thường cần tenacity của Edison để tìm và fix issue.
Nhưng grit không phải asset duy nhất developer cần. Cần information để debug code: Symptoms và effects của issue là gì? Frequency? Pervasiveness? Provenance? Evidence và artifacts của bug — core dump, stack trace, log, hoặc test case — invaluable.
Hãy explore vài techniques và tools sẵn có cho Ruby và Rails developers để gather và investigate evidence của issue. Data không thể supplant tenacity, nhưng có thể ease efforts (và spare you your sleep).
Rails cung cấp excellent tools để peer into running application, bao gồm configurable Logger capture diagnostics của nó và bất cứ thứ bạn muốn thêm. Rails cũng cung cấp verbose query log để pinpoint origin của database queries và verbose enqueue log để illuminate nơi background jobs được queued. Hai log sau enabled by default trong môi trường development; bạn enable both trong environments khác với hai statements.
Một lesser-known log option available since Rails 7 annotates mỗi SQL query với comments. Nếu thêm sau vào config/application.rb hoặc environment file:
Query log tự động amended với application name, controller name, action name, hoặc background job name. Sample output sau đến trực tiếp từ Rails debugging guide:
Bạn likely không want enable all features trong production. Log generation có thể costly về memory và time (finite resources cho app under load).
Tuy nhiên, có exceptions. Bạn có thể muốn briefly enable on-demand feature, especially khi debugging trong development và test modes. Thay vì alter code (và perhaps redeploy) để enable hoặc disable diagnostic, dùng environment variables control state. Trong some environments, như Heroku, thay đổi setting environment variable không mandate new deployment.
Ví dụ, bạn define set variables control logging và verbosity.
Cho convenience, tạo small class query configuration settings.
Bây giờ dùng variables và code set logging features trong config/application.rb:
Dùng shell, dotenv file, continuous integration, hoặc hosting và deployment platform set each option. Bạn cũng dùng feature on demand. Chỉ cần start application với environment variable defined on command line.
Tune Puma cho Development
Xây dựng trên section trước, hãy xem cách dùng environment variables tailor Puma configuration cho debugging trong development environment.
Typically, Puma configured maximize throughput trong production, chạy multiple workers và many threads per worker. Trong development, bạn muốn opposite: one worker, one thread, và very long timeout cho interactive debugging. Mỗi cái là parameter bạn tune.
Alter config/puma.rb reflect code sau.
Bây giờ configure ba environment variables control Puma trong mỗi environment. Trong development, set values optimize cho interactive debugging.
Nếu muốn validate Puma settings, set environment variable PUMA_LOG_CONFIG=true và start application. Puma emits active configuration on startup.
Coincidentally, default Puma configuration trong recent Rails release similar như shown here (thanks to Nate Matykiewicz for the tip).
Run Background Jobs Inline
Rails application bất kỳ complexity thường leverage background jobs chạy compute-intensive và (relatively) long-running tasks. Background jobs chạy asynchronously, disconnected từ request/response cycle. Ideal candidates cho "out of band" processing bao gồm generating reports, sending emails, và interacting với third-party APIs. Nhưng asynchronous nature của jobs cũng complicate debugging.
Để simplify troubleshooting, chạy jobs immediately trong local development và test environments. Trong immediate mode, jobs không queued, mà execute instantaneously. Chạy trong "foreground", bạn có thể set breakpoints và inspect state interactively.
Hãy xem example dùng Delayed Job, popular và easy-to-manage queueing backend cho Active Job. Delayed Job cung cấp setting enable queueing. By default, setting là true và jobs queued as per usual. Tuy nhiên, nếu set to false, jobs chạy immediately.
Thêm code sau vào application trong config/initializers/delayed_job.rb:
Nếu DELAYED_JOBS_DISABLE_JOB_QUEUES set to any value, queueing disabled. Nếu environment variable blank hoặc not defined, queueing enabled.
Tiếp, trong shell, trên command line, hoặc dot files, set DELAYED_JOBS_DISABLE_JOB_QUEUES as needed.
Set environment variable to nothing hoặc delete environment variable để restore queueing.
Không có rules cho naming environment variables. Chọn names meaningful to you. One helpful convention categorize variables là add package name as prefix, như PUMA_ và DELAYED_JOB_. Former chỉ variables affecting Puma; latter connotes variables used by Delayed Job.
Peer Into Network Calls
Giống background jobs, Rails applications cũng consume application programming interfaces (APIs). APIs cung cấp access đến external services, như GraphQL databases, e-commerce transactions, và public data sources.
Đây example khác conditionally emit HTTP requests và responses từ Net::HTTP library. Nếu environment variable DEBUG_HTTP set to any non-blank value, outgoing request và inbound responses printed to STDOUT.
Để see network activity, simply start application với environment variable defined on command line.
debug? method cung cấp abstraction từ actual flag implementation. Nó, và rest of this code, có thể form base class cho all your network requests, như shown in this gist taken from production code.
Universe of Ruby gems vast: impossible cover all great gems available for debugging. Thay vào đó, hãy nhìn few tools bạn có thể add today cho instant boost. Bạn likely add each of these to all your projects.
-
awesome_printvàtable_printtạo rich, readable inspections của Ruby data structures, bao gồm Active Record models. Bạn dùng either gem trong code hoặc từ console.Đây example model emitted by
awesome_printtrong console:Thay vì
p, dùngapshow enhanced output. awesome_print list attributes alphabetical order, one attribute per line, among other niceties. -
better_errorsreplaces standard Rails error page với enhanced stack backtrace, parameter list, và interactive console nơi bạn probe stack frame và variables tại scene của exception. Bạn cũng tie source code links đến favorite editor. Đây code tiebetter_errorsto Visual Studio Code:Run
export BETTER_ERRORS_EDITOR=vscodein shell và restart Rails server. Links to files open automatically in Visual Studio. -
Giữ
fakervàfactory_botgems (hoặc alternatives) trong both testing và development groups trong Gemfile. Cả hai invaluable nếu cần generate data quickly trong console.
One more idea: Nếu bạn dùng AppSignal as application monitoring tool, nó có features interpret your logs và pinpoint source của errors. Xem Debugging in Ruby with AppSignal cho more details.
Debugging is a Skill
Debugging code là something of an art, và như any creative endeavor, the more practice you have, the better you become.
Debug while pairing with another developer, especially experienced developer. Nếu partner willing, think out loud together và exchange hunches và insights.
Go forth and hack!
P.S. Nếu bạn muốn đọc Ruby Magic posts ngay khi off the press, subscribe Ruby Magic newsletter và never miss a single post!
Martin Streicher
Tác giả khách Martin là professional Ruby developer. Anh earned advanced degree in Computer Science từ Purdue University, served as Editor-in-Chief của Linux Magazine (US) năm năm, và là founding author của "Speaking in Unix" column published trong IBM's former developerWorks portal. Khi không coding hoặc writing about code, anh collects art và wrangles many small dogs.
Tất cả bài viết của Martin Streicher