[8.x] [UII] Advanced agent monitoring options UI for HTTP endpoint and diagnostics (#193361) (#193658)

# Backport

This will backport the following commits from `main` to `8.x`:
- [[UII] Advanced agent monitoring options UI for HTTP endpoint and
diagnostics (#193361)](https://github.com/elastic/kibana/pull/193361)

<!--- Backport version: 9.4.3 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Jen
Huang","email":"its.jenetic@gmail.com"},"sourceCommit":{"committedDate":"2024-09-22T10:49:33Z","message":"[UII]
Advanced agent monitoring options UI for HTTP endpoint and diagnostics
(#193361)\n\n## Summary\r\n\r\nResolves
https://github.com/elastic/kibana/issues/153950.\r\n\r\nThis PR
implements a UI to configure advanced Elastic Agent
monitoring\r\noptions under agent policy settings. These advanced
options include\r\nenabling HTTP monitoring endpoints and various
options for agent\r\ndiagnostics. They are shown under an a toggle under
the existing agent\r\nmonitoring logs and metrics collection
options:\r\n\r\n<img width=\"1326\"
alt=\"image\"\r\nsrc=\"https://github.com/user-attachments/assets/ac8cbe00-d838-4c9a-8a35-3dbf31222dc9\">\r\n\r\nIf
the base HTTP monitoring endpoint is not enabled, the rest of
the\r\nHTTP options are disabled:\r\n\r\n<img width=\"1328\"
alt=\"image\"\r\nsrc=\"https://github.com/user-attachments/assets/2eac787c-3055-4862-b3eb-2566a39ee86c\">\r\n\r\nThe
following new fields are added to agent policy schema to
support\r\nthis:\r\n```\r\nmonitoring_http\r\nmonitoring_pprof_enabled\r\nmonitoring_diagnostics\r\n```\r\n\r\nThis
work supersedes the previous `HTTP monitoring endpoint` options\r\nunder
`Advanced Settings` at the bottom of the page. Any
previous\r\nconfiguration under an agent
policy's\r\n`advanced_settings.agent_monitoring_http` saved object field
are\r\nmigrated over to the new `monitoring_http` field and the old
field is\r\ndeleted. See the migration fn
`backfillAgentPolicyToV4`.\r\n\r\nThese new options are compiled to
agent yaml like this:\r\n\r\n```yml\r\nagent:\r\n monitoring:\r\n
enabled: true\r\n use_output: default\r\n logs: true\r\n metrics:
true\r\n traces: true\r\n namespace: default\r\n pprof:\r\n enabled:
true\r\n http:\r\n enabled: true\r\n host: localhost\r\n port: 6791\r\n
diagnostics:\r\n limit:\r\n interval: 1m\r\n burst: 1\r\n uploader:\r\n
max_retries: 10\r\n init_dur: 1s\r\n max_dur: 10m\r\n```\r\nSummarize
your PR. If it involves visual changes include a screenshot
or\r\ngif.\r\n\r\n### To-do\r\n- [x] API integration tests\r\n- [x] Full
manual test of SO migration\r\n- [x] Full manual test with agent using
these settings\r\n\r\n### Checklist\r\n\r\nDelete any items that are not
applicable to this PR.\r\n\r\n- [x] Any text added follows [EUI's
writing\r\nguidelines](https://elastic.github.io/eui/#/guidelines/writing),
uses\r\nsentence case text and includes
[i18n\r\nsupport](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)\r\n-
[
]\r\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\r\nwas
added for features that require explanation or tutorials\r\n -
https://github.com/elastic/ingest-docs/issues/1333 \r\n- [x] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common
scenarios\r\n\r\n---------\r\n\r\nCo-authored-by: kibanamachine
<42973632+kibanamachine@users.noreply.github.com>","sha":"87cdc2db728b088a44ff6e1977679f326bfd38d2","branchLabelMapping":{"^v9.0.0$":"main","^v8.16.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["Team:Fleet","v9.0.0","release_note:feature","backport:prev-minor"],"title":"[UII]
Advanced agent monitoring options UI for HTTP endpoint and
diagnostics","number":193361,"url":"https://github.com/elastic/kibana/pull/193361","mergeCommit":{"message":"[UII]
Advanced agent monitoring options UI for HTTP endpoint and diagnostics
(#193361)\n\n## Summary\r\n\r\nResolves
https://github.com/elastic/kibana/issues/153950.\r\n\r\nThis PR
implements a UI to configure advanced Elastic Agent
monitoring\r\noptions under agent policy settings. These advanced
options include\r\nenabling HTTP monitoring endpoints and various
options for agent\r\ndiagnostics. They are shown under an a toggle under
the existing agent\r\nmonitoring logs and metrics collection
options:\r\n\r\n<img width=\"1326\"
alt=\"image\"\r\nsrc=\"https://github.com/user-attachments/assets/ac8cbe00-d838-4c9a-8a35-3dbf31222dc9\">\r\n\r\nIf
the base HTTP monitoring endpoint is not enabled, the rest of
the\r\nHTTP options are disabled:\r\n\r\n<img width=\"1328\"
alt=\"image\"\r\nsrc=\"https://github.com/user-attachments/assets/2eac787c-3055-4862-b3eb-2566a39ee86c\">\r\n\r\nThe
following new fields are added to agent policy schema to
support\r\nthis:\r\n```\r\nmonitoring_http\r\nmonitoring_pprof_enabled\r\nmonitoring_diagnostics\r\n```\r\n\r\nThis
work supersedes the previous `HTTP monitoring endpoint` options\r\nunder
`Advanced Settings` at the bottom of the page. Any
previous\r\nconfiguration under an agent
policy's\r\n`advanced_settings.agent_monitoring_http` saved object field
are\r\nmigrated over to the new `monitoring_http` field and the old
field is\r\ndeleted. See the migration fn
`backfillAgentPolicyToV4`.\r\n\r\nThese new options are compiled to
agent yaml like this:\r\n\r\n```yml\r\nagent:\r\n monitoring:\r\n
enabled: true\r\n use_output: default\r\n logs: true\r\n metrics:
true\r\n traces: true\r\n namespace: default\r\n pprof:\r\n enabled:
true\r\n http:\r\n enabled: true\r\n host: localhost\r\n port: 6791\r\n
diagnostics:\r\n limit:\r\n interval: 1m\r\n burst: 1\r\n uploader:\r\n
max_retries: 10\r\n init_dur: 1s\r\n max_dur: 10m\r\n```\r\nSummarize
your PR. If it involves visual changes include a screenshot
or\r\ngif.\r\n\r\n### To-do\r\n- [x] API integration tests\r\n- [x] Full
manual test of SO migration\r\n- [x] Full manual test with agent using
these settings\r\n\r\n### Checklist\r\n\r\nDelete any items that are not
applicable to this PR.\r\n\r\n- [x] Any text added follows [EUI's
writing\r\nguidelines](https://elastic.github.io/eui/#/guidelines/writing),
uses\r\nsentence case text and includes
[i18n\r\nsupport](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)\r\n-
[
]\r\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\r\nwas
added for features that require explanation or tutorials\r\n -
https://github.com/elastic/ingest-docs/issues/1333 \r\n- [x] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common
scenarios\r\n\r\n---------\r\n\r\nCo-authored-by: kibanamachine
<42973632+kibanamachine@users.noreply.github.com>","sha":"87cdc2db728b088a44ff6e1977679f326bfd38d2"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","branchLabelMappingKey":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/193361","number":193361,"mergeCommit":{"message":"[UII]
Advanced agent monitoring options UI for HTTP endpoint and diagnostics
(#193361)\n\n## Summary\r\n\r\nResolves
https://github.com/elastic/kibana/issues/153950.\r\n\r\nThis PR
implements a UI to configure advanced Elastic Agent
monitoring\r\noptions under agent policy settings. These advanced
options include\r\nenabling HTTP monitoring endpoints and various
options for agent\r\ndiagnostics. They are shown under an a toggle under
the existing agent\r\nmonitoring logs and metrics collection
options:\r\n\r\n<img width=\"1326\"
alt=\"image\"\r\nsrc=\"https://github.com/user-attachments/assets/ac8cbe00-d838-4c9a-8a35-3dbf31222dc9\">\r\n\r\nIf
the base HTTP monitoring endpoint is not enabled, the rest of
the\r\nHTTP options are disabled:\r\n\r\n<img width=\"1328\"
alt=\"image\"\r\nsrc=\"https://github.com/user-attachments/assets/2eac787c-3055-4862-b3eb-2566a39ee86c\">\r\n\r\nThe
following new fields are added to agent policy schema to
support\r\nthis:\r\n```\r\nmonitoring_http\r\nmonitoring_pprof_enabled\r\nmonitoring_diagnostics\r\n```\r\n\r\nThis
work supersedes the previous `HTTP monitoring endpoint` options\r\nunder
`Advanced Settings` at the bottom of the page. Any
previous\r\nconfiguration under an agent
policy's\r\n`advanced_settings.agent_monitoring_http` saved object field
are\r\nmigrated over to the new `monitoring_http` field and the old
field is\r\ndeleted. See the migration fn
`backfillAgentPolicyToV4`.\r\n\r\nThese new options are compiled to
agent yaml like this:\r\n\r\n```yml\r\nagent:\r\n monitoring:\r\n
enabled: true\r\n use_output: default\r\n logs: true\r\n metrics:
true\r\n traces: true\r\n namespace: default\r\n pprof:\r\n enabled:
true\r\n http:\r\n enabled: true\r\n host: localhost\r\n port: 6791\r\n
diagnostics:\r\n limit:\r\n interval: 1m\r\n burst: 1\r\n uploader:\r\n
max_retries: 10\r\n init_dur: 1s\r\n max_dur: 10m\r\n```\r\nSummarize
your PR. If it involves visual changes include a screenshot
or\r\ngif.\r\n\r\n### To-do\r\n- [x] API integration tests\r\n- [x] Full
manual test of SO migration\r\n- [x] Full manual test with agent using
these settings\r\n\r\n### Checklist\r\n\r\nDelete any items that are not
applicable to this PR.\r\n\r\n- [x] Any text added follows [EUI's
writing\r\nguidelines](https://elastic.github.io/eui/#/guidelines/writing),
uses\r\nsentence case text and includes
[i18n\r\nsupport](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)\r\n-
[
]\r\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\r\nwas
added for features that require explanation or tutorials\r\n -
https://github.com/elastic/ingest-docs/issues/1333 \r\n- [x] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common
scenarios\r\n\r\n---------\r\n\r\nCo-authored-by: kibanamachine
<42973632+kibanamachine@users.noreply.github.com>","sha":"87cdc2db728b088a44ff6e1977679f326bfd38d2"}}]}]
BACKPORT-->

---------

Co-authored-by: Jen Huang <its.jenetic@gmail.com>
This commit is contained in:
Kibana Machine 2024-09-22 23:00:13 +10:00 committed by GitHub
parent 6a9663fa3a
commit ea4ee399bb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
36 changed files with 2027 additions and 136 deletions

View file

@ -19761,6 +19761,25 @@ components:
collection will be disabled
nullable: true
type: boolean
monitoring_diagnostics:
type: object
properties:
limit:
type: object
properties:
burst:
type: number
interval:
type: string
uploader:
type: object
properties:
init_dur:
type: string
max_dur:
type: string
max_retries:
type: number
monitoring_enabled:
items:
enum:
@ -19768,9 +19787,22 @@ components:
- logs
type: string
type: array
monitoring_http:
type: object
properties:
enabled:
type: boolean
host:
type: string
port:
type: number
required:
- enabled
monitoring_output_id:
nullable: true
type: string
monitoring_pprof_enabled:
type: boolean
name:
type: string
namespace:
@ -20242,6 +20274,63 @@ components:
type: string
inputs:
type: string
monitoring:
type: object
properties:
diagnostics:
type: object
properties:
limit:
type: object
properties:
burst:
type: number
interval:
type: string
uploader:
type: object
properties:
init_dur:
type: string
max_dur:
type: string
max_retries:
type: number
enabled:
type: boolean
http:
type: object
properties:
enabled:
type: boolean
host:
type: string
port:
type: number
required:
- enabled
logs:
type: boolean
metrics:
type: boolean
namespace:
type: string
pprof:
type: object
properties:
enabled:
type: boolean
required:
- enabled
traces:
type: boolean
use_output:
type: string
required:
- enabled
- metrics
- logs
- traces
output_permissions:
additionalProperties:
type: object

View file

@ -12634,6 +12634,25 @@ components:
collection will be disabled
nullable: true
type: boolean
monitoring_diagnostics:
type: object
properties:
limit:
type: object
properties:
burst:
type: number
interval:
type: string
uploader:
type: object
properties:
init_dur:
type: string
max_dur:
type: string
max_retries:
type: number
monitoring_enabled:
items:
enum:
@ -12641,9 +12660,22 @@ components:
- logs
type: string
type: array
monitoring_http:
type: object
properties:
enabled:
type: boolean
host:
type: string
port:
type: number
required:
- enabled
monitoring_output_id:
nullable: true
type: string
monitoring_pprof_enabled:
type: boolean
name:
type: string
namespace:
@ -13115,6 +13147,63 @@ components:
type: string
inputs:
type: string
monitoring:
type: object
properties:
diagnostics:
type: object
properties:
limit:
type: object
properties:
burst:
type: number
interval:
type: string
uploader:
type: object
properties:
init_dur:
type: string
max_dur:
type: string
max_retries:
type: number
enabled:
type: boolean
http:
type: object
properties:
enabled:
type: boolean
host:
type: string
port:
type: number
required:
- enabled
logs:
type: boolean
metrics:
type: boolean
namespace:
type: string
pprof:
type: object
properties:
enabled:
type: boolean
required:
- enabled
traces:
type: boolean
use_output:
type: string
required:
- enabled
- metrics
- logs
- traces
output_permissions:
additionalProperties:
type: object

View file

@ -27556,6 +27556,25 @@ components:
collection will be disabled
nullable: true
type: boolean
monitoring_diagnostics:
type: object
properties:
limit:
type: object
properties:
burst:
type: number
interval:
type: string
uploader:
type: object
properties:
init_dur:
type: string
max_dur:
type: string
max_retries:
type: number
monitoring_enabled:
items:
enum:
@ -27563,9 +27582,22 @@ components:
- logs
type: string
type: array
monitoring_http:
type: object
properties:
enabled:
type: boolean
host:
type: string
port:
type: number
required:
- enabled
monitoring_output_id:
nullable: true
type: string
monitoring_pprof_enabled:
type: boolean
name:
type: string
namespace:
@ -28037,6 +28069,63 @@ components:
type: string
inputs:
type: string
monitoring:
type: object
properties:
diagnostics:
type: object
properties:
limit:
type: object
properties:
burst:
type: number
interval:
type: string
uploader:
type: object
properties:
init_dur:
type: string
max_dur:
type: string
max_retries:
type: number
enabled:
type: boolean
http:
type: object
properties:
enabled:
type: boolean
host:
type: string
port:
type: number
required:
- enabled
logs:
type: boolean
metrics:
type: boolean
namespace:
type: string
pprof:
type: object
properties:
enabled:
type: boolean
required:
- enabled
traces:
type: boolean
use_output:
type: string
required:
- enabled
- metrics
- logs
- traces
output_permissions:
additionalProperties:
type: object

View file

@ -19593,6 +19593,25 @@ components:
collection will be disabled
nullable: true
type: boolean
monitoring_diagnostics:
type: object
properties:
limit:
type: object
properties:
burst:
type: number
interval:
type: string
uploader:
type: object
properties:
init_dur:
type: string
max_dur:
type: string
max_retries:
type: number
monitoring_enabled:
items:
enum:
@ -19600,9 +19619,22 @@ components:
- logs
type: string
type: array
monitoring_http:
type: object
properties:
enabled:
type: boolean
host:
type: string
port:
type: number
required:
- enabled
monitoring_output_id:
nullable: true
type: string
monitoring_pprof_enabled:
type: boolean
name:
type: string
namespace:
@ -20074,6 +20106,63 @@ components:
type: string
inputs:
type: string
monitoring:
type: object
properties:
diagnostics:
type: object
properties:
limit:
type: object
properties:
burst:
type: number
interval:
type: string
uploader:
type: object
properties:
init_dur:
type: string
max_dur:
type: string
max_retries:
type: number
enabled:
type: boolean
http:
type: object
properties:
enabled:
type: boolean
host:
type: string
port:
type: number
required:
- enabled
logs:
type: boolean
metrics:
type: boolean
namespace:
type: string
pprof:
type: object
properties:
enabled:
type: boolean
required:
- enabled
traces:
type: boolean
use_output:
type: string
required:
- enabled
- metrics
- logs
- traces
output_permissions:
additionalProperties:
type: object

View file

@ -605,8 +605,11 @@
"is_preconfigured",
"is_protected",
"keep_monitoring_alive",
"monitoring_diagnostics",
"monitoring_enabled",
"monitoring_http",
"monitoring_output_id",
"monitoring_pprof_enabled",
"name",
"namespace",
"overrides",

View file

@ -1996,13 +1996,25 @@
"keep_monitoring_alive": {
"type": "boolean"
},
"monitoring_diagnostics": {
"index": false,
"type": "flattened"
},
"monitoring_enabled": {
"index": false,
"type": "keyword"
},
"monitoring_http": {
"index": false,
"type": "flattened"
},
"monitoring_output_id": {
"type": "keyword"
},
"monitoring_pprof_enabled": {
"index": false,
"type": "boolean"
},
"name": {
"type": "keyword"
},

View file

@ -879,6 +879,7 @@ export const getDocLinks = ({ kibanaBranch, buildFlavor }: GetDocLinkOptions): D
roleAndPrivileges: `${FLEET_DOCS}fleet-roles-and-privileges.html`,
proxiesSettings: `${FLEET_DOCS}fleet-agent-proxy-support.html`,
unprivilegedMode: `${FLEET_DOCS}elastic-agent-unprivileged.html#unprivileged-change-mode`,
httpMonitoring: `${FLEET_DOCS}agent-policy.html#change-policy-enable-agent-monitoring`,
},
integrationDeveloper: {
upload: `${INTEGRATIONS_DEV_DOCS}upload-a-new-integration.html`,

View file

@ -564,6 +564,7 @@ export interface DocLinks {
roleAndPrivileges: string;
proxiesSettings: string;
unprivilegedMode: string;
httpMonitoring: string;
}>;
readonly integrationDeveloper: {
upload: string;

View file

@ -120,7 +120,7 @@ describe('checking migration metadata changes on all registered SO types', () =>
"infra-custom-dashboards": "1a5994f2e05bb8a1609825ddbf5012f77c5c67f3",
"infrastructure-monitoring-log-view": "5f86709d3c27aed7a8379153b08ee5d3d90d77f5",
"infrastructure-ui-source": "113182d6895764378dfe7fa9fa027244f3a457c4",
"ingest-agent-policies": "90625b4a5ded9d4867358fcccc14a57c0454fcee",
"ingest-agent-policies": "5e95e539826a40ad08fd0c1d161da0a4d86ffc6d",
"ingest-download-sources": "279a68147e62e4d8858c09ad1cf03bd5551ce58d",
"ingest-outputs": "daafff49255ab700e07491376fe89f04fc998b91",
"ingest-package-policies": "53a94064674835fdb35e5186233bcd7052eabd22",

View file

@ -7592,6 +7592,56 @@
},
"description": "User defined data tags that are added to all of the inputs. The values can be strings or numbers."
}
},
"monitoring_pprof_enabled": {
"type": "boolean"
},
"monitoring_http": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean"
},
"host": {
"type": "string"
},
"port": {
"type": "number"
}
},
"required": [
"enabled"
]
},
"monitoring_diagnostics": {
"type": "object",
"properties": {
"limit": {
"type": "object",
"properties": {
"interval": {
"type": "string"
},
"burst": {
"type": "number"
}
}
},
"uploader": {
"type": "object",
"properties": {
"max_retries": {
"type": "number"
},
"init_dur": {
"type": "string"
},
"max_dur": {
"type": "string"
}
}
}
}
}
},
"required": [
@ -7874,6 +7924,93 @@
}
}
},
"monitoring": {
"type": "object",
"properties": {
"namespace": {
"type": "string"
},
"use_output": {
"type": "string"
},
"enabled": {
"type": "boolean"
},
"metrics": {
"type": "boolean"
},
"logs": {
"type": "boolean"
},
"traces": {
"type": "boolean"
},
"pprof": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean"
}
},
"required": [
"enabled"
]
},
"http": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean"
},
"host": {
"type": "string"
},
"port": {
"type": "number"
}
},
"required": [
"enabled"
]
},
"diagnostics": {
"type": "object",
"properties": {
"limit": {
"type": "object",
"properties": {
"interval": {
"type": "string"
},
"burst": {
"type": "number"
}
}
},
"uploader": {
"type": "object",
"properties": {
"max_retries": {
"type": "number"
},
"init_dur": {
"type": "string"
},
"max_dur": {
"type": "string"
}
}
}
}
}
},
"required": [
"enabled",
"metrics",
"logs",
"traces"
]
},
"fleet": {
"oneOf": [
{

View file

@ -4861,6 +4861,38 @@ components:
description: >-
User defined data tags that are added to all of the inputs. The
values can be strings or numbers.
monitoring_pprof_enabled:
type: boolean
monitoring_http:
type: object
properties:
enabled:
type: boolean
host:
type: string
port:
type: number
required:
- enabled
monitoring_diagnostics:
type: object
properties:
limit:
type: object
properties:
interval:
type: string
burst:
type: number
uploader:
type: object
properties:
max_retries:
type: number
init_dur:
type: string
max_dur:
type: string
required:
- id
- status
@ -5054,6 +5086,63 @@ components:
type: integer
data:
$ref: '#/components/schemas/full_agent_policy_output_permissions'
monitoring:
type: object
properties:
namespace:
type: string
use_output:
type: string
enabled:
type: boolean
metrics:
type: boolean
logs:
type: boolean
traces:
type: boolean
pprof:
type: object
properties:
enabled:
type: boolean
required:
- enabled
http:
type: object
properties:
enabled:
type: boolean
host:
type: string
port:
type: number
required:
- enabled
diagnostics:
type: object
properties:
limit:
type: object
properties:
interval:
type: string
burst:
type: number
uploader:
type: object
properties:
max_retries:
type: number
init_dur:
type: string
max_dur:
type: string
required:
- enabled
- metrics
- logs
- traces
fleet:
oneOf:
- type: object

View file

@ -87,6 +87,38 @@ properties:
- type: string
- type: number
description: User defined data tags that are added to all of the inputs. The values can be strings or numbers.
monitoring_pprof_enabled:
type: boolean
monitoring_http:
type: object
properties:
enabled:
type: boolean
host:
type: string
port:
type: number
required:
- enabled
monitoring_diagnostics:
type: object
properties:
limit:
type: object
properties:
interval:
type: string
burst:
type: number
uploader:
type: object
properties:
max_retries:
type: number
init_dur:
type: string
max_dur:
type: string
required:
- id
- status

View file

@ -16,6 +16,63 @@ properties:
type: integer
data:
$ref: ./full_agent_policy_output_permissions.yaml
monitoring:
type: object
properties:
namespace:
type: string
use_output:
type: string
enabled:
type: boolean
metrics:
type: boolean
logs:
type: boolean
traces:
type: boolean
pprof:
type: object
properties:
enabled:
type: boolean
required:
- enabled
http:
type: object
properties:
enabled:
type: boolean
host:
type: string
port:
type: number
required:
- enabled
diagnostics:
type: object
properties:
limit:
type: object
properties:
interval:
type: string
burst:
type: number
uploader:
type: object
properties:
max_retries:
type: number
init_dur:
type: string
max_dur:
type: string
required:
- enabled
- metrics
- logs
- traces
fleet:
oneOf:
- type: object

View file

@ -105,32 +105,6 @@ export const AGENT_POLICY_ADVANCED_SETTINGS: SettingsConfig[] = [
'https://www.elastic.co/guide/en/fleet/current/elastic-agent-standalone-logging-config.html#elastic-agent-standalone-logging-settings',
schema: zodStringWithDurationValidation.default('30s'),
},
{
name: 'agent.monitoring.http',
api_field: {
name: 'agent_monitoring_http',
},
title: i18n.translate('xpack.fleet.settings.agentPolicyAdvanced.agentMonitoringHttpTitle', {
defaultMessage: 'HTTP monitoring endpoint',
}),
description: i18n.translate(
'xpack.fleet.settings.agentPolicyAdvanced.agentMonitoringHttpDescription',
{
defaultMessage:
'Enables a liveness HTTP endpoint that returns the overall health of Elastic Agent. This can be used by Kubernetes to restart the container, for example.',
}
),
learnMoreLink:
'https://www.elastic.co/guide/en/fleet/current/agent-policy.html#agent-policy-http-monitoring',
schema: z
.object({
enabled: z.boolean().describe('Enabled').default(false),
host: z.string().describe('Host').default('localhost'),
port: z.number().describe('Port').min(0).max(65353).default(6791),
'buffer.enabled': z.boolean().describe('Buffer Enabled').default(false),
})
.default({}),
},
{
name: 'agent.logging.level',
title: i18n.translate('xpack.fleet.settings.agentPolicyAdvanced.agentLoggingLevelTitle', {

View file

@ -44,6 +44,23 @@ export interface NewAgentPolicy {
keep_monitoring_alive?: boolean | null;
supports_agentless?: boolean | null;
global_data_tags?: GlobalDataTag[];
monitoring_pprof_enabled?: boolean;
monitoring_http?: {
enabled: boolean;
host?: string;
port?: number;
};
monitoring_diagnostics?: {
limit?: {
interval?: string;
burst?: number;
};
uploader?: {
max_retries?: number;
init_dur?: string;
max_dur?: string;
};
};
}
export interface GlobalDataTag {
@ -119,6 +136,25 @@ export interface FullAgentPolicyMonitoring {
metrics: boolean;
logs: boolean;
traces: boolean;
pprof?: {
enabled: boolean;
};
http?: {
enabled: boolean;
host?: string;
port?: number;
};
diagnostics?: {
limit?: {
interval?: string;
burst?: number;
};
uploader?: {
max_retries?: number;
init_dur?: string;
max_dur?: string;
};
};
}
export interface FullAgentPolicy {

View file

@ -118,7 +118,7 @@ describe('Home page', () => {
'be.visible'
);
cy.getBySel(AGENT_POLICY_CREATE_AGENT_POLICY_NAME_FIELD).type('testName');
cy.get('.ingest-active-button').click();
cy.getBySel(AGENT_POLICIES_CREATE_AGENT_POLICY_FLYOUT.ADVANCED_OPTIONS_TOGGLE).click();
cy.getBySel(AGENT_POLICIES_FLYOUT_ADVANCED_DEFAULT_NAMESPACE_HEADER, {
timeout: 15000,
}).should('be.visible');

View file

@ -95,6 +95,7 @@ export const AGENT_FLYOUT = {
export const AGENT_POLICIES_CREATE_AGENT_POLICY_FLYOUT = {
TITLE: 'createAgentPolicyFlyoutTitle',
CREATE_BUTTON: 'createAgentPolicyButton',
ADVANCED_OPTIONS_TOGGLE: 'advancedOptionsButton',
COLLECT_LOGS_CHECKBOX: 'collectLogsCheckbox',
COLLECT_METRICS_CHECKBOX: 'collectMetricsCheckbox',
};

View file

@ -102,70 +102,6 @@ describe('ConfiguredSettings', () => {
expect(mockUpdateAdvancedSettingsHasErrors).toHaveBeenCalledWith(true);
});
it('should render field group', () => {
const result = render([
{
name: 'agent.monitoring.http',
api_field: {
name: 'agent_monitoring_http',
},
title: 'Agent HTTP monitoring',
description: 'Agent HTTP monitoring settings',
learnMoreLink:
'https://www.elastic.co/guide/en/fleet/current/enable-custom-policy-settings.html#override-default-monitoring-port',
schema: z
.object({
enabled: z.boolean().describe('Enabled').default(false),
host: z.string().describe('Host').default('localhost'),
port: z.number().describe('Port').min(0).max(65353).default(6791),
'buffer.enabled': z.boolean().describe('Buffer Enabled').default(false),
})
.default({}),
},
]);
expect(result.getByText('Agent HTTP monitoring')).not.toBeNull();
expect(result.getByText('Buffer Enabled')).not.toBeNull();
const switches = result.getAllByRole('switch');
expect(switches).toHaveLength(2);
expect(switches[0]).not.toBeChecked();
expect(switches[1]).not.toBeChecked();
const port = result.getByTestId('configuredSetting-agent.monitoring.http-port');
expect(port).toHaveValue(6791);
const host = result.getByTestId('configuredSetting-agent.monitoring.http-host');
expect(host).toHaveValue('localhost');
act(() => {
fireEvent.click(switches[0]);
});
expect(mockUpdateAgentPolicy).toHaveBeenCalledWith(
expect.objectContaining({
advanced_settings: expect.objectContaining({ agent_monitoring_http: { enabled: true } }),
})
);
act(() => {
fireEvent.change(port, { target: { value: '6792' } });
});
expect(mockUpdateAgentPolicy).toHaveBeenCalledWith(
expect.objectContaining({
advanced_settings: expect.objectContaining({ agent_monitoring_http: { port: 6792 } }),
})
);
act(() => {
fireEvent.change(host, { target: { value: '1.2.3.4' } });
});
expect(mockUpdateAgentPolicy).toHaveBeenCalledWith(
expect.objectContaining({
advanced_settings: expect.objectContaining({ agent_monitoring_http: { host: '1.2.3.4' } }),
})
);
});
it('should not render field if hidden', () => {
const result = render([
{

View file

@ -0,0 +1,535 @@
/*
* 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 {
EuiDescribedFormGroup,
EuiSpacer,
EuiCheckbox,
EuiLink,
EuiAccordion,
EuiCode,
EuiFlexGroup,
EuiFlexItem,
EuiFormRow,
EuiFieldText,
EuiFieldNumber,
} from '@elastic/eui';
import styled from 'styled-components';
import { FormattedMessage } from '@kbn/i18n-react';
import type { NewAgentPolicy, AgentPolicy } from '../../../../types';
import { useStartServices } from '../../../../hooks';
import type { ValidationResults } from '../agent_policy_validation';
const StyledEuiAccordion = styled(EuiAccordion)`
margin-block-start: ${(props) => props.theme.eui.euiSizeS};
.ingest-active-button {
color: ${(props) => props.theme.eui.euiColorPrimary};
}
`;
const PushedDescribedFormGroup = styled(EuiDescribedFormGroup)`
h3,
.euiDescribedFormGroup__description {
padding-left: ${(props) => props.theme.eui.euiSizeL};
}
`;
export const AgentPolicyAdvancedMonitoringOptions: React.FunctionComponent<{
agentPolicy: Partial<NewAgentPolicy | AgentPolicy>;
disabled: boolean;
validation: ValidationResults;
touchedFields: { [key: string]: boolean };
updateTouchedFields: (fields: { [key: string]: boolean }) => void;
updateAgentPolicy: (u: Partial<NewAgentPolicy | AgentPolicy>) => void;
}> = ({
agentPolicy,
disabled,
validation,
touchedFields,
updateTouchedFields,
updateAgentPolicy,
}) => {
const { docLinks } = useStartServices();
return (
<StyledEuiAccordion
id="advancedMonitoringOptions"
buttonContent={
<FormattedMessage
id="xpack.fleet.agentPolicyForm.advancedMonitoringOptionsToggleLabel"
defaultMessage="Advanced monitoring options"
/>
}
buttonClassName={disabled ? undefined : 'ingest-active-button'}
isDisabled={disabled === true}
>
<EuiSpacer size="s" />
{/* HTTP monitoring endpoint */}
<PushedDescribedFormGroup
fullWidth
title={
<h3>
<FormattedMessage
id="xpack.fleet.agentPolicyForm.monitoringHttpLabel"
defaultMessage="HTTP monitoring endpoint"
/>
</h3>
}
description={
<FormattedMessage
id="xpack.fleet.agentPolicyForm.monitoringHttpDescription"
defaultMessage="Enable a liveness HTTP endpoint that returns the overall health of Elastic Agent. This can be used by Kubernetes to restart the container, for example. {learnMoreLink}."
values={{
learnMoreLink: (
<EuiLink href={docLinks.links.fleet.httpMonitoring} target="_blank">
<FormattedMessage
id="xpack.fleet.agentPolicyForm.monitoringHttpDescription.learnMoreLinkLabel"
defaultMessage="Learn more"
/>
</EuiLink>
),
}}
/>
}
>
<EuiSpacer size="l" />
{/* Enable base HTTP monitoring endpoint */}
<EuiCheckbox
id="httpMonitoringEnabled"
label={
<FormattedMessage
id="xpack.fleet.agentPolicyForm.enableHttpMonitoringLabel"
defaultMessage="Enable HTTP endpoint at {monitoringEndpoint}"
values={{
monitoringEndpoint: <EuiCode>/liveness</EuiCode>,
}}
/>
}
disabled={disabled}
checked={agentPolicy.monitoring_http?.enabled}
onChange={(e) => {
const isEnabled = e.target.checked;
const host = isEnabled && !agentPolicy.monitoring_http?.host ? 'localhost' : undefined;
const port = isEnabled && !agentPolicy.monitoring_http?.port ? 6791 : undefined;
updateTouchedFields({ 'monitoring_http.enabled': true });
updateAgentPolicy({
monitoring_http: {
...agentPolicy.monitoring_http,
...(host ? { host } : {}),
...(port ? { port } : {}),
enabled: isEnabled,
},
});
}}
/>
<EuiSpacer size="s" />
{/* Host and port */}
<EuiFlexGroup direction="row">
<EuiFlexItem>
<EuiFormRow
fullWidth
label={
<FormattedMessage
id="xpack.fleet.agentPolicyForm.monitoringHttp.hostFieldLabel"
defaultMessage="Host"
/>
}
isDisabled={disabled || !agentPolicy.monitoring_http?.enabled}
error={
touchedFields['monitoring_http.host'] && validation['monitoring_http.host']
? validation['monitoring_http.host']
: null
}
isInvalid={Boolean(
touchedFields['monitoring_http.host'] && validation['monitoring_http.host']
)}
>
<EuiFieldText
fullWidth
disabled={disabled || !agentPolicy.monitoring_http?.enabled}
placeholder="localhost"
value={agentPolicy.monitoring_http?.host}
onChange={(e) => {
updateAgentPolicy({
monitoring_http: {
...agentPolicy.monitoring_http!,
host: e.target.value,
},
});
}}
onBlur={() => updateTouchedFields({ 'monitoring_http.host': true })}
isInvalid={Boolean(
touchedFields['monitoring_http.host'] && validation['monitoring_http.host']
)}
/>
</EuiFormRow>
</EuiFlexItem>
<EuiFlexItem>
<EuiFormRow
fullWidth
label={
<FormattedMessage
id="xpack.fleet.agentPolicyForm.monitoringHttp.portFieldLabel"
defaultMessage="Port"
/>
}
isDisabled={disabled || !agentPolicy.monitoring_http?.enabled}
error={
touchedFields['monitoring_http.port'] && validation['monitoring_http.port']
? validation['monitoring_http.port']
: null
}
isInvalid={Boolean(
touchedFields['monitoring_http.port'] && validation['monitoring_http.port']
)}
>
<EuiFieldNumber
fullWidth
disabled={disabled || !agentPolicy.monitoring_http?.enabled}
placeholder="6791"
min={1}
max={65535}
value={agentPolicy.monitoring_http?.port}
onChange={(e) => {
updateAgentPolicy({
monitoring_http: {
...agentPolicy.monitoring_http!,
port: e.target.value ? Number(e.target.value) : 0,
},
});
}}
onBlur={() => updateTouchedFields({ 'monitoring_http.port': true })}
isInvalid={Boolean(
touchedFields['monitoring_http.port'] && validation['monitoring_http.port']
)}
/>
</EuiFormRow>
</EuiFlexItem>
</EuiFlexGroup>
<EuiSpacer size="s" />
{/* Profiling endpoint */}
<EuiCheckbox
id="httpMonitoringProfilingEnabled"
label={
<FormattedMessage
id="xpack.fleet.agentPolicyForm.enableHttpMonitoringPprofLabel"
defaultMessage="Enable profiling at {profilingEndpoint}"
values={{
profilingEndpoint: <EuiCode>/debug/pprof</EuiCode>,
}}
/>
}
disabled={disabled || !agentPolicy.monitoring_http?.enabled}
checked={agentPolicy.monitoring_pprof_enabled}
onChange={(e) => {
updateTouchedFields({ monitoring_pprof_enabled: true });
updateAgentPolicy({
monitoring_pprof_enabled: e.target.checked,
});
}}
/>
</PushedDescribedFormGroup>
{/* Diagnostics rate limiting */}
<PushedDescribedFormGroup
fullWidth
title={
<h3>
<FormattedMessage
id="xpack.fleet.agentPolicyForm.diagnosticsRateLimitLabel"
defaultMessage="Diagnostics rate limiting"
/>
</h3>
}
description={
<FormattedMessage
id="xpack.fleet.agentPolicyForm.diagnosticsRateLimitDescription"
defaultMessage="Rate limit for the request diagnostics action handler. Does not affect diagnostics collected through the CLI. {learnMoreLink}."
values={{
learnMoreLink: (
<EuiLink href={docLinks.links.fleet.httpMonitoring} target="_blank">
<FormattedMessage
id="xpack.fleet.agentPolicyForm.diagnosticsRateLimitDescription.learnMoreLinkLabel"
defaultMessage="Learn more"
/>
</EuiLink>
),
}}
/>
}
>
<EuiFlexGroup>
<EuiFlexItem grow={1}>
<EuiFormRow
label={
<FormattedMessage
id="xpack.fleet.agentPolicyForm.diagnosticsRateLimit.intervalFieldLabel"
defaultMessage="Interval"
/>
}
isDisabled={disabled}
error={
touchedFields['monitoring_diagnostics.limit.interval'] &&
validation['monitoring_diagnostics.limit.interval']
? validation['monitoring_diagnostics.limit.interval']
: null
}
isInvalid={Boolean(
touchedFields['monitoring_diagnostics.limit.interval'] &&
validation['monitoring_diagnostics.limit.interval']
)}
>
<EuiFieldText
disabled={disabled}
placeholder="1m"
value={agentPolicy.monitoring_diagnostics?.limit?.interval}
onChange={(e) => {
updateAgentPolicy({
monitoring_diagnostics: {
...agentPolicy.monitoring_diagnostics,
limit: {
...agentPolicy.monitoring_diagnostics?.limit,
interval: e.target.value ? e.target.value : undefined,
},
},
});
}}
onBlur={() =>
updateTouchedFields({ 'monitoring_diagnostics.limit.interval': true })
}
isInvalid={Boolean(
touchedFields['monitoring_diagnostics.limit.interval'] &&
validation['monitoring_diagnostics.limit.interval']
)}
/>
</EuiFormRow>
</EuiFlexItem>
<EuiFlexItem grow={1}>
<EuiFormRow
label={
<FormattedMessage
id="xpack.fleet.agentPolicyForm.diagnosticsRateLimit.burstFieldLabel"
defaultMessage="Burst"
/>
}
isDisabled={disabled}
error={
touchedFields['monitoring_diagnostics.limit.burst'] &&
validation['monitoring_diagnostics.limit.burst']
? validation['monitoring_diagnostics.limit.burst']
: null
}
isInvalid={Boolean(
touchedFields['monitoring_diagnostics.limit.burst'] &&
validation['monitoring_diagnostics.limit.burst']
)}
>
<EuiFieldNumber
disabled={disabled}
placeholder="1"
min={1}
value={agentPolicy.monitoring_diagnostics?.limit?.burst}
onChange={(e) => {
updateAgentPolicy({
monitoring_diagnostics: {
...agentPolicy.monitoring_diagnostics,
limit: {
...agentPolicy.monitoring_diagnostics?.limit,
burst: e.target.value ? Number(e.target.value) : undefined,
},
},
});
}}
onBlur={() => updateTouchedFields({ 'monitoring_diagnostics.limit.burst': true })}
isInvalid={Boolean(
touchedFields['monitoring_diagnostics.limit.burst'] &&
validation['monitoring_diagnostics.limit.burst']
)}
/>
</EuiFormRow>
</EuiFlexItem>
<EuiFlexItem grow={1}>{/* Empty to match colums with upload fields below */}</EuiFlexItem>
</EuiFlexGroup>
</PushedDescribedFormGroup>
{/* Diagnostics file upload */}
<PushedDescribedFormGroup
fullWidth
title={
<h3>
<FormattedMessage
id="xpack.fleet.agentPolicyForm.diagnosticsFileUploadLabel"
defaultMessage="Diagnostics file upload"
/>
</h3>
}
description={
<FormattedMessage
id="xpack.fleet.agentPolicyForm.diagnosticsFileUploadDescription"
defaultMessage="Retry configuration for the file upload client. Client may retry failed requests with exponential backoff. {learnMoreLink}."
values={{
learnMoreLink: (
<EuiLink href={docLinks.links.fleet.httpMonitoring} target="_blank">
<FormattedMessage
id="xpack.fleet.agentPolicyForm.diagnosticsFileUploadDescription.learnMoreLinkLabel"
defaultMessage="Learn more"
/>
</EuiLink>
),
}}
/>
}
>
<EuiFlexGroup>
<EuiFlexItem grow={1}>
<EuiFormRow
label={
<FormattedMessage
id="xpack.fleet.agentPolicyForm.diagnosticsFileUpload.maxRetriesFieldLabel"
defaultMessage="Max retries"
/>
}
isDisabled={disabled}
error={
touchedFields['monitoring_diagnostics.uploader.max_retries'] &&
validation['monitoring_diagnostics.uploader.max_retries']
? validation['monitoring_diagnostics.uploader.max_retries']
: null
}
isInvalid={Boolean(
touchedFields['monitoring_diagnostics.uploader.max_retries'] &&
validation['monitoring_diagnostics.uploader.max_retries']
)}
>
<EuiFieldNumber
disabled={disabled}
placeholder="10"
min={1}
value={agentPolicy.monitoring_diagnostics?.uploader?.max_retries}
onChange={(e) => {
updateAgentPolicy({
monitoring_diagnostics: {
...agentPolicy.monitoring_diagnostics,
uploader: {
...agentPolicy.monitoring_diagnostics?.uploader,
max_retries: e.target.value ? Number(e.target.value) : undefined,
},
},
});
}}
onBlur={() =>
updateTouchedFields({ 'monitoring_diagnostics.uploader.max_retries': true })
}
isInvalid={Boolean(
touchedFields['monitoring_diagnostics.uploader.max_retries'] &&
validation['monitoring_diagnostics.uploader.max_retries']
)}
/>
</EuiFormRow>
</EuiFlexItem>
<EuiFlexItem grow={1}>
<EuiFormRow
label={
<FormattedMessage
id="xpack.fleet.agentPolicyForm.diagnosticsFileUpload.initialDurationFieldLabel"
defaultMessage="Initial duration"
/>
}
isDisabled={disabled}
error={
touchedFields['monitoring_diagnostics.uploader.init_dur'] &&
validation['monitoring_diagnostics.uploader.init_dur']
? validation['monitoring_diagnostics.uploader.init_dur']
: null
}
isInvalid={Boolean(
touchedFields['monitoring_diagnostics.uploader.init_dur'] &&
validation['monitoring_diagnostics.uploader.init_dur']
)}
>
<EuiFieldText
disabled={disabled}
placeholder="1s"
value={agentPolicy.monitoring_diagnostics?.uploader?.init_dur}
onChange={(e) => {
updateAgentPolicy({
monitoring_diagnostics: {
...agentPolicy.monitoring_diagnostics,
uploader: {
...agentPolicy.monitoring_diagnostics?.uploader,
init_dur: e.target.value ? e.target.value : undefined,
},
},
});
}}
onBlur={() =>
updateTouchedFields({ 'monitoring_diagnostics.uploader.init_dur': true })
}
isInvalid={Boolean(
touchedFields['monitoring_diagnostics.uploader.init_dur'] &&
validation['monitoring_diagnostics.uploader.init_dur']
)}
/>
</EuiFormRow>
</EuiFlexItem>
<EuiFlexItem grow={1}>
<EuiFormRow
label={
<FormattedMessage
id="xpack.fleet.agentPolicyForm.diagnosticsFileUpload.maxDurationFieldLabel"
defaultMessage="Backoff duration"
/>
}
isDisabled={disabled}
error={
touchedFields['monitoring_diagnostics.uploader.max_dur'] &&
validation['monitoring_diagnostics.uploader.max_dur']
? validation['monitoring_diagnostics.uploader.max_dur']
: null
}
isInvalid={Boolean(
touchedFields['monitoring_diagnostics.uploader.max_dur'] &&
validation['monitoring_diagnostics.uploader.max_dur']
)}
>
<EuiFieldText
disabled={disabled}
placeholder="1m"
value={agentPolicy.monitoring_diagnostics?.uploader?.max_dur}
onChange={(e) => {
updateAgentPolicy({
monitoring_diagnostics: {
...agentPolicy.monitoring_diagnostics,
uploader: {
...agentPolicy.monitoring_diagnostics?.uploader,
max_dur: e.target.value ? e.target.value : undefined,
},
},
});
}}
onBlur={() =>
updateTouchedFields({ 'monitoring_diagnostics.uploader.max_dur': true })
}
isInvalid={Boolean(
touchedFields['monitoring_diagnostics.uploader.max_dur'] &&
validation['monitoring_diagnostics.uploader.max_dur']
)}
/>
</EuiFormRow>
</EuiFlexItem>
</EuiFlexGroup>
</PushedDescribedFormGroup>
</StyledEuiAccordion>
);
};

View file

@ -62,6 +62,7 @@ import {
import { CustomFields } from './custom_fields';
import { SpaceSelector } from './space_selector';
import { AgentPolicyAdvancedMonitoringOptions } from './advanced_monitoring';
interface Props {
agentPolicy: Partial<NewAgentPolicy | AgentPolicy>;
@ -141,6 +142,7 @@ export const AgentPolicyAdvancedOptionsContent: React.FunctionComponent<Props> =
/>
}
>
<EuiSpacer size="l" />
<EuiSwitch
label={
<>
@ -401,6 +403,7 @@ export const AgentPolicyAdvancedOptionsContent: React.FunctionComponent<Props> =
/>
}
>
<EuiSpacer size="l" />
<EuiCheckboxGroup
disabled={disabled || agentPolicy.is_managed === true}
options={[
@ -476,6 +479,17 @@ export const AgentPolicyAdvancedOptionsContent: React.FunctionComponent<Props> =
}}
/>
</EuiDescribedFormGroup>
<AgentPolicyAdvancedMonitoringOptions
agentPolicy={agentPolicy}
disabled={disabled || agentPolicy.is_managed === true}
validation={validation}
touchedFields={touchedFields}
updateTouchedFields={(fields) => setTouchedFields({ ...touchedFields, ...fields })}
updateAgentPolicy={updateAgentPolicy}
/>
<EuiSpacer size="l" />
{AgentTamperProtectionSection}
<EuiDescribedFormGroup

View file

@ -129,6 +129,7 @@ export const AgentPolicyForm: React.FunctionComponent<Props> = ({
<EuiSpacer size="xs" />
<StyledEuiAccordion
id="advancedOptions"
data-test-subj="advancedOptionsButton"
buttonContent={
<FormattedMessage
id="xpack.fleet.agentPolicyForm.advancedOptionsToggleLabel"

View file

@ -25,7 +25,7 @@ describe('Agent Policy form validation', () => {
it('should return error when agentPolicy has empty namespace', () => {
const result = agentPolicyFormValidation({
namespace: 'Default',
namespace: '',
name: 'policy',
});
expect(result.namespace).toBeDefined();
@ -33,18 +33,113 @@ describe('Agent Policy form validation', () => {
it('should return error when agentPolicy has negative unenroll timeout', () => {
const result = agentPolicyFormValidation({
namespace: 'Default',
namespace: 'default',
name: 'policy',
unenroll_timeout: -1,
});
expect(result.unenroll_timeout).toBeDefined();
});
it('should return error when agentPolicy has negative inactivity timeout', () => {
const result = agentPolicyFormValidation({
namespace: 'Default',
namespace: 'default',
name: 'policy',
inactivity_timeout: -1,
});
expect(result.inactivity_timeout).toBeDefined();
});
it('should return error when agentPolicy has http monitoring enabled without host or port', () => {
expect(
agentPolicyFormValidation({
namespace: 'default',
name: 'policy',
monitoring_http: {
enabled: true,
host: 'localhost',
port: 123,
},
})
).toEqual({});
expect(
agentPolicyFormValidation({
namespace: 'default',
name: 'policy',
monitoring_http: {
enabled: false,
host: '',
},
})
).toEqual({});
expect(
Object.keys(
agentPolicyFormValidation({
namespace: 'default',
name: 'policy',
monitoring_http: {
enabled: true,
host: '',
port: 123,
},
})
)
).toEqual(['monitoring_http.host']);
expect(
Object.keys(
agentPolicyFormValidation({
namespace: 'default',
name: 'policy',
monitoring_http: {
enabled: true,
host: '',
},
})
)
).toEqual(['monitoring_http.host', 'monitoring_http.port']);
});
it('should return error when agentPolicy has invalid diagnostics options', () => {
expect(
Object.keys(
agentPolicyFormValidation({
namespace: 'default',
name: 'policy',
monitoring_diagnostics: {
limit: {
burst: 0,
},
uploader: {
max_retries: -1,
},
},
})
)
).toEqual([
'monitoring_diagnostics.limit.burst',
'monitoring_diagnostics.uploader.max_retries',
]);
expect(
Object.keys(
agentPolicyFormValidation({
namespace: 'default',
name: 'policy',
monitoring_diagnostics: {
limit: {
burst: -1,
},
uploader: {
max_retries: 0,
},
},
})
)
).toEqual([
'monitoring_diagnostics.limit.burst',
'monitoring_diagnostics.uploader.max_retries',
]);
});
});

View file

@ -42,7 +42,7 @@ export const agentPolicyFormValidation = (
errors.unenroll_timeout = [
<FormattedMessage
id="xpack.fleet.agentPolicyForm.unenrollTimeoutMinValueErrorMessage"
defaultMessage="Unenroll timeout must be an integer greater than zero."
defaultMessage="Unenroll timeout must be an integer greater than zero"
/>,
];
}
@ -51,7 +51,54 @@ export const agentPolicyFormValidation = (
errors.inactivity_timeout = [
<FormattedMessage
id="xpack.fleet.agentPolicyForm.inactivityTimeoutMinValueErrorMessage"
defaultMessage="Inactivity timeout must be an integer greater than zero."
defaultMessage="Inactivity timeout must be an integer greater than zero"
/>,
];
}
if (agentPolicy.monitoring_http?.enabled) {
if (!agentPolicy.monitoring_http.host?.trim()) {
errors['monitoring_http.host'] = [
<FormattedMessage
id="xpack.fleet.agentPolicyForm.monitoringHttpHostRequiredErrorMessage"
defaultMessage="Host is required for HTTP monitoring"
/>,
];
}
if (
!agentPolicy.monitoring_http.port ||
(agentPolicy.monitoring_http.port !== undefined && agentPolicy.monitoring_http.port <= 0)
) {
errors['monitoring_http.port'] = [
<FormattedMessage
id="xpack.fleet.agentPolicyForm.monitoringHttpPortRequiredErrorMessage"
defaultMessage="Port is required for HTTP monitoring"
/>,
];
}
}
if (
agentPolicy.monitoring_diagnostics?.limit?.burst !== undefined &&
agentPolicy.monitoring_diagnostics?.limit?.burst <= 0
) {
errors['monitoring_diagnostics.limit.burst'] = [
<FormattedMessage
id="xpack.fleet.agentPolicyForm.diagnosticsLimitBurstMinValueErrorMessage"
defaultMessage="Burst must be an integer greater than zero"
/>,
];
}
if (
agentPolicy.monitoring_diagnostics?.uploader?.max_retries !== undefined &&
agentPolicy.monitoring_diagnostics?.uploader?.max_retries <= 0
) {
errors['monitoring_diagnostics.uploader.max_retries'] = [
<FormattedMessage
id="xpack.fleet.agentPolicyForm.diagnosticsLimitBurstMinValueErrorMessage"
defaultMessage="Max retries must be an integer greater than zero"
/>,
];
}

View file

@ -57,6 +57,9 @@ const pickAgentPolicyKeysToSend = (agentPolicy: AgentPolicy) =>
'is_protected',
'advanced_settings',
'global_data_tags',
'monitoring_pprof_enabled',
'monitoring_http',
'monitoring_diagnostics',
]);
const FormWrapper = styled.div`

View file

@ -91,7 +91,7 @@ import {
migratePackagePolicyToV81102,
migratePackagePolicyEvictionsFromV81102,
} from './migrations/security_solution/to_v8_11_0_2';
import { settingsV1 } from './model_versions/v1';
import { settingsV1 } from './model_versions/settings_v1';
import {
packagePolicyV13AdvancedFields,
packagePolicyV10OnWriteScanFix,
@ -100,6 +100,7 @@ import {
migratePackagePolicyIdsToV8150,
migratePackagePolicySetRequiresRootToV8150,
} from './migrations/to_v8_15_0';
import { backfillAgentPolicyToV4 } from './model_versions/agent_policy_v4';
/*
* Saved object types and mappings
@ -223,6 +224,9 @@ export const getSavedObjectTypes = (
advanced_settings: { type: 'flattened', index: false },
supports_agentless: { type: 'boolean' },
global_data_tags: { type: 'flattened', index: false },
monitoring_pprof_enabled: { type: 'boolean', index: false },
monitoring_http: { type: 'flattened', index: false },
monitoring_diagnostics: { type: 'flattened', index: false },
},
},
migrations: {
@ -263,6 +267,22 @@ export const getSavedObjectTypes = (
},
],
},
'4': {
changes: [
{
type: 'mappings_addition',
addedMappings: {
monitoring_pprof_enabled: { type: 'boolean', index: false },
monitoring_http: { type: 'flattened', index: false },
monitoring_diagnostics: { type: 'flattened', index: false },
},
},
{
type: 'data_backfill',
backfillFn: backfillAgentPolicyToV4,
},
],
},
},
},
[AGENT_POLICY_SAVED_OBJECT_TYPE]: {

View file

@ -0,0 +1,131 @@
/*
* 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 {
SavedObject,
SavedObjectModelTransformationContext,
} from '@kbn/core-saved-objects-server';
import type { AgentPolicy } from '../../../common';
import { backfillAgentPolicyToV4 } from './agent_policy_v4';
describe('migrateAgentPolicyToV8160', () => {
it('should migrate advanced_settings.agent_monitoring_http to monitoring_http', () => {
const agentPolicyDoc: SavedObject<AgentPolicy> = {
id: 'policy1',
type: 'ingest-agent-policies',
references: [],
attributes: {
id: 'policy1',
name: 'Policy 1',
namespace: 'default',
advanced_settings: {
agent_monitoring_http: {
enabled: true,
host: 'localhost',
port: 1111,
'buffer.enabled': true,
},
},
is_managed: false,
status: 'active',
updated_at: '2021-08-17T14:00:00.000Z',
updated_by: 'elastic',
revision: 1,
is_protected: false,
},
};
const migratedAgentPolicyDoc = backfillAgentPolicyToV4(
agentPolicyDoc,
{} as SavedObjectModelTransformationContext
);
expect(migratedAgentPolicyDoc.attributes.monitoring_http).toEqual({
enabled: true,
host: 'localhost',
port: 1111,
});
expect(
migratedAgentPolicyDoc.attributes.advanced_settings?.agent_monitoring_http
).toBeUndefined();
});
it('should migrate advanced_settings.agent_monitoring_http to monitoring_http when most values are missing', () => {
const agentPolicyDoc: SavedObject<AgentPolicy> = {
id: 'policy1',
type: 'ingest-agent-policies',
references: [],
attributes: {
id: 'policy1',
name: 'Policy 1',
namespace: 'default',
advanced_settings: {
agent_monitoring_http: {
enabled: true,
},
},
is_managed: false,
status: 'active',
updated_at: '2021-08-17T14:00:00.000Z',
updated_by: 'elastic',
revision: 1,
is_protected: false,
},
};
const migratedAgentPolicyDoc = backfillAgentPolicyToV4(
agentPolicyDoc,
{} as SavedObjectModelTransformationContext
);
expect(migratedAgentPolicyDoc.attributes.monitoring_http).toEqual({
enabled: true,
});
expect(
migratedAgentPolicyDoc.attributes.advanced_settings?.agent_monitoring_http
).toBeUndefined();
});
it('should migrate advanced_settings.agent_monitoring_http to monitoring_http when some values are missing', () => {
const agentPolicyDoc: SavedObject<AgentPolicy> = {
id: 'policy1',
type: 'ingest-agent-policies',
references: [],
attributes: {
id: 'policy1',
name: 'Policy 1',
namespace: 'default',
advanced_settings: {
agent_monitoring_http: {
enabled: true,
'buffer.enabled': true,
},
},
is_managed: false,
status: 'active',
updated_at: '2021-08-17T14:00:00.000Z',
updated_by: 'elastic',
revision: 1,
is_protected: false,
},
};
const migratedAgentPolicyDoc = backfillAgentPolicyToV4(
agentPolicyDoc,
{} as SavedObjectModelTransformationContext
);
expect(migratedAgentPolicyDoc.attributes.monitoring_http).toEqual({
enabled: true,
});
expect(
migratedAgentPolicyDoc.attributes.advanced_settings?.agent_monitoring_http
).toBeUndefined();
});
});

View file

@ -0,0 +1,25 @@
/*
* 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 { SavedObjectModelDataBackfillFn } from '@kbn/core-saved-objects-server';
import type { AgentPolicy } from '../../../common';
export const backfillAgentPolicyToV4: SavedObjectModelDataBackfillFn<AgentPolicy, AgentPolicy> = (
agentPolicyDoc
) => {
const advancedSettings = agentPolicyDoc.attributes.advanced_settings;
if (advancedSettings?.agent_monitoring_http) {
agentPolicyDoc.attributes.monitoring_http = {
enabled: advancedSettings.agent_monitoring_http.enabled,
host: advancedSettings.agent_monitoring_http.host,
port: advancedSettings.agent_monitoring_http.port,
};
delete advancedSettings.agent_monitoring_http;
}
return agentPolicyDoc;
};

View file

@ -20,6 +20,7 @@ import { getPackageInfo } from '../epm/packages';
import {
generateFleetConfig,
getFullAgentPolicy,
getFullMonitoringSettings,
transformOutputToFullPolicyOutput,
} from './full_agent_policy';
import { getMonitoringPermissions } from './monitoring_permissions';
@ -901,6 +902,167 @@ describe('getFullAgentPolicy', () => {
});
});
describe('getFullMonitoringSettings', () => {
it('should return the correct settings when all values are present', async () => {
const monitoringSettings = getFullMonitoringSettings(
{
namespace: 'default',
monitoring_enabled: ['metrics', 'logs', 'traces'],
monitoring_pprof_enabled: true,
monitoring_http: {
enabled: true,
host: 'localhost',
port: 1111,
},
monitoring_diagnostics: {
limit: {
interval: '1m',
burst: 10,
},
uploader: {
max_retries: 3,
init_dur: '1m',
max_dur: '10m',
},
},
},
{
id: 'some-output',
is_default: false,
type: 'elasticsearch',
}
);
expect(monitoringSettings).toEqual({
enabled: true,
logs: true,
metrics: true,
traces: true,
namespace: 'default',
use_output: 'some-output',
pprof: { enabled: true },
http: {
enabled: true,
host: 'localhost',
port: 1111,
},
diagnostics: {
limit: {
interval: '1m',
burst: 10,
},
uploader: {
max_retries: 3,
init_dur: '1m',
max_dur: '10m',
},
},
});
});
it('should return the correct settings when some values are present', async () => {
const monitoringSettings = getFullMonitoringSettings(
{
namespace: 'default',
monitoring_enabled: ['metrics'],
monitoring_pprof_enabled: false,
monitoring_http: {
enabled: true,
host: 'localhost',
},
monitoring_diagnostics: {
limit: {
interval: '1m',
},
uploader: {
max_dur: '10m',
},
},
},
{
id: 'some-output',
is_default: true,
type: 'elasticsearch',
}
);
expect(monitoringSettings).toEqual({
enabled: true,
logs: false,
metrics: true,
traces: false,
namespace: 'default',
use_output: 'default',
pprof: { enabled: false },
http: {
enabled: true,
host: 'localhost',
},
diagnostics: {
limit: {
interval: '1m',
},
uploader: {
max_dur: '10m',
},
},
});
});
it('should return the correct settings when beats monitoring is disabled and minimal values are present', async () => {
const monitoringSettings = getFullMonitoringSettings(
{
namespace: 'default',
monitoring_enabled: [],
monitoring_http: {
enabled: true,
},
monitoring_diagnostics: {},
},
{
id: 'some-output',
is_default: true,
type: 'elasticsearch',
}
);
expect(monitoringSettings).toEqual({
enabled: true,
logs: false,
metrics: false,
traces: false,
http: {
enabled: true,
},
});
});
it('should disable monitoring if beats and http monitoring are disabled', async () => {
const monitoringSettings = getFullMonitoringSettings(
{
namespace: 'default',
monitoring_enabled: [],
monitoring_http: {
enabled: false,
},
monitoring_diagnostics: {},
},
{
id: 'some-output',
is_default: true,
type: 'elasticsearch',
}
);
expect(monitoringSettings).toEqual({
enabled: false,
logs: false,
metrics: false,
traces: false,
});
});
});
describe('transformOutputToFullPolicyOutput', () => {
it('should works with only required field on a output', () => {
const policyOutput = transformOutputToFullPolicyOutput({

View file

@ -136,36 +136,6 @@ export async function getFullAgentPolicy(
const packagePolicySecretReferences = (agentPolicy?.package_policies || []).flatMap(
(policy) => policy.secret_references || []
);
const defaultMonitoringConfig: FullAgentPolicyMonitoring = {
enabled: false,
logs: false,
metrics: false,
traces: false,
};
let monitoring: FullAgentPolicyMonitoring = { ...defaultMonitoringConfig };
// If the agent policy has monitoring enabled for at least one of "logs", "metrics", or "traces"
// generate a monitoring config for the resulting compiled agent policy
if (agentPolicy.monitoring_enabled && agentPolicy.monitoring_enabled.length > 0) {
monitoring = {
namespace: agentPolicy.namespace,
use_output: getOutputIdForAgentPolicy(monitoringOutput),
enabled: true,
logs: agentPolicy.monitoring_enabled.includes(dataTypes.Logs),
metrics: agentPolicy.monitoring_enabled.includes(dataTypes.Metrics),
traces: agentPolicy.monitoring_enabled.includes(dataTypes.Traces),
};
// If the `keep_monitoring_alive` flag is set, enable monitoring but don't enable logs or metrics.
// This allows cloud or other environments to keep the monitoring server alive without tearing it down.
} else if (agentPolicy.keep_monitoring_alive) {
monitoring = {
enabled: true,
logs: false,
metrics: false,
traces: false,
};
}
const fullAgentPolicy: FullAgentPolicy = {
id: agentPolicy.id,
@ -188,7 +158,7 @@ export async function getFullAgentPolicy(
sourceURI: downloadSourceUri,
...(downloadSourceProxyUri ? { proxy_url: downloadSourceProxyUri } : {}),
},
monitoring,
monitoring: getFullMonitoringSettings(agentPolicy, monitoringOutput),
features,
protection: {
enabled: agentPolicy.is_protected,
@ -550,11 +520,102 @@ export function transformOutputToFullPolicyOutput(
return newOutput;
}
export function getFullMonitoringSettings(
agentPolicy: Pick<
AgentPolicy,
| 'namespace'
| 'monitoring_enabled'
| 'keep_monitoring_alive'
| 'monitoring_pprof_enabled'
| 'monitoring_http'
| 'monitoring_diagnostics'
>,
monitoringOutput: Pick<Output, 'id' | 'is_default' | 'type'>
): FullAgentPolicyMonitoring {
// Set base beats monitoring settings
const monitoring: FullAgentPolicyMonitoring = {
enabled: Boolean(
(agentPolicy.monitoring_enabled && agentPolicy.monitoring_enabled.length > 0) ||
agentPolicy.monitoring_http?.enabled ||
agentPolicy.keep_monitoring_alive
),
logs: false,
metrics: false,
traces: false,
};
// If the agent policy has monitoring enabled for at least one of "logs", "metrics", or "traces"
// generate a monitoring config for the resulting compiled agent policy
if (agentPolicy.monitoring_enabled && agentPolicy.monitoring_enabled.length > 0) {
monitoring.namespace = agentPolicy.namespace;
monitoring.use_output = getOutputIdForAgentPolicy(monitoringOutput);
monitoring.logs = agentPolicy.monitoring_enabled.includes(dataTypes.Logs);
monitoring.metrics = agentPolicy.monitoring_enabled.includes(dataTypes.Metrics);
monitoring.traces = agentPolicy.monitoring_enabled.includes(dataTypes.Traces);
}
if (agentPolicy.monitoring_pprof_enabled !== undefined) {
monitoring.pprof = {
enabled: agentPolicy.monitoring_pprof_enabled,
};
}
// Conditionally set http monitoring settings
if (agentPolicy.monitoring_http?.enabled) {
monitoring.http = {
enabled: agentPolicy.monitoring_http.enabled,
...(agentPolicy.monitoring_http.host && { host: agentPolicy.monitoring_http.host }),
...(agentPolicy.monitoring_http.port && { port: agentPolicy.monitoring_http.port }),
};
}
// Conditionally set diagnostics monitoring settings
if (agentPolicy.monitoring_diagnostics?.limit || agentPolicy.monitoring_diagnostics?.uploader) {
monitoring.diagnostics = {};
if (
agentPolicy.monitoring_diagnostics.limit &&
(agentPolicy.monitoring_diagnostics.limit.interval ||
typeof agentPolicy.monitoring_diagnostics.limit.burst === 'number')
) {
monitoring.diagnostics.limit = {
...(agentPolicy.monitoring_diagnostics.limit.interval && {
interval: agentPolicy.monitoring_diagnostics.limit.interval,
}),
...(typeof agentPolicy.monitoring_diagnostics.limit.burst === 'number' && {
burst: agentPolicy.monitoring_diagnostics.limit.burst,
}),
};
}
if (
agentPolicy.monitoring_diagnostics.uploader &&
(typeof agentPolicy.monitoring_diagnostics.uploader.max_retries === 'number' ||
agentPolicy.monitoring_diagnostics.uploader.init_dur ||
agentPolicy.monitoring_diagnostics.uploader.max_dur)
) {
monitoring.diagnostics.uploader = {
...(typeof agentPolicy.monitoring_diagnostics.uploader.max_retries === 'number' && {
max_retries: agentPolicy.monitoring_diagnostics.uploader.max_retries,
}),
...(agentPolicy.monitoring_diagnostics.uploader.init_dur && {
init_dur: agentPolicy.monitoring_diagnostics.uploader.init_dur,
}),
...(agentPolicy.monitoring_diagnostics.uploader.max_dur && {
max_dur: agentPolicy.monitoring_diagnostics.uploader.max_dur,
}),
};
}
}
return monitoring;
}
/**
* Get id used in full agent policy (sent to the agents)
* we use "default" for the default policy to avoid breaking changes
*/
function getOutputIdForAgentPolicy(output: Output) {
function getOutputIdForAgentPolicy(output: Pick<Output, 'id' | 'is_default' | 'type'>) {
if (output.is_default && output.type === outputType.Elasticsearch) {
return DEFAULT_OUTPUT.name;
}

View file

@ -759,6 +759,9 @@ class AgentPolicyService {
'fleet_server_host_id',
'supports_agentless',
'global_data_tags',
'monitoring_pprof_enabled',
'monitoring_http',
'monitoring_diagnostics',
]),
...newAgentPolicyProps,
},

View file

@ -102,6 +102,32 @@ export const AgentPolicyBaseSchema = {
}
)
),
monitoring_pprof_enabled: schema.maybe(schema.boolean()),
monitoring_http: schema.maybe(
schema.object({
enabled: schema.boolean(),
host: schema.maybe(schema.string({ defaultValue: 'localhost' })),
port: schema.maybe(schema.number({ min: 0, max: 65353, defaultValue: 6791 })),
buffer: schema.maybe(schema.object({ enabled: schema.boolean({ defaultValue: false }) })),
})
),
monitoring_diagnostics: schema.maybe(
schema.object({
limit: schema.maybe(
schema.object({
interval: schema.maybe(schema.string()),
burst: schema.maybe(schema.number()),
})
),
uploader: schema.maybe(
schema.object({
max_retries: schema.maybe(schema.number()),
init_dur: schema.maybe(schema.string()),
max_dur: schema.maybe(schema.string()),
})
),
})
),
};
function validateGlobalDataTagInput(tags: GlobalDataTag[]): string | undefined {

View file

@ -20371,8 +20371,6 @@
"xpack.fleet.settings.agentPolicyAdvanced.agentLoggingLevelTitle": "Niveau de logging de l'agent",
"xpack.fleet.settings.agentPolicyAdvanced.agentLoggingMetricsPeriodDescription": "Fréquence de logging des indicateurs internes d'Elastic Agent.",
"xpack.fleet.settings.agentPolicyAdvanced.agentLoggingMetricsPeriodTitle": "Période de mesure de logging de l'agent",
"xpack.fleet.settings.agentPolicyAdvanced.agentMonitoringHttpDescription": "Active un point de terminaison HTTP actif qui renvoie l'état dintégrité global d'Elastic Agent. Il peut par exemple être utilisé par Kubernetes pour redémarrer le conteneur.",
"xpack.fleet.settings.agentPolicyAdvanced.agentMonitoringHttpTitle": "Point de terminaison de surveillance HTTP",
"xpack.fleet.settings.agentPolicyAdvanced.downloadTimeoutDescription": "Le délai d'expiration pour le téléchargement du binaire des agents.",
"xpack.fleet.settings.agentPolicyAdvanced.downloadTimeoutTitle": "Délai d'expiration de téléchargement du binaire des agents",
"xpack.fleet.settings.agentPolicyAdvanced.downloadTimeoutValidationMessage": "Doit être une chaîne avec une unité de temps, par exemple 30 s, 5 m, 2 h, 1 d",

View file

@ -20361,8 +20361,6 @@
"xpack.fleet.settings.agentPolicyAdvanced.agentLoggingLevelTitle": "エージェントログレベル",
"xpack.fleet.settings.agentPolicyAdvanced.agentLoggingMetricsPeriodDescription": "内部Elasticエージェントメトリックをログに記録する頻度。",
"xpack.fleet.settings.agentPolicyAdvanced.agentLoggingMetricsPeriodTitle": "エージェントログメトリック期間",
"xpack.fleet.settings.agentPolicyAdvanced.agentMonitoringHttpDescription": "Elasticエージェントの全体的な正常性を返すライブネスHTTPエンドポイントを有効化します。これは、たとえば、コンテナーを再起動するためにKubernetesによって使用されることがあります。",
"xpack.fleet.settings.agentPolicyAdvanced.agentMonitoringHttpTitle": "HTTP監視エンドポイント",
"xpack.fleet.settings.agentPolicyAdvanced.downloadTimeoutDescription": "エージェントバイナリのダウンロードに関するタイムアウト。",
"xpack.fleet.settings.agentPolicyAdvanced.downloadTimeoutTitle": "エージェントバイナリダウンロードタイムアウト",
"xpack.fleet.settings.agentPolicyAdvanced.downloadTimeoutValidationMessage": "30s、5m、2h、1dなどの時間単位の文字列でなければなりません",

View file

@ -20388,8 +20388,6 @@
"xpack.fleet.settings.agentPolicyAdvanced.agentLoggingLevelTitle": "代理日志记录级别",
"xpack.fleet.settings.agentPolicyAdvanced.agentLoggingMetricsPeriodDescription": "记录内部 Elastic 代理指标的频率。",
"xpack.fleet.settings.agentPolicyAdvanced.agentLoggingMetricsPeriodTitle": "代理日志记录指标期间",
"xpack.fleet.settings.agentPolicyAdvanced.agentMonitoringHttpDescription": "启用返回 Elastic 代理的整体运行状况的活性 HTTP 终端。例如,这可由 Kubernetes 用于重新启动容器。",
"xpack.fleet.settings.agentPolicyAdvanced.agentMonitoringHttpTitle": "HTTP 监测终端",
"xpack.fleet.settings.agentPolicyAdvanced.downloadTimeoutDescription": "下载代理二进制文件时的超时值。",
"xpack.fleet.settings.agentPolicyAdvanced.downloadTimeoutTitle": "代理二进制文件下载超时",
"xpack.fleet.settings.agentPolicyAdvanced.downloadTimeoutValidationMessage": "必须为带时间单位的字符串,如 30s、5m、2h、1d",

View file

@ -532,6 +532,86 @@ export default function (providerContext: FtrProviderContext) {
});
}
});
it('should create policy with advanced monitoring options', async () => {
const {
body: { item: createdPolicy },
} = await supertest
.post(`/api/fleet/agent_policies?sys_monitoring=true`)
.set('kbn-xsrf', 'xxxx')
.send({
name: 'advanced monitoring test',
namespace: 'default',
monitoring_pprof_enabled: true,
monitoring_http: {
host: 'localhost',
port: 6791,
enabled: true,
},
monitoring_diagnostics: {
limit: {
interval: '1m',
burst: 1,
},
uploader: {
max_retries: 10,
init_dur: '1s',
max_dur: '10m',
},
},
})
.expect(200);
const policyResponse = await supertest
.get(`/api/fleet/agent_policies/${createdPolicy.id}`)
.expect(200);
expect(policyResponse.body.item.monitoring_pprof_enabled).to.eql(true);
expect(policyResponse.body.item.monitoring_http).to.eql({
host: 'localhost',
port: 6791,
enabled: true,
});
expect(policyResponse.body.item.monitoring_diagnostics).to.eql({
limit: {
interval: '1m',
burst: 1,
},
uploader: {
max_retries: 10,
init_dur: '1s',
max_dur: '10m',
},
});
const fullPolicyResponse = await supertest
.get(`/api/fleet/agent_policies/${createdPolicy.id}/full`)
.expect(200);
expect(fullPolicyResponse.body.item.agent.monitoring).to.eql({
enabled: true,
logs: false,
metrics: false,
traces: false,
pprof: {
enabled: true,
},
http: {
enabled: true,
host: 'localhost',
port: 6791,
},
diagnostics: {
limit: {
interval: '1m',
burst: 1,
},
uploader: {
max_retries: 10,
init_dur: '1s',
max_dur: '10m',
},
},
});
});
});
describe('POST /api/fleet/agent_policies/{agentPolicyId}/copy', () => {
@ -978,6 +1058,65 @@ export default function (providerContext: FtrProviderContext) {
expect(newPolicy.global_data_tags).to.eql([{ name: 'testName', value: 'testValue' }]);
});
it('should copy advanced monitoring options', async () => {
const {
body: { item: policyWithAdvancedMonitoring },
} = await supertest
.post(`/api/fleet/agent_policies`)
.set('kbn-xsrf', 'xxxx')
.send({
name: 'advanced monitoring test',
namespace: 'default',
monitoring_pprof_enabled: true,
monitoring_http: {
host: 'localhost',
port: 6791,
enabled: true,
},
monitoring_diagnostics: {
limit: {
interval: '1m',
burst: 1,
},
uploader: {
max_retries: 10,
init_dur: '1s',
max_dur: '10m',
},
},
})
.expect(200);
const {
body: { item: newPolicy },
} = await supertest
.post(`/api/fleet/agent_policies/${policyWithAdvancedMonitoring.id}/copy`)
.set('kbn-xsrf', 'xxxx')
.send({
name: 'advanced monitoring test copy',
description: 'Test',
})
.expect(200);
expect(newPolicy.monitoring_pprof_enabled).to.eql(true);
expect(newPolicy.monitoring_http).to.eql({
host: 'localhost',
port: 6791,
enabled: true,
});
expect(newPolicy.monitoring_diagnostics).to.eql({
limit: {
interval: '1m',
burst: 1,
},
uploader: {
max_retries: 10,
init_dur: '1s',
max_dur: '10m',
},
});
});
});
describe('PUT /api/fleet/agent_policies/{agentPolicyId}', () => {