Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Cloud] Extend metadata #189001

Merged
merged 5 commits into from
Jul 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/developer/plugin-list.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,7 @@ The plugin exposes the static DefaultEditorController class to consume.


|{kib-repo}blob/{branch}/x-pack/plugins/cloud/README.md[cloud]
|The cloud plugin adds Cloud-specific features to Kibana.
|The cloud plugin exposes Cloud-specific metadata to Kibana.


|{kib-repo}blob/{branch}/x-pack/plugins/cloud_integrations/cloud_chat/README.md[cloudChat]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ export default function ({ getService }: PluginFunctionalProviderContext) {
'xpack.cloud_integrations.full_story.eventTypesAllowlist (array)',
'xpack.cloud_integrations.full_story.pageVarsDebounceTime (duration)',
'xpack.cloud.id (string)',
'xpack.cloud.organization_id (string)',
'xpack.cloud.organization_url (string)',
'xpack.cloud.billing_url (string)',
'xpack.cloud.profile_url (string)',
Expand All @@ -256,6 +257,7 @@ export default function ({ getService }: PluginFunctionalProviderContext) {
'xpack.cloud.serverless.project_id (string)',
'xpack.cloud.serverless.project_name (string)',
'xpack.cloud.serverless.project_type (string)',
'xpack.cloud.serverless.orchestrator_target (string)',
'xpack.cloud.onboarding.default_solution (string)',
'xpack.discoverEnhanced.actions.exploreDataInChart.enabled (boolean)',
'xpack.discoverEnhanced.actions.exploreDataInContextMenu.enabled (boolean)',
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/cloud/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# `cloud` plugin

The `cloud` plugin adds Cloud-specific features to Kibana.
The `cloud` plugin exposes Cloud-specific metadata to Kibana.
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ import { parseDeploymentIdFromDeploymentUrl } from './parse_deployment_id_from_d

export interface CloudDeploymentMetadata {
id?: string;
organization_id?: string;
trial_end_date?: string;
is_elastic_staff_owned?: boolean;
deployment_url?: string;
serverless?: {
project_id?: string;
project_type?: string;
orchestrator_target?: string;
};
}

Expand All @@ -29,26 +31,40 @@ export function registerCloudDeploymentMetadataAnalyticsContext(
}
const {
id: cloudId,
organization_id: organizationId,
trial_end_date: cloudTrialEndDate,
is_elastic_staff_owned: cloudIsElasticStaffOwned,
serverless: { project_id: projectId, project_type: projectType } = {},
serverless: {
project_id: projectId,
project_type: projectType,
orchestrator_target: orchestratorTarget,
} = {},
} = cloudMetadata;

analytics.registerContextProvider({
name: 'Cloud Deployment Metadata',
context$: of({
cloudId,
organizationId,
deploymentId: parseDeploymentIdFromDeploymentUrl(cloudMetadata.deployment_url),
cloudTrialEndDate,
cloudIsElasticStaffOwned,
projectId,
projectType,
orchestratorTarget,
}),
schema: {
cloudId: {
type: 'keyword',
_meta: { description: 'The Cloud ID' },
},
organizationId: {
type: 'keyword',
_meta: {
description: 'The Elastic Cloud Organization ID that owns the deployment/project',
optional: true,
},
},
deploymentId: {
type: 'keyword',
_meta: { description: 'The Deployment ID', optional: true },
Expand All @@ -72,6 +88,13 @@ export function registerCloudDeploymentMetadataAnalyticsContext(
type: 'keyword',
_meta: { description: 'The Serverless Project type', optional: true },
},
orchestratorTarget: {
type: 'keyword',
_meta: {
description: 'The Orchestrator Target where it is deployed (canary/non-canary)',
optional: true,
},
},
},
});
}
4 changes: 4 additions & 0 deletions x-pack/plugins/cloud/public/plugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { getSupportUrl } from './utils';

export interface CloudConfigType {
id?: string;
organization_id?: string;
cname?: string;
base_url?: string;
profile_url?: string;
Expand All @@ -40,6 +41,7 @@ export interface CloudConfigType {
project_id: string;
project_name?: string;
project_type?: string;
orchestrator_target?: string;
};
}

Expand Down Expand Up @@ -89,6 +91,7 @@ export class CloudPlugin implements Plugin<CloudSetup> {

return {
cloudId: id,
organizationId: this.config.organization_id,
deploymentId: parseDeploymentIdFromDeploymentUrl(this.config.deployment_url),
cname,
baseUrl,
Expand All @@ -108,6 +111,7 @@ export class CloudPlugin implements Plugin<CloudSetup> {
projectId: this.config.serverless?.project_id,
projectName: this.config.serverless?.project_name,
projectType: this.config.serverless?.project_type,
orchestratorTarget: this.config.serverless?.orchestrator_target,
},
registerCloudService: (contextProvider) => {
this.contextProviders.push(contextProvider);
Expand Down
9 changes: 9 additions & 0 deletions x-pack/plugins/cloud/public/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ export interface CloudSetup {
* Cloud ID. Undefined if not running on Cloud.
*/
cloudId?: string;
/**
* The Elastic Cloud Organization that owns this deployment/project.
*/
organizationId?: string;
/**
* The deployment's ID. Only available when running on Elastic Cloud.
*/
Expand Down Expand Up @@ -208,5 +212,10 @@ export interface CloudSetup {
* Will always be present if `isServerlessEnabled` is `true`
*/
projectType?: string;
/**
* The serverless orchestrator target. The potential values are `canary` or `non-canary`
* Will always be present if `isServerlessEnabled` is `true`
*/
orchestratorTarget?: string;
};
}
2 changes: 2 additions & 0 deletions x-pack/plugins/cloud/server/__snapshots__/plugin.test.ts.snap

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,12 @@ describe('createCloudUsageCollector', () => {
expect(await collector.fetch(collectorFetchContext)).toStrictEqual({
isCloudEnabled: true,
isElasticStaffOwned: undefined,
organizationId: undefined,
trialEndDate: undefined,
deploymentId: undefined,
projectId: undefined,
projectType: undefined,
orchestratorTarget: undefined,
});
});

Expand All @@ -54,11 +56,13 @@ describe('createCloudUsageCollector', () => {
expect(await collector.fetch(collectorFetchContext)).toStrictEqual({
isCloudEnabled: true,
isElasticStaffOwned: undefined,
organizationId: undefined,
trialEndDate: '2020-10-01T14:30:16Z',
inTrial: false,
deploymentId: undefined,
projectId: undefined,
projectType: undefined,
orchestratorTarget: undefined,
});
});

Expand All @@ -67,19 +71,23 @@ describe('createCloudUsageCollector', () => {
isCloudEnabled: true,
trialEndDate: '2020-10-01T14:30:16Z',
isElasticStaffOwned: true,
organizationId: '1234',
deploymentId: 'a-deployment-id',
projectId: 'a-project-id',
projectType: 'security',
orchestratorTarget: 'canary',
});

expect(await collector.fetch(collectorFetchContext)).toStrictEqual({
isCloudEnabled: true,
trialEndDate: '2020-10-01T14:30:16Z',
inTrial: false,
isElasticStaffOwned: true,
organizationId: '1234',
deploymentId: 'a-deployment-id',
projectId: 'a-project-id',
projectType: 'security',
orchestratorTarget: 'canary',
});
});
});
Expand Down
35 changes: 31 additions & 4 deletions x-pack/plugins/cloud/server/collectors/cloud_usage_collector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,23 @@ export interface CloudUsageCollectorConfig {
// Using * | undefined instead of ?: to force the calling code to list all the options (even when they can be undefined)
trialEndDate: string | undefined;
isElasticStaffOwned: boolean | undefined;
organizationId: string | undefined;
deploymentId: string | undefined;
projectId: string | undefined;
projectType: string | undefined;
orchestratorTarget: string | undefined;
}

interface CloudUsage {
isCloudEnabled: boolean;
trialEndDate?: string;
inTrial?: boolean;
isElasticStaffOwned?: boolean;
organizationId?: string;
deploymentId?: string;
projectId?: string;
projectType?: string;
orchestratorTarget?: string;
}

export function createCloudUsageCollector(
Expand All @@ -35,19 +39,36 @@ export function createCloudUsageCollector(
isCloudEnabled,
trialEndDate,
isElasticStaffOwned,
organizationId,
deploymentId,
projectId,
projectType,
orchestratorTarget,
} = config;
const trialEndDateMs = trialEndDate ? new Date(trialEndDate).getTime() : undefined;
return usageCollection.makeUsageCollector<CloudUsage>({
type: 'cloud',
isReady: () => true,
schema: {
isCloudEnabled: { type: 'boolean' },
trialEndDate: { type: 'date' },
inTrial: { type: 'boolean' },
isElasticStaffOwned: { type: 'boolean' },
isCloudEnabled: {
type: 'boolean',
_meta: { description: 'Is the deployment running in Elastic Cloud (ESS or Serverless)?' },
},
trialEndDate: { type: 'date', _meta: { description: 'End of the trial period' } },
inTrial: {
type: 'boolean',
_meta: { description: 'Is the organization during the trial period?' },
},
isElasticStaffOwned: {
type: 'boolean',
_meta: { description: 'Is the deploymend owned by an Elastician' },
},
organizationId: {
type: 'keyword',
_meta: {
description: 'The Elastic Cloud Organization ID that owns the deployment/project',
},
},
deploymentId: {
type: 'keyword',
_meta: { description: 'The ESS Deployment ID' },
Expand All @@ -60,16 +81,22 @@ export function createCloudUsageCollector(
type: 'keyword',
_meta: { description: 'The Serverless Project type' },
},
orchestratorTarget: {
type: 'keyword',
_meta: { description: 'The Orchestrator Target where it is deployed (canary/non-canary)' },
},
},
fetch: () => {
return {
isCloudEnabled,
isElasticStaffOwned,
organizationId,
trialEndDate,
...(trialEndDateMs ? { inTrial: Date.now() <= trialEndDateMs } : {}),
deploymentId,
projectId,
projectType,
orchestratorTarget,
};
},
});
Expand Down
4 changes: 4 additions & 0 deletions x-pack/plugins/cloud/server/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const configSchema = schema.object({
deployments_url: schema.string({ defaultValue: '/deployments' }),
deployment_url: schema.maybe(schema.string()),
id: schema.maybe(schema.string()),
organization_id: schema.maybe(schema.string()),
billing_url: schema.maybe(schema.string()),
performance_url: schema.maybe(schema.string()),
users_and_roles_url: schema.maybe(schema.string()),
Expand All @@ -44,6 +45,7 @@ const configSchema = schema.object({
project_id: schema.maybe(schema.string()),
project_name: schema.maybe(schema.string()),
project_type: schema.maybe(schema.string()),
orchestrator_target: schema.maybe(schema.string()),
},
// avoid future chicken-and-egg situation with the component populating the config
{ unknowns: 'ignore' }
Expand All @@ -60,6 +62,7 @@ export const config: PluginConfigDescriptor<CloudConfigType> = {
deployments_url: true,
deployment_url: true,
id: true,
organization_id: true,
billing_url: true,
users_and_roles_url: true,
performance_url: true,
Expand All @@ -72,6 +75,7 @@ export const config: PluginConfigDescriptor<CloudConfigType> = {
project_id: true,
project_name: true,
project_type: true,
orchestrator_target: true,
},
onboarding: {
default_solution: true,
Expand Down
Loading