Source code is the ultimate documentation

Source code is the ultimate documentation

So I've been coding a custom Sentry SDK. While developing a Sentry SDK they recommend you to run a Sentry Relay - the thing that gets the events, filters them and forwards them to Sentry-land - on your localhost. There's a Github repo where you can download a build for your OS.

I've downloaded it and after some fumbling with the configuration got it to work with verbose logging and route my events to my Sentry project. All was well until I've started working on more sophisticated events called transactions.

Even though the events were received by Sentry successfully, the transactions just weren't appearing in the dashboard. I've looked at the Relay logs and in all the verbose mess of trace level logging I've noticed "invalid transaction dropped".

And that's it. No details. Just that.

I've blindly tried to minimize the number of fields I was sending to only the required once. I've tried some changes based on guessing. Didn't help.

I've googled. Of course I did. I've googled the error and through some hops found the place in the Relay's source code it was doing the transaction validation.

Here's the link if you want to follow along:

https://github.com/getsentry/relay/blob/695acf3df9a44ab4817f7d746fbd311c957f304c/relay-event-normalization/src/transactions/processor.rs#L132

The code is in Rust and the function is called validate_transaction.

OK. There are checks for having a trace context and for that context to have specific fields. I've had all that in my transactions. But there was also a call to another function - validate_timestamps. And the first check is:

  if end < start {
    return Err(ProcessingAction::InvalidTransaction(
          "end timestamp is smaller than start timestamp",
          ));
  }        

Yeah. So I don't know about you, but when I need a timestamp I just call now or something. And the way I called it in my test code was first for the end timestamp and then for the start timestamp, making the time go in the wrong direction.

The two lessons

Lesson one: when you write a software that does validations, please tell the users of that software why validation failed. Don't just say "validation failed". Add the reason.

Lesson two: if the source code is available, jump into it and start digging. It's probably faster that way and unlike documentation it doesn't have missing bits or outdated information. And the more times you do it, the easier it gets to read source code that you didn't write. You actually get some satisfaction from it. Like you've uncovered some knowledge from the source directly. No one spoon fed you. You did it yourself. Have a cookie!

To view or add a comment, sign in

More articles by Evgheni Kondratenko

  • Share utilities, not flow

    Sometimes a program you're working on have multiple flows that look very similar. It could be something like this:…

    1 Comment
  • With or without str

    There are useful functions in Clojure that do not return anything but print text to out (usually the REPL, the log, or…

  • Clj-kondo in a monorepo

    This season monorepos are back on the streets. You can see monorepos everywhere: in a startup, in a scale up, in a…

  • A book about Hackers

    The last episode of the CoRecursive podcast has a story about a veteran game developer and designer Mick West…

  • Your desk is not a mess it's a playground

    Software engineers' work desks used to be interesting and fun. They looked like chaos at a first glance, but if you…

  • Single-header file libraries

    When I've started writing C/C++ programs twenty years ago I've learned that there are two types of files in my program:…

  • Life before LSP

    You know, there was a time when LSP didn't exist. Yeah, I know.

  • Flatten with caution

    In one of my previous Clojure posts I've used flatten in my examples to concatenate collection of collections after a…

    3 Comments
  • There is more than one way

    In one of my recent Clojure posts Dave Liepmann has commented: ..

  • Batching in Clojure is boring

    Sometimes you need to process data. And sometimes it's a lot of data so you want to do the processing in batches.

    1 Comment

Explore content categories