diff --git a/docs/api/spaces-management.asciidoc b/docs/api/spaces-management.asciidoc index 2e3b9abec9120..333a06cf3754e 100644 --- a/docs/api/spaces-management.asciidoc +++ b/docs/api/spaces-management.asciidoc @@ -20,6 +20,8 @@ The following {kib} spaces APIs are available: * <> to overwrite saved objects returned as errors from the copy saved objects to space API +* <> to disable legacy URL aliases if an error is encountered + include::spaces-management/post.asciidoc[] include::spaces-management/put.asciidoc[] include::spaces-management/get.asciidoc[] @@ -27,3 +29,4 @@ include::spaces-management/get_all.asciidoc[] include::spaces-management/delete.asciidoc[] include::spaces-management/copy_saved_objects.asciidoc[] include::spaces-management/resolve_copy_saved_objects_conflicts.asciidoc[] +include::spaces-management/disable_legacy_url_aliases.asciidoc[] diff --git a/docs/api/spaces-management/disable_legacy_url_aliases.asciidoc b/docs/api/spaces-management/disable_legacy_url_aliases.asciidoc new file mode 100644 index 0000000000000..3f713d9d0c25e --- /dev/null +++ b/docs/api/spaces-management/disable_legacy_url_aliases.asciidoc @@ -0,0 +1,59 @@ +[[spaces-api-disable-legacy-url-aliases]] +=== Disable legacy URL aliases API +++++ +Disable legacy URL aliases +++++ + +experimental[] Disable a <> in {kib}. + +[[spaces-api-disable-legacy-url-aliases-request]] +==== {api-request-title} + +`POST :/api/spaces/_disable_legacy_url_aliases` + +[role="child_attributes"] +[[spaces-api-disable-legacy-url-aliases-request-body]] +==== {api-request-body-title} + +`aliases`:: + (Required, object array) The aliases to disable. ++ +.Properties of `aliases` +[%collapsible%open] +===== + `targetSpace`::: + (Required, string) The space where the alias target object exists. + + `targetType`::: + (Required, string) The type of the alias target object. + + `sourceId`::: + (Required, string) The ID of the alias source object. This is the "legacy" object ID. +===== + +[[spaces-api-disable-legacy-url-aliases-response-codes]] +==== {api-response-codes-title} + +`204`:: + Indicates a successful call. + +[[spaces-api-disable-legacy-url-aliases-example]] +==== {api-examples-title} + +[source,sh] +-------------------------------------------------- +$ curl -X POST api/spaces/_disable_legacy_url_aliases +{ + "aliases": [ + { + "targetSpace": "bills-space", + "targetType": "dashboard", + "sourceId": "123" + } + ] +} +-------------------------------------------------- +// KIBANA + +This example leaves the alias intact, but the legacy URL for this alias, http://localhost:5601/s/bills-space/app/dashboards#/view/123, will +no longer function. The dashboard still exists, and you can access it with the new URL. \ No newline at end of file diff --git a/docs/developer/advanced/index.asciidoc b/docs/developer/advanced/index.asciidoc index 289b88cddd7a9..27072d85b6507 100644 --- a/docs/developer/advanced/index.asciidoc +++ b/docs/developer/advanced/index.asciidoc @@ -6,6 +6,7 @@ * <> * <> * <> +* <> include::development-es-snapshots.asciidoc[leveloffset=+1] @@ -15,4 +16,6 @@ include::development-basepath.asciidoc[leveloffset=+1] include::upgrading-nodejs.asciidoc[leveloffset=+1] -include::sharing-saved-objects.asciidoc[leveloffset=+1] \ No newline at end of file +include::sharing-saved-objects.asciidoc[leveloffset=+1] + +include::legacy-url-aliases.asciidoc[leveloffset=+1] \ No newline at end of file diff --git a/docs/developer/advanced/legacy-url-aliases.asciidoc b/docs/developer/advanced/legacy-url-aliases.asciidoc new file mode 100644 index 0000000000000..3e441dd582123 --- /dev/null +++ b/docs/developer/advanced/legacy-url-aliases.asciidoc @@ -0,0 +1,45 @@ +[[legacy-url-aliases]] +== Legacy URL Aliases + +This page describes legacy URL aliases: what they are, where they come from, and how to disable them. + +[[legacy-url-aliases-overview]] +=== Overview + +Many saved object types were converted in {kib} 8.0, so they can eventually be shared across <>. Before 8.0, you could +have two objects with the same type and same ID in two different spaces. Part of this conversion is to make sure all object IDs of a given +type are *globally unique across all spaces*. + +{kib} creates a special entity called a **legacy URL alias** for each saved object that requires a new ID. This legacy URL alias allows +{kib} to preserve any deep link URLs that exist for these objects. + +[[legacy-url-aliases-example]] +=== Example + +Consider the following scenario: + +You have {kib} 7.16, and you create a new dashboard.The ID of this dashboard is "123". You create a new space called "Bill's space" and +<> your dashboard to the other space. Now you have two different dashboards that can be accessed +at the following URLs: + +* *Default space*: `http://localhost:5601/app/dashboards#/view/123` +* *Bill's space*: `http://localhost:5601/s/bills-space/app/dashboards#/view/123` + +You use these two dashboards frequently, so you bookmark them in your web browser. After some time, you decide to upgrade to {kib} 8.0. When +these two dashboards go through the conversion process, the one in "Bill's space" will have its ID changed to "456". The URL to access that +dashboard is different -- not to worry though, there is a legacy URL alias for that dashboard. + +If you use your bookmark to access that dashboard using its old URL, {kib} detects that you are using a legacy URL, and finds the new object +ID. If you navigate to `http://localhost:5601/s/bills-space/app/dashboards#/view/123`, you'll see a message indicating that the dashboard +has a new URL, and you're automatically redirected to `http://localhost:5601/s/bills-space/app/dashboards#/view/456`. + +[[legacy-url-aliases-handling-errors]] +=== Handling errors + +Legacy URL aliases are intended to be fully transparent, but there are rare situations where this can lead to an error. For example, you +might have a dashboard and one of the visualizations fails to load, directing you to this page. If you encounter an error in this situation, +you might want to disable the legacy URL alias completely. This leaves the saved object intact, and you will not lose any data -- you just +won't be able to use the old URL to access that saved object. + +To disable a legacy URL alias, you need three pieces of information: the `targetSpace`, the `targetType`, and the `sourceId`. Then use the +<> API to disable the problematic legacy URL alias. diff --git a/x-pack/plugins/apm/public/components/app/service_logs/index.test.ts b/x-pack/plugins/apm/public/components/app/service_logs/index.test.ts new file mode 100644 index 0000000000000..b0cc134778d21 --- /dev/null +++ b/x-pack/plugins/apm/public/components/app/service_logs/index.test.ts @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { getInfrastructureKQLFilter } from './'; + +describe('service logs', () => { + describe('getInfrastructureKQLFilter', () => { + it('filter by container id', () => { + expect( + getInfrastructureKQLFilter({ + serviceInfrastructure: { + containerIds: ['foo', 'bar'], + hostNames: ['baz', `quz`], + }, + }) + ).toEqual('container.id: "foo" or container.id: "bar"'); + }); + it('filter by host names', () => { + expect( + getInfrastructureKQLFilter({ + serviceInfrastructure: { + containerIds: [], + hostNames: ['baz', `quz`], + }, + }) + ).toEqual('host.name: "baz" or host.name: "quz"'); + }); + }); +}); diff --git a/x-pack/plugins/apm/public/components/app/service_logs/index.tsx b/x-pack/plugins/apm/public/components/app/service_logs/index.tsx index e8ac370368365..ac4a4fb51ce8a 100644 --- a/x-pack/plugins/apm/public/components/app/service_logs/index.tsx +++ b/x-pack/plugins/apm/public/components/app/service_logs/index.tsx @@ -18,7 +18,6 @@ import { APIReturnType } from '../../../services/rest/createCallApmApi'; import { CONTAINER_ID, HOSTNAME, - POD_NAME, } from '../../../../common/elasticsearch_fieldnames'; import { useApmParams } from '../../../hooks/use_apm_params'; import { useTimeRange } from '../../../hooks/use_time_range'; @@ -55,8 +54,7 @@ export function ServiceLogs() { const noInfrastructureData = useMemo(() => { return ( isEmpty(data?.serviceInfrastructure?.containerIds) && - isEmpty(data?.serviceInfrastructure?.hostNames) && - isEmpty(data?.serviceInfrastructure?.podNames) + isEmpty(data?.serviceInfrastructure?.hostNames) ); }, [data]); @@ -93,16 +91,15 @@ export function ServiceLogs() { ); } -const getInfrastructureKQLFilter = ( +export const getInfrastructureKQLFilter = ( data?: APIReturnType<'GET /api/apm/services/{serviceName}/infrastructure'> ) => { const containerIds = data?.serviceInfrastructure?.containerIds ?? []; const hostNames = data?.serviceInfrastructure?.hostNames ?? []; - const podNames = data?.serviceInfrastructure?.podNames ?? []; - return [ - ...containerIds.map((id) => `${CONTAINER_ID}: "${id}"`), - ...hostNames.map((id) => `${HOSTNAME}: "${id}"`), - ...podNames.map((id) => `${POD_NAME}: "${id}"`), - ].join(' or '); + const kqlFilter = containerIds.length + ? containerIds.map((id) => `${CONTAINER_ID}: "${id}"`) + : hostNames.map((id) => `${HOSTNAME}: "${id}"`); + + return kqlFilter.join(' or '); }; diff --git a/x-pack/plugins/apm/server/lib/services/get_service_infrastructure.ts b/x-pack/plugins/apm/server/lib/services/get_service_infrastructure.ts index b6621d590b17d..90be97d9497b2 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_infrastructure.ts +++ b/x-pack/plugins/apm/server/lib/services/get_service_infrastructure.ts @@ -14,7 +14,6 @@ import { SERVICE_NAME, CONTAINER_ID, HOSTNAME, - POD_NAME, } from '../../../common/elasticsearch_fieldnames'; export const getServiceInfrastructure = async ({ @@ -61,12 +60,6 @@ export const getServiceInfrastructure = async ({ size: 500, }, }, - podNames: { - terms: { - field: POD_NAME, - size: 500, - }, - }, }, }, }); @@ -74,13 +67,11 @@ export const getServiceInfrastructure = async ({ return { containerIds: response.aggregations?.containerIds?.buckets.map( - (bucket) => bucket.key + (bucket) => bucket.key as string ) ?? [], hostNames: - response.aggregations?.hostNames?.buckets.map((bucket) => bucket.key) ?? - [], - podNames: - response.aggregations?.podNames?.buckets.map((bucket) => bucket.key) ?? - [], + response.aggregations?.hostNames?.buckets.map( + (bucket) => bucket.key as string + ) ?? [], }; };