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