< Back home

Leveraging UUIDs to the Max

Posted on December 17, 2022

UUIDs

<Imagine a very deep introduction into why UUIDs are beautiful and important in today’s world and how they amazingly simplify our lives>

But!

UUIDs are a pain in the ass to look at! Maybe you’re looking at your production logs, maybe it’s your Kafka stream of events, deployment configurations for different customers/countries? magic UUID values in your source code on Github. It’s just UUIDs all over the place and if you’ve worked at your current job for a long enough time (very uncommon nowadays) you may recognize at most the top 5 most common ones. I for instance only remember that our German sales channel (the biggest one) ends in ...f4 and the identifier for Zalando in the list of retailers ends in ...c7. But we have 24 sales channels and thousands of retailers.

TODO insert screenshot

We’re not really leveraging the power of computers

what is my purpose?

Facebook is pumping money into augmented reality goggles and we’re not even augmenting the already virtual.

In this specific case all we need for a basic proof of concept is 100 lines of JavaScript + 20 lines of JSON.

There’s a Browser API for that!

Since web pages are not static documents anymore (and haven’t been for a while now), our basic goal is to regularly “scan” the document for new UUIDs and add a tooltip action next to them. Despite sounding like a really expensive operation the web platform allows us to be fairly smart about it. The 🔥DOM🔥 has this really cool API Document.createNodeIterator() that allows us to iterate over all the nodes of the document while also allowing us to be fairly granular in specifying which nodes are actually relevant to us.

In our case we are only interested in text nodes - the leaf nodes of an HTML document. In the most basic form it would look something like this:

const iterator = document.createNodeIterator(
  document.getRootNode(),
  NodeFilter.SHOW_TEXT
)

But the API goes one step further and actually allows us to specify a filtering predicate which will allow us to skip big paragraphs of text and focus only on small text nodes containing only UUIDs or some kind of identifer derived from a UUID (e.g. a Kafka topic name specific to a country):

const iterator = document.createNodeIterator(
  document.getRootNode(),
  NodeFilter.SHOW_TEXT,
  n => isSingleUuidNode(n) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT
)

// https://stackoverflow.com/a/6640851
const uuidRegex = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/

function isSingleUuidNode(node) {
  // ignore very big text nodes
  // (we are afterall periodically iterating over the whole document)
  if (node.data.length > 1000) {
    return false;
  } else {
    // we don't perform an exact match (/^...$/) since we want to be able
    // to annotate even text that might INCLUDE a UUID (e.g. per-entity resources)
    const uuidsInNode = node.data.match(new RegExp(uuidRegex, 'g')) || []
    // more than 1 match not interesting as it wouldn't be clear which UUID the tooltip is for
    // and splitting text nodes is beyond the scope for now
    return (uuidsInNode.length === 1)
  }
}

Perfect! Now we just need to iterate over all the found UUIDs and see if we already decorated them in the past or in case of new discoveries we:

  1. extract the UUID
  2. pass it to a user-supplied function that transforms a UUID into an HTML snippet
  3. build up the HTML elements for the tooltip and the action icon displayed next to the UUID
while (currentNode = iterator.nextNode()) {
  const parent = currentNode.parentElement
  if (!isDecorated(parent)) {
    const uuid = currentNode.data.match(uuidRegex)[0];
    const tooltipHtmlContents = resolveFn(uuid);
    const actionIcon = createActionIcon(tooltipHtmlContents)
    parent.appendChild(actionIcon);
  }
}

function isDecorated(element) {
  return Array.from(element.children).some(x => x.classList.contains(`action-icon`))
}

as a result the this HTML snippet would be subject to the following transformation:

BEFORE:

<div>
334e7b07-cfae-4759-8c9f-c64f152cd627
</div>

AFTER:

<div>
334e7b07-cfae-4759-8c9f-c64f152cd627
<div class="action-icon">
  ℹ️
  <div class="tooltip">Best <b>UUID</b> ever!</div>
</div>
</div>

Then it’s just a matter of running this periodically and sprinkling in some CSS in order to hide/show the tooltip when we hover the “ℹ️” symbol.

TODO screenshot

You promised a browser extension!

Google Chrome makes it really trivial to take this chunk of JavaScript and pack it up as an extension for your browser. Just add this 20 line JSON manifest to your folder and Chrome will be happy to load it up and run your script on any web page you visit.

{
  "manifest_version": 3,
  "name": "Annotated UUIDs",
  "version": "1.0",
  "description": "Augmented reality for people who regularly look at UUIDs",
  "icons": {
    "32": "images/icon-32.png"
  },
  "content_scripts": [
    {
      "js": ["scripts/content.js"],
      "matches": [
        "http://*/*",
        "https://*/*"
      ]
    }
  ]
}

Build your own!

You can find all the above described code in this demo Github repository.

If you want to build your own Chrome extension like this I would encourage you to make use of this template:

The template also already shows a more advanced implementation of what is presented here (e.g. it uses an external library to create the tooltip and it allows for asynchronous loading of data).

hack-the-planet

Comments