[Chore] Remove Investigate plugin, Investigate app plugin, and Investigation-schema package (#216342)

## Summary

Removes unused code from the Investigate and Investigate app plugin.

Removes all references to those plugins in storybook, i18n, types, etc.

Removes codeowner requirements for those plugins

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Dominique Clarke 2025-04-08 12:25:21 -04:00 committed by GitHub
parent a2e0bb1422
commit 9d56263413
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
238 changed files with 49 additions and 46852 deletions

3
.github/CODEOWNERS vendored
View file

@ -957,7 +957,6 @@ x-pack/solutions/observability/packages/get-padded-alert-time-range-util @elasti
x-pack/solutions/observability/packages/kbn-alerts-grouping @elastic/response-ops
x-pack/solutions/observability/packages/kbn-custom-integrations @elastic/obs-ux-logs-team
x-pack/solutions/observability/packages/kbn-genai-cli @elastic/obs-knowledge-team
x-pack/solutions/observability/packages/kbn-investigation-shared @elastic/obs-ux-management-team
x-pack/solutions/observability/packages/kbn-observability-schema @elastic/obs-ux-management-team
x-pack/solutions/observability/packages/kbn-scout-oblt @elastic/appex-qa
x-pack/solutions/observability/packages/observability-ai/observability-ai-common @elastic/obs-ai-assistant
@ -975,8 +974,6 @@ x-pack/solutions/observability/plugins/exploratory_view @elastic/obs-ux-manageme
x-pack/solutions/observability/plugins/infra @elastic/obs-ux-logs-team @elastic/obs-ux-infra_services-team
x-pack/solutions/observability/plugins/inventory @elastic/obs-ux-infra_services-team
x-pack/solutions/observability/plugins/inventory/e2e @elastic/obs-ux-infra_services-team
x-pack/solutions/observability/plugins/investigate @elastic/obs-ux-management-team
x-pack/solutions/observability/plugins/investigate_app @elastic/obs-ux-management-team
x-pack/solutions/observability/plugins/metrics_data_access @elastic/obs-ux-infra_services-team
x-pack/solutions/observability/plugins/observability @elastic/obs-ux-management-team
x-pack/solutions/observability/plugins/observability_ai_assistant_app @elastic/obs-ai-assistant

View file

@ -24,8 +24,6 @@ xpack.apm.enabled: false
xpack.entities_data_access.enabled: false
xpack.infra.enabled: false
xpack.inventory.enabled: false
xpack.investigate.enabled: false
xpack.investigateApp.enabled: false
xpack.observability.enabled: false
xpack.observabilityAIAssistantApp.enabled: false
xpack.observabilityLogsExplorer.enabled: false

View file

@ -163,8 +163,6 @@ mapped_pages:
| [infra](https://github.com/elastic/kibana/blob/main/x-pack/solutions/observability/plugins/infra/README.md) | This is the home of the infra plugin, which aims to provide a solution for the infrastructure monitoring use-case within Kibana. |
| [ingestPipelines](https://github.com/elastic/kibana/blob/main/x-pack/platform/plugins/shared/ingest_pipelines/README.md) | The ingest_pipelines plugin provides Kibana support for Elasticsearch's ingest pipelines. |
| [inventory](https://github.com/elastic/kibana/blob/main/x-pack/solutions/observability/plugins/inventory/README.md) | Home of the Inventory plugin, which renders the... inventory. |
| [investigate](https://github.com/elastic/kibana/blob/main/x-pack/solutions/observability/plugins/investigate/README.md) | WARNING: Missing or empty README. |
| [investigateApp](https://github.com/elastic/kibana/blob/main/x-pack/solutions/observability/plugins/investigate_app/README.md) | WARNING: Missing or empty README. |
| [lens](https://github.com/elastic/kibana/blob/main/x-pack/platform/plugins/shared/lens/readme.md) | Lens is a visualization editor allowing to quickly and easily configure compelling visualizations to use on dashboards and canvas workpads. |
| [licenseApiGuard](https://github.com/elastic/kibana/blob/main/x-pack/platform/plugins/private/license_api_guard/README.md) | This plugin is used by ES UI plugins to reject API requests when the plugin is unsupported by the user's license. |
| [licenseManagement](https://github.com/elastic/kibana/blob/main/x-pack/platform/plugins/shared/license_management/README.md) | This plugin enables users to activate a trial license, downgrade to Basic, and upload a new license. |

View file

@ -607,9 +607,6 @@
"@kbn/interactive-setup-test-endpoints-plugin": "link:src/platform/test/interactive_setup_api_integration/plugins/test_endpoints",
"@kbn/interpreter": "link:src/platform/packages/shared/kbn-interpreter",
"@kbn/inventory-plugin": "link:x-pack/solutions/observability/plugins/inventory",
"@kbn/investigate-app-plugin": "link:x-pack/solutions/observability/plugins/investigate_app",
"@kbn/investigate-plugin": "link:x-pack/solutions/observability/plugins/investigate",
"@kbn/investigation-shared": "link:x-pack/solutions/observability/packages/kbn-investigation-shared",
"@kbn/io-ts-utils": "link:src/platform/packages/shared/kbn-io-ts-utils",
"@kbn/ipynb": "link:x-pack/solutions/search/packages/kbn-ipynb",
"@kbn/item-buffer": "link:src/platform/packages/private/kbn-item-buffer",

View file

@ -88,8 +88,6 @@ pageLoadAssetSize:
inspector: 17600
interactiveSetup: 80000
inventory: 27430
investigate: 17970
investigateApp: 91898
kibanaOverview: 56279
kibanaReact: 74422
kibanaUsageCollection: 16463

View file

@ -88,6 +88,11 @@ Object {
"type": "guided-setup-state",
},
},
Object {
"term": Object {
"type": "investigation",
},
},
Object {
"term": Object {
"type": "maps-telemetry",
@ -311,6 +316,11 @@ Object {
"type": "guided-setup-state",
},
},
Object {
"term": Object {
"type": "investigation",
},
},
Object {
"term": Object {
"type": "maps-telemetry",
@ -538,6 +548,11 @@ Object {
"type": "guided-setup-state",
},
},
Object {
"term": Object {
"type": "investigation",
},
},
Object {
"term": Object {
"type": "maps-telemetry",
@ -769,6 +784,11 @@ Object {
"type": "guided-setup-state",
},
},
Object {
"term": Object {
"type": "investigation",
},
},
Object {
"term": Object {
"type": "maps-telemetry",
@ -1036,6 +1056,11 @@ Object {
"type": "guided-setup-state",
},
},
Object {
"term": Object {
"type": "investigation",
},
},
Object {
"term": Object {
"type": "maps-telemetry",
@ -1270,6 +1295,11 @@ Object {
"type": "guided-setup-state",
},
},
Object {
"term": Object {
"type": "investigation",
},
},
Object {
"term": Object {
"type": "maps-telemetry",

View file

@ -52,6 +52,8 @@ export const REMOVED_TYPES: string[] = [
'upgrade-assistant-telemetry',
// Removed in 8.8 https://github.com/elastic/kibana/pull/155204
'endpoint:user-artifact',
// Removed in 9.1 https://github.com/elastic/kibana/pull/216342
'investigation',
].sort();
export const excludeUnusedTypesQuery: QueryDslQueryContainer = {

View file

@ -194,6 +194,11 @@ describe('createInitialState', () => {
"type": "guided-setup-state",
},
},
Object {
"term": Object {
"type": "investigation",
},
},
Object {
"term": Object {
"type": "maps-telemetry",

View file

@ -94,6 +94,7 @@ const previouslyRegisteredTypes = [
'ingest-package-policies',
'ingest_manager_settings',
'inventory-view',
'investigation',
'kql-telemetry',
'legacy-url-alias',
'lens',

View file

@ -47,7 +47,6 @@ export const storybookAliases = {
home: 'src/platform/plugins/shared/home/.storybook',
infra: 'x-pack/solutions/observability/plugins/infra/.storybook',
inventory: 'x-pack/solutions/observability/plugins/inventory/.storybook',
investigate: 'x-pack/solutions/observability/plugins/investigate_app/.storybook',
kibana_react: 'src/platform/plugins/shared/kibana_react/.storybook',
language_documentation_popover:
'src/platform/packages/private/kbn-language-documentation/.storybook',

View file

@ -28,8 +28,6 @@ export const SLO_APP_ID = 'slo';
export const AI_ASSISTANT_APP_ID = 'observabilityAIAssistant';
export const INVESTIGATE_APP_ID = 'investigate';
export const OBLT_UX_APP_ID = 'ux';
export const OBLT_PROFILING_APP_ID = 'profiling';

View file

@ -1118,12 +1118,6 @@
"@kbn/inventory-e2e/*": ["x-pack/solutions/observability/plugins/inventory/e2e/*"],
"@kbn/inventory-plugin": ["x-pack/solutions/observability/plugins/inventory"],
"@kbn/inventory-plugin/*": ["x-pack/solutions/observability/plugins/inventory/*"],
"@kbn/investigate-app-plugin": ["x-pack/solutions/observability/plugins/investigate_app"],
"@kbn/investigate-app-plugin/*": ["x-pack/solutions/observability/plugins/investigate_app/*"],
"@kbn/investigate-plugin": ["x-pack/solutions/observability/plugins/investigate"],
"@kbn/investigate-plugin/*": ["x-pack/solutions/observability/plugins/investigate/*"],
"@kbn/investigation-shared": ["x-pack/solutions/observability/packages/kbn-investigation-shared"],
"@kbn/investigation-shared/*": ["x-pack/solutions/observability/packages/kbn-investigation-shared/*"],
"@kbn/io-ts-utils": ["src/platform/packages/shared/kbn-io-ts-utils"],
"@kbn/io-ts-utils/*": ["src/platform/packages/shared/kbn-io-ts-utils/*"],
"@kbn/ipynb": ["x-pack/solutions/search/packages/kbn-ipynb"],

View file

@ -67,8 +67,6 @@
"xpack.automaticImport": "platform/plugins/shared/automatic_import",
"xpack.inference": "platform/plugins/shared/inference",
"xpack.inventory": "solutions/observability/plugins/inventory",
"xpack.investigate": "solutions/observability/plugins/investigate",
"xpack.investigateApp": "solutions/observability/plugins/investigate_app",
"xpack.kubernetesSecurity": "solutions/security/plugins/kubernetes_security",
"xpack.lens": "platform/plugins/shared/lens",
"xpack.licenseApiGuard": "platform/plugins/private/license_api_guard",

View file

@ -7757,138 +7757,6 @@
}
}
},
"investigation": {
"properties": {
"investigation": {
"properties": {
"total": {
"type": "long",
"_meta": {
"description": "The total number of investigations in the cluster"
}
},
"by_status": {
"properties": {
"triage": {
"type": "long",
"_meta": {
"description": "The number of investigations in triage status in the cluster"
}
},
"active": {
"type": "long",
"_meta": {
"description": "The number of investigations in active status in the cluster"
}
},
"mitigated": {
"type": "long",
"_meta": {
"description": "The number of investigations in mitigated status in the cluster"
}
},
"resolved": {
"type": "long",
"_meta": {
"description": "The number of investigations in resolved status in the cluster"
}
},
"cancelled": {
"type": "long",
"_meta": {
"description": "The number of investigations in cancelled status in the cluster"
}
}
}
},
"by_origin": {
"properties": {
"alert": {
"type": "long",
"_meta": {
"description": "The number of investigations created from alerts in the cluster"
}
},
"blank": {
"type": "long",
"_meta": {
"description": "The number of investigations created from scratch in the cluster"
}
}
}
},
"items": {
"properties": {
"avg": {
"type": "long",
"_meta": {
"description": "The average number of items across all investigations in the cluster"
}
},
"p90": {
"type": "long",
"_meta": {
"description": "The 90th percentile of the number of items across all investigations in the cluster"
}
},
"p95": {
"type": "long",
"_meta": {
"description": "The 95th percentile of the number of items across all investigations in the cluster"
}
},
"max": {
"type": "long",
"_meta": {
"description": "The maximum number of items across all investigations in the cluster"
}
},
"min": {
"type": "long",
"_meta": {
"description": "The minimum number of items across all investigations in the cluster"
}
}
}
},
"notes": {
"properties": {
"avg": {
"type": "long",
"_meta": {
"description": "The average number of notes across all investigations in the cluster"
}
},
"p90": {
"type": "long",
"_meta": {
"description": "The 90th percentile of the number of notes across all investigations in the cluster"
}
},
"p95": {
"type": "long",
"_meta": {
"description": "The 95th percentile of the number of notes across all investigations in the cluster"
}
},
"max": {
"type": "long",
"_meta": {
"description": "The maximum number of notes across all investigations in the cluster"
}
},
"min": {
"type": "long",
"_meta": {
"description": "The minimum number of notes across all investigations in the cluster"
}
}
}
}
}
}
}
},
"slo": {
"properties": {
"slo": {

View file

@ -24551,110 +24551,6 @@
"xpack.inventory.shareLink.shareButtonLabel": "Partager",
"xpack.inventory.shareLink.shareToastFailureLabel": "Les URL courtes ne peuvent pas être copiées.",
"xpack.inventory.shareLink.shareToastSuccessLabel": "URL courte copiée dans le presse-papiers !",
"xpack.investigateApp.addFromLibraryButtonLabel": "Importer depuis la bibliothèque",
"xpack.investigateApp.addInvestigationItem.errorMessage": "une erreur s'est produite",
"xpack.investigateApp.addInvestigationItem.errorTitle": "Erreur",
"xpack.investigateApp.addInvestigationItem.successMessage": "Élément enregistré",
"xpack.investigateApp.addInvestigationNote.errorMessage": "une erreur s'est produite",
"xpack.investigateApp.addInvestigationNote.errorTitle": "Erreur",
"xpack.investigateApp.addInvestigationNote.successMessage": "Note enregistrée",
"xpack.investigateApp.addObservationUI.addAnObservationChartButtonLabel": "Ajouter un tableau d'observation",
"xpack.investigateApp.addObservationUI.cancelButtonLabel": "Annuler",
"xpack.investigateApp.addObservationUI.h2.addAnObservationChartLabel": "Ajouter un graphique d'observation",
"xpack.investigateApp.addObservationUI.p.selectADataSourceLabel": "Sélectionnez une source de données pour générer un graphique d'aperçu",
"xpack.investigateApp.appTitle": "Investigations",
"xpack.investigateApp.assistantHypothesis.analysisAborted": "L'analyse a été annulée",
"xpack.investigateApp.assistantHypothesis.failedToLoadAnalysis": "Échec de chargement de l'analyse",
"xpack.investigateApp.defaultChart.error_equation.description": "Vérifiez l'équation.",
"xpack.investigateApp.defaultChart.error_equation.title": "Une erreur s'est produite lors de l'affichage du graphique",
"xpack.investigateApp.defaultChart.noData.title": "Aucune donnée graphique disponible",
"xpack.investigateApp.deleteInvestigationError": "Impossible de supprimer l'investigation : une erreur s'est produite",
"xpack.investigateApp.deleteInvestigationErrorTitle": "Erreur",
"xpack.investigateApp.deleteInvestigationSuccess": "L'investigation a été supprimée avec succès",
"xpack.investigateApp.deleteModal.cancel": "Annuler",
"xpack.investigateApp.deleteModal.confirm": "Supprimer",
"xpack.investigateApp.deleteModal.description": "Vous ne pouvez pas récupérer cette investigation après la suppression.",
"xpack.investigateApp.deleteModal.title": "Supprimer",
"xpack.investigateApp.detailsPage.breadcrumb.details": "Détails de l'investigation",
"xpack.investigateApp.detailsPage.breadcrumb.list": "Investigations",
"xpack.investigateApp.esqlWidget.groupedByDateLabel": "@timestamp",
"xpack.investigateApp.events.fetch.error": "Une erreur s'est produite lors de la récupération des événements",
"xpack.investigateApp.investigationDetails.editButtonLabel": "Modifier",
"xpack.investigateApp.investigationDetails.escalateButtonLabel": "Faire remonter",
"xpack.investigateApp.investigationDetailsPage.closeButtonEmptyLabel": "Fermer",
"xpack.investigateApp.investigationDetailsPage.h2.createLabel": "Créer",
"xpack.investigateApp.investigationDetailsPage.h2.editLabel": "Modifier",
"xpack.investigateApp.investigationDetailsPage.newInvestigationLabel": "Nouvelle investigation",
"xpack.investigateApp.investigationDetailsPage.saveButtonLabel": "Enregistrer",
"xpack.investigateApp.investigationEditForm.externalIncidentUrlLabel": "URL d'incident externe",
"xpack.investigateApp.investigationEditForm.span.statusLabel": "Statut",
"xpack.investigateApp.investigationEditForm.span.tagsLabel": "Balises",
"xpack.investigateApp.investigationEditForm.span.titleLabel": "Titre",
"xpack.investigateApp.investigationEventTypesFilter.alertLabel": "Alerte",
"xpack.investigateApp.investigationEventTypesFilter.annotationLabel": "Annotation",
"xpack.investigateApp.investigationEventTypesFilter.filterEventTypePopoverTitleLabel": "Filtrer les types d'événements",
"xpack.investigateApp.investigationEventTypesFilter.filtersFilterButtonLabel": "Filtres",
"xpack.investigateApp.investigationHeader.externalIncidentTextLabel": "Incident externe",
"xpack.investigateApp.investigationHeader.startedLabel": "Démarré : il y a {timeAgo}",
"xpack.investigateApp.investigationList.allLabel": "Affichage de tous les éléments",
"xpack.investigateApp.investigationList.createdByLabel": "Créé par",
"xpack.investigateApp.investigationList.deleteAction": "Supprimer",
"xpack.investigateApp.investigationList.deleteAction.ariaLabel": "Supprimer l'investigation \"{name}\"",
"xpack.investigateApp.investigationList.editAction": "Modifier",
"xpack.investigateApp.investigationList.editAction.ariaLabel": "Modifier l'investigation \"{name}\"",
"xpack.investigateApp.investigationList.notesLabel": "Commentaires",
"xpack.investigateApp.investigationList.searchField.label": "Rechercher...",
"xpack.investigateApp.investigationList.showingLabel": "Affichage de {startItem}-{endItem} sur {totalItemCount}",
"xpack.investigateApp.investigationList.stats.activeLabel": "Actif",
"xpack.investigateApp.investigationList.stats.cancelledLabel": "Annulé",
"xpack.investigateApp.investigationList.stats.mitigatedLabel": "Limité",
"xpack.investigateApp.investigationList.stats.resolvedLabel": "Résolu",
"xpack.investigateApp.investigationList.stats.triageLabel": "Tri",
"xpack.investigateApp.investigationList.tableCaption": "Liste des investigations",
"xpack.investigateApp.investigationList.tagsLabel": "Balises",
"xpack.investigateApp.investigationList.titleLabel": "Nom",
"xpack.investigateApp.investigationList.updatedAtLabel": "Mis à jour à",
"xpack.investigateApp.investigationListPage.createButtonLabel": "Créer",
"xpack.investigateApp.investigationNotes.addButtonLabel": "Ajouter",
"xpack.investigateApp.investigationNotes.cancelEditButtonLabel": "Annuler",
"xpack.investigateApp.investigationNotes.euiFormRow.notesLabel": "Notes",
"xpack.investigateApp.investigationNotes.header": "Notes",
"xpack.investigateApp.investigationNotes.placeholder": "Ajouter une note à l'investigation",
"xpack.investigateApp.investigationNotes.updateNoteButtonLabel": "Mettre à jour la note",
"xpack.investigateApp.InvestigationNotFound.body": "Une erreur s'est produite lors du chargement de l'investigation. Contactez votre administrateur pour obtenir de l'aide.",
"xpack.investigateApp.InvestigationNotFound.title": "Impossible de charger l'investigation",
"xpack.investigateApp.investigationsDeepLinkTitle": "Toutes les investigations",
"xpack.investigateApp.InvestigationsNotFound.body": "Une erreur s'est produite lors du chargement des investigations. Contactez votre administrateur pour obtenir de l'aide.",
"xpack.investigateApp.InvestigationsNotFound.title": "Impossible de charger les investigations",
"xpack.investigateApp.listPage.breadcrumb.list": "Investigations",
"xpack.investigateApp.listPage.title": "Investigations",
"xpack.investigateApp.newInvestigateDeepLinkTitle": "Nouvelle investigation",
"xpack.investigateApp.renderableItems.div.notFoundLabel": "Introuvable pour le type {type}",
"xpack.investigateApp.searchBar.statusFilterButtonLabel": "Statut",
"xpack.investigateApp.searchBar.tagsFilterButtonLabel": "Balises",
"xpack.investigateApp.suggestVisualizationList.errorLoadingSuggestionsLabel": "Erreur lors du chargement des suggestions : {message}",
"xpack.investigateApp.suggestVisualizationList.loadingSuggestionsLabel": "Chargement des suggestions",
"xpack.investigateApp.suggestVisualizationList.noSuggestionsLabel": "Aucune suggestion appropriée",
"xpack.investigateApp.useCreateInvestigation.errorMessage": "une erreur s'est produite",
"xpack.investigateApp.useCreateInvestigation.errorTitle": "Erreur",
"xpack.investigateApp.useCreateInvestigation.successMessage": "Investigation créée",
"xpack.investigateApp.useDeleteInvestigationItem.errorMessage": "une erreur s'est produite",
"xpack.investigateApp.useDeleteInvestigationItem.errorTitle": "Erreur",
"xpack.investigateApp.useDeleteInvestigationItem.successMessage": "Élément supprimé",
"xpack.investigateApp.useDeleteInvestigationNote.errorMessage": "une erreur s'est produite",
"xpack.investigateApp.useDeleteInvestigationNote.errorTitle": "Erreur",
"xpack.investigateApp.useDeleteInvestigationNote.successMessage": "Note supprimée",
"xpack.investigateApp.useFetchAllInvestigationStats.errorTitle": "Un problème est survenu lors de la récupération des statistiques d'investigation",
"xpack.investigateApp.useFetchAllInvestigationTags.errorTitle": "Un problème est survenu lors de la récupération des balises d'investigation",
"xpack.investigateApp.useFetchInvestigation.errorTitle": "Un problème est survenu lors de la récupération de l'investigation",
"xpack.investigateApp.useFetchInvestigationItems.errorTitle": "Un problème est survenu lors de la récupération des éléments d'investigation",
"xpack.investigateApp.useFetchInvestigationList.errorTitle": "Un problème est survenu lors de la récupération des investigations",
"xpack.investigateApp.useFetchInvestigationNotes.errorTitle": "Un problème est survenu lors de la récupération des notes d'investigation",
"xpack.investigateApp.useFetchUserProfiles.errorTitle": "Un problème est survenu lors de la récupération des profils d'utilisateurs",
"xpack.investigateApp.useUpdateInvestigation.successMessage": "Enquête mise à jour",
"xpack.investigateApp.useUpdateInvestigationNote.errorMessage": "une erreur s'est produite",
"xpack.investigateApp.useUpdateInvestigationNote.errorTitle": "Erreur",
"xpack.investigateApp.useUpdateInvestigationNote.successMessage": "Note mise à jour",
"xpack.lens.action.exploreInDiscover": "Explorer dans Discover",
"xpack.lens.AggBasedLabel": "visualisation basée sur l'agrégation",
"xpack.lens.app.addToLibrary": "Enregistrer dans la bibliothèque",
@ -32254,7 +32150,6 @@
"xpack.observability.component.tags.moreTags": "+{number} de plus",
"xpack.observability.component.tags.moreTags.ariaLabel": "badge plus de balises",
"xpack.observability.create.annotation": "Un problème est survenu lors de la création de l'annotation {message}",
"xpack.observability.create.errorNotification": "Une erreur s'est produite lors de la création de l'investigation",
"xpack.observability.createAnnotation.addAnnotationModalHeaderTitleLabel": "Créer une annotation",
"xpack.observability.createAnnotation.closeButtonEmptyLabel": "Fermer",
"xpack.observability.createAnnotation.deleteButtonLabel": "Supprimer",

View file

@ -24530,109 +24530,6 @@
"xpack.inventory.shareLink.shareButtonLabel": "共有",
"xpack.inventory.shareLink.shareToastFailureLabel": "短縮URLをコピーできません。",
"xpack.inventory.shareLink.shareToastSuccessLabel": "短縮URLがクリップボードにコピーされました",
"xpack.investigateApp.addFromLibraryButtonLabel": "ライブラリからインポート",
"xpack.investigateApp.addInvestigationItem.errorMessage": "エラーが発生しました",
"xpack.investigateApp.addInvestigationItem.errorTitle": "エラー",
"xpack.investigateApp.addInvestigationItem.successMessage": "項目が保存されました",
"xpack.investigateApp.addInvestigationNote.errorMessage": "エラーが発生しました",
"xpack.investigateApp.addInvestigationNote.errorTitle": "エラー",
"xpack.investigateApp.addInvestigationNote.successMessage": "メモが保存されました",
"xpack.investigateApp.addObservationUI.addAnObservationChartButtonLabel": "観測グラフを追加",
"xpack.investigateApp.addObservationUI.cancelButtonLabel": "キャンセル",
"xpack.investigateApp.addObservationUI.h2.addAnObservationChartLabel": "観測グラフを追加",
"xpack.investigateApp.addObservationUI.p.selectADataSourceLabel": "データソースを選択して、プレビューグラフを生成",
"xpack.investigateApp.appTitle": "調査",
"xpack.investigateApp.assistantHypothesis.analysisAborted": "分析が中断されました",
"xpack.investigateApp.assistantHypothesis.failedToLoadAnalysis": "分析の読み込みに失敗しました",
"xpack.investigateApp.defaultChart.error_equation.description": "式を確認してください。",
"xpack.investigateApp.defaultChart.error_equation.title": "グラフの表示中にエラーが発生しました",
"xpack.investigateApp.defaultChart.noData.title": "グラフデータがありません",
"xpack.investigateApp.deleteInvestigationError": "調査を削除できません:エラーが発生しました",
"xpack.investigateApp.deleteInvestigationErrorTitle": "エラー",
"xpack.investigateApp.deleteInvestigationSuccess": "調査が正常に削除されました",
"xpack.investigateApp.deleteModal.cancel": "キャンセル",
"xpack.investigateApp.deleteModal.confirm": "削除",
"xpack.investigateApp.deleteModal.description": "削除後に調査を回復できません。",
"xpack.investigateApp.deleteModal.title": "削除",
"xpack.investigateApp.detailsPage.breadcrumb.details": "調査詳細",
"xpack.investigateApp.detailsPage.breadcrumb.list": "調査",
"xpack.investigateApp.esqlWidget.groupedByDateLabel": "@timestamp",
"xpack.investigateApp.events.fetch.error": "イベントの取得中に問題が発生しました",
"xpack.investigateApp.investigationDetails.editButtonLabel": "編集",
"xpack.investigateApp.investigationDetails.escalateButtonLabel": "エスカレーション",
"xpack.investigateApp.investigationDetailsPage.closeButtonEmptyLabel": "閉じる",
"xpack.investigateApp.investigationDetailsPage.h2.createLabel": "作成",
"xpack.investigateApp.investigationDetailsPage.h2.editLabel": "編集",
"xpack.investigateApp.investigationDetailsPage.newInvestigationLabel": "新しい調査",
"xpack.investigateApp.investigationDetailsPage.saveButtonLabel": "保存",
"xpack.investigateApp.investigationEditForm.externalIncidentUrlLabel": "外部インシデントURL",
"xpack.investigateApp.investigationEditForm.span.statusLabel": "ステータス",
"xpack.investigateApp.investigationEditForm.span.tagsLabel": "タグ",
"xpack.investigateApp.investigationEditForm.span.titleLabel": "タイトル",
"xpack.investigateApp.investigationEventTypesFilter.alertLabel": "アラート",
"xpack.investigateApp.investigationEventTypesFilter.annotationLabel": "注釈",
"xpack.investigateApp.investigationEventTypesFilter.filterEventTypePopoverTitleLabel": "イベントタイプをフィルター",
"xpack.investigateApp.investigationEventTypesFilter.filtersFilterButtonLabel": "フィルター",
"xpack.investigateApp.investigationHeader.externalIncidentTextLabel": "外部インシデント",
"xpack.investigateApp.investigationHeader.startedLabel": "開始:{timeAgo}",
"xpack.investigateApp.investigationList.allLabel": "すべて表示中",
"xpack.investigateApp.investigationList.createdByLabel": "作成者",
"xpack.investigateApp.investigationList.deleteAction": "削除",
"xpack.investigateApp.investigationList.deleteAction.ariaLabel": "調査\"{name}\"を削除",
"xpack.investigateApp.investigationList.editAction": "編集",
"xpack.investigateApp.investigationList.editAction.ariaLabel": "調査\"{name}\"を編集",
"xpack.investigateApp.investigationList.notesLabel": "コメント",
"xpack.investigateApp.investigationList.searchField.label": "検索...",
"xpack.investigateApp.investigationList.stats.activeLabel": "アクティブ",
"xpack.investigateApp.investigationList.stats.cancelledLabel": "キャンセル済み",
"xpack.investigateApp.investigationList.stats.mitigatedLabel": "移行済み",
"xpack.investigateApp.investigationList.stats.resolvedLabel": "解決済み",
"xpack.investigateApp.investigationList.stats.triageLabel": "トリアージ",
"xpack.investigateApp.investigationList.tableCaption": "調査リスト",
"xpack.investigateApp.investigationList.tagsLabel": "タグ",
"xpack.investigateApp.investigationList.titleLabel": "名前",
"xpack.investigateApp.investigationList.updatedAtLabel": "更新日時",
"xpack.investigateApp.investigationListPage.createButtonLabel": "作成",
"xpack.investigateApp.investigationNotes.addButtonLabel": "追加",
"xpack.investigateApp.investigationNotes.cancelEditButtonLabel": "キャンセル",
"xpack.investigateApp.investigationNotes.euiFormRow.notesLabel": "メモ",
"xpack.investigateApp.investigationNotes.header": "メモ",
"xpack.investigateApp.investigationNotes.placeholder": "メモを調査に追加",
"xpack.investigateApp.investigationNotes.updateNoteButtonLabel": "メモを更新",
"xpack.investigateApp.InvestigationNotFound.body": "調査の読み込みエラーが発生しました。ヘルプについては、管理者にお問い合わせください。",
"xpack.investigateApp.InvestigationNotFound.title": "調査を読み込めませんでした",
"xpack.investigateApp.investigationsDeepLinkTitle": "すべての調査",
"xpack.investigateApp.InvestigationsNotFound.body": "調査の読み込みエラーが発生しました。ヘルプについては、管理者にお問い合わせください。",
"xpack.investigateApp.InvestigationsNotFound.title": "調査を読み込めません",
"xpack.investigateApp.listPage.breadcrumb.list": "調査",
"xpack.investigateApp.listPage.title": "調査",
"xpack.investigateApp.newInvestigateDeepLinkTitle": "新しい調査",
"xpack.investigateApp.renderableItems.div.notFoundLabel": "タイプ\"{type}\"が見つかりません",
"xpack.investigateApp.searchBar.statusFilterButtonLabel": "ステータス",
"xpack.investigateApp.searchBar.tagsFilterButtonLabel": "タグ",
"xpack.investigateApp.suggestVisualizationList.errorLoadingSuggestionsLabel": "候補の読み込みエラー:{message}",
"xpack.investigateApp.suggestVisualizationList.loadingSuggestionsLabel": "候補を読み込み中",
"xpack.investigateApp.suggestVisualizationList.noSuggestionsLabel": "適切な候補がありません",
"xpack.investigateApp.useCreateInvestigation.errorMessage": "エラーが発生しました",
"xpack.investigateApp.useCreateInvestigation.errorTitle": "エラー",
"xpack.investigateApp.useCreateInvestigation.successMessage": "調査が作成されました",
"xpack.investigateApp.useDeleteInvestigationItem.errorMessage": "エラーが発生しました",
"xpack.investigateApp.useDeleteInvestigationItem.errorTitle": "エラー",
"xpack.investigateApp.useDeleteInvestigationItem.successMessage": "項目が削除されました",
"xpack.investigateApp.useDeleteInvestigationNote.errorMessage": "エラーが発生しました",
"xpack.investigateApp.useDeleteInvestigationNote.errorTitle": "エラー",
"xpack.investigateApp.useDeleteInvestigationNote.successMessage": "メモが削除されました",
"xpack.investigateApp.useFetchAllInvestigationStats.errorTitle": "調査統計の取得中に問題が発生しました",
"xpack.investigateApp.useFetchAllInvestigationTags.errorTitle": "調査タグの取得中に問題が発生しました",
"xpack.investigateApp.useFetchInvestigation.errorTitle": "調査の取得中に問題が発生しました",
"xpack.investigateApp.useFetchInvestigationItems.errorTitle": "調査項目の取得中に問題が発生しました",
"xpack.investigateApp.useFetchInvestigationList.errorTitle": "調査の取得中に問題が発生しました",
"xpack.investigateApp.useFetchInvestigationNotes.errorTitle": "調査メモの取得中に問題が発生しました",
"xpack.investigateApp.useFetchUserProfiles.errorTitle": "ユーザープロファイル取得中に問題が発生しました",
"xpack.investigateApp.useUpdateInvestigation.successMessage": "調査が更新されました",
"xpack.investigateApp.useUpdateInvestigationNote.errorMessage": "エラーが発生しました",
"xpack.investigateApp.useUpdateInvestigationNote.errorTitle": "エラー",
"xpack.investigateApp.useUpdateInvestigationNote.successMessage": "メモが更新されました",
"xpack.lens.action.exploreInDiscover": "Discoverで探索",
"xpack.lens.AggBasedLabel": "集約に基づく可視化",
"xpack.lens.app.addToLibrary": "ライブラリに保存",
@ -32231,7 +32128,6 @@
"xpack.observability.component.tags.moreTags": "その他{number}",
"xpack.observability.component.tags.moreTags.ariaLabel": "その他のタグバッジ",
"xpack.observability.create.annotation": "注釈の作成中に問題が発生しました。{message}",
"xpack.observability.create.errorNotification": "調査の作成中に問題が発生しました",
"xpack.observability.createAnnotation.addAnnotationModalHeaderTitleLabel": "注釈を作成",
"xpack.observability.createAnnotation.closeButtonEmptyLabel": "閉じる",
"xpack.observability.createAnnotation.deleteButtonLabel": "削除",

View file

@ -24577,110 +24577,6 @@
"xpack.inventory.shareLink.shareButtonLabel": "共享",
"xpack.inventory.shareLink.shareToastFailureLabel": "无法复制短 URL。",
"xpack.inventory.shareLink.shareToastSuccessLabel": "短 URL 已复制到剪贴板!",
"xpack.investigateApp.addFromLibraryButtonLabel": "从库中导入",
"xpack.investigateApp.addInvestigationItem.errorMessage": "发生错误",
"xpack.investigateApp.addInvestigationItem.errorTitle": "错误",
"xpack.investigateApp.addInvestigationItem.successMessage": "项目已保存",
"xpack.investigateApp.addInvestigationNote.errorMessage": "发生错误",
"xpack.investigateApp.addInvestigationNote.errorTitle": "错误",
"xpack.investigateApp.addInvestigationNote.successMessage": "备注已保存",
"xpack.investigateApp.addObservationUI.addAnObservationChartButtonLabel": "添加观察图表",
"xpack.investigateApp.addObservationUI.cancelButtonLabel": "取消",
"xpack.investigateApp.addObservationUI.h2.addAnObservationChartLabel": "添加观察图表",
"xpack.investigateApp.addObservationUI.p.selectADataSourceLabel": "选择数据源以生成预览图表",
"xpack.investigateApp.appTitle": "调查",
"xpack.investigateApp.assistantHypothesis.analysisAborted": "分析已中止",
"xpack.investigateApp.assistantHypothesis.failedToLoadAnalysis": "无法加载分析",
"xpack.investigateApp.defaultChart.error_equation.description": "检查方程。",
"xpack.investigateApp.defaultChart.error_equation.title": "渲染图表时出错",
"xpack.investigateApp.defaultChart.noData.title": "没有可用图表数据",
"xpack.investigateApp.deleteInvestigationError": "无法删除调查:发生错误",
"xpack.investigateApp.deleteInvestigationErrorTitle": "错误",
"xpack.investigateApp.deleteInvestigationSuccess": "已成功删除调查",
"xpack.investigateApp.deleteModal.cancel": "取消",
"xpack.investigateApp.deleteModal.confirm": "删除",
"xpack.investigateApp.deleteModal.description": "无法在删除后恢复此调查。",
"xpack.investigateApp.deleteModal.title": "删除",
"xpack.investigateApp.detailsPage.breadcrumb.details": "调查详情",
"xpack.investigateApp.detailsPage.breadcrumb.list": "调查",
"xpack.investigateApp.esqlWidget.groupedByDateLabel": "@timestamp",
"xpack.investigateApp.events.fetch.error": "提取事件时出现问题",
"xpack.investigateApp.investigationDetails.editButtonLabel": "编辑",
"xpack.investigateApp.investigationDetails.escalateButtonLabel": "上报",
"xpack.investigateApp.investigationDetailsPage.closeButtonEmptyLabel": "关闭",
"xpack.investigateApp.investigationDetailsPage.h2.createLabel": "创建",
"xpack.investigateApp.investigationDetailsPage.h2.editLabel": "编辑",
"xpack.investigateApp.investigationDetailsPage.newInvestigationLabel": "新调查",
"xpack.investigateApp.investigationDetailsPage.saveButtonLabel": "保存",
"xpack.investigateApp.investigationEditForm.externalIncidentUrlLabel": "外部事件 URL",
"xpack.investigateApp.investigationEditForm.span.statusLabel": "状态",
"xpack.investigateApp.investigationEditForm.span.tagsLabel": "标签",
"xpack.investigateApp.investigationEditForm.span.titleLabel": "标题",
"xpack.investigateApp.investigationEventTypesFilter.alertLabel": "告警",
"xpack.investigateApp.investigationEventTypesFilter.annotationLabel": "标注",
"xpack.investigateApp.investigationEventTypesFilter.filterEventTypePopoverTitleLabel": "筛选事件类型",
"xpack.investigateApp.investigationEventTypesFilter.filtersFilterButtonLabel": "筛选",
"xpack.investigateApp.investigationHeader.externalIncidentTextLabel": "外部事件",
"xpack.investigateApp.investigationHeader.startedLabel": "已启动:{timeAgo}",
"xpack.investigateApp.investigationList.allLabel": "正在显示所有项",
"xpack.investigateApp.investigationList.createdByLabel": "创建者",
"xpack.investigateApp.investigationList.deleteAction": "删除",
"xpack.investigateApp.investigationList.deleteAction.ariaLabel": "删除调查“{name}”",
"xpack.investigateApp.investigationList.editAction": "编辑",
"xpack.investigateApp.investigationList.editAction.ariaLabel": "编辑调查“{name}”",
"xpack.investigateApp.investigationList.notesLabel": "注释",
"xpack.investigateApp.investigationList.searchField.label": "搜索......",
"xpack.investigateApp.investigationList.showingLabel": "正在显示第 {startItem}-{endItem} 个(共 {totalItemCount} 个)",
"xpack.investigateApp.investigationList.stats.activeLabel": "活动",
"xpack.investigateApp.investigationList.stats.cancelledLabel": "已取消",
"xpack.investigateApp.investigationList.stats.mitigatedLabel": "已缓解",
"xpack.investigateApp.investigationList.stats.resolvedLabel": "已解决",
"xpack.investigateApp.investigationList.stats.triageLabel": "分类",
"xpack.investigateApp.investigationList.tableCaption": "调查列表",
"xpack.investigateApp.investigationList.tagsLabel": "标签",
"xpack.investigateApp.investigationList.titleLabel": "名称",
"xpack.investigateApp.investigationList.updatedAtLabel": "更新时间",
"xpack.investigateApp.investigationListPage.createButtonLabel": "创建",
"xpack.investigateApp.investigationNotes.addButtonLabel": "添加",
"xpack.investigateApp.investigationNotes.cancelEditButtonLabel": "取消",
"xpack.investigateApp.investigationNotes.euiFormRow.notesLabel": "备注",
"xpack.investigateApp.investigationNotes.header": "备注",
"xpack.investigateApp.investigationNotes.placeholder": "为调查添加备注",
"xpack.investigateApp.investigationNotes.updateNoteButtonLabel": "更新备注",
"xpack.investigateApp.InvestigationNotFound.body": "加载调查时出错。请联系您的管理员寻求帮助。",
"xpack.investigateApp.InvestigationNotFound.title": "无法加载调查",
"xpack.investigateApp.investigationsDeepLinkTitle": "所有调查",
"xpack.investigateApp.InvestigationsNotFound.body": "加载调查时出错。请联系您的管理员寻求帮助。",
"xpack.investigateApp.InvestigationsNotFound.title": "无法加载调查",
"xpack.investigateApp.listPage.breadcrumb.list": "调查",
"xpack.investigateApp.listPage.title": "调查",
"xpack.investigateApp.newInvestigateDeepLinkTitle": "新调查",
"xpack.investigateApp.renderableItems.div.notFoundLabel": "找不到类型 {type}",
"xpack.investigateApp.searchBar.statusFilterButtonLabel": "状态",
"xpack.investigateApp.searchBar.tagsFilterButtonLabel": "标签",
"xpack.investigateApp.suggestVisualizationList.errorLoadingSuggestionsLabel": "加载建议时出错:{message}",
"xpack.investigateApp.suggestVisualizationList.loadingSuggestionsLabel": "正在加载建议",
"xpack.investigateApp.suggestVisualizationList.noSuggestionsLabel": "无合适建议",
"xpack.investigateApp.useCreateInvestigation.errorMessage": "发生错误",
"xpack.investigateApp.useCreateInvestigation.errorTitle": "错误",
"xpack.investigateApp.useCreateInvestigation.successMessage": "调查已创建",
"xpack.investigateApp.useDeleteInvestigationItem.errorMessage": "发生错误",
"xpack.investigateApp.useDeleteInvestigationItem.errorTitle": "错误",
"xpack.investigateApp.useDeleteInvestigationItem.successMessage": "项目已删除",
"xpack.investigateApp.useDeleteInvestigationNote.errorMessage": "发生错误",
"xpack.investigateApp.useDeleteInvestigationNote.errorTitle": "错误",
"xpack.investigateApp.useDeleteInvestigationNote.successMessage": "备注已删除",
"xpack.investigateApp.useFetchAllInvestigationStats.errorTitle": "提取调查统计信息时出现问题",
"xpack.investigateApp.useFetchAllInvestigationTags.errorTitle": "提取调查标签时出现问题",
"xpack.investigateApp.useFetchInvestigation.errorTitle": "提取调查时出现问题",
"xpack.investigateApp.useFetchInvestigationItems.errorTitle": "提取调查项目时出现问题",
"xpack.investigateApp.useFetchInvestigationList.errorTitle": "提取调查时出现问题",
"xpack.investigateApp.useFetchInvestigationNotes.errorTitle": "提取调查备注时出现问题",
"xpack.investigateApp.useFetchUserProfiles.errorTitle": "提取用户配置文件时出现问题",
"xpack.investigateApp.useUpdateInvestigation.successMessage": "调查已更新",
"xpack.investigateApp.useUpdateInvestigationNote.errorMessage": "发生错误",
"xpack.investigateApp.useUpdateInvestigationNote.errorTitle": "错误",
"xpack.investigateApp.useUpdateInvestigationNote.successMessage": "备注已更新",
"xpack.lens.action.exploreInDiscover": "在 Discover 中浏览",
"xpack.lens.AggBasedLabel": "基于聚合的可视化",
"xpack.lens.app.addToLibrary": "保存到库",
@ -32287,7 +32183,6 @@
"xpack.observability.component.tags.moreTags": "+ 另外 {number} 个",
"xpack.observability.component.tags.moreTags.ariaLabel": "更多标签徽章",
"xpack.observability.create.annotation": "创建标注 {message} 时出现问题",
"xpack.observability.create.errorNotification": "创建调查时出现问题",
"xpack.observability.createAnnotation.addAnnotationModalHeaderTitleLabel": "创建标注",
"xpack.observability.createAnnotation.closeButtonEmptyLabel": "关闭",
"xpack.observability.createAnnotation.deleteButtonLabel": "删除",

View file

@ -1,3 +0,0 @@
# @kbn/investigation-shared
Empty package generated by @kbn/generate

View file

@ -1,8 +0,0 @@
/*
* 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.
*/
export * from './src';

View file

@ -1,12 +0,0 @@
/*
* 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.
*/
module.exports = {
preset: '@kbn/test/jest_node',
rootDir: '../../../../..',
roots: ['<rootDir>/x-pack/solutions/observability/packages/kbn-investigation-shared'],
};

View file

@ -1,9 +0,0 @@
{
"type": "shared-common",
"id": "@kbn/investigation-shared",
"owner": [
"@elastic/obs-ux-management-team"
],
"group": "observability",
"visibility": "private"
}

View file

@ -1,6 +0,0 @@
{
"name": "@kbn/investigation-shared",
"private": true,
"version": "1.0.0",
"license": "Elastic License 2.0"
}

View file

@ -1,9 +0,0 @@
/*
* 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.
*/
export * from './rest_specs';
export * from './schema';

View file

@ -1,31 +0,0 @@
/*
* 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 { z } from '@kbn/zod';
import { investigationResponseSchema } from './investigation';
import { alertOriginSchema, blankOriginSchema } from '../schema';
const createInvestigationParamsSchema = z.object({
body: z.object({
id: z.string(),
title: z.string(),
params: z.object({
timeRange: z.object({ from: z.number(), to: z.number() }),
}),
origin: z.union([alertOriginSchema, blankOriginSchema]),
tags: z.array(z.string()),
externalIncidentUrl: z.string().nullable(),
}),
});
const createInvestigationResponseSchema = investigationResponseSchema;
type CreateInvestigationParams = z.infer<typeof createInvestigationParamsSchema.shape.body>;
type CreateInvestigationResponse = z.output<typeof createInvestigationResponseSchema>;
export { createInvestigationParamsSchema, createInvestigationResponseSchema };
export type { CreateInvestigationParams, CreateInvestigationResponse };

View file

@ -1,25 +0,0 @@
/*
* 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 { z } from '@kbn/zod';
import { itemSchema } from '../schema';
import { investigationItemResponseSchema } from './investigation_item';
const createInvestigationItemParamsSchema = z.object({
path: z.object({
investigationId: z.string(),
}),
body: itemSchema,
});
const createInvestigationItemResponseSchema = investigationItemResponseSchema;
type CreateInvestigationItemParams = z.infer<typeof createInvestigationItemParamsSchema.shape.body>;
type CreateInvestigationItemResponse = z.output<typeof createInvestigationItemResponseSchema>;
export { createInvestigationItemParamsSchema, createInvestigationItemResponseSchema };
export type { CreateInvestigationItemParams, CreateInvestigationItemResponse };

View file

@ -1,26 +0,0 @@
/*
* 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 { z } from '@kbn/zod';
import { investigationNoteResponseSchema } from './investigation_note';
const createInvestigationNoteParamsSchema = z.object({
path: z.object({
investigationId: z.string(),
}),
body: z.object({
content: z.string(),
}),
});
const createInvestigationNoteResponseSchema = investigationNoteResponseSchema;
type CreateInvestigationNoteParams = z.infer<typeof createInvestigationNoteParamsSchema.shape.body>;
type CreateInvestigationNoteResponse = z.output<typeof createInvestigationNoteResponseSchema>;
export { createInvestigationNoteParamsSchema, createInvestigationNoteResponseSchema };
export type { CreateInvestigationNoteParams, CreateInvestigationNoteResponse };

View file

@ -1,18 +0,0 @@
/*
* 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 { z } from '@kbn/zod';
const deleteInvestigationParamsSchema = z.object({
path: z.object({
investigationId: z.string(),
}),
});
type DeleteInvestigationParams = z.infer<typeof deleteInvestigationParamsSchema.shape.path>;
export { deleteInvestigationParamsSchema };
export type { DeleteInvestigationParams };

View file

@ -1,20 +0,0 @@
/*
* 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 { z } from '@kbn/zod';
const deleteInvestigationItemParamsSchema = z.object({
path: z.object({
investigationId: z.string(),
itemId: z.string(),
}),
});
type DeleteInvestigationItemParams = z.infer<typeof deleteInvestigationItemParamsSchema.shape.path>;
export { deleteInvestigationItemParamsSchema };
export type { DeleteInvestigationItemParams };

View file

@ -1,20 +0,0 @@
/*
* 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 { z } from '@kbn/zod';
const deleteInvestigationNoteParamsSchema = z.object({
path: z.object({
investigationId: z.string(),
noteId: z.string(),
}),
});
type DeleteInvestigationNoteParams = z.infer<typeof deleteInvestigationNoteParamsSchema.shape.path>;
export { deleteInvestigationNoteParamsSchema };
export type { DeleteInvestigationNoteParams };

View file

@ -1,45 +0,0 @@
/*
* 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 { z } from '@kbn/zod';
const metricsSchema = z.object({
failedTransactionRate: z.number().optional(),
latency: z.number().optional(),
throughput: z.number().optional(),
logErrorRate: z.number().optional(),
logRate: z.number().optional(),
});
const entitySchema = z.object({
id: z.string(),
definition_id: z.string(),
definition_version: z.string(),
display_name: z.string(),
last_seen_timestamp: z.string(),
identity_fields: z.array(z.string()),
schema_version: z.string(),
type: z.string(),
metrics: metricsSchema,
});
const entitySourceSchema = z.object({
dataStream: z.string().optional(),
});
const entityWithSourceSchema = z.intersection(
entitySchema,
z.object({
sources: z.array(entitySourceSchema),
})
);
type EntityWithSource = z.output<typeof entityWithSourceSchema>;
type EntitySource = z.output<typeof entitySourceSchema>;
export { entitySchema, entityWithSourceSchema };
export type { EntityWithSource, EntitySource };

View file

@ -1,36 +0,0 @@
/*
* 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 { z } from '@kbn/zod';
import { investigationResponseSchema } from './investigation';
const findInvestigationsParamsSchema = z
.object({
query: z
.object({
alertId: z.string(),
search: z.string(),
filter: z.string(),
page: z.coerce.number(),
perPage: z.coerce.number(),
})
.partial(),
})
.partial();
const findInvestigationsResponseSchema = z.object({
page: z.number(),
perPage: z.number(),
total: z.number(),
results: z.array(investigationResponseSchema),
});
type FindInvestigationsParams = z.infer<typeof findInvestigationsParamsSchema.shape.query>;
type FindInvestigationsResponse = z.output<typeof findInvestigationsResponseSchema>;
export { findInvestigationsParamsSchema, findInvestigationsResponseSchema };
export type { FindInvestigationsParams, FindInvestigationsResponse };

View file

@ -1,23 +0,0 @@
/*
* 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 { z } from '@kbn/zod';
import { investigationResponseSchema } from './investigation';
const getInvestigationParamsSchema = z.object({
path: z.object({
investigationId: z.string(),
}),
});
const getInvestigationResponseSchema = investigationResponseSchema;
type GetInvestigationParams = z.infer<typeof getInvestigationParamsSchema.shape.path>; // Parsed payload used by the backend
type GetInvestigationResponse = z.output<typeof getInvestigationResponseSchema>; // Raw response sent to the frontend
export { getInvestigationParamsSchema, getInvestigationResponseSchema };
export type { GetInvestigationParams, GetInvestigationResponse };

View file

@ -1,23 +0,0 @@
/*
* 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 { z } from '@kbn/zod';
import { statusSchema } from '../schema';
const getAllInvestigationStatsParamsSchema = z.object({
query: z.object({}),
});
const getAllInvestigationStatsResponseSchema = z.object({
count: z.record(statusSchema, z.number()),
total: z.number(),
});
type GetAllInvestigationStatsResponse = z.output<typeof getAllInvestigationStatsResponseSchema>;
export { getAllInvestigationStatsParamsSchema, getAllInvestigationStatsResponseSchema };
export type { GetAllInvestigationStatsResponse };

View file

@ -1,19 +0,0 @@
/*
* 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 { z } from '@kbn/zod';
const getAllInvestigationTagsParamsSchema = z.object({
query: z.object({}),
});
const getAllInvestigationTagsResponseSchema = z.string().array();
type GetAllInvestigationTagsResponse = z.output<typeof getAllInvestigationTagsResponseSchema>;
export { getAllInvestigationTagsParamsSchema, getAllInvestigationTagsResponseSchema };
export type { GetAllInvestigationTagsResponse };

View file

@ -1,32 +0,0 @@
/*
* 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 { z } from '@kbn/zod';
import { entityWithSourceSchema } from './entity';
const getEntitiesParamsSchema = z
.object({
query: z
.object({
'service.name': z.string(),
'service.environment': z.string(),
'host.name': z.string(),
'container.id': z.string(),
})
.partial(),
})
.partial();
const getEntitiesResponseSchema = z.object({
entities: z.array(entityWithSourceSchema),
});
type GetEntitiesParams = z.infer<typeof getEntitiesParamsSchema.shape.query>;
type GetEntitiesResponse = z.output<typeof getEntitiesResponseSchema>;
export { getEntitiesParamsSchema, getEntitiesResponseSchema };
export type { GetEntitiesParams, GetEntitiesResponse };

View file

@ -1,41 +0,0 @@
/*
* 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 { z } from '@kbn/zod';
import { eventTypeSchema, eventSchema } from '../schema';
const getEventsParamsSchema = z
.object({
query: z
.object({
rangeFrom: z.string(),
rangeTo: z.string(),
filter: z.string(),
eventTypes: z.string().transform((val, ctx) => {
const eventTypes = val.split(',');
const hasInvalidType = eventTypes.some((eventType) => !eventTypeSchema.parse(eventType));
if (hasInvalidType) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: 'Invalid event type',
});
return z.NEVER;
}
return val.split(',').map((v) => eventTypeSchema.parse(v));
}),
})
.partial(),
})
.partial();
const getEventsResponseSchema = z.array(eventSchema);
type GetEventsParams = z.infer<typeof getEventsParamsSchema.shape.query>;
type GetEventsResponse = z.output<typeof getEventsResponseSchema>;
export { getEventsParamsSchema, getEventsResponseSchema };
export type { GetEventsParams, GetEventsResponse };

View file

@ -1,22 +0,0 @@
/*
* 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 { z } from '@kbn/zod';
import { investigationItemResponseSchema } from './investigation_item';
const getInvestigationItemsParamsSchema = z.object({
path: z.object({
investigationId: z.string(),
}),
});
const getInvestigationItemsResponseSchema = z.array(investigationItemResponseSchema);
type GetInvestigationItemsResponse = z.output<typeof getInvestigationItemsResponseSchema>;
export { getInvestigationItemsParamsSchema, getInvestigationItemsResponseSchema };
export type { GetInvestigationItemsResponse };

View file

@ -1,22 +0,0 @@
/*
* 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 { z } from '@kbn/zod';
import { investigationNoteResponseSchema } from './investigation_note';
const getInvestigationNotesParamsSchema = z.object({
path: z.object({
investigationId: z.string(),
}),
});
const getInvestigationNotesResponseSchema = z.array(investigationNoteResponseSchema);
type GetInvestigationNotesResponse = z.output<typeof getInvestigationNotesResponseSchema>;
export { getInvestigationNotesParamsSchema, getInvestigationNotesResponseSchema };
export type { GetInvestigationNotesResponse };

View file

@ -1,50 +0,0 @@
/*
* 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.
*/
export type * from './create';
export type * from './create_item';
export type * from './create_note';
export type * from './delete';
export type * from './delete_item';
export type * from './delete_note';
export type * from './find';
export type * from './get';
export type * from './get_items';
export type * from './get_notes';
export type * from './get_all_investigation_stats';
export type * from './get_all_investigation_tags';
export type * from './investigation';
export type * from './investigation_item';
export type * from './investigation_note';
export type * from './update';
export type * from './update_item';
export type * from './update_note';
export type * from './get_events';
export type * from './entity';
export type * from './get_entities';
export * from './create';
export * from './create_item';
export * from './create_note';
export * from './delete';
export * from './delete_item';
export * from './delete_note';
export * from './find';
export * from './get';
export * from './get_items';
export * from './get_notes';
export * from './get_all_investigation_stats';
export * from './get_all_investigation_tags';
export * from './investigation';
export * from './investigation_item';
export * from './investigation_note';
export * from './update';
export * from './update_item';
export * from './update_note';
export * from './get_events';
export * from './entity';
export * from './get_entities';

View file

@ -1,16 +0,0 @@
/*
* 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 { z } from '@kbn/zod';
import { investigationSchema } from '../schema';
const investigationResponseSchema = investigationSchema;
type InvestigationResponse = z.output<typeof investigationResponseSchema>;
export { investigationResponseSchema };
export type { InvestigationResponse };

View file

@ -1,16 +0,0 @@
/*
* 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 { z } from '@kbn/zod';
import { investigationItemSchema } from '../schema';
const investigationItemResponseSchema = investigationItemSchema;
type InvestigationItemResponse = z.output<typeof investigationItemResponseSchema>;
export { investigationItemResponseSchema };
export type { InvestigationItemResponse };

View file

@ -1,16 +0,0 @@
/*
* 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 { z } from '@kbn/zod';
import { investigationNoteSchema } from '../schema';
const investigationNoteResponseSchema = investigationNoteSchema;
type InvestigationNoteResponse = z.output<typeof investigationNoteResponseSchema>;
export { investigationNoteResponseSchema };
export type { InvestigationNoteResponse };

View file

@ -1,38 +0,0 @@
/*
* 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 { z } from '@kbn/zod';
import { investigationResponseSchema } from './investigation';
import { statusSchema } from '../schema';
const updateInvestigationParamsSchema = z.object({
path: z.object({
investigationId: z.string(),
}),
body: z
.object({
title: z.string(),
status: statusSchema,
params: z.object({
timeRange: z.object({ from: z.number(), to: z.number() }),
}),
tags: z.array(z.string()),
externalIncidentUrl: z.string().nullable(),
rootCauseAnalysis: z.object({
events: z.array(z.any()),
}),
})
.partial(),
});
const updateInvestigationResponseSchema = investigationResponseSchema;
type UpdateInvestigationParams = z.infer<typeof updateInvestigationParamsSchema.shape.body>;
type UpdateInvestigationResponse = z.output<typeof updateInvestigationResponseSchema>;
export { updateInvestigationParamsSchema, updateInvestigationResponseSchema };
export type { UpdateInvestigationParams, UpdateInvestigationResponse };

View file

@ -1,26 +0,0 @@
/*
* 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 { z } from '@kbn/zod';
import { investigationItemResponseSchema } from './investigation_item';
import { itemSchema } from '../schema';
const updateInvestigationItemParamsSchema = z.object({
path: z.object({
investigationId: z.string(),
itemId: z.string(),
}),
body: itemSchema,
});
const updateInvestigationItemResponseSchema = investigationItemResponseSchema;
type UpdateInvestigationItemParams = z.infer<typeof updateInvestigationItemParamsSchema.shape.body>;
type UpdateInvestigationItemResponse = z.output<typeof updateInvestigationItemResponseSchema>;
export { updateInvestigationItemParamsSchema, updateInvestigationItemResponseSchema };
export type { UpdateInvestigationItemParams, UpdateInvestigationItemResponse };

View file

@ -1,27 +0,0 @@
/*
* 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 { z } from '@kbn/zod';
import { investigationNoteResponseSchema } from './investigation_note';
const updateInvestigationNoteParamsSchema = z.object({
path: z.object({
investigationId: z.string(),
noteId: z.string(),
}),
body: z.object({
content: z.string(),
}),
});
const updateInvestigationNoteResponseSchema = investigationNoteResponseSchema;
type UpdateInvestigationNoteParams = z.infer<typeof updateInvestigationNoteParamsSchema.shape.body>;
type UpdateInvestigationNoteResponse = z.output<typeof updateInvestigationNoteResponseSchema>;
export { updateInvestigationNoteParamsSchema, updateInvestigationNoteResponseSchema };
export type { UpdateInvestigationNoteParams, UpdateInvestigationNoteResponse };

View file

@ -1,54 +0,0 @@
/*
* 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 { z } from '@kbn/zod';
const eventTypeSchema = z.union([
z.literal('annotation'),
z.literal('alert'),
z.literal('error_rate'),
z.literal('latency'),
z.literal('anomaly'),
]);
const sourceSchema = z.record(z.string(), z.any());
const annotationEventSchema = z.object({
eventType: z.literal('annotation'),
id: z.string(),
title: z.string(),
description: z.string(),
timestamp: z.number(),
source: sourceSchema.optional(),
annotationType: z.string().optional(),
});
const alertStatusSchema = z.union([
z.literal('active'),
z.literal('flapping'),
z.literal('recovered'),
z.literal('untracked'),
]);
const alertEventSchema = z.object({
eventType: z.literal('alert'),
id: z.string(),
title: z.string(),
description: z.string(),
timestamp: z.number(),
source: sourceSchema.optional(),
alertStatus: alertStatusSchema,
});
const eventSchema = z.discriminatedUnion('eventType', [annotationEventSchema, alertEventSchema]);
type EventResponse = z.output<typeof eventSchema>;
type AlertEventResponse = z.output<typeof alertEventSchema>;
type AnnotationEventResponse = z.output<typeof annotationEventSchema>;
export type { EventResponse, AlertEventResponse, AnnotationEventResponse };
export { eventSchema, eventTypeSchema, alertEventSchema, annotationEventSchema };

View file

@ -1,14 +0,0 @@
/*
* 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.
*/
export * from './investigation';
export * from './investigation_item';
export * from './investigation_note';
export * from './origin';
export * from './event';
export type * from './investigation';

View file

@ -1,46 +0,0 @@
/*
* 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 { z } from '@kbn/zod';
import { alertOriginSchema, blankOriginSchema } from './origin';
import { investigationNoteSchema } from './investigation_note';
import { investigationItemSchema } from './investigation_item';
const statusSchema = z.union([
z.literal('triage'),
z.literal('active'),
z.literal('mitigated'),
z.literal('resolved'),
z.literal('cancelled'),
]);
const investigationSchema = z.object({
id: z.string(),
title: z.string(),
createdAt: z.number(),
createdBy: z.string(),
updatedAt: z.number(),
params: z.object({
timeRange: z.object({ from: z.number(), to: z.number() }),
}),
origin: z.union([alertOriginSchema, blankOriginSchema]),
status: statusSchema,
tags: z.array(z.string()),
notes: z.array(investigationNoteSchema),
items: z.array(investigationItemSchema),
externalIncidentUrl: z.string().nullable(),
rootCauseAnalysis: z
.object({
events: z.array(z.any()),
})
.optional(),
});
type Status = z.infer<typeof statusSchema>;
export type { Status };
export { investigationSchema, statusSchema };

View file

@ -1,30 +0,0 @@
/*
* 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 { z } from '@kbn/zod';
const itemSchema = z.object({
title: z.string(),
type: z.string(),
params: z.record(z.string(), z.any()),
});
const investigationItemSchema = z.intersection(
z.object({
id: z.string(),
createdAt: z.number(),
createdBy: z.string(),
updatedAt: z.number(),
}),
itemSchema
);
type Item = z.infer<typeof itemSchema>;
type InvestigationItem = z.infer<typeof investigationItemSchema>;
export type { Item, InvestigationItem };
export { investigationItemSchema, itemSchema };

View file

@ -1,18 +0,0 @@
/*
* 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 { z } from '@kbn/zod';
const investigationNoteSchema = z.object({
id: z.string(),
content: z.string(),
createdAt: z.number(),
updatedAt: z.number(),
createdBy: z.string(),
});
export { investigationNoteSchema };

View file

@ -1,13 +0,0 @@
/*
* 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 { z } from '@kbn/zod';
const blankOriginSchema = z.object({ type: z.literal('blank') });
const alertOriginSchema = z.object({ type: z.literal('alert'), id: z.string() });
export { alertOriginSchema, blankOriginSchema };

View file

@ -1,19 +0,0 @@
{
"extends": "../../../../../tsconfig.base.json",
"compilerOptions": {
"outDir": "target/types",
"types": [
"jest",
"node"
]
},
"include": [
"**/*.ts",
],
"exclude": [
"target/**/*"
],
"kbn_references": [
"@kbn/zod"
]
}

View file

@ -1,8 +0,0 @@
/*
* 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.
*/
export { mergePlainObjects } from './utils/merge_plain_objects';

View file

@ -1,13 +0,0 @@
/*
* 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.
*/
export interface GlobalWidgetParameters {
timeRange: {
from: string;
to: string;
};
}

View file

@ -1,74 +0,0 @@
/*
* 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 type { RequiredKeys } from 'utility-types';
import { isPlainObject, mergeWith, MergeWithCustomizer } from 'lodash';
type DeepOverwrite<T, U> = U extends Record<string, any>
? Omit<T, RequiredKeys<U>> & {
[K in keyof U]: K extends keyof T ? DeepOverwrite<T[K], U[K]> : U[K];
}
: U extends undefined
? T
: U;
type DeepPartialPlainObjects<T> = T extends Record<string, any>
? Partial<{
[TKey in keyof T]: DeepPartialPlainObjects<T[TKey]>;
}>
: T;
type Mergable = Record<string, any>;
type MergeRecursively<TMergables extends Mergable[]> = TMergables extends [
infer THead,
...infer TTail
]
? TTail extends Mergable[]
? DeepOverwrite<THead, MergeRecursively<TTail>>
: THead
: TMergables extends [infer THead]
? THead
: TMergables extends []
? {}
: {};
const customMergeFunction: MergeWithCustomizer = (value, sourceValue) => {
if (isPlainObject(sourceValue)) {
return mergeWith(value, sourceValue, customMergeFunction);
}
return undefined;
};
function mergePlainObjectsOnly(...sources: Mergable[]) {
return mergeWith({}, ...sources.concat(customMergeFunction));
}
export function mergePlainObjects<T1 extends Record<string, any> | undefined>(t1: T1): T1;
export function mergePlainObjects<T1 extends Mergable, T2 extends DeepPartialPlainObjects<T1>>(
t1: T1,
t2: T2
): MergeRecursively<[T1, T2]>;
export function mergePlainObjects<
T1 extends Mergable,
T2 extends DeepPartialPlainObjects<T1>,
T3 extends DeepPartialPlainObjects<T2>
>(t1: T1, t2: T2, t3: T3): MergeRecursively<[T1, T2, T3]>;
export function mergePlainObjects<
T1 extends Mergable,
T2 extends DeepPartialPlainObjects<T1>,
T3 extends DeepPartialPlainObjects<T2>,
T4 extends DeepPartialPlainObjects<T3>
>(t1: T1, t2: T2, t3: T4): MergeRecursively<[T1, T2, T3, T4]>;
export function mergePlainObjects(...sources: Array<Record<string, any>>) {
const merged = mergePlainObjectsOnly(...sources);
return merged;
}

View file

@ -1,23 +0,0 @@
/*
* 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.
*/
module.exports = {
preset: '@kbn/test',
rootDir: '../../../../..',
roots: [
'<rootDir>/x-pack/solutions/observability/plugins/investigate/public',
'<rootDir>/x-pack/solutions/observability/plugins/investigate/common',
'<rootDir>/x-pack/solutions/observability/plugins/investigate/server',
],
setupFiles: [],
collectCoverage: true,
collectCoverageFrom: [
'<rootDir>/x-pack/solutions/observability/plugins/investigate/{common,public,server}/**/*.{js,ts,tsx}',
],
coverageReporters: ['html'],
};

View file

@ -1,20 +0,0 @@
{
"type": "plugin",
"id": "@kbn/investigate-plugin",
"owner": "@elastic/obs-ux-management-team",
"group": "observability",
"visibility": "private",
"plugin": {
"id": "investigate",
"server": true,
"browser": true,
"configPath": ["xpack", "investigate"],
"requiredPlugins": [
"observabilityAIAssistant"
],
"requiredBundles": [
],
"optionalPlugins": [],
"extraPublicDirs": []
}
}

View file

@ -1,32 +0,0 @@
/*
* 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 type { PluginInitializer, PluginInitializerContext } from '@kbn/core/public';
import { InvestigatePlugin } from './plugin';
import type {
InvestigatePublicSetup,
InvestigatePublicStart,
InvestigateSetupDependencies,
InvestigateStartDependencies,
ConfigSchema,
} from './types';
export type { InvestigatePublicSetup, InvestigatePublicStart };
export { type GlobalWidgetParameters } from '../common/types';
export { mergePlainObjects } from '../common/utils/merge_plain_objects';
export { getEsFilterFromGlobalParameters } from './util/get_es_filters_from_global_parameters';
export const plugin: PluginInitializer<
InvestigatePublicSetup,
InvestigatePublicStart,
InvestigateSetupDependencies,
InvestigateStartDependencies
> = (pluginInitializerContext: PluginInitializerContext<ConfigSchema>) =>
new InvestigatePlugin(pluginInitializerContext);

View file

@ -1,45 +0,0 @@
/*
* 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 { GlobalWidgetParameters } from '../../common/types';
export type ItemDefinitionData = Record<string, any>;
export type ItemDefinitionParams = Record<string, any>;
export interface ItemDefinition<
Params extends ItemDefinitionParams = {},
Data extends ItemDefinitionData = {}
> {
type: string;
generate: (option: { itemParams: Params; globalParams: GlobalWidgetParameters }) => Promise<Data>;
render: (option: {
data: Data;
itemParams: Params;
globalParams: GlobalWidgetParameters;
}) => React.ReactNode;
}
export class ItemDefinitionRegistry {
private readonly definitions: ItemDefinition[] = [];
constructor() {}
public registerItem<Params extends ItemDefinitionParams, Data extends ItemDefinitionData>(
definition: ItemDefinition<Params, Data>
) {
// @ts-ignore TODO fix this type issue with generics
this.definitions.push(definition);
}
public getItemDefinitions(): ItemDefinition[] {
return this.definitions;
}
public getItemDefinitionByType(type: string): ItemDefinition | undefined {
return this.definitions.find((definition) => definition.type === type);
}
}

View file

@ -1,55 +0,0 @@
/*
* 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 type { CoreSetup, CoreStart, Plugin, PluginInitializerContext } from '@kbn/core/public';
import {
ItemDefinition,
ItemDefinitionData,
ItemDefinitionParams,
ItemDefinitionRegistry,
} from './investigation/item_definition_registry';
import type {
ConfigSchema,
InvestigatePublicSetup,
InvestigatePublicStart,
InvestigateSetupDependencies,
InvestigateStartDependencies,
} from './types';
export class InvestigatePlugin
implements
Plugin<
InvestigatePublicSetup,
InvestigatePublicStart,
InvestigateSetupDependencies,
InvestigateStartDependencies
>
{
private itemDefinitionRegistry: ItemDefinitionRegistry = new ItemDefinitionRegistry();
constructor(context: PluginInitializerContext<ConfigSchema>) {}
setup(coreSetup: CoreSetup, pluginsSetup: InvestigateSetupDependencies): InvestigatePublicSetup {
return {
registerItemDefinition: <
Params extends ItemDefinitionParams,
Data extends ItemDefinitionData
>(
definition: ItemDefinition<Params, Data>
) => {
this.itemDefinitionRegistry.registerItem(definition);
},
};
}
start(coreStart: CoreStart, pluginsStart: InvestigateStartDependencies): InvestigatePublicStart {
return {
getItemDefinitions: () => this.itemDefinitionRegistry.getItemDefinitions(),
getItemDefinitionByType: (type: string) =>
this.itemDefinitionRegistry.getItemDefinitionByType(type),
};
}
}

View file

@ -1,33 +0,0 @@
/*
* 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.
*/
/* eslint-disable @typescript-eslint/no-empty-interface*/
import {
ItemDefinition,
ItemDefinitionData,
ItemDefinitionParams,
} from './investigation/item_definition_registry';
export interface ConfigSchema {}
export interface InvestigateSetupDependencies {}
export interface InvestigateStartDependencies {}
export interface InvestigatePublicSetup {
registerItemDefinition: <
Params extends ItemDefinitionParams = {},
Data extends ItemDefinitionData = {}
>(
itemDefinition: ItemDefinition<Params, Data>
) => void;
}
export interface InvestigatePublicStart {
getItemDefinitions: () => ItemDefinition[];
getItemDefinitionByType: (type: string) => ItemDefinition | undefined;
}

View file

@ -1,28 +0,0 @@
/*
* 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 { type BoolQuery, buildEsQuery } from '@kbn/es-query';
import type { GlobalWidgetParameters } from '../../common/types';
export function getEsFilterFromGlobalParameters({ timeRange }: Partial<GlobalWidgetParameters>): {
bool: BoolQuery;
} {
const esFilter = buildEsQuery(undefined, [], []);
if (timeRange) {
esFilter.bool.filter.push({
range: {
'@timestamp': {
gte: timeRange.from,
lte: timeRange.to,
},
},
});
}
return esFilter;
}

View file

@ -1,14 +0,0 @@
/*
* 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 { schema, type TypeOf } from '@kbn/config-schema';
export const config = schema.object({
enabled: schema.boolean({ defaultValue: false }),
});
export type InvestigateConfig = TypeOf<typeof config>;

View file

@ -1,36 +0,0 @@
/*
* 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 type {
PluginInitializer,
PluginInitializerContext,
PluginConfigDescriptor,
} from '@kbn/core/server';
import { InvestigateConfig } from './config';
import { InvestigatePlugin } from './plugin';
import type {
InvestigateServerSetup,
InvestigateServerStart,
InvestigateSetupDependencies,
InvestigateStartDependencies,
} from './types';
import { config as configSchema } from './config';
export type { InvestigateServerSetup, InvestigateServerStart };
export const config: PluginConfigDescriptor<InvestigateConfig> = {
schema: configSchema,
};
export const plugin: PluginInitializer<
InvestigateServerSetup,
InvestigateServerStart,
InvestigateSetupDependencies,
InvestigateStartDependencies
> = async (pluginInitializerContext: PluginInitializerContext<InvestigateConfig>) =>
await new InvestigatePlugin(pluginInitializerContext);

View file

@ -1,39 +0,0 @@
/*
* 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 type { CoreSetup, CoreStart, Plugin, PluginInitializerContext } from '@kbn/core/server';
import type { Logger } from '@kbn/logging';
import type { InvestigateConfig } from './config';
import type {
InvestigateServerSetup,
InvestigateServerStart,
InvestigateSetupDependencies,
InvestigateStartDependencies,
} from './types';
export class InvestigatePlugin
implements
Plugin<
InvestigateServerSetup,
InvestigateServerStart,
InvestigateSetupDependencies,
InvestigateStartDependencies
>
{
logger: Logger;
constructor(context: PluginInitializerContext<InvestigateConfig>) {
this.logger = context.logger.get();
}
setup(coreSetup: CoreSetup, pluginsSetup: InvestigateSetupDependencies): InvestigateServerSetup {
return {};
}
start(coreStart: CoreStart, pluginsStart: InvestigateStartDependencies): InvestigateServerStart {
return {};
}
}

View file

@ -1,16 +0,0 @@
/*
* 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.
*/
/* eslint-disable @typescript-eslint/no-empty-interface*/
export interface InvestigateSetupDependencies {}
export interface InvestigateStartDependencies {}
export interface InvestigateServerSetup {}
export interface InvestigateServerStart {}

View file

@ -1,20 +0,0 @@
{
"extends": "../../../../../tsconfig.base.json",
"compilerOptions": {
"outDir": "target/types"
},
"include": [
"../../../../typings/**/*",
"common/**/*",
"public/**/*",
"typings/**/*",
"public/**/*.json",
"server/**/*", ],
"kbn_references": [
"@kbn/core",
"@kbn/logging",
"@kbn/config-schema",
"@kbn/es-query",
],
"exclude": ["target/**/*"]
}

View file

@ -1,34 +0,0 @@
/*
* 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 { isPlainObject, mergeWith } from 'lodash';
type DeepOverwrite<T, U> = T extends Record<string, any>
? Omit<T, keyof U> & {
[TKey in keyof U]: T extends Record<TKey, any> ? DeepOverwrite<T[TKey], U[TKey]> : U[TKey];
}
: U;
type DeepPartialPlainObjects<T> = T extends Record<string, any>
? Partial<{
[TKey in keyof T]: DeepPartialPlainObjects<T[TKey]>;
}>
: T;
function mergePlainObjectsOnly<T, U>(val: T, src: U): DeepOverwrite<T, U> {
if (isPlainObject(src)) {
return mergeWith({}, val, src, mergePlainObjectsOnly) as DeepOverwrite<T, U>;
}
return src as DeepOverwrite<T, U>;
}
export function extendProps<
T extends Record<string, any> | undefined,
U extends DeepPartialPlainObjects<T>
>(props: T, extension: U): DeepOverwrite<T, U> {
return mergePlainObjectsOnly(props, extension);
}

View file

@ -1,117 +0,0 @@
/*
* 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, { useMemo } from 'react';
import type { DeeplyMockedKeys } from '@kbn/utility-types-jest';
import type { ESQLSearchResponse } from '@kbn/es-types';
import type { DataView } from '@kbn/data-views-plugin/common';
import { coreMock } from '@kbn/core/public/mocks';
import { dataViewPluginMocks } from '@kbn/data-views-plugin/public/mocks';
import { dataPluginMock } from '@kbn/data-plugin/public/mocks';
import { embeddablePluginMock } from '@kbn/embeddable-plugin/public/mocks';
import { unifiedSearchPluginMock } from '@kbn/unified-search-plugin/public/mocks';
import { SearchBar, IUnifiedSearchPluginServices } from '@kbn/unified-search-plugin/public';
import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
import { merge } from 'lodash';
import { Storage } from '@kbn/kibana-utils-plugin/public';
import { of } from 'rxjs';
import type { EsqlQueryMeta } from '../public/services/esql';
import type { InvestigateAppServices } from '../public/services/types';
import { InvestigateAppKibanaContext } from '../public/hooks/use_kibana';
export function getMockInvestigateAppContext(): DeeplyMockedKeys<InvestigateAppKibanaContext> {
const services: DeeplyMockedKeys<InvestigateAppServices> = {
esql: {
meta: jest.fn().mockImplementation((): Promise<EsqlQueryMeta> => {
return Promise.resolve({
suggestions: [],
columns: [],
dataView: {} as DataView,
});
}),
query: jest.fn().mockImplementation((): Promise<ESQLSearchResponse> => {
return Promise.resolve({
values: [],
columns: [],
});
}),
queryWithMeta: jest
.fn()
.mockImplementation((): Promise<{ meta: EsqlQueryMeta; query: ESQLSearchResponse }> => {
return Promise.resolve({
meta: {
suggestions: [],
columns: [],
dataView: {} as DataView,
},
query: {
values: [],
columns: [],
},
});
}),
},
charts: {} as any,
investigateAppRepositoryClient: {
fetch: jest.fn().mockImplementation(() => Promise.resolve()),
stream: jest.fn().mockImplementation(() => of()) as any,
},
};
const core = coreMock.createStart();
const dataMock = merge({}, dataPluginMock.createStartContract(), {
query: {
savedQueries: {},
timefilter: {
timefilter: {
getTime: () => ({ from: 'now-15m', to: 'now', mode: 'relative' }),
},
},
},
});
return {
core: core as any,
dependencies: {
start: {
data: dataMock,
unifiedSearch: merge({}, unifiedSearchPluginMock.createStartContract(), {
ui: {
SearchBar: function SearchBarWithContext(props: {}) {
const unifiedSearchServices = useMemo(() => {
return {
data: dataMock,
storage: new Storage(window.localStorage),
uiSettings: core.uiSettings,
} as unknown as IUnifiedSearchPluginServices;
}, []);
return (
<KibanaContextProvider services={unifiedSearchServices}>
<SearchBar {...props} />
</KibanaContextProvider>
);
},
},
}),
embeddable: merge({}, embeddablePluginMock.createStartContract(), {
getEmbeddableFactories: () => [
{
canCreateNew: () => true,
getDisplayName: () => 'Alerts',
type: 'alerts',
},
],
}),
investigate: {},
lens: {},
observabilityShared: {},
dataViews: dataViewPluginMocks.createStartContract(),
},
} as any,
services,
};
}

View file

@ -1,11 +0,0 @@
/*
* 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 { setProjectAnnotations } from '@storybook/react';
import * as globalStorybookConfig from './preview';
setProjectAnnotations(globalStorybookConfig);

View file

@ -1,8 +0,0 @@
/*
* 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.
*/
module.exports = require('@kbn/storybook').defaultConfig;

View file

@ -1,54 +0,0 @@
/*
* 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 { setKibanaServices } from '@kbn/esql/public/kibana_services';
import { coreMock } from '@kbn/core/public/mocks';
import { dataViewPluginMocks } from '@kbn/data-views-plugin/public/mocks';
import { dataPluginMock } from '@kbn/data-plugin/public/mocks';
import { expressionsPluginMock } from '@kbn/expressions-plugin/public/mocks';
import { uiActionsPluginMock } from '@kbn/ui-actions-plugin/public/mocks';
import type { Storage } from '@kbn/kibana-utils-plugin/public';
class LocalStorageMock {
public store: Record<string, unknown>;
constructor(defaultStore: Record<string, unknown>) {
this.store = defaultStore;
}
clear() {
this.store = {};
}
get(key: string) {
return this.store[key] || null;
}
set(key: string, value: unknown) {
this.store[key] = String(value);
}
remove(key: string) {
delete this.store[key];
}
}
const storage = new LocalStorageMock({}) as unknown as Storage;
setKibanaServices(
{
getJoinIndicesAutocomplete: async () => ({ indices: [] }),
variablesService: {
esqlVariables: [],
areSuggestionsEnabled: false,
enableSuggestions: () => undefined,
disableSuggestions: () => undefined,
clearVariables: () => undefined,
addVariable: () => undefined,
},
},
coreMock.createStart(),
dataViewPluginMocks.createStartContract(),
dataPluginMock.createStartContract(),
expressionsPluginMock.createStartContract(),
storage,
uiActionsPluginMock.createStartContract()
);

View file

@ -1,13 +0,0 @@
/*
* 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 { EuiThemeProviderDecorator } from '@kbn/kibana-react-plugin/common';
import * as jest from 'jest-mock';
window.jest = jest;
export const decorators = [EuiThemeProviderDecorator];

View file

@ -1,18 +0,0 @@
/*
* 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, { ComponentType, useMemo } from 'react';
import { InvestigateAppContextProvider } from '../public/components/investigate_app_context_provider';
import { getMockInvestigateAppContext } from './get_mock_investigate_app_services';
export function KibanaReactStorybookDecorator(Story: ComponentType) {
const context = useMemo(() => getMockInvestigateAppContext(), []);
return (
<InvestigateAppContextProvider context={context}>
<Story />
</InvestigateAppContextProvider>
);
}

View file

@ -1,14 +0,0 @@
/*
* 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.
*/
export const paths = {
investigations: `/app/investigations`,
create: `/app/investigations/new`,
investigationDetails: (id: string) => {
return `/app/investigations/${encodeURIComponent(id)}`;
},
};

View file

@ -1,36 +0,0 @@
/*
* 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 { EcsFieldsResponse } from '@kbn/rule-registry-plugin/common';
import {
ALERT_FLAPPING_HISTORY,
ALERT_RULE_EXECUTION_TIMESTAMP,
ALERT_RULE_EXECUTION_UUID,
EVENT_ACTION,
EVENT_KIND,
} from '@kbn/rule-registry-plugin/common/technical_rule_data_field_names';
import { omit } from 'lodash';
export function sanitizeAlert(alert: EcsFieldsResponse) {
return omit(
alert,
ALERT_RULE_EXECUTION_TIMESTAMP,
'_index',
ALERT_FLAPPING_HISTORY,
EVENT_ACTION,
EVENT_KIND,
ALERT_RULE_EXECUTION_UUID,
'@timestamp'
);
}
export function getRCAContext(alert: EcsFieldsResponse, serviceName: string) {
return `The user is investigating an alert for the ${serviceName} service,
and wants to find the root cause. Here is the alert:
${JSON.stringify(sanitizeAlert(alert))}`;
}

View file

@ -1,24 +0,0 @@
/*
* 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.
*/
module.exports = {
preset: '@kbn/test',
rootDir: '../../../../..',
roots: [
'<rootDir>/x-pack/solutions/observability/plugins/investigate_app/public',
'<rootDir>/x-pack/solutions/observability/plugins/investigate_app/server',
],
setupFiles: [
'<rootDir>/x-pack/solutions/observability/plugins/investigate_app/.storybook/jest_setup.js',
],
collectCoverage: true,
collectCoverageFrom: [
'<rootDir>/x-pack/solutions/observability/plugins/investigate_app/{public,server}/**/*.{js,ts,tsx}',
],
coverageReporters: ['html'],
};

View file

@ -1,45 +0,0 @@
{
"type": "plugin",
"id": "@kbn/investigate-app-plugin",
"owner": "@elastic/obs-ux-management-team",
"visibility": "private",
"group": "observability",
"plugin": {
"id": "investigateApp",
"server": true,
"browser": true,
"configPath": ["xpack", "investigateApp"],
"requiredPlugins": [
"investigate",
"observabilityShared",
"lens",
"charts",
"dataViews",
"data",
"embeddable",
"contentManagement",
"datasetQuality",
"unifiedSearch",
"security",
"observability",
"licensing",
"ruleRegistry",
"inference",
"alerting",
"spaces",
"slo",
"apmDataAccess",
"usageCollection"
],
"optionalPlugins": [
"observabilityAIAssistant",
"observabilityAIAssistantApp"
],
"requiredBundles": [
"esql",
"kibanaReact",
"kibanaUtils"
],
"extraPublicDirs": []
}
}

View file

@ -1,50 +0,0 @@
/*
* 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 type { CoreSetup, CoreStart, HttpFetchOptions } from '@kbn/core/public';
import type {
ClientRequestParamsOf,
ReturnOf,
RouteRepositoryClient,
} from '@kbn/server-route-repository';
import { createRepositoryClient } from '@kbn/server-route-repository-client';
import type { InvestigateAppServerRouteRepository } from '../../server';
type FetchOptions = Omit<HttpFetchOptions, 'body'> & {
body?: any;
};
export type InvestigateAppAPIClientOptions = Omit<
FetchOptions,
'query' | 'body' | 'pathname' | 'signal'
> & {
signal: AbortSignal | null;
};
export type InvestigateAppRepositoryClient = RouteRepositoryClient<
InvestigateAppServerRouteRepository,
InvestigateAppAPIClientOptions
>;
export type AutoAbortedInvestigateAppRepositoryClient = RouteRepositoryClient<
InvestigateAppServerRouteRepository,
Omit<InvestigateAppAPIClientOptions, 'signal'>
>;
export type InvestigateAppAPIEndpoint = keyof InvestigateAppServerRouteRepository;
export type APIReturnType<TEndpoint extends InvestigateAppAPIEndpoint> = ReturnOf<
InvestigateAppServerRouteRepository,
TEndpoint
>;
export type InvestigateAppAPIClientRequestParamsOf<TEndpoint extends InvestigateAppAPIEndpoint> =
ClientRequestParamsOf<InvestigateAppServerRouteRepository, TEndpoint>;
export function createInvestigateAppRepositoryClient(core: CoreStart | CoreSetup) {
return createRepositoryClient(core) as InvestigateAppRepositoryClient;
}

View file

@ -1,85 +0,0 @@
/*
* 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 type { CoreStart, CoreTheme } from '@kbn/core/public';
import { KibanaThemeProvider } from '@kbn/react-kibana-context-theme';
import { RedirectAppLinks } from '@kbn/shared-ux-link-redirect-app';
import { Route, Router, Routes } from '@kbn/shared-ux-router';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import type { History } from 'history';
import React, { useMemo } from 'react';
import type { Observable } from 'rxjs';
import { InvestigateAppContextProvider } from './components/investigate_app_context_provider';
import { InvestigateAppKibanaContext } from './hooks/use_kibana';
import { getRoutes } from './routes/config';
import { InvestigateAppServices } from './services/types';
import type { InvestigateAppStartDependencies } from './types';
const queryClient = new QueryClient();
function Application({
coreStart,
history,
pluginsStart,
theme$,
services,
}: {
coreStart: CoreStart;
history: History;
pluginsStart: InvestigateAppStartDependencies;
theme$: Observable<CoreTheme>;
services: InvestigateAppServices;
}) {
const theme = useMemo(() => {
return { theme$ };
}, [theme$]);
const context: InvestigateAppKibanaContext = useMemo(
() => ({
core: coreStart,
dependencies: {
start: pluginsStart,
},
services,
}),
[coreStart, pluginsStart, services]
);
const App = () => {
const routes = getRoutes();
return (
<Routes>
{Object.keys(routes).map((path) => {
const { handler, exact } = routes[path];
const Wrapper = () => {
return handler();
};
return <Route key={path} path={path} exact={exact} component={Wrapper} />;
})}
</Routes>
);
};
return (
<KibanaThemeProvider theme={theme}>
<InvestigateAppContextProvider context={context}>
<RedirectAppLinks coreStart={coreStart}>
<coreStart.i18n.Context>
<Router history={history}>
<QueryClientProvider client={queryClient}>
<App />
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
</Router>
</coreStart.i18n.Context>
</RedirectAppLinks>
</InvestigateAppContextProvider>
</KibanaThemeProvider>
);
}
export { Application };

View file

@ -1,21 +0,0 @@
/*
* 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 { EuiErrorBoundary } from '@elastic/eui';
import React from 'react';
function ThrowError({ error }: { error: Error }) {
throw error;
return <></>;
}
export function ErrorMessage({ error }: { error: Error }) {
return (
<EuiErrorBoundary>
<ThrowError error={error} />
</EuiErrorBoundary>
);
}

View file

@ -1,19 +0,0 @@
/*
* 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 from 'react';
import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
import { InvestigateAppKibanaContext } from '../../hooks/use_kibana';
export function InvestigateAppContextProvider({
context,
children,
}: {
context: InvestigateAppKibanaContext;
children: React.ReactNode;
}) {
return <KibanaContextProvider services={context}>{children}</KibanaContextProvider>;
}

View file

@ -1,74 +0,0 @@
/*
* 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 { EuiButtonEmpty, EuiText } from '@elastic/eui';
import { css } from '@emotion/css';
import classNames from 'classnames';
import React from 'react';
const buttonClassName = css`
opacity: 0.5;
&:disabled,
&:hover {
opacity: 1;
}
&:disabled {
color: inherit;
}
`;
const buttonOnlyClassName = css`
.euiButtonEmpty__content {
gap: 0;
}
`;
interface InvestigateTextButtonProps {
iconType: string;
disabled?: boolean;
onClick: () => void;
onMouseEnter?: React.MouseEventHandler<HTMLButtonElement>;
onMouseLeave?: React.MouseEventHandler<HTMLButtonElement>;
children?: string;
className?: string;
type?: 'submit' | 'reset' | 'button';
color?: React.ComponentProps<typeof EuiButtonEmpty>['color'];
size?: 'xs' | 's' | 'm';
iconSize?: 's' | 'm';
}
export function InvestigateTextButton({
iconType,
disabled,
onClick,
children,
onMouseEnter,
onMouseLeave,
className,
type,
color = 'text',
size = 's',
iconSize = 's',
}: InvestigateTextButtonProps) {
const props = {
size,
iconSize,
iconType,
color,
disabled,
className: classNames(buttonClassName, className, {
[buttonOnlyClassName]: !children,
}),
onClick,
onMouseEnter,
onMouseLeave,
type,
children: children ? <EuiText size="xs">{children}</EuiText> : undefined,
};
return <EuiButtonEmpty data-test-subj="investigateTextButton" {...props} />;
}

View file

@ -1,45 +0,0 @@
/*
* 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 { EuiFormRow, EuiFieldText } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React from 'react';
import { Controller, useFormContext } from 'react-hook-form';
import { InvestigationForm } from '../investigation_edit_form';
const I18N_LABEL = i18n.translate(
'xpack.investigateApp.investigationEditForm.externalIncidentUrlLabel',
{ defaultMessage: 'External incident URL' }
);
export function ExternalIncidentField() {
const { control, getFieldState } = useFormContext<InvestigationForm>();
return (
<EuiFormRow
fullWidth
isInvalid={getFieldState('externalIncidentUrl').invalid}
label={I18N_LABEL}
>
<Controller
name="externalIncidentUrl"
control={control}
rules={{ required: false }}
render={({ field: { ref, ...field }, fieldState }) => (
<EuiFieldText
{...field}
value={field.value || ''}
data-test-subj="investigateAppExternalIncidentFieldFieldText"
fullWidth
isInvalid={fieldState.invalid}
placeholder={I18N_LABEL}
/>
)}
/>
</EuiFormRow>
);
}

View file

@ -1,84 +0,0 @@
/*
* 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 { EuiComboBox, EuiFormRow } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { InvestigationResponse } from '@kbn/investigation-shared';
import React from 'react';
import { Controller, useFormContext } from 'react-hook-form';
import { InvestigationForm } from '../investigation_edit_form';
const I18N_STATUS_LABEL = i18n.translate(
'xpack.investigateApp.investigationEditForm.span.statusLabel',
{ defaultMessage: 'Status' }
);
export const statusToColor: Record<InvestigationResponse['status'], string> = {
triage: 'warning',
active: 'danger',
mitigated: 'success',
resolved: 'success',
cancelled: 'default',
};
const options = [
{
label: 'Triage',
value: 'triage',
color: statusToColor.triage,
},
{
label: 'Active',
value: 'active',
color: statusToColor.active,
},
{
label: 'Mitigated',
value: 'mitigated',
color: statusToColor.mitigated,
},
{
label: 'Resolved',
value: 'resolved',
color: statusToColor.resolved,
},
{
label: 'Cancelled',
value: 'cancelled',
color: statusToColor.cancelled,
},
];
export function StatusField() {
const { control, getFieldState } = useFormContext<InvestigationForm>();
return (
<EuiFormRow label={I18N_STATUS_LABEL} fullWidth isInvalid={getFieldState('status').invalid}>
<Controller
control={control}
name="status"
rules={{ required: true }}
render={({ field, fieldState }) => (
<EuiComboBox
{...field}
fullWidth
isInvalid={fieldState.invalid}
isClearable={false}
aria-label={I18N_STATUS_LABEL}
placeholder={I18N_STATUS_LABEL}
options={options}
selectedOptions={options.filter((option) => option.value === field.value)}
onChange={(selected) => {
return field.onChange(selected[0].value);
}}
singleSelection
/>
)}
/>
</EuiFormRow>
);
}

View file

@ -1,76 +0,0 @@
/*
* 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 { EuiFormRow, EuiComboBox } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React from 'react';
import { Controller, useFormContext } from 'react-hook-form';
import { InvestigationForm } from '../investigation_edit_form';
import { useFetchAllInvestigationTags } from '../../../hooks/use_fetch_all_investigation_tags';
const I18N_TAGS_LABEL = i18n.translate(
'xpack.investigateApp.investigationEditForm.span.tagsLabel',
{ defaultMessage: 'Tags' }
);
export function TagsField() {
const { control, getFieldState } = useFormContext<InvestigationForm>();
const { isLoading, data: tags } = useFetchAllInvestigationTags();
return (
<EuiFormRow label={I18N_TAGS_LABEL} fullWidth isInvalid={getFieldState('tags').invalid}>
<Controller
control={control}
name="tags"
defaultValue={[]}
rules={{ required: false }}
render={({ field, fieldState }) => (
<EuiComboBox
{...field}
aria-label={I18N_TAGS_LABEL}
placeholder={I18N_TAGS_LABEL}
fullWidth
isInvalid={fieldState.invalid}
isClearable
isLoading={isLoading}
options={tags?.map((tag) => ({ label: tag, value: tag })) ?? []}
selectedOptions={generateTagOptions(field.value)}
onChange={(selected) => {
if (selected.length) {
return field.onChange(selected.map((opts) => opts.value));
}
field.onChange([]);
}}
onCreateOption={(searchValue: string) => {
const normalizedSearchValue = searchValue.trim().toLowerCase();
if (!normalizedSearchValue) {
return;
}
const values = field.value ?? [];
const tagAlreadyExists = values.find(
(tag) => tag.trim().toLowerCase() === normalizedSearchValue
);
if (!tagAlreadyExists) {
field.onChange([...values, searchValue]);
}
}}
/>
)}
/>
</EuiFormRow>
);
}
function generateTagOptions(tags: string[] = []) {
return tags.map((tag) => ({
label: tag,
value: tag,
}));
}

View file

@ -1,43 +0,0 @@
/*
* 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 { CreateInvestigationParams, UpdateInvestigationParams } from '@kbn/investigation-shared';
import { v4 as uuidv4 } from 'uuid';
import type { InvestigationForm } from './investigation_edit_form';
export function toCreateInvestigationParams(data: InvestigationForm): CreateInvestigationParams {
return {
id: uuidv4(),
title: data.title,
params: {
timeRange: {
from: new Date(new Date().getTime() - 30 * 60 * 1000).getTime(),
to: new Date().getTime(),
},
},
tags: data.tags,
origin: {
type: 'blank',
},
externalIncidentUrl:
data.externalIncidentUrl && data.externalIncidentUrl.trim().length > 0
? data.externalIncidentUrl
: null,
};
}
export function toUpdateInvestigationParams(data: InvestigationForm): UpdateInvestigationParams {
return {
title: data.title,
status: data.status,
tags: data.tags,
externalIncidentUrl:
data.externalIncidentUrl && data.externalIncidentUrl.trim().length > 0
? data.externalIncidentUrl
: null,
};
}

View file

@ -1,191 +0,0 @@
/*
* 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 {
EuiButton,
EuiButtonEmpty,
EuiFieldText,
EuiFlexGroup,
EuiFlexItem,
EuiFlyout,
EuiFlyoutBody,
EuiFlyoutFooter,
EuiFlyoutHeader,
EuiFormRow,
EuiLoadingSpinner,
EuiTitle,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { InvestigationResponse } from '@kbn/investigation-shared';
import { pick } from 'lodash';
import React from 'react';
import { Controller, FormProvider, useForm } from 'react-hook-form';
import { paths } from '../../../common/paths';
import { useCreateInvestigation } from '../../hooks/use_create_investigation';
import { useFetchInvestigation } from '../../hooks/use_fetch_investigation';
import { useKibana } from '../../hooks/use_kibana';
import { useUpdateInvestigation } from '../../hooks/use_update_investigation';
import { InvestigationNotFound } from '../investigation_not_found/investigation_not_found';
import { ExternalIncidentField } from './fields/external_incident_field';
import { StatusField } from './fields/status_field';
import { TagsField } from './fields/tags_field';
import { toCreateInvestigationParams, toUpdateInvestigationParams } from './form_helper';
export interface InvestigationForm {
title: string;
status: InvestigationResponse['status'];
tags: string[];
externalIncidentUrl: string | null;
}
interface Props {
investigationId?: string;
onClose: () => void;
}
export function InvestigationEditForm({ investigationId, onClose }: Props) {
const {
core: {
http: { basePath },
application: { navigateToUrl },
},
} = useKibana();
const isEditing = Boolean(investigationId);
const {
data: investigation,
isLoading,
isError,
} = useFetchInvestigation({ id: investigationId });
const { mutateAsync: updateInvestigation } = useUpdateInvestigation();
const { mutateAsync: createInvestigation } = useCreateInvestigation();
const methods = useForm<InvestigationForm>({
defaultValues: {
title: i18n.translate('xpack.investigateApp.investigationDetailsPage.newInvestigationLabel', {
defaultMessage: 'New investigation',
}),
status: 'triage',
tags: [],
externalIncidentUrl: null,
},
values: investigation
? pick(investigation, ['title', 'status', 'tags', 'externalIncidentUrl'])
: undefined,
mode: 'all',
});
if (isError) {
return <InvestigationNotFound />;
}
if (isEditing && (isLoading || !investigation)) {
return <EuiLoadingSpinner size="xl" />;
}
const onSubmit = async (data: InvestigationForm) => {
if (isEditing) {
await updateInvestigation({
investigationId: investigationId!,
payload: toUpdateInvestigationParams(data),
});
onClose();
} else {
const resp = await createInvestigation(toCreateInvestigationParams(data));
navigateToUrl(basePath.prepend(paths.investigationDetails(resp.id)));
}
};
return (
<FormProvider {...methods}>
<form onSubmit={methods.handleSubmit(onSubmit)}>
<EuiFlyout ownFocus onClose={() => onClose()} size="s">
<EuiFlyoutHeader hasBorder>
<EuiTitle size="m">
<h2>
{isEditing
? i18n.translate('xpack.investigateApp.investigationDetailsPage.h2.editLabel', {
defaultMessage: 'Edit',
})
: i18n.translate('xpack.investigateApp.investigationDetailsPage.h2.createLabel', {
defaultMessage: 'Create',
})}
</h2>
</EuiTitle>
</EuiFlyoutHeader>
<EuiFlyoutBody>
<EuiFlexGroup direction="column" gutterSize="l">
<EuiFlexItem grow>
<EuiFormRow
fullWidth
label={i18n.translate(
'xpack.investigateApp.investigationEditForm.span.titleLabel',
{ defaultMessage: 'Title' }
)}
isInvalid={methods.getFieldState('title').invalid}
>
<Controller
name="title"
control={methods.control}
rules={{ required: true }}
render={({ field: { ref, ...field }, fieldState }) => (
<EuiFieldText
{...field}
fullWidth
data-test-subj="titleInput"
required
isInvalid={fieldState.invalid}
value={field.value}
onChange={(event) => field.onChange(event.target.value)}
/>
)}
/>
</EuiFormRow>
</EuiFlexItem>
{isEditing && (
<EuiFlexItem grow>
<StatusField />
</EuiFlexItem>
)}
<EuiFlexItem grow>
<TagsField />
</EuiFlexItem>
<EuiFlexItem grow>
<ExternalIncidentField />
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlyoutBody>
<EuiFlyoutFooter>
<EuiFlexGroup justifyContent="spaceBetween">
<EuiFlexItem grow={false}>
<EuiButtonEmpty
data-test-subj="closeBtn"
iconType="cross"
onClick={() => onClose()}
flush="left"
>
{i18n.translate(
'xpack.investigateApp.investigationDetailsPage.closeButtonEmptyLabel',
{ defaultMessage: 'Close' }
)}
</EuiButtonEmpty>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton data-test-subj="saveBtn" onClick={methods.handleSubmit(onSubmit)} fill>
{i18n.translate('xpack.investigateApp.investigationDetailsPage.saveButtonLabel', {
defaultMessage: 'Save',
})}
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlyoutFooter>
</EuiFlyout>
</form>
</FormProvider>
);
}

View file

@ -1,34 +0,0 @@
/*
* 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 { EuiEmptyPrompt } from '@elastic/eui';
import React from 'react';
import { i18n } from '@kbn/i18n';
export function InvestigationNotFound() {
return (
<EuiEmptyPrompt
iconType="error"
color="danger"
title={
<h2>
{i18n.translate('xpack.investigateApp.InvestigationNotFound.title', {
defaultMessage: 'Unable to load the investigation',
})}
</h2>
}
body={
<p>
{i18n.translate('xpack.investigateApp.InvestigationNotFound.body', {
defaultMessage:
'There was an error loading the investigation. Contact your administrator for help.',
})}
</p>
}
/>
);
}

View file

@ -1,19 +0,0 @@
/*
* 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 { EuiBadge } from '@elastic/eui';
import { InvestigationResponse } from '@kbn/investigation-shared';
import React from 'react';
import { statusToColor } from '../investigation_edit_form/fields/status_field';
interface Props {
status: InvestigationResponse['status'];
}
export function InvestigationStatusBadge({ status }: Props) {
return <EuiBadge color={statusToColor[status]}>{status}</EuiBadge>;
}

View file

@ -1,21 +0,0 @@
/*
* 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 { EuiFlexItem, EuiBadge } from '@elastic/eui';
import React from 'react';
interface Props {
tag: string;
}
export function InvestigationTag({ tag }: Props) {
return (
<EuiFlexItem grow={false}>
<EuiBadge color="hollow">{tag}</EuiBadge>
</EuiFlexItem>
);
}

View file

@ -1,30 +0,0 @@
/*
* 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 { Meta, StoryObj } from '@storybook/react';
import React from 'react';
import { PreviewLensSuggestion as Component } from '.';
import { KibanaReactStorybookDecorator } from '../../../.storybook/storybook_decorator';
const meta: Meta<typeof Component> = {
component: Component,
title: 'app/Molecules/PreviewLensSuggestion',
decorators: [KibanaReactStorybookDecorator],
};
export default meta;
const defaultProps: StoryObj<typeof Component> = {
args: {},
render: (props) => <Component {...props} />,
};
export const PreviewLensSuggestionStory: StoryObj<typeof Component> = {
...defaultProps,
args: {},
name: 'default',
};

View file

@ -1,63 +0,0 @@
/*
* 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 from 'react';
import type { TypedLensByValueInput } from '@kbn/lens-plugin/public';
import { EuiFlexGroup, EuiFlexItem, EuiLoadingSpinner, EuiPanel } from '@elastic/eui';
import { css } from '@emotion/css';
import { useKibana } from '../../hooks/use_kibana';
function Container({ children }: { children: React.ReactNode }) {
return (
<EuiFlexGroup direction="row" alignItems="center" justifyContent="center">
<EuiFlexItem grow={false}>{children}</EuiFlexItem>
</EuiFlexGroup>
);
}
const panelContainerClassName = css`
overflow: clip auto;
height: 100%;
`;
const panelContentClassName = css`
height: 100%;
overflow: clip auto;
> div {
height: 100%;
}
`;
export function PreviewLensSuggestion({
input,
loading,
error,
}: {
input: TypedLensByValueInput;
loading: boolean;
error?: Error;
}) {
const {
dependencies: {
start: { lens },
},
} = useKibana();
if (loading) {
return (
<Container>
<EuiLoadingSpinner />
</Container>
);
}
return (
<EuiPanel hasBorder={false} hasShadow={true} className={panelContainerClassName}>
<div className={panelContentClassName}>
<lens.EmbeddableComponent {...input} />
</div>
</EuiPanel>
);
}

View file

@ -1,78 +0,0 @@
/*
* 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 type { Suggestion } from '@kbn/lens-plugin/public';
import { Meta, StoryObj } from '@storybook/react';
import React from 'react';
import { v4 } from 'uuid';
import { SuggestVisualizationList as Component } from '.';
import '../../../.storybook/mock_kibana_services';
import { KibanaReactStorybookDecorator } from '../../../.storybook/storybook_decorator';
import { metricSuggestion, tableSuggestion, treemapSuggestion } from './suggestions.mock';
const meta: Meta<typeof Component> = {
component: Component,
title: 'app/Molecules/SuggestVisualizationList',
decorators: [KibanaReactStorybookDecorator],
};
export default meta;
function mapWithIds(suggestions: Suggestion[]) {
return suggestions.map((suggestion) => ({ id: v4(), ...suggestion }));
}
const defaultProps: StoryObj<typeof Component> = {
render: (props) => {
return <Component {...props} />;
},
};
export const WithSuggestions: StoryObj<typeof Component> = {
...defaultProps,
args: {
loading: false,
suggestions: mapWithIds([tableSuggestion, treemapSuggestion]),
},
name: 'With suggestions',
};
export const WithoutSuggestions: StoryObj<typeof Component> = {
...defaultProps,
args: {
loading: false,
suggestions: [],
},
name: 'Without suggestions',
};
export const LoadingStory: StoryObj<typeof Component> = {
...defaultProps,
args: {
loading: true,
suggestions: [],
},
name: 'Loading without suggestions',
};
export const LoadingWithSuggestionsStory: StoryObj<typeof Component> = {
...defaultProps,
args: {
loading: true,
suggestions: mapWithIds([metricSuggestion, treemapSuggestion]),
},
name: 'Loading with suggestions',
};
export const ErrorStory: StoryObj<typeof Component> = {
...defaultProps,
args: {
error: new Error('Network error'),
suggestions: [],
},
name: 'Error',
};

View file

@ -1,144 +0,0 @@
/*
* 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 from 'react';
import type { Suggestion } from '@kbn/lens-plugin/public';
import {
EuiButton,
EuiFlexGroup,
EuiFlexItem,
EuiIcon,
EuiLoadingSpinner,
EuiText,
} from '@elastic/eui';
import { css } from '@emotion/css';
import { i18n } from '@kbn/i18n';
const containerClassName = css`
min-height: 32px;
`;
const suggestionClassName = css`
.euiText {
text-overflow: ellipsis;
white-space: nowrap;
max-width: 140px;
overflow: hidden;
text-align: left;
}
span {
justify-content: flex-start;
}
`;
const iconContainerClassName = css`
display: flex;
align-items: center;
width: 16px;
`;
interface Props {
suggestions?: Array<
Suggestion & {
id: string;
}
>;
loading: boolean;
error?: Error;
onSuggestionClick: (suggestion: Suggestion) => void;
onSuggestionRollOver: (suggestion: Suggestion) => void;
onMouseLeave: () => void;
}
export function SuggestVisualizationList({
suggestions,
loading,
error,
onSuggestionClick,
onSuggestionRollOver,
onMouseLeave,
}: Props) {
if (error) {
return (
<EuiFlexGroup
direction="row"
gutterSize="s"
alignItems="center"
className={containerClassName}
>
<EuiFlexItem grow={false}>
<EuiIcon color="danger" size="s" type="warning" />
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiText size="xs" color="danger">
{i18n.translate(
'xpack.investigateApp.suggestVisualizationList.errorLoadingSuggestionsLabel',
{
defaultMessage: 'Error loading suggestions: {message}',
values: { message: error.message },
}
)}
</EuiText>
</EuiFlexItem>
</EuiFlexGroup>
);
}
const icon = loading ? <EuiLoadingSpinner size="s" /> : <EuiIcon type="sortRight" />;
let message: string = '';
if (loading && !suggestions?.length) {
message = i18n.translate(
'xpack.investigateApp.suggestVisualizationList.loadingSuggestionsLabel',
{
defaultMessage: 'Loading suggestions',
}
);
} else if (!loading && !suggestions?.length) {
message = i18n.translate('xpack.investigateApp.suggestVisualizationList.noSuggestionsLabel', {
defaultMessage: 'No suitable suggestions',
});
}
return (
<EuiFlexGroup direction="row" gutterSize="s" alignItems="center" className={containerClassName}>
<EuiFlexItem grow={false} className={iconContainerClassName}>
{icon}
</EuiFlexItem>
<EuiFlexItem grow>
{message ? (
<EuiText size="xs">{message}</EuiText>
) : (
<EuiFlexGroup direction="row" gutterSize="s">
{suggestions?.map((suggestion) => (
<EuiFlexItem key={suggestion.id} className={suggestionClassName} grow={false}>
<EuiButton
data-test-subj="investigateSuggestVisualizationListButton"
iconType={suggestion.previewIcon}
iconSize="s"
color="text"
size="s"
onClick={() => {
onSuggestionClick(suggestion);
}}
onMouseEnter={() => {
onSuggestionRollOver(suggestion);
}}
onMouseLeave={() => {
onMouseLeave();
}}
>
<EuiText size="xs">{suggestion.title}</EuiText>
</EuiButton>
</EuiFlexItem>
))}
</EuiFlexGroup>
)}
</EuiFlexItem>
</EuiFlexGroup>
);
}

View file

@ -1,384 +0,0 @@
/*
* 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 { Suggestion } from '@kbn/lens-plugin/public';
export const tableSuggestion: Suggestion = {
title:
'Table @timestamp & agent.activation_method & agent.ephemeral_id & agent.name & agent.version',
score: 0.2,
hide: true,
visualizationId: 'lnsDatatable',
previewIcon: 'visTable',
visualizationState: {
layerId: '5594a808-654b-4170-825d-26c58069bb27',
layerType: 'data',
columns: [
{
columnId: '@timestamp',
},
{
columnId: 'agent.activation_method',
},
{
columnId: 'agent.ephemeral_id',
},
{
columnId: 'agent.name',
},
{
columnId: 'agent.version',
},
],
},
keptLayerIds: ['5594a808-654b-4170-825d-26c58069bb27'],
datasourceState: {
layers: {
'5594a808-654b-4170-825d-26c58069bb27': {
index: '6176e654c875b9d3d9a3a69414fa44c561964cbb174a1f64f69e34eced7debac',
query: {
esql: 'FROM logs-apm.error-default',
},
columns: [
{
columnId: '@timestamp',
fieldName: '@timestamp',
meta: {
type: 'date',
},
inMetricDimension: true,
},
{
columnId: 'agent.activation_method',
fieldName: 'agent.activation_method',
meta: {
type: 'string',
},
inMetricDimension: true,
},
{
columnId: 'agent.ephemeral_id',
fieldName: 'agent.ephemeral_id',
meta: {
type: 'string',
},
inMetricDimension: true,
},
{
columnId: 'agent.name',
fieldName: 'agent.name',
meta: {
type: 'string',
},
inMetricDimension: true,
},
{
columnId: 'agent.version',
fieldName: 'agent.version',
meta: {
type: 'string',
},
inMetricDimension: true,
},
],
},
},
indexPatternRefs: [
{
id: '6176e654c875b9d3d9a3a69414fa44c561964cbb174a1f64f69e34eced7debac',
title: 'logs-apm.error-default',
},
],
},
datasourceId: 'textBased',
columns: 5,
changeType: 'initial',
};
export const metricSuggestion: Suggestion = {
title: 'Metric',
score: 0.51,
hide: true,
visualizationId: 'lnsMetric',
previewIcon: 'visMetric',
visualizationState: {
layerId: 'ecd36789-1acb-4278-b087-2e46cf459f89',
layerType: 'data',
metricAccessor: 'COUNT(*)',
},
keptLayerIds: ['ecd36789-1acb-4278-b087-2e46cf459f89'],
datasourceState: {
layers: {
'ecd36789-1acb-4278-b087-2e46cf459f89': {
index: '6176e654c875b9d3d9a3a69414fa44c561964cbb174a1f64f69e34eced7debac',
query: {
esql: 'FROM logs-apm.error-default | STATS COUNT(*)',
},
columns: [
{
columnId: 'COUNT(*)',
fieldName: 'COUNT(*)',
meta: {
type: 'number',
},
inMetricDimension: true,
},
],
},
},
indexPatternRefs: [
{
id: '6176e654c875b9d3d9a3a69414fa44c561964cbb174a1f64f69e34eced7debac',
title: 'logs-apm.error-default',
},
],
},
datasourceId: 'textBased',
columns: 1,
changeType: 'initial',
};
export const barSuggestion: Suggestion = {
title: 'Bar vertical stacked',
score: 0.16666666666666666,
hide: false,
incomplete: false,
visualizationId: 'lnsXY',
previewIcon: 'visBarVerticalStacked',
visualizationState: {
legend: {
isVisible: true,
position: 'right',
},
valueLabels: 'hide',
fittingFunction: 'None',
axisTitlesVisibilitySettings: {
x: true,
yLeft: true,
yRight: true,
},
tickLabelsVisibilitySettings: {
x: true,
yLeft: true,
yRight: true,
},
labelsOrientation: {
x: 0,
yLeft: 0,
yRight: 0,
},
gridlinesVisibilitySettings: {
x: true,
yLeft: true,
yRight: true,
},
preferredSeriesType: 'bar_stacked',
layers: [
{
layerId: '6aeee1c5-c080-4c22-8548-c887a213a433',
seriesType: 'bar_stacked',
xAccessor: 'BUCKET(@timestamp, 1 minute)',
accessors: ['COUNT(*)'],
layerType: 'data',
colorMapping: {
assignments: [],
specialAssignments: [
{
rule: {
type: 'other',
},
color: {
type: 'loop',
},
touched: false,
},
],
paletteId: 'eui_amsterdam_color_blind',
colorMode: {
type: 'categorical',
},
},
},
],
},
keptLayerIds: ['6aeee1c5-c080-4c22-8548-c887a213a433'],
datasourceState: {
layers: {
'6aeee1c5-c080-4c22-8548-c887a213a433': {
index: '6176e654c875b9d3d9a3a69414fa44c561964cbb174a1f64f69e34eced7debac',
query: {
esql: 'FROM logs-apm.error-default | WHERE @timestamp >= NOW() - 15 minutes | STATS COUNT(*) BY BUCKET(@timestamp, 1 minute)',
},
columns: [
{
columnId: 'COUNT(*)',
fieldName: 'COUNT(*)',
meta: {
type: 'number',
},
inMetricDimension: true,
},
{
columnId: 'BUCKET(@timestamp, 1 minute)',
fieldName: 'BUCKET(@timestamp, 1 minute)',
meta: {
type: 'date',
},
},
],
},
},
indexPatternRefs: [
{
id: '6176e654c875b9d3d9a3a69414fa44c561964cbb174a1f64f69e34eced7debac',
title: 'logs-apm.error-default',
},
],
},
datasourceId: 'textBased',
columns: 2,
changeType: 'unchanged',
};
export const treemapSuggestion: Suggestion = {
title: 'Treemap',
score: 0.56,
hide: false,
incomplete: false,
visualizationId: 'lnsPie',
previewIcon: 'namespace',
visualizationState: {
shape: 'treemap',
layers: [
{
layerId: '6aeee1c5-c080-4c22-8548-c887a213a433',
primaryGroups: ['BUCKET(@timestamp, 1 minute)'],
metrics: ['COUNT(*)'],
numberDisplay: 'percent',
categoryDisplay: 'default',
legendDisplay: 'default',
nestedLegend: false,
layerType: 'data',
},
],
},
keptLayerIds: ['6aeee1c5-c080-4c22-8548-c887a213a433'],
datasourceState: {
layers: {
'6aeee1c5-c080-4c22-8548-c887a213a433': {
index: '6176e654c875b9d3d9a3a69414fa44c561964cbb174a1f64f69e34eced7debac',
query: {
esql: 'FROM logs-apm.error-default | WHERE @timestamp >= NOW() - 15 minutes | STATS COUNT(*) BY BUCKET(@timestamp, 1 minute)',
},
columns: [
{
columnId: 'COUNT(*)',
fieldName: 'COUNT(*)',
meta: {
type: 'number',
},
inMetricDimension: true,
},
{
columnId: 'BUCKET(@timestamp, 1 minute)',
fieldName: 'BUCKET(@timestamp, 1 minute)',
meta: {
type: 'date',
},
},
],
},
},
indexPatternRefs: [
{
id: '6176e654c875b9d3d9a3a69414fa44c561964cbb174a1f64f69e34eced7debac',
title: 'logs-apm.error-default',
},
],
},
datasourceId: 'textBased',
columns: 2,
changeType: 'initial',
};
export const donutSuggestion: Suggestion = {
title: 'Donut',
score: 0.46,
hide: false,
incomplete: false,
visualizationId: 'lnsPie',
previewIcon: 'help',
visualizationState: {
shape: 'donut',
layers: [
{
layerId: '6aeee1c5-c080-4c22-8548-c887a213a433',
primaryGroups: ['BUCKET(@timestamp, 1 minute)'],
metrics: ['COUNT(*)'],
numberDisplay: 'percent',
categoryDisplay: 'default',
legendDisplay: 'default',
nestedLegend: false,
layerType: 'data',
colorMapping: {
assignments: [],
specialAssignments: [
{
rule: {
type: 'other',
},
color: {
type: 'loop',
},
touched: false,
},
],
paletteId: 'eui_amsterdam_color_blind',
colorMode: {
type: 'categorical',
},
},
},
],
},
keptLayerIds: ['6aeee1c5-c080-4c22-8548-c887a213a433'],
datasourceState: {
layers: {
'6aeee1c5-c080-4c22-8548-c887a213a433': {
index: '6176e654c875b9d3d9a3a69414fa44c561964cbb174a1f64f69e34eced7debac',
query: {
esql: 'FROM logs-apm.error-default | WHERE @timestamp >= NOW() - 15 minutes | STATS COUNT(*) BY BUCKET(@timestamp, 1 minute)',
},
columns: [
{
columnId: 'COUNT(*)',
fieldName: 'COUNT(*)',
meta: {
type: 'number',
},
inMetricDimension: true,
},
{
columnId: 'BUCKET(@timestamp, 1 minute)',
fieldName: 'BUCKET(@timestamp, 1 minute)',
meta: {
type: 'date',
},
},
],
},
},
indexPatternRefs: [
{
id: '6176e654c875b9d3d9a3a69414fa44c561964cbb174a1f64f69e34eced7debac',
title: 'logs-apm.error-default',
},
],
},
datasourceId: 'textBased',
columns: 2,
changeType: 'unchanged',
};

View file

@ -1,9 +0,0 @@
/*
* 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.
*/
export const ESQL_WIDGET_NAME = 'esql';
export const EMBEDDABLE_WIDGET_NAME = 'embeddable';

View file

@ -1,43 +0,0 @@
/*
* 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.
*/
'investigations,list,{page:1,perPage:25}';
export const investigationKeys = {
all: ['investigations'] as const,
userProfiles: (profileIds: Set<string>) =>
[...investigationKeys.all, 'userProfiles', ...profileIds] as const,
tags: () => [...investigationKeys.all, 'tags'] as const,
events: (params: {
rangeFrom?: string;
rangeTo?: string;
filter?: string;
eventTypes?: string[];
}) => [...investigationKeys.all, 'events', params] as const,
stats: () => [...investigationKeys.all, 'stats'] as const,
lists: () => [...investigationKeys.all, 'list'] as const,
list: (params: { page: number; perPage: number; search?: string; filter?: string }) =>
[...investigationKeys.lists(), params] as const,
details: () => [...investigationKeys.all, 'detail'] as const,
detail: (investigationId: string) => [...investigationKeys.details(), investigationId] as const,
detailNotes: (investigationId: string) =>
[...investigationKeys.detail(investigationId), 'notes'] as const,
detailItems: (investigationId: string) =>
[...investigationKeys.detail(investigationId), 'items'] as const,
entities: ({
investigationId,
...params
}: {
investigationId: string;
serviceName?: string;
serviceEnvironment?: string;
hostName?: string;
containerId?: string;
}) => [...investigationKeys.detail(investigationId), 'entities', params] as const,
};
export type InvestigationKeys = typeof investigationKeys;

Some files were not shown because too many files have changed in this diff Show more