rugyoga

rugyoga

Audit - a library for understanding changes in large data structures

My work at Lob involves a program called Dora that performs address verification. It validates addresses, repairs them to something valid or rejects them and tells you the issue. It’s basically a very long pipeline processing an Address struct with lots of rules and steps that gradually enrich the data structure as it passes along the pipeline.

The original authors have since moved on so we had to come up with techniques to understand why Dora makes the decisions and modifications it does.

To that end, I came up with Audit (hex,
github)

It operates by adding an extra field to the data structure of interest: __audit_trail__.
You then wrap your updates with the audit macro.
This will record the current file and line number (hence the use of a macro) and store the current version of the data structure.
The __audit_trail__ field is effectively a linked list history of every version of the
data structure you wrapped in audit.

The to_string method will take a struct with the __audit_trail__
and pretty print the list deltas and with the line of code that caused it
(as a github link, a filename/line number and a code snippet from the actual line in the file)
e.g. some example output:

github url: https://github.com/lob/dora/tree/leverage_audit_hex_package/lib/dora/.../standard.ex#L234
local path: lib/dora/.../standard.ex:234
code: address = %Address{audit(address) | primary_number: primary}
diff: [{[:primary_number], {:add, "18"}}]
=====
github url: https://github.com/lob/dora/tree/leverage_audit_hex_package/lib/dora/.../standard.ex#L228
local path: lib/dora/.../standard.ex:228
code: address = %Address{audit(address) | street_name: street}
diff: [{[:street_name], {:add, "BERNICE"}}]
=====
github url: https://github.com/lob/dora/tree/leverage_audit_hex_package/lib/dora/.../standard.ex#L217
local path: lib/dora/.../standard.ex:217
code: address = %Address{audit(address) | street_suffix: suffix}
diff: [{[:street_suffix], {:add, "ST"}}]

To kick the tires, add the following to your deps:

      {:audit, "~> 0.1.6"},

Add the __audit_trail__ field to your struct.
And modify your instances of:

%struct{ v | ... }

to be:

%struct{ audit(v) | ... }

then do the following to your resulting data structure:

r 
|> Audit.to_string()
|> IO.puts

First Post!

egze

egze

That is very cool and the usage seems quite nice.

Can you please edit the main post and include the GitHub Repo and a link to hex.pm? :wink:

Where Next?

Popular in Libraries Top

devonestes
Introducing assertions, the library that helps you write really great test assertions! GitHub: https://github.com/devonestes/assertions ...
New
sabiwara
Dune is a sandbox for Elixir and aims to safely evaluate user-provided code. You can try it out using this basic Elixir playground made ...
New
OvermindDL1
Been making an MLElixir thing (not released yet…) for fun in spare time in the past day. I’m just trying to see how much I can get an ML...
132 13487 106
New
pkrawat1
Presenting Aviacommerce, open source e-commerce platform in Elixir Aviacommerce is an open source e-commerce platform in Elixir. We at...
New
mindok
What is ContEx? A pure Elixir server-side data plotting/charting library outputting SVG. It has nice barcharts in particular and works g...
New
benlime
I created a new library GitHub - benvp/ex_cva: Class Variance Authority for Elixir which aims to make it very easy to define different va...
New
josevalim
Yes, yet another parser combinator library! Most of the parser combinators in the ecosystem are either compile-time, often using AST tra...
159 18262 141
New
OvermindDL1
I created a new library (rather I pulled out a couple files from my big project), it manages an operating system PID file for the BEAM. ...
New
KallDrexx
For a good number of months I've been working on creating a very basic RTMP live video streaming server. Now that I have a very, very ba...
New
New

Other popular topics Top

senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
Tee
can someone please explain to me how Enum.reduce works with maps
New
pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
yawaramin
In the Dialyzer docs ( http://erlang.org/doc/man/dialyzer.html#requesting-or-suppressing-warnings-in-source-files ), there is a way to tu...
New
KronicDeth
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine) This is a plugin that adds support for Elixir to JetBrains IntelliJ...
289 35421 110
New
script
If I have a string “1000 cfu/ml” . I want to remove the characters and / and space . So the string is like this "1000" What is the ...
New
vac
Hi, I'm quite new in Elixir and I'm trying to format a string to a PEM format. I have the certificate value like MIIDBTCCAe2...... and ...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
AstonJ
We’ve put together this wiki for Phoenix LiveView - please feel free to add any info you feel is worth including. What is Phoenix LiveV...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New

Sub Categories:

We're in Beta

About us Mission Statement