Kibana Short URL Intended Use

Hi,

We've historically used Kibana's short URL feature to provide users with reliable links to predefined Kibana discover queries.
This has been needed as we have Kibana behind a single sign-on flow which causes URL fragments to be dropped when users are sent through the flow, so a request to e.g. /app/discover#/?_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now))&_a=(columns:!(),filters:!(),index:'90943e30-9a47-11e8-b64d-95841ca0b247',interval:auto,query:(language:kuery,query:''),sort:!(!(timestamp,desc))) ultimately ends up just sending them to the main discover page, /app/discover

To get around this, instead of linking users direct to Kibana, we instead link to another service (e.g. https://redirector/logs/application/myapp), this service will interpolate the relevant params (in this case myapp) into a predefined discover search query, and then use the Kibana short URL API to generate a short URL for that discover address/query, this is then returned to the user as a redirect to the generated short URL (e.g. https://kibana/goto/someid).
For a given search (e.g. application logs) the query is much the same, except we interpolate specifics into the search, e.g. changing on the search terms to be the application the user is clicking through for. We then have a number of different URI's on this redirect service that generate short URLs to different Kibana searches.

This works well as users are only ever sent to short URL's that aren't problematic when going through redirect flows (such as when they have a new sso session). Up to Kibana 7.16 the short URL API has just taken a simple payload that is the discover URL string:

{
  "url": "/app/kibana#/dashboard?_g=()&_a=(description:'',filters:!(),fullScreenMode:!f,options:(darkTheme:!f,hidePanelTitles:!f,useMargins:!t),panels:!((embeddableConfig:(),gridData:(h:15,i:'1',w:24,x:0,y:0),id:'8f4d0c00-4c86-11e8-b3d7-01146121b73d',panelIndex:'1',type:visualization,version:'7.0.0-alpha1')),query:(language:lucene,query:''),timeRestore:!f,title:'New%20Dashboard',viewMode:edit)"
}

This API appears to use some consistent hashing; on the initial request for a given URL that has not yet been generated the API will generate short URL. This request has some latency tied in with the refresh interval of the Kibana index. Subsequent identical requests return much master as they are just returned from the Kibana index. This makes the short URL API implementation in these Kibana versions idempotent, for a given url, the same urlID is always returned.

However, in 7.16.x the short URL API has changed significantly and it's now less clear how it is intended to be used.
Using the LEGACY_SHORT_URL_LOCATOR locator that exists (I'm not actually sure what the locator ID is for normal Discover to test that out) and accepts a similar input to the previous shorten url API (a URL for a discover query) you have the below payload:

{
    "locatorId": "LEGACY_SHORT_URL_LOCATOR",
    "params": {"url":"/app/discover#/?_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:now-1h,to:now))&_a=(columns:!(bytes),filters:!(('$state':(store:appState),meta:(alias:!n,disabled:!f,index:'90943e30-9a47-11e8-b64d-95841ca0b247',key:geo.src,negate:!f,params:(query:US),type:phrase),query:(match_phrase:(geo.src:US)))),index:'90943e30-9a47-11e8-b64d-95841ca0b247',interval:auto,query:(language:kuery,query:''),sort:!(!('@timestamp',desc)))"}
}

Making subsequent identical requests, a new goto ID is returned each and every time which feels inefficient, as these objects will likely build up in Kibana's index over time, and will presumably have extra latency while the link is generated.

If you opt to add a slug to the payload to give it a readable name as in the example below, this works too. However if you make a subsequent post request with the same payload, kibana returns a 500 internal server error:

{
    "locatorId": "LEGACY_SHORT_URL_LOCATOR",
    "params": {"url":"/app/discover#/?_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:now-1h,to:now))&_a=(columns:!(bytes),filters:!(('$state':(store:appState),meta:(alias:!n,disabled:!f,index:'90943e30-9a47-11e8-b64d-95841ca0b247',key:geo.src,negate:!f,params:(query:US),type:phrase),query:(match_phrase:(geo.src:US)))),index:'90943e30-9a47-11e8-b64d-95841ca0b247',interval:auto,query:(language:kuery,query:''),sort:!(!('@timestamp',desc)))"},
    "slug": "some-redirect"
}
app_1            | {"type":"error","@timestamp":"2022-02-18T15:05:43+00:00","tags":[],"pid":1,"level":"error","error":{"message":"Internal Server Error","name":"Error","stack":"Error: Internal Server Error\n    at HapiResponseAdapter.toInternalError (/usr/share/kibana/src/core/server/http/router/response_adapter.js:61:19)\n    at Router.handle (/usr/share/kibana/src/core/server/http/router/router.js:172:34)\n    at processTicksAndRejections (node:internal/process/task_queues:96:5)\n    at handler (/usr/share/kibana/src/core/server/http/router/router.js:124:50)\n    at exports.Manager.execute (/usr/share/kibana/node_modules/@hapi/hapi/lib/toolkit.js:60:28)\n    at Object.internals.handler (/usr/share/kibana/node_modules/@hapi/hapi/lib/handler.js:46:20)\n    at exports.execute (/usr/share/kibana/node_modules/@hapi/hapi/lib/handler.js:31:20)\n    at Request._lifecycle (/usr/share/kibana/node_modules/@hapi/hapi/lib/request.js:371:32)\n    at Request._execute (/usr/share/kibana/node_modules/@hapi/hapi/lib/request.js:281:9)"},"url":"http://127.0.0.1:5601/api/short_url","message":"Internal Server Error"}

It's unclear what the pattern should be here for dynamically generating and reusing short URL's in a programmatic fashion with the new short URL API.

Would you instead need to first:

  • Attempt to see if a slug already exists with GET api/short_url/_slug/some-redirect (Which also currently returns a 500 if it does not exist)
  • If not, create the short URL

This feels more cumbersome than the previous implementation so I'm wondering if there's a simpler way

Cheers,
Mike

Hi
This looks like there is room for improvement and also better error handling in the new implementation. Could you open an issue in our repository? Issues · elastic/kibana · GitHub then it could be forwarded and triaged by the right team.

Many thx!
Matthias

Thanks @matw

I raised this issue Short URL API Internal Server Error · Issue #126173 · elastic/kibana · GitHub yesterday afternoon specifically around the 500's, I wasn't sure if it was the right place to talk about potential improvements or not too.

One quick question, do you know what the Locator ID would be for the Discover app when using the short URL API and not using the legacy short URL locator?

Cheers

One quick question, do you know what the Locator ID would be for the Discover app when using the short URL API and not using the legacy short URL locator?

For Discover it is DISCOVER_APP_LOCATOR.

You can also find in DiscoverAppLocatorParams the list of parameters it supports, here.

1 Like

To address your core question. It seems for you problem it would be best to be able to redirect the user without creating a short URL, as short URL creates a url document in Elasticsearch, and it seems what you need is to simply redirect a user to the Discover app. For that, there is actually a redirect endpoint, which can redirect your user while preserving the Discover locator state.

You can use the locator redirect endpoint at /app/r?l=DISCOVER_APP_LOCATOR&v=7.16.0&p=.... In this example, in the p URL parameter you put the Discover locator params, serialized as JSON. You can see an example here.

I'd tried that with e.g. an empty params but I get the below:

POST /api/short_url

{
    "locatorId": "DISCOVER_APP_LOCATOR",
    "params": {}
}
{
    "statusCode": 409,
    "error": "Conflict",
    "message": "Locator not found."
}

This is on 7.16.3

This looks really promising, something I haven't come across before. I will have a play around with this and see if it works for our use case; on the surface it definitely looks like a better implementation than our current short URL generation

Thanks!

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.