If you’ve used the ELK stack, you’ve probably had the joy of trying to share a Kibana URL with someone. If you were naive enough to just copy the link from your browser (rather than creating a shortlink), you’re faced with something that looks like this monstrosity:

https://kibana/app/discover#/?_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now))&_a=(columns:!(_source),filters:!(),index:ea073d70-8ed6-11ea-88e9-39648e0749be,interval:auto,query:(language:lucene,query:'machine:%20164%20AND%20service:%20fun-times'),sort:!())

Discover is right Kibana URL, although we may have a bit of trepidation over what we’ve just discovered, because what are those ?_g and ?_a parameters?

Those parameters are an encoding scheme called RISON. And today I want to explore it a bit, and postulate on why it doesn’t really exist anymore.

Motivation

RISON was not originally made for Kibana, although Kibana was one of the early adopters and as far as I can tell is the only real surviving user. It was born out of two observations:

  • Characters like {, }, ', and " get escaped in URLs and are hard for a human to parse
  • JSON has lots of {, }, ', and "

RISON attempts to minimise the use of such characters and provide an encoding that only gets minimally escaped when encoding a URL, providing a format that should be reasonably human readable when sharing URLs around. Seems reasonable enough.

How RISON works

RISON attempts to be reasonably close to JSON. It supports nested objects, arrays, and typed values, but differs from JSON in how they are encoded. RISON attempts to limit its set of syntax to characters that wont be mangled by URI encoding, in order to maintain its human-readable state after going through that process.

Values

Values in RISON are represented rather similar to YAML, with inferred typing. Strings are unquoted and numbers are inferred as numbers (although can be coerced to strings through quotes, e.g. value:'0'). RISON does define interesting values for booleans however - instead of true and false, RISON encodes these as !t and !f. This gives us both brevity, and removes parsing ambiguity.

Extracting a few examples from the above URL, we have:

  • from:now-15m - the value of from is the string "now-15m
  • pause:!t - the value of pause is true
  • value:0 - the value of value is 0

Arrays and Objects

Arrays in RISON use the syntax !(a,b,c). Again, we see the use of non url escaped characters like ! and ( over JSONs [ and ]. Values inside arrays are encoded as above, and arrays do not enforce typing, like JSON.

From above, we have columns:!(_source) - the value of columns is the array [_source]

Objects in RISON use the syntax (k:v,x:y), again encoding values as above. It’s interesting to see how RISON cuts down its character list, encoding objects and arrays with the same () notation.

None of the arrays or objects contain whitespace. As if RISON were attempting to be the villain in YAMLs store, RISON enforces that no whitespace (except for quoted strings) is allowed in RISON objects. This cuts down on ambiguity around encodings, but also enforces compactness which is important when you’re dealing with URLs which may butt up against size limits enforced by servers, middleware boxes, or end user applications.

Breaking down the above URL

So let’s look at our Kibana URL. We’ll take the ?_a parameter as an example:

(columns:!(_source),filters:!(),index:ea073d70-8ed6-11ea-88e9-39648e0749be,interval:auto,query:(language:lucene,query:'machine:%20164%20AND%20service:%20fun-times'),sort:!())

It starts with a (, so we know that this is an object, and we can proceed parsing KV pairs.

  • columns:!(_source) has a value that starts with !( which makes this an array, and parsing that further we find that it’s an array of a single element, _source
  • filters:!() similarly is an array, although this one is empty
  • index:ea073d70-8ed6-11ea-88e9-39648e0749be and interval:auto are string literals
  • query:(language:lucene,query:'machine:%20164%20AND%20service:%20fun-times') starts with a (, so we have nested object! This object contains two keys - language:lucene and query:'machine:%20164%20AND%20service:%20fun-times'. Note that query contains whitespace (%20 is the URL encoding of a space character), and thus it has to be quoted with single quotes.
  • And finally we have sort:!() which is another empty array

All that together means that our RISON decodes to the JSON object:

{
    "columns": ["_source"],
    "filters": [],
    "index":"ea073d70-8ed6-11ea-88e9-39648e0749be",
    "interval":"auto",
    "query": {
        "language":"lucene",
        "query":"machine: 164 AND service: fun-times"
    },
    "sort": []
}

So where is RISON now?

Outside of Kibana, I’m unaware of any mainstream RISON usecases. Even the original site describing it has since been removed, although there exists a few maintained implementations, and backups of the site are available via the Internet Archive. As such I would consider RISON to be functionally dead. But why is that? The idea of a URL safe structured format seems like a good idea, but in practice we seem to be able to go without. Many applications where RISON might have been used simply use flat structured in their URLs, eschewing the need for any sort of structure. If we go that way, then the need for RISON and all its syntax to denote structure falls away.

But even outside the questionable need for structured data, the premise that RISON is built on is shaky. RISON arises out of a desire to have a human readable format for encoding data in URLs, without questioning whether or not that’s actually necessary. In fact, it goes against its other design goal of being compact - human readable formats are necessarily more verbose than not (we humans sure are inefficient creatures). The reality is that when we’re given a link, we’re not parsing it deeply ourselves. We’re clicking on the link, upon which we’ll be taken to a nice page that has parsed the query string for us, hopefully displaying it front and center in a nice UI. The need for a completly human-readable structure simply isn’t a necessity given the way we interact with these sorts of applications.

If you’re aware of other usecases of RISON however, I’d like to know - reach out!

I'm on Twitter: @sinkingpoint and BlueSky: @colindou.ch. Come yell at me!