close


Helvetic Ruby 2026 is coming up! Zurich, Switzerland • November 19-20, 2026
Get Tickets
Summarized using AI

Ask your logs

Youssef Boulkaid • May 17, 2024 • Zurich, ZH, Switzerland • Talk

In the talk titled "Ask your logs," Youssef Boulkaid discusses the importance of structured logging in Ruby on Rails applications and how it can significantly enhance the insights derived from logs. The session is aimed at engineers who wish to improve their understanding and utilization of logs to address common issues faced when analyzing unstructured data.

Key points discussed include:

  • Logging Issues: Youssef recounts an experience where his team faced a CPU usage crisis due to over 800,000 jobs in progress, highlighting the inadequacies of unstructured logs, which are hard to analyze and lack essential insights.
  • Structure Matters: The talk emphasizes transforming logs from unstructured text into structured data, which allows for effective querying and analysis. The use of gems like Lograge and Semantic Logger are recommended for consolidating logs into single-line JSON documents.
  • Questions Over Answers: Youssef argues that formulating the right questions is more important than deriving answers. Questions should focus on user actions, job queues, API endpoint usage, and performance impacts of feature flags.
  • Four Problems with Current Logs: Boulkaid identifies four main issues with existing logs: they are multi-line, unstructured, lacking essential data, and uncorrelated across systems. He provides solutions to each of these problems to enable better log management and data extraction.
  • Log Correlation: The importance of correlating logs from various systems is underscored, particularly in distributed environments where multiple services interact. Use of correlation IDs to track requests is shared as a practical solution.
  • Insight Derivation: The talk transitions to how structured logs can be analyzed using tools like Kibana to gain actionable insights, demonstrating how to ask specific questions about user actions and job processing.
  • Broader Context: Boulkaid points out that structured logging isn't a new idea. Companies like Heroku, Stripe, Shopify, and others have recognized its value for years, yet many in the Ruby community have yet to embrace this approach.

The main takeaway from the presentation is that adopting structured logging practices can transform how developers perceive and interact with logs, enabling them to extract valuable insights quickly and efficiently. Boulkaid encourages the audience to start implementing structured logging in their Rails applications to ask meaningful questions and carry out better data analysis.

Ask your logs
Youssef Boulkaid • Zurich, ZH, Switzerland • Talk

Held on: May 17, 2024
Published:

Logging is often an afterthought when we put our apps in production. It's there, it's configured by default and it's... good enough?

If you have ever tried to debug a production issue by digging in your application logs, you know that it is a challenge to find the information you need in the gigabyte-sized haystack that is the default rails log output.

In this talk, let's explore how we can use structured logging to turn our logs into data and use dedicated tools to ask — and answer — some non-obvious questions of our logs.

Helvetic Ruby 2024

English
00:04 first talk after lunch I wonder how many
00:07 of you are you know like energized
00:08 versus
00:11 sleeping all right let's do this so I
00:14 want to start with a story our story
00:16 starts uh a couple years ago back then I
00:20 was part of a team working on a small
00:22 internal application in a previous
00:25 company one day we got paged by our
00:28 infrastructure team because our workers
00:30 servers were at 100% CPU usage and had
00:33 been that way for a couple
00:35 hours something was wrong this was
00:38 related to our workers so of course the
00:40 first thing we do is we open our
00:42 sidekick dashboard and we saw
00:46 this yeah that's right over 800,000 jobs
00:50 in CU this was a small internal app so
00:53 this was not expected at all we fixed
00:56 the issue I don't want to get into the
00:58 details here but we wanted to figure out
01:00 why this happened so this wouldn't
01:02 happen again so someone in the team
01:04 asked the natural question hey can we
01:07 check our
01:08 logs and when they said that the first
01:11 thing that popped into my mind was
01:12 something like
01:16 this so we do have logs but there're
01:19 piles of raw texts that are hard to use
01:22 and to find anything in it was painful
01:25 and far from the best
01:27 experience the second thing that pum in
01:30 my mind is was this site I read a couple
01:32 months prior and that came back to haunt
01:43 me so yeah our logs are trash this hits
01:46 too close to home now that keep me
01:50 thinking why trash why can't we use them
01:54 to get actionable insights that's why
01:56 they're trash because we can't do that
01:58 so what did what charity me meant was
02:02 that our logs were not data they're just
02:05 piles of raw text with no
02:07 value but that got me thinking what if
02:10 they were What If instead of piles of
02:13 unstructured texts we could treat our
02:15 logs like data and use them to get
02:17 valuable and actable
02:20 insights hi my name is Yousef and I want
02:22 to talk to you about turning logs into
02:26 Data I am a senior engineer at workato
02:29 where we create a product for companies
02:31 to automate their business processes
02:33 without writing any
02:36 code like all of you I love writing Ruby
02:39 I've been coding in Ruby almost my
02:41 entire professional career and I
02:43 especially enjoy working on developer
02:45 tools because I believe that coding
02:48 should never be a chore and that making
02:50 developers more productive is is just a
02:53 joy to work on and it's actually my
02:55 second favorite
02:57 hobby my second because I said say
02:59 second because my first Passion is
03:01 photography I rarely go out without my
03:03 camera and if I'm lucky I get back with
03:06 some shots that I'm happy with such as
03:18 these So speaking of
03:24 logs our agenda for today we're going to
03:26 start by looking at the default raise
03:28 logs which question question they can
03:30 help us answer and which ones they can't
03:33 in the second part we're going to to
03:34 going to introduce more structure into
03:37 them and shape them into data and
03:40 finally we're going to see a Showcase of
03:42 the kind of insights we're going to get
03:43 from
03:44 them so let's start by looking at the
03:46 default race logs and to get logs we
03:50 have have to first run some codes so
03:51 there's a basic action that everyone
03:53 should be familiar with so just an
03:56 update user user update action you take
03:58 an user you find find them you update
04:01 and then you redirect to an
04:04 action so the default race logs look
04:07 something like this in a very simplified
04:09 case so we have five lines output total
04:13 and uh we
04:15 do see we can
04:17 this we start by like the request starts
04:21 and then we output a line then we start
04:23 processing the request and we output a
04:25 second line here and then we also output
04:28 the parameters uh which like the user
04:31 the country the local like everything
04:33 that is in your application then we
04:35 redirect so we also output something
04:37 here and then at the end we have a
04:39 little summary of the
04:42 request so these are the logs we already
04:45 we all have by default so what kind of
04:49 what kind of questions we can ask these
04:51 logs so we can
04:54 ask how many patch requests do we
04:57 process per day
04:59 we can
05:00 ask which controllers are our
05:04 busiest
05:06 or what's our rate of 404
05:10 responses but are these really the
05:13 questions we want to ask as one French
05:16 philosopher once wrote judge a man by
05:19 his questions rather than by his
05:22 answers so I went to French school so by
05:24 law I have to quote volter at least once
05:26 a month or they come for me
05:31 but in all seriousness I find that
05:33 thinking about questions is often more
05:35 valuable than getting the answers so
05:38 what are the questions we want to
05:41 ask so we want to be able to ask which
05:44 requests did this specific user
05:47 perform
05:49 or why did we suddenly enq a large
05:52 amount of
05:55 jobs or how many users are using this
05:58 Legacy API end points that we've been
06:00 wanting to retire for a while and what
06:03 do they all have in
06:05 common or another question that's a bit
06:08 more complex is is this feature flag
06:10 affecting database
06:12 performance on some revision of our code
06:15 in Us East one so notice that this
06:18 question is about correlating data from
06:20 completely different parts of our stack
06:22 so the application the database kits and
06:27 infrastructure so why can't we answer
06:29 this question with our logs
06:31 today my my theory is that there's four
06:35 main issues with these logs so first
06:39 they're
06:40 multi-line so it's okay when we see
06:42 things like this it's relatively okay
06:43 because when when we process a single
06:45 request but then when we aggregate the
06:47 logs from multiple servers which we can
06:49 have hundreds of they all become
06:51 intertwined and it gets impossible to
06:53 actually make sense of
06:55 them second they're not structured
06:58 they're made for human eyes but it's
07:01 hard to analyze programmatically and
07:03 like actually get patterns from
07:06 them third they're missing the main data
07:10 so there's no concept of user or like
07:12 revision or AWS Zone there's nothing
07:16 here so there's no nothing we can query
07:20 against to analyze the
07:22 data and finally they're uncorrelated
07:25 between systems so meaning each systems
07:28 and each apps logs only refer to that
07:31 single system and we can't correlate for
07:34 example the logs that are output from a
07:36 worker from and from
07:40 web so can we fix this at least what we
07:43 have with these four issues is that we
07:45 have a very so we have four problems we
07:48 can tackle them one by
07:49 one and that takes us to second part of
07:52 the talk where we'll take all these four
07:54 points and see how one by one we can fix
07:57 them so our first problem was that logs
08:00 were
08:02 multi-line this is what we saw before so
08:05 I call them print as you go logs so as
08:07 the request goes through the rail stack
08:10 it outputs log lines for each step so
08:14 this gives us a kind of a story for the
08:16 request life cycle it's telling us oh I
08:18 started and now I'm processing and then
08:20 I'm redirecting and I'm
08:23 finished but that's not interesting to
08:25 us what we want is we want a summary of
08:27 that request we want to have all the
08:29 information all at
08:31 once so what we do is we can consolidate
08:35 these these logs and it's actually
08:38 pretty easy when you're doing Ruby so
08:40 there's a gem for that you can use log
08:44 Rage which is the OG or a ra semantic
08:47 logger uh which is more
08:50 advanced both of these will give you
08:53 something like this so all the request
08:57 goes through the stack there's nothing
08:58 output and just before the request
09:01 exits that it outputs one single line
09:05 with exactly the information that we had
09:06 before so we have the methods the path
09:09 format everything that we had before but
09:12 Consolidated on a single line at the end
09:14 of the
09:15 request so we fixed the first part
09:18 problem number two those logs are
09:21 unstructured when we have unstructured
09:23 logs we can structure them so what we
09:26 can do to enable structure logs is uh
09:29 both the gems I mentioned before have a
09:31 setting for uh formatting logs in a
09:33 certain way so here we're going to use
09:37 the Json formatter for log
09:40 R and what it does is that instead of
09:44 having this a key value pair that we had
09:46 before we have a Json document as an
09:49 output uh it's a bit hard to read here
09:52 so I just expand it but it's it's still
09:55 one single line that's
09:57 output and here we have yeah it's key
09:59 value pair is a Json document we all
10:02 know that in that has all the
10:05 information from all the request that
10:07 just came through our stack and we can
10:09 even structure information inside like
10:11 this parms here where we have a nested
10:13 Json document so we can actually have
10:16 structure so this is a key Point what we
10:19 just did here is we turn logs into
10:22 Data if you're going to remember one key
10:25 point from this that's it structured
10:27 logging turn turns log into Data by
10:30 outputting one single structured line at
10:33 the end of each request you can think of
10:36 them as an events that the uh that the
10:39 request produces an event
10:42 summary so we can continue by talking
10:46 problem number three logs are missing
10:49 data so we can do is we can enrich our
10:54 logs because now they're structured but
10:55 they only contain generic information
10:58 they don't know anything about our app
11:00 so we can enrich them with domain
11:03 information I'm very thankful that the
11:04 screen is
11:06 big so we can have like for example
11:08 Environ information from the environment
11:11 here so the we can pass the proc type
11:13 the revision or the a region
11:16 here we can have the extra data from the
11:19 request like the request ID and the user
11:23 agent or we can have anything that you
11:25 can think about in your
11:27 controller so we can can output the
11:30 local we can output the current user
11:33 information and anything that is
11:35 relevant to your specific
11:39 application and we get something like
11:41 this at the end it's truncated but it's
11:44 exactly what you expect so we have all
11:47 the information filled in the Json
11:49 document we had the pro type revision
11:52 local and I want to spend some time
11:56 here uh with a couple warnings
11:59 it's a bit too easy to shoot yourself in
12:01 the foot doing this there's two points I
12:03 want to
12:04 address the first one is
12:09 performance so only log information that
12:11 is cheap to compute so environment
12:13 variables are
12:15 okay objects you already have in memory
12:17 are okay but don't put extra database
12:20 calls to enrich your logs because the
12:23 overhead there can be
12:26 significant and the second one which a
12:28 bit more pricious
12:30 is accidentally exposing private
12:32 information it's way too easy to
12:35 accidentally log sensitive information
12:36 to
12:37 logs and actually if you didn't do
12:41 anything to your rails app by default
12:43 you're probably outputting sensitive
12:45 data to your logs because we're
12:46 outputting the params object by default
12:50 and that can contain name emails birth
12:52 dates Social Security numbers because
12:55 you have the user update action and
12:57 there's a lot of stuff in there
13:00 so what you can do is if you're really
13:03 strict about that don't output the parm
13:06 object or what you can do is that you
13:09 can uh use the axis4 has a feature
13:11 called parameter filter and it can be
13:14 used to filter some sensitive data for
13:16 example if you know that all your params
13:18 are okay but maybe name and email are
13:20 not okay you can have an blocking list
13:25 there and I want to end this section by
13:27 just showing you one example of this
13:29 going wrong in the
13:32 wild so 5 years ago Facebook was caught
13:36 storing user passwords in plain text and
13:40 this is not because they were storing
13:41 the data itself in plain text in their
13:43 database they're too smart for that but
13:46 because they were logging them as part
13:47 of their
13:49 parameters so yeah be careful about
13:54 this and lastly we want to check problem
13:57 number four where the logs are
13:59 correlated between systems so what we do
14:02 again when we have uncorrelated logs we
14:04 can
14:06 correlate so correlation means linking
14:08 logs between different systems and as
14:11 such it's like we
14:13 can is it all depends on your systems so
14:16 it's hard to give general advice here
14:19 but I want to show you two examples of
14:21 corating logs just for
14:24 inspiration so the first example is in
14:26 the context of distributed systems
14:30 sometimes you have dozens of
14:32 microservices calling each other just to
14:34 answer one single HTTP request I don't
14:37 know why you would do that
14:39 okay so how do you track this how do you
14:41 track who calls whom and like which
14:43 requests were done
14:45 to answer this one
14:47 request so one way is to have the first
14:50 entry point service maybe the Gateway
14:52 generate a unique ID which is usually
14:54 called correlation ID and then you pass
14:57 it as an HTTP header to any subsequent
15:00 request so this is the header that we
15:04 passing and then any any system that
15:07 gets this correlation ID will output it
15:10 again in their logs so that means that
15:13 if you filter by your logs by
15:14 correlation ID you get to see all the
15:17 requests that are in in the
15:22 chain a second
15:24 example is how to correlate jobs and web
15:27 requests
15:29 so sidekick has the concept of
15:30 middlewares where you can add metadata
15:33 to jobs when they are ened so what we
15:36 can do is you can have this ined by
15:40 request
15:41 ID U ID that you you add to the job
15:45 request to the job uh when when it's
15:48 seced
15:49 automatically so that whenever you have
15:51 a job that's executed it will output
15:54 this request ID so you can trace exactly
15:56 where the job came from
16:01 so to
16:02 recap we have Consolidated our logs into
16:06 one line per
16:07 request we structured them into Json
16:10 documents we enriched them using the
16:12 main data and we correlated them between
16:16 our
16:17 systems and that gives us something like
16:19 the log line right
16:22 there so what
16:25 now this the fun part of the
16:27 talk we we're entering the third part of
16:30 our agenda where we'll see how we can
16:31 analyze our logs in different
16:34 ways logs are now data so we can treat
16:37 them as such and what we do is we first
16:41 ingest them into our data analysis
16:43 platform of choice there are many to
16:45 choose from I do want to give a special
16:48 me mention to better stack who's
16:49 sponsoring this
16:51 conference you can find them in the
16:53 booth outside and they'll be happy to
16:54 talk to you about
16:56 this but for this presentation I'm going
16:58 to be using kibana which is based on
17:00 elastic search sorry but
17:04 stack they're not paying me for this I
17:06 just uh like their
17:09 product so this allows us to go from
17:11 this one log line to this it's a
17:15 document in a
17:16 database and from this
17:21 nonsense to this it's a queriable
17:23 database of all our
17:27 requests so back to our question
17:28 question
17:30 s we asked we wanted to ask which
17:33 requests did this specific user
17:36 perform now we're going to see how we
17:39 can do this in uh using this
17:43 kibana so we're going to start from
17:46 having all the
17:48 logs 24,000
17:51 here and we are logging the user ID so
17:53 we can use this to filter the requests
17:56 that come from that user ID
17:59 there you go 20 hits not only that but
18:02 we can
18:03 also select different fields that we're
18:06 interested in for example we want to see
18:08 which controller which action and what
18:11 the duration of the
18:13 requests and now we have a nice table
18:15 here where we see for each of the 20
18:17 requests that the user made exactly
18:19 which data we wanted we wanted to see
18:32 so next we wanted to ask why did we
18:35 suddenly enue a large amount of
18:39 jobs
18:41 again we're going to start from Ora
18:44 logs and we're interesting jobs so we're
18:46 going to start by filtering the sidekick
18:49 logs
18:52 only and here we can visually see that
18:55 this app doesn't have a lot of activity
18:57 except here
19:00 so we're going to try to focus on those
19:04 those log lines
19:06 there we know roughly when they
19:11 appeared and then we're going to try to
19:13 look how can we correlate all of these
19:15 things remember we added this ined by
19:19 request ID to our logs before to our
19:21 sidekick logs so we can add it to the
19:27 table then we can and see if we can find
19:29 anything that's
19:33 weird and here we we see a lot of jobs
19:36 that have the same request ID that in
19:41 them that is
19:43 fishy but we have something we have the
19:45 request ID so we can just look for
19:51 it you find it
20:00 then we can see which controller
20:02 maintenance tasks controller okay action
20:05 start daily cleanup that sounds
20:08 weird so now we know exactly what
20:10 happened and why we ined all these jobs
20:13 but we can do more we can see who in
20:15 this
20:16 jobs and you can get the user email and
20:19 user ID from
20:23 there and of course it's super admin so
20:25 me
20:30 so yeah from our logs we were able now
20:33 because we had all the data there to get
20:35 actionable
20:37 insites and know why this problem
20:39 occurred and what we can do about
20:43 it we're going to
20:45 continue how many users are using this
20:48 API endpoint this Legacy API endpoint
20:50 and what do they have in
20:52 common so now instead of seeing like the
20:55 logs in a list we're going to visualize
20:58 them
21:02 so we're going to first try to see how
21:04 many users we
21:05 have so we want to count the unique
21:10 users by filter the unique request by
21:13 user
21:15 ID and we got the number 109 but that's
21:18 for all are up we want to see exactly
21:21 who's who's hitting the Legacy
21:24 controller so you can filter by the
21:26 Legacy things controller
21:30 and there you go we have seven users
21:32 that are using this Legacy
21:35 controller but we want to do more than
21:37 that who are these users and what do
21:40 they have in common so that we can
21:42 actually retire this
21:45 endpoint so we do the same thing but now
21:48 instead of just a number we're going to
21:49 do a pie
21:51 chart so we're going to
21:53 count those are all of our
21:56 requests same thing so before we're
21:58 going uh filter by
22:05 controller and then we're going to slice
22:07 the data by guesses let's see maybe they
22:12 all come from the same AWS
22:15 region no they all come from all
22:21 over so maybe they're coming from like
22:24 they the request are in specific format
22:27 no we have both HTML and Json
22:29 on maybe they're using specific
22:34 language
22:36 nope maybe I don't know user agent is
22:40 the
22:45 same there we go so we figure out that
22:48 all our requests that hit are hitting
22:50 the Legacy controller is are coming from
22:52 our old mobile app and we can take the
22:55 iPhones away from people so we just have
22:57 to retired
23:00 them and this our last question remember
23:03 this is one this the one that went like
23:05 all across the stack is this feature
23:07 flag affecting the database performance
23:10 on revision something in Us East
23:13 one and what we did when we enriched our
23:16 data like our log data is that we kind
23:19 of collapsed all of these St this places
23:23 in our infrastructure into one single
23:27 level so this this is now actually
23:29 pretty easy to do so it's going to be a
23:31 bit
23:31 faster so you want
23:33 to have a graph of the database front
23:39 time filtered by revision
23:44 revision and AWS
23:52 region and we want to splice it by is
23:55 the feature flag enable or not
24:06 there we go we see that clearly if you
24:08 enable the feature flag the database
24:10 performance takes a
24:12 hit so structure logs are
24:17 awesome by turning logs into Data we can
24:20 use them in new ways we can slice and
24:23 dice the data to explor patterns
24:26 answering new questions without changing
24:28 any
24:29 code these questions can range from the
24:31 need and Hast stack kind of questions to
24:35 long-term
24:36 trends you can almost think of them as
24:39 technical business intelligence for
24:42 developers and I can guarantee that once
24:44 you try this you can't go back to
24:47 tailing
24:50 logs so we're nearing the end of the
24:53 presentation so I wanted to mention just
24:55 a couple final words about structure
24:56 logging in a larger context
24:59 first is this is not new this practice
25:02 has been around for
25:05 years Heroku has that in their
25:10 guides stripe has a blog post from 2019
25:14 calling them canonical log lines but
25:16 it's just the
25:17 same and even a couple months ago there
25:20 was this blog on blog post on hyper news
25:23 with like white events is what you need
25:25 white events is just this structured
25:27 logging
25:28 they call them wide events because
25:30 they're theories that you can you should
25:32 try to put all the data you can in them
25:34 so the Json documents get pretty
25:38 big and there's this even this quote by
25:41 DH stting that Shopify and 37 signals
25:44 have been using in-house structure login
25:46 for a long
25:47 time so this is not new at all it's just
25:50 it's not a very well-known feature out
25:52 of outside of larger
25:54 companies so we are lagging behind
25:58 we the Ruby and the whales Community are
26:00 lagging behind in the adoption of this
26:02 practice other communities like if you
26:05 turn into the Java communities and the
26:07 goine communities they have integrated
26:09 this into their tooling a while ago and
26:11 it's almost a given for new
26:14 projects but in ra project you still
26:16 have to do some work to get this and you
26:20 only see that happen in mature
26:23 projects but let's fix
26:26 this rails builders
26:28 if you're building anything try this
26:31 approach try structure loggings use it
26:34 and spread the word about it I guarantee
26:36 you will not regret
26:38 it gem maintainers if you have a gem
26:41 consider adding an optional structured
26:43 login option for your gem so that all
26:46 your logs can be
26:48 ingested in such
26:51 systems by the way this applies to rails
26:54 too the DHS codes I just gave you it
26:57 actually comes from an issue that was
26:59 created late last year there was a
27:02 proposal to add structured login
27:03 directly into
27:05 rails I'm very happy about
27:08 that but we don't have to wait in the
27:11 meantime we can only use structured
27:13 login today and start asking our logs
27:16 the questions we want to have answered
27:18 instead of merely the ones we
27:20 can thank you
More from Youssef Boulkaid (4)
Brewing potions with Ruby and linear programming
29:34
Brewing potions with Ruby and linear programming
tiny ruby #{conf} 2025
Failed to Build Gem Native Extension
30:01
Failed to Build Gem Native Extension
Baltic Ruby 2025
Ask your logs
27:44
Ask your logs
RailsConf 2024

Helvetic Ruby is a yearly conference held in Switzerland and features 12 talks from various speakers.

12
Talks
12
Speakers
1
Day
4
Editions

Full Schedule

Similar Talks that share the same topics:

From Chaos to Clarity: Structured Event Reporting in Rails
29:32
From Chaos to Clarity: Structured Event Reporting in Rails
Adrianna Chang • Rails World 2025
Workshop: How to instrument your Rails app with OpenTelemetry
01:38:57
Workshop: How to instrument your Rails app with OpenTelemetry
Kayla Reopelle • RailsConf 2025
Squash Production Defects Quickly - The Power of Structured Logging in Rails
22:45
Squash Production Defects Quickly - The Power of Structured Logging in Rails
John Gallagher • EuRuKo 2024
Fix Production Bugs Quickly - The Power of Structured Logging in Rails
35:57
Fix Production Bugs Quickly - The Power of Structured Logging in Rails
John Gallagher • Ruby Community Conference Summer Edition 2024
Ask your logs
27:44
Ask your logs
Youssef Boulkaid • RailsConf 2024
Growing Software From Seed
33:30
Growing Software From Seed
Sweta Sanghavi • RailsConf 2021
Building for Gracious Failure
32:22
Building for Gracious Failure
James Thompson • RailsConf 2019
Troubleshoot Your RoR Microservices with Distributed Tracing
31:22
Troubleshoot Your RoR Microservices with Distributed Tracing
Yoshinori Kawasaki • RailsConf 2019
Forensic Log Analysis with BigQuery
24:05
Forensic Log Analysis with BigQuery
Aja Hammerly • MountainWest RubyConf 2015
Explore all talks recorded at Helvetic Ruby 2024
Image
Image
Image
Image
Image
Image
Image
Image