[APM UI] Add dynamic version selection for Java agent integration (#134461)

* Add dynamic version selection for Java agent integration (Auto-Attachment)

* Introduce a new placeholder translation for java agent select input

* * Add latest option to the select input
* Fix an issue on the validation

* refactoring

* typo

* adding tests

* fixing bug

* addressing PR comments

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: cauemarcondes <caue.marcondes@elastic.co>
Co-authored-by: Cauê Marcondes <55978943+cauemarcondes@users.noreply.github.com>
This commit is contained in:
Younes meliani 2022-07-06 20:20:51 +02:00 committed by GitHub
parent ad5baf46a3
commit a764233a53
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 318 additions and 117 deletions

View file

@ -52,7 +52,7 @@ export interface Operation {
types: Option[];
}
const versionRegex = new RegExp(/^\d+\.\d+\.\d+$/);
const versionRegex = new RegExp(/latest|^\d+\.\d+\.\d+(\.\w+)?$/);
export function validateVersion(version: RuntimeAttachmentSettings['version']) {
if (version) {
return versionRegex.test(version);

View file

@ -0,0 +1,115 @@
/*
* 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 React, { useEffect } from 'react';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import { EuiFlexItem, EuiFormRow, EuiLink, EuiComboBox } from '@elastic/eui';
import { useKibana } from '@kbn/kibana-react-plugin/public';
import { CoreStart } from '@kbn/core/public';
import { createCallApmApi } from '../../../../services/rest/create_call_apm_api';
import { FETCH_STATUS, useFetcher } from '../../../../hooks/use_fetcher';
import { RuntimeAttachmentSettings } from '.';
interface Props {
isValid: boolean;
version: string | null;
onChange: (nextVersion: RuntimeAttachmentSettings['version']) => void;
}
export function JavaAgentVersionInput({ isValid, version, onChange }: Props) {
const { services } = useKibana();
useEffect(() => {
createCallApmApi(services as CoreStart);
}, [services]);
const { data, status } = useFetcher((callApmApi) => {
return callApmApi('GET /internal/apm/fleet/java_agent_versions');
}, []);
useEffect(() => {
// When version is not available on the fleet package sets it to "latest"
if (version === null) {
// This is necessary due to a possible bug in Fleet where even thought the form is valid
// the save button is still disabled: https://github.com/elastic/kibana/issues/135131
setTimeout(() => {
onChange('latest');
}, 1);
}
}, [version, onChange]);
const isLoading = status === FETCH_STATUS.LOADING;
const agentJavaVersions =
!isLoading && data?.versions
? data.versions.map((label) => ({ label }))
: [];
const hasOptions = !!agentJavaVersions.length;
const selectedOption = [{ label: version || '' }];
const comboProps = !hasOptions
? {
// Leaving the onCreateOption out disables custom option
// so only enables it when no options was returned from the API
onCreateOption: (nextVersion: string) => {
onChange(nextVersion);
},
}
: {};
return (
<EuiFlexItem>
<EuiFormRow
label={i18n.translate(
'xpack.apm.fleetIntegration.apmAgent.runtimeAttachment.version',
{ defaultMessage: 'Version' }
)}
isInvalid={!isValid}
error={i18n.translate(
'xpack.apm.fleetIntegration.apmAgent.runtimeAttachment.version.invalid',
{ defaultMessage: 'Invalid version' }
)}
helpText={
<FormattedMessage
id="xpack.apm.fleetIntegration.apmAgent.runtimeAttachment.version.helpText"
defaultMessage="Enter the {versionLink} of the Elastic APM Java agent that should be attached."
values={{
versionLink: (
<EuiLink
href={`${services.docLinks?.ELASTIC_WEBSITE_URL}/guide/en/apm/agent/java/current/release-notes.html`}
target="_blank"
>
{i18n.translate(
'xpack.apm.fleetIntegration.apmAgent.runtimeAttachment.version.helpText.version',
{ defaultMessage: 'version' }
)}
</EuiLink>
),
}}
/>
}
>
<EuiComboBox
placeholder={i18n.translate(
'xpack.apm.fleetIntegration.apmAgent.runtimeAttachment.versionSelect.placeHolder',
{ defaultMessage: 'Select a version' }
)}
singleSelection={{ asPlainText: true }}
isLoading={isLoading}
noSuggestions={!hasOptions}
isClearable={!hasOptions}
options={agentJavaVersions}
selectedOptions={selectedOption}
onChange={(selectedOptions) => {
const nextVersion = selectedOptions[0]?.label;
onChange(nextVersion || '');
}}
{...comboProps}
/>
</EuiFormRow>
</EuiFlexItem>
);
}

View file

@ -7,18 +7,38 @@
import { Meta, Story } from '@storybook/react';
import React, { useState } from 'react';
import { CoreStart } from '@kbn/core/public';
import { createKibanaReactContext } from '@kbn/kibana-react-plugin/public';
import { RuntimeAttachment } from '.';
import { JavaRuntimeAttachment } from './supported_agents/java_runtime_attachment';
import { createCallApmApi } from '../../../../services/rest/create_call_apm_api';
const coreMock = {
http: {
get: async () => ({
versions: ['1.1.0', '1.1.2', '2.0.1'],
latest: '2.0.1',
}),
},
notifications: { toasts: { add: () => {} } },
uiSettings: { get: () => {} },
} as unknown as CoreStart;
const KibanaReactContext = createKibanaReactContext(coreMock);
const stories: Meta<{}> = {
title: 'fleet/Runtime agent attachment',
component: RuntimeAttachment,
decorators: [
(StoryComponent) => {
createCallApmApi(coreMock);
return (
<div style={{ width: 700 }}>
<StoryComponent />
</div>
<KibanaReactContext.Provider>
<div style={{ width: 700 }}>
<StoryComponent />
</div>
</KibanaReactContext.Provider>
);
},
],

View file

@ -18,19 +18,14 @@ import {
EuiDraggable,
EuiIcon,
DropResult,
EuiFormRow,
EuiFieldText,
EuiLink,
} from '@elastic/eui';
import React, { ReactNode } from 'react';
import { i18n } from '@kbn/i18n';
import { isEmpty } from 'lodash';
import { FormattedMessage } from '@kbn/i18n-react';
import { useKibana } from '@kbn/kibana-react-plugin/public';
import { DiscoveryRule } from './discovery_rule';
import { DefaultDiscoveryRule } from './default_discovery_rule';
import { EditDiscoveryRule } from './edit_discovery_rule';
import { IDiscoveryRuleList, Operation, RuntimeAttachmentSettings } from '.';
import { JavaAgentVersionInput } from './java_agent_version_input';
interface Props {
isEnabled: boolean;
@ -85,9 +80,6 @@ export function RuntimeAttachment({
onChangeVersion,
isValidVersion,
}: Props) {
const {
services: { docLinks },
} = useKibana();
return (
<div>
{showUnsavedWarning && (
@ -123,50 +115,11 @@ export function RuntimeAttachment({
</EuiText>
</EuiFlexItem>
{isEnabled && (
<EuiFlexItem>
<EuiFormRow
label={i18n.translate(
'xpack.apm.fleetIntegration.apmAgent.runtimeAttachment.version',
{ defaultMessage: 'Version' }
)}
isInvalid={!isValidVersion}
error={i18n.translate(
'xpack.apm.fleetIntegration.apmAgent.runtimeAttachment.version.invalid',
{ defaultMessage: 'Invalid version' }
)}
helpText={
<FormattedMessage
id="xpack.apm.fleetIntegration.apmAgent.runtimeAttachment.version.helpText"
defaultMessage="Enter the {versionLink} of the Elastic APM Java agent that should be attached."
values={{
versionLink: (
<EuiLink
href={`${docLinks?.ELASTIC_WEBSITE_URL}/guide/en/apm/agent/java/current/release-notes.html`}
target="_blank"
>
{i18n.translate(
'xpack.apm.fleetIntegration.apmAgent.runtimeAttachment.version.helpText.version',
{ defaultMessage: 'version' }
)}
</EuiLink>
),
}}
/>
}
>
<EuiFieldText
value={version || ''}
onChange={(e) => {
const nextVersion = e.target.value;
onChangeVersion(isEmpty(nextVersion) ? null : nextVersion);
}}
placeholder={i18n.translate(
'xpack.apm.fleetIntegration.apmAgent.runtimeAttachment.version.placeHolder',
{ defaultMessage: 'Add a version' }
)}
/>
</EuiFormRow>
</EuiFlexItem>
<JavaAgentVersionInput
version={version}
onChange={onChangeVersion}
isValid={isValidVersion}
/>
)}
</EuiFlexGroup>
{isEnabled && (

View file

@ -0,0 +1,24 @@
/*
* 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 { validateVersion } from '.';
describe('validateVersion', () => {
describe('invalid versions', () => {
['foo', '123', '1.x.2', 'last', '#', '', '1.2', null].map((invalidInput) =>
it(`${invalidInput}: is an invalid version`, () => {
expect(validateVersion(invalidInput)).toBeFalsy();
})
);
});
describe('valid versions', () => {
['1.234.5', '1.2.3', '0.0.0', 'latest'].map((validVersion) =>
it(`${validVersion}: is a valid version`, () => {
expect(validateVersion(validVersion)).toBeTruthy();
})
);
});
});

View file

@ -0,0 +1,53 @@
/*
* 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.
*/
jest.mock('node-fetch');
import fetch from 'node-fetch';
const { Response } = jest.requireActual('node-fetch');
import { getJavaAgentVersionsFromRegistry } from './get_java_agent_versions';
const javaVersionsXML = `<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<groupId>co.elastic.apm</groupId>
<artifactId>elastic-apm-agent</artifactId>
<versioning>
<latest>1.32.0</latest>
<release>1.32.0</release>
<versions>
<version>1.30.1</version>
<version>1.31.0</version>
<version>1.32.0</version>
</versions>
<lastUpdated>20220613135218</lastUpdated>
</versioning>
</metadata>
`;
describe('getJavaAgentVersionsFromRegistry', () => {
const mockFetch = fetch as jest.MockedFunction<typeof fetch>;
describe('With valid API return type', () => {
it('returns latest as first option', async () => {
mockFetch.mockReturnValue(new Response(javaVersionsXML));
const versions = await getJavaAgentVersionsFromRegistry();
expect(versions?.[0]).toEqual('latest');
});
it('returns versions in descending order', async () => {
mockFetch.mockReturnValue(new Response(javaVersionsXML));
const versions = await getJavaAgentVersionsFromRegistry();
expect(versions).toEqual(['latest', '1.32.0', '1.31.0', '1.30.1']);
});
});
describe('With invalid API return type', () => {
it('returns versions in descending order', async () => {
mockFetch.mockReturnValue(new Response(`404`));
const versions = await getJavaAgentVersionsFromRegistry();
expect(versions).toBeUndefined();
});
});
});

View file

@ -0,0 +1,26 @@
/*
* 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 fetch from 'node-fetch';
const mavenJavaAgentUrl =
'https://repo1.maven.org/maven2/co/elastic/apm/elastic-apm-agent/maven-metadata.xml';
const versionRegex = /<version>(\d+\.\d+\.\d+.*?)<\/version>/gm;
export async function getJavaAgentVersionsFromRegistry() {
const response = await (await fetch(mavenJavaAgentUrl)).text();
const matchedVersions = [...response.matchAll(versionRegex)];
if (!matchedVersions.length) {
return undefined;
}
return matchedVersions
.map((aMatch) => aMatch[1])
.concat(['latest'])
.reverse();
}

View file

@ -26,6 +26,7 @@ import { getInternalSavedObjectsClient } from '../../lib/helpers/get_internal_sa
import { setupRequest } from '../../lib/helpers/setup_request';
import { createApmServerRoute } from '../apm_routes/create_apm_server_route';
import { getLatestApmPackage } from './get_latest_apm_package';
import { getJavaAgentVersionsFromRegistry } from './get_java_agent_versions';
const hasFleetDataRoute = createApmServerRoute({
endpoint: 'GET /internal/apm/fleet/has_apm_policies',
@ -260,6 +261,17 @@ const createCloudApmPackagePolicyRoute = createApmServerRoute({
},
});
const javaAgentVersions = createApmServerRoute({
endpoint: 'GET /internal/apm/fleet/java_agent_versions',
options: { tags: [] },
handler: async (): Promise<{ versions: string[] | undefined }> => {
const versions = await getJavaAgentVersionsFromRegistry();
return {
versions,
};
},
});
export const apmFleetRouteRepository = {
...hasFleetDataRoute,
...fleetAgentsRoute,
@ -267,6 +279,7 @@ export const apmFleetRouteRepository = {
...getUnsupportedApmServerSchemaRoute,
...getMigrationCheckRoute,
...createCloudApmPackagePolicyRoute,
...javaAgentVersions,
};
const FLEET_SECURITY_REQUIRED_MESSAGE = i18n.translate(

View file

@ -3900,25 +3900,6 @@
"home.sampleData.logsSpec.webTrafficTitle": "[Logs] Trafic Internet",
"home.sampleData.logsSpecDescription": "Exemple de données, de visualisations et de tableaux de bord pour le monitoring des logs Internet.",
"home.sampleData.logsSpecTitle": "Exemple de logs Internet",
"homePackages.sampleDataSet.installedLabel": "{name} installé",
"homePackages.sampleDataSet.unableToInstallErrorMessage": "Impossible d'installer l'exemple densemble de données : {name}.",
"homePackages.sampleDataSet.unableToLoadListErrorMessage": "Impossible de charger la liste des exemples densemble de données",
"homePackages.sampleDataSet.unableToUninstallErrorMessage": "Impossible de désinstaller l'exemple densemble de données : {name}.",
"homePackages.sampleDataSet.uninstalledLabel": "{name} désinstallé",
"homePackages.sampleDataCard.addButtonAriaLabel": "Ajouter {datasetName}",
"homePackages.sampleDataCard.addButtonLabel": "Ajouter des données",
"homePackages.sampleDataCard.addingButtonAriaLabel": "Ajout de {datasetName}",
"homePackages.sampleDataCard.addingButtonLabel": "Ajout",
"homePackages.sampleDataCard.dashboardLinkLabel": "Tableau de bord",
"homePackages.sampleDataCard.default.addButtonAriaLabel": "Ajouter {datasetName}",
"homePackages.sampleDataCard.default.addButtonLabel": "Ajouter des données",
"homePackages.sampleDataCard.default.unableToVerifyErrorMessage": "Impossible de vérifier le statut de l'ensemble de données. Erreur : {statusMsg}.",
"homePackages.sampleDataCard.removeButtonAriaLabel": "Supprimer {datasetName}",
"homePackages.sampleDataCard.removeButtonLabel": "Supprimer",
"homePackages.sampleDataCard.removingButtonAriaLabel": "Suppression de {datasetName}",
"homePackages.sampleDataCard.removingButtonLabel": "Suppression",
"homePackages.sampleDataCard.viewDataButtonAriaLabel": "Consulter {datasetName}",
"homePackages.sampleDataCard.viewDataButtonLabel": "Consulter les données",
"home.solutionsSection.sectionTitle": "Choisir votre solution",
"home.tryButtonLabel": "Ajouter des intégrations",
"home.tutorial.addDataToKibanaDescription": "En plus d'ajouter {integrationsLink}, vous pouvez essayer l'exemple de données ou charger vos propres données.",
@ -4667,6 +4648,25 @@
"home.tutorials.zscalerLogs.nameTitle": "Logs Zscaler",
"home.tutorials.zscalerLogs.shortDescription": "Collectez et analysez les logs à partir de Zscaler NSS avec Filebeat.",
"home.welcomeTitle": "Bienvenue dans Elastic",
"homePackages.sampleDataSet.installedLabel": "{name} installé",
"homePackages.sampleDataSet.unableToInstallErrorMessage": "Impossible d'installer l'exemple densemble de données : {name}.",
"homePackages.sampleDataSet.unableToLoadListErrorMessage": "Impossible de charger la liste des exemples densemble de données",
"homePackages.sampleDataSet.unableToUninstallErrorMessage": "Impossible de désinstaller l'exemple densemble de données : {name}.",
"homePackages.sampleDataSet.uninstalledLabel": "{name} désinstallé",
"homePackages.sampleDataCard.addButtonAriaLabel": "Ajouter {datasetName}",
"homePackages.sampleDataCard.addButtonLabel": "Ajouter des données",
"homePackages.sampleDataCard.addingButtonAriaLabel": "Ajout de {datasetName}",
"homePackages.sampleDataCard.addingButtonLabel": "Ajout",
"homePackages.sampleDataCard.dashboardLinkLabel": "Tableau de bord",
"homePackages.sampleDataCard.default.addButtonAriaLabel": "Ajouter {datasetName}",
"homePackages.sampleDataCard.default.addButtonLabel": "Ajouter des données",
"homePackages.sampleDataCard.default.unableToVerifyErrorMessage": "Impossible de vérifier le statut de l'ensemble de données. Erreur : {statusMsg}.",
"homePackages.sampleDataCard.removeButtonAriaLabel": "Supprimer {datasetName}",
"homePackages.sampleDataCard.removeButtonLabel": "Supprimer",
"homePackages.sampleDataCard.removingButtonAriaLabel": "Suppression de {datasetName}",
"homePackages.sampleDataCard.removingButtonLabel": "Suppression",
"homePackages.sampleDataCard.viewDataButtonAriaLabel": "Consulter {datasetName}",
"homePackages.sampleDataCard.viewDataButtonLabel": "Consulter les données",
"indexPatternEditor.aliasLabel": "Alias",
"indexPatternEditor.createIndex.noMatch": "Le nom doit correspondre à au moins un flux de données, index ou alias d'index.",
"indexPatternEditor.createIndexPattern.stepTime.noTimeFieldOptionLabel": "--- Je ne souhaite pas utiliser le filtre temporel ---",
@ -7835,7 +7835,6 @@
"xpack.apm.fleetIntegration.apmAgent.runtimeAttachment.version.helpText": "Entrez la {versionLink} de l'agent Java Elastic APM qui doit être attachée.",
"xpack.apm.fleetIntegration.apmAgent.runtimeAttachment.version.helpText.version": "version",
"xpack.apm.fleetIntegration.apmAgent.runtimeAttachment.version.invalid": "Version non valide",
"xpack.apm.fleetIntegration.apmAgent.runtimeAttachment.version.placeHolder": "Ajouter une version",
"xpack.apm.fleetIntegration.assets.description": "Consulter les traces de l'application et les cartes de service dans APM",
"xpack.apm.fleetIntegration.assets.name": "Services",
"xpack.apm.fleetIntegration.enrollmentFlyout.installApmAgentButtonText": "Installer l'agent APM",

View file

@ -3898,25 +3898,6 @@
"home.sampleData.logsSpec.webTrafficTitle": "[ログ] Web トラフィック",
"home.sampleData.logsSpecDescription": "Web ログを監視するサンプルデータ、ビジュアライゼーション、ダッシュボードです。",
"home.sampleData.logsSpecTitle": "サンプル Web ログ",
"homePackages.sampleDataSet.installedLabel": "{name} がインストールされました",
"homePackages.sampleDataSet.unableToInstallErrorMessage": "サンプルデータセット「{name}」をインストールできません",
"homePackages.sampleDataSet.unableToLoadListErrorMessage": "サンプルデータセットのリストを読み込めません",
"homePackages.sampleDataSet.unableToUninstallErrorMessage": "サンプルデータセット「{name}」をアンインストールできません",
"homePackages.sampleDataSet.uninstalledLabel": "{name} がアンインストールされました",
"homePackages.sampleDataCard.addButtonAriaLabel": "{datasetName} を追加",
"homePackages.sampleDataCard.addButtonLabel": "データの追加",
"homePackages.sampleDataCard.addingButtonAriaLabel": "{datasetName} を追加",
"homePackages.sampleDataCard.addingButtonLabel": "追加中",
"homePackages.sampleDataCard.dashboardLinkLabel": "ダッシュボード",
"homePackages.sampleDataCard.default.addButtonAriaLabel": "{datasetName} を追加",
"homePackages.sampleDataCard.default.addButtonLabel": "データの追加",
"homePackages.sampleDataCard.default.unableToVerifyErrorMessage": "データセットステータスを確認できません、エラー:{statusMsg}",
"homePackages.sampleDataCard.removeButtonAriaLabel": "{datasetName} を削除",
"homePackages.sampleDataCard.removeButtonLabel": "削除",
"homePackages.sampleDataCard.removingButtonAriaLabel": "{datasetName} を削除中",
"homePackages.sampleDataCard.removingButtonLabel": "削除中",
"homePackages.sampleDataCard.viewDataButtonAriaLabel": "{datasetName} を表示",
"homePackages.sampleDataCard.viewDataButtonLabel": "データを表示",
"home.solutionsSection.sectionTitle": "ソリューションを選択",
"home.tryButtonLabel": "統合の追加",
"home.tutorial.addDataToKibanaDescription": "{integrationsLink}を追加するほかに、サンプルデータを試したり、独自のデータをアップロードしたりできます。",
@ -4664,6 +4645,25 @@
"home.tutorials.zscalerLogs.nameTitle": "Zscaler ログ",
"home.tutorials.zscalerLogs.shortDescription": "Filebeatを使用してZscaler NSSからログを収集して解析します。",
"home.welcomeTitle": "Elasticへようこそ",
"homePackages.sampleDataSet.installedLabel": "{name} がインストールされました",
"homePackages.sampleDataSet.unableToInstallErrorMessage": "サンプルデータセット「{name}」をインストールできません",
"homePackages.sampleDataSet.unableToLoadListErrorMessage": "サンプルデータセットのリストを読み込めません",
"homePackages.sampleDataSet.unableToUninstallErrorMessage": "サンプルデータセット「{name}」をアンインストールできません",
"homePackages.sampleDataSet.uninstalledLabel": "{name} がアンインストールされました",
"homePackages.sampleDataCard.addButtonAriaLabel": "{datasetName} を追加",
"homePackages.sampleDataCard.addButtonLabel": "データの追加",
"homePackages.sampleDataCard.addingButtonAriaLabel": "{datasetName} を追加",
"homePackages.sampleDataCard.addingButtonLabel": "追加中",
"homePackages.sampleDataCard.dashboardLinkLabel": "ダッシュボード",
"homePackages.sampleDataCard.default.addButtonAriaLabel": "{datasetName} を追加",
"homePackages.sampleDataCard.default.addButtonLabel": "データの追加",
"homePackages.sampleDataCard.default.unableToVerifyErrorMessage": "データセットステータスを確認できません、エラー:{statusMsg}",
"homePackages.sampleDataCard.removeButtonAriaLabel": "{datasetName} を削除",
"homePackages.sampleDataCard.removeButtonLabel": "削除",
"homePackages.sampleDataCard.removingButtonAriaLabel": "{datasetName} を削除中",
"homePackages.sampleDataCard.removingButtonLabel": "削除中",
"homePackages.sampleDataCard.viewDataButtonAriaLabel": "{datasetName} を表示",
"homePackages.sampleDataCard.viewDataButtonLabel": "データを表示",
"indexPatternEditor.aliasLabel": "エイリアス",
"indexPatternEditor.createIndex.noMatch": "名前は1つ以上のデータストリーム、インデックス、またはインデックスエイリアスと一致する必要があります。",
"indexPatternEditor.createIndexPattern.stepTime.noTimeFieldOptionLabel": "--- 時間フィルターを使用しない ---",
@ -7829,7 +7829,6 @@
"xpack.apm.fleetIntegration.apmAgent.runtimeAttachment.version.helpText": "関連付けるElastic APM Javaエージェントの{versionLink}を入力します。",
"xpack.apm.fleetIntegration.apmAgent.runtimeAttachment.version.helpText.version": "バージョン",
"xpack.apm.fleetIntegration.apmAgent.runtimeAttachment.version.invalid": "無効なバージョン",
"xpack.apm.fleetIntegration.apmAgent.runtimeAttachment.version.placeHolder": "バージョンの追加",
"xpack.apm.fleetIntegration.assets.description": "APMでアプリケーショントレースとサービスマップを表示",
"xpack.apm.fleetIntegration.assets.name": "サービス",
"xpack.apm.fleetIntegration.enrollmentFlyout.installApmAgentButtonText": "APMエージェントのインストール",

View file

@ -3902,25 +3902,6 @@
"home.sampleData.logsSpec.webTrafficTitle": "[日志] 网络流量",
"home.sampleData.logsSpecDescription": "用于监测 Web 日志的样例数据、可视化和仪表板。",
"home.sampleData.logsSpecTitle": "样例 Web 日志",
"homePackages.sampleDataSet.installedLabel": "{name} 已安装",
"homePackages.sampleDataSet.unableToInstallErrorMessage": "无法安装样例数据集:{name}",
"homePackages.sampleDataSet.unableToLoadListErrorMessage": "无法加载样例数据集列表",
"homePackages.sampleDataSet.unableToUninstallErrorMessage": "无法卸载样例数据集:{name}",
"homePackages.sampleDataSet.uninstalledLabel": "{name} 已卸载",
"homePackages.sampleDataCard.addButtonAriaLabel": "添加 {datasetName}",
"homePackages.sampleDataCard.addButtonLabel": "添加数据",
"homePackages.sampleDataCard.addingButtonAriaLabel": "正在添加 {datasetName}",
"homePackages.sampleDataCard.addingButtonLabel": "正在添加",
"homePackages.sampleDataCard.dashboardLinkLabel": "仪表板",
"homePackages.sampleDataCard.default.addButtonAriaLabel": "添加 {datasetName}",
"homePackages.sampleDataCard.default.addButtonLabel": "添加数据",
"homePackages.sampleDataCard.default.unableToVerifyErrorMessage": "无法确认数据集状态,错误:{statusMsg}",
"homePackages.sampleDataCard.removeButtonAriaLabel": "移除 {datasetName}",
"homePackages.sampleDataCard.removeButtonLabel": "移除",
"homePackages.sampleDataCard.removingButtonAriaLabel": "正在移除 {datasetName}",
"homePackages.sampleDataCard.removingButtonLabel": "正在移除",
"homePackages.sampleDataCard.viewDataButtonAriaLabel": "查看 {datasetName}",
"homePackages.sampleDataCard.viewDataButtonLabel": "查看数据",
"home.solutionsSection.sectionTitle": "选取您的解决方案",
"home.tryButtonLabel": "添加集成",
"home.tutorial.addDataToKibanaDescription": "除了添加 {integrationsLink} 以外,您还可以试用样例数据或上传自己的数据。",
@ -4669,6 +4650,25 @@
"home.tutorials.zscalerLogs.nameTitle": "Zscaler 日志",
"home.tutorials.zscalerLogs.shortDescription": "使用 Filebeat 从 Zscaler NSS 收集并解析日志。",
"home.welcomeTitle": "欢迎使用 Elastic",
"homePackages.sampleDataSet.installedLabel": "{name} 已安装",
"homePackages.sampleDataSet.unableToInstallErrorMessage": "无法安装样例数据集:{name}",
"homePackages.sampleDataSet.unableToLoadListErrorMessage": "无法加载样例数据集列表",
"homePackages.sampleDataSet.unableToUninstallErrorMessage": "无法卸载样例数据集:{name}",
"homePackages.sampleDataSet.uninstalledLabel": "{name} 已卸载",
"homePackages.sampleDataCard.addButtonAriaLabel": "添加 {datasetName}",
"homePackages.sampleDataCard.addButtonLabel": "添加数据",
"homePackages.sampleDataCard.addingButtonAriaLabel": "正在添加 {datasetName}",
"homePackages.sampleDataCard.addingButtonLabel": "正在添加",
"homePackages.sampleDataCard.dashboardLinkLabel": "仪表板",
"homePackages.sampleDataCard.default.addButtonAriaLabel": "添加 {datasetName}",
"homePackages.sampleDataCard.default.addButtonLabel": "添加数据",
"homePackages.sampleDataCard.default.unableToVerifyErrorMessage": "无法确认数据集状态,错误:{statusMsg}",
"homePackages.sampleDataCard.removeButtonAriaLabel": "移除 {datasetName}",
"homePackages.sampleDataCard.removeButtonLabel": "移除",
"homePackages.sampleDataCard.removingButtonAriaLabel": "正在移除 {datasetName}",
"homePackages.sampleDataCard.removingButtonLabel": "正在移除",
"homePackages.sampleDataCard.viewDataButtonAriaLabel": "查看 {datasetName}",
"homePackages.sampleDataCard.viewDataButtonLabel": "查看数据",
"indexPatternEditor.aliasLabel": "别名",
"indexPatternEditor.createIndex.noMatch": "名称必须匹配一个或多个数据流、索引或索引别名。",
"indexPatternEditor.createIndexPattern.stepTime.noTimeFieldOptionLabel": "--- 我不想使用时间筛选 ---",
@ -7840,7 +7840,6 @@
"xpack.apm.fleetIntegration.apmAgent.runtimeAttachment.version.helpText": "输入应附加的 Elastic APM Java 代理的 {versionLink}。",
"xpack.apm.fleetIntegration.apmAgent.runtimeAttachment.version.helpText.version": "版本",
"xpack.apm.fleetIntegration.apmAgent.runtimeAttachment.version.invalid": "版本无效",
"xpack.apm.fleetIntegration.apmAgent.runtimeAttachment.version.placeHolder": "添加版本",
"xpack.apm.fleetIntegration.assets.description": "在 APM 中查看应用程序跟踪和服务地图",
"xpack.apm.fleetIntegration.assets.name": "服务",
"xpack.apm.fleetIntegration.enrollmentFlyout.installApmAgentButtonText": "安装 APM 代理",