Skip to content

Commit 9e02beb

Browse files
VJeansteveny91
andauthored
Nextcloud: make the nextcloud.system.apps.* metrics optional (DataDog#2653)
* add a spec and re-sync example configuration example configuration was updated and synced with Validating default configuration files for 1 checks... Writing config file to `/home/jean/git/integrations-extras/nextcloud/datadog_checks/nextcloud/data/conf.yaml.example` All 2 configuration files are valid! * add flag to provide optional metrics * enforce url param format=json in code ensure stats are retrieved in json format rather than relying on the users to set it properly in conf * unpin nextcloud version * set default value to false * add an option for nextcloud apps stats * improve tests setup by waiting on startup logs * use util function to get current directory * wait for nextcloud to be available improves the reliability of the tests (Nextcloud seems to be taking longer to spin up in some cases) and is better than checking for logs * update version * format code * Shorten changelog entry * add a note about optional metrics in Readme * Bump major version Users on Nextcloud < 28 will not get the `apps.*` metrics anymore, unless they enable `apps_stats`. With the same config, they can no longer get the same amount of metrics. Co-authored-by: Steven Yuen <[email protected]> * Update __about__.py --------- Co-authored-by: Steven Yuen <[email protected]>
1 parent 199167d commit 9e02beb

File tree

11 files changed

+159
-28
lines changed

11 files changed

+159
-28
lines changed

nextcloud/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,8 @@
11
# CHANGELOG - Nextcloud
22

3+
# 2.0.0 / 2025-04-25
4+
5+
6+
***Changed***:
7+
8+
* Collect `nextcloud.system.apps.*` metrics when the `apps_stats` option is enabled.

nextcloud/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ Run the [Agent's status subcommand][10] and look for `nextcloud` under the Check
3636

3737
See [metadata.csv][11] for a list of metrics provided by this check.
3838

39+
#### Optional metrics
40+
41+
The `nextcloud.system.apps.*` metrics are optional and enabled with the `apps_stats` configuration key. Beginning with Nextcloud 28, the monitoring endpoint no longer provides information about available app updates, as gathering the data always involves at least one external request to apps.nextcloud.com.
42+
43+
It is still possible to ask the monitoring endpoint to [show new app updates][14] by using the URL parameter `skipApps=false`. However, Nextcloud recommends to not check this endpoint too often.
44+
3945
### Events
4046

4147
Nextcloud does not include any events.
@@ -60,3 +66,4 @@ Need help? Contact [Datadog support][12].
6066
[11]: https://github.com/DataDog/integrations-extras/blob/master/nextcloud/metadata.csv
6167
[12]: https://docs.datadoghq.com/help/
6268
[13]: https://github.com/DataDog/integrations-extras/blob/master/nextcloud/assets/service_checks.json
69+
[14]: https://github.com/nextcloud/serverinfo#api
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: Nextcloud
2+
files:
3+
- name: nextcloud.yaml
4+
options:
5+
- template: init_config
6+
options:
7+
- template: init_config/default
8+
- template: instances
9+
options:
10+
- name: url
11+
description: |
12+
The URL to the Nextcloud serverinfo info endpoint.
13+
This is used to fetch statistics.
14+
required: true
15+
value:
16+
type: string
17+
example: http://localhost/ocs/v2.php/apps/serverinfo/api/v1/info
18+
- name: username
19+
description: User name, that must have admin access to Nextcloud in order to reach the monitoring metrics endpoint
20+
required: true
21+
value:
22+
type: string
23+
- name: password
24+
description: User password, that must have admin access to Nextcloud in order to reach the monitoring metrics endpoint
25+
required: true
26+
value:
27+
type: string
28+
secret: true
29+
- name: apps_stats
30+
description: |
31+
Enable optional metrics about available app updates, at the cost of an external request to the app store
32+
value:
33+
type: boolean
34+
example: false
35+
- template: instances/default
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = '1.0.0'
1+
__version__ = '2.0.0'
Lines changed: 60 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,75 @@
1+
## All options defined here are available to all instances.
2+
#
13
init_config:
24

5+
## @param service - string - optional
6+
## Attach the tag `service:<SERVICE>` to every metric, event, and service check emitted by this integration.
7+
##
8+
## Additionally, this sets the default `service` for every log source.
9+
#
10+
# service: <SERVICE>
11+
12+
## Every instance is scheduled independently of the others.
13+
#
314
instances:
415

516
## @param url - string - required
6-
## The URL where nextcloud accepts HTTP requests.
17+
## The URL to the Nextcloud serverinfo info endpoint.
718
## This is used to fetch statistics.
819
#
9-
- url: http://localhost/ocs/v2.php/apps/serverinfo/api/v1/info?format=json
20+
- url: http://localhost/ocs/v2.php/apps/serverinfo/api/v1/info
1021

1122
## @param username - string - required
12-
## User name and password, that must have admin access to Nextcloud in
13-
## order to reach the monitoring metrics endpoint
23+
## User name, that must have admin access to Nextcloud in order to reach the monitoring metrics endpoint
1424
#
1525
username: <USERNAME>
1626

1727
## @param password - string - required
18-
## User password, that must have admin access to Nextcloud in
19-
## order to reach the monitoring metrics endpoint
28+
## User password, that must have admin access to Nextcloud in order to reach the monitoring metrics endpoint
2029
#
2130
password: <PASSWORD>
31+
32+
## @param apps_stats - boolean - optional - default: false
33+
## Enable optional metrics about available app updates, at the cost of an external request to the app store
34+
#
35+
# apps_stats: false
36+
37+
## @param tags - list of strings - optional
38+
## A list of tags to attach to every metric and service check emitted by this instance.
39+
##
40+
## Learn more about tagging at https://docs.datadoghq.com/tagging
41+
#
42+
# tags:
43+
# - <KEY_1>:<VALUE_1>
44+
# - <KEY_2>:<VALUE_2>
45+
46+
## @param service - string - optional
47+
## Attach the tag `service:<SERVICE>` to every metric, event, and service check emitted by this integration.
48+
##
49+
## Overrides any `service` defined in the `init_config` section.
50+
#
51+
# service: <SERVICE>
52+
53+
## @param min_collection_interval - number - optional - default: 15
54+
## This changes the collection interval of the check. For more information, see:
55+
## https://docs.datadoghq.com/developers/write_agent_check/#collection-interval
56+
#
57+
# min_collection_interval: 15
58+
59+
## @param empty_default_hostname - boolean - optional - default: false
60+
## This forces the check to send metrics with no hostname.
61+
##
62+
## This is useful for cluster-level checks.
63+
#
64+
# empty_default_hostname: false
65+
66+
## @param metric_patterns - mapping - optional
67+
## A mapping of metrics to include or exclude, with each entry being a regular expression.
68+
##
69+
## Metrics defined in `exclude` will take precedence in case of overlap.
70+
#
71+
# metric_patterns:
72+
# include:
73+
# - <INCLUDE_REGEX>
74+
# exclude:
75+
# - <EXCLUDE_REGEX>

nextcloud/datadog_checks/nextcloud/nextcloud.py

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ class NextcloudCheck(AgentCheck):
88
METRICS_PREFIX = "nextcloud"
99
METRICS_GAUGES = [
1010
"nextcloud.system.freespace",
11-
"nextcloud.system.apps.num_installed",
12-
"nextcloud.system.apps.num_updates_available",
1311
"nextcloud.storage.num_users",
1412
"nextcloud.storage.num_files",
1513
"nextcloud.storage.num_storages",
@@ -30,6 +28,10 @@ class NextcloudCheck(AgentCheck):
3028
"activeUsers.last1hour",
3129
"activeUsers.last24hours",
3230
]
31+
OPTIONAL_APP_STATS_METRICS_GAUGES = [
32+
"nextcloud.system.apps.num_installed",
33+
"nextcloud.system.apps.num_updates_available",
34+
]
3335

3436
# Tags that will be applied to all metrics
3537
GLOBAL_TAGS = [
@@ -41,10 +43,19 @@ class NextcloudCheck(AgentCheck):
4143

4244
def check(self, _):
4345
url = self.instance['url']
46+
# getting app-related stats is disabled by default as
47+
# this causes an additional external request to apps.nextcloud.com
48+
get_apps_stats = self.instance.get('apps_stats')
49+
params = {"format": "json", "skipApps": "false" if get_apps_stats else "true"}
50+
metrics_to_parse = (
51+
NextcloudCheck.METRICS_GAUGES
52+
if not get_apps_stats
53+
else NextcloudCheck.METRICS_GAUGES + NextcloudCheck.OPTIONAL_APP_STATS_METRICS_GAUGES
54+
)
4455

4556
try:
4657
self.log.debug("Checking against %s", url)
47-
response = self.http.get(url, extra_headers=headers(self.agentConfig))
58+
response = self.http.get(url, extra_headers=headers(self.agentConfig), params=params)
4859
if response.status_code != 200:
4960
self.service_check(
5061
NextcloudCheck.STATUS_CHECK, AgentCheck.CRITICAL, message="Problem requesting {}.".format(url)
@@ -54,7 +65,7 @@ def check(self, _):
5465
if json_response["ocs"]["meta"]["status"] == "ok":
5566
self.service_check(NextcloudCheck.STATUS_CHECK, AgentCheck.OK)
5667
self.parse_tags(json_response["ocs"]["data"])
57-
self.parse_metrics(json_response["ocs"]["data"])
68+
self.parse_metrics(json_response["ocs"]["data"], metrics_to_parse)
5869
else:
5970
self.service_check(
6071
NextcloudCheck.STATUS_CHECK,
@@ -83,7 +94,7 @@ def parse_tags(self, json_data):
8394
value = self.json_nested_get(json_data, tag["json_path"])
8495
self.tags.append("{}:{}".format(tag["name"], value))
8596

86-
def parse_metrics(self, json_data):
87-
for metric in NextcloudCheck.METRICS_GAUGES:
97+
def parse_metrics(self, json_data, expected_metrics):
98+
for metric in expected_metrics:
8899
metric_display_name = self.get_metric_display_name(metric)
89100
self.gauge(metric_display_name, self.json_nested_get(json_data, metric), tags=self.tags)

nextcloud/manifest.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@
2828
"assets": {
2929
"integration": {
3030
"source_type_name": "Nextcloud",
31-
"configuration": {},
31+
"configuration": {
32+
"spec": "assets/configuration/spec.yaml"
33+
},
3234
"events": {
3335
"creates_events": false
3436
},

nextcloud/tests/common.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,14 @@
11
# (C) Datadog, Inc. 2018
22
# All rights reserved
33
# Licensed under a 3-clause BSD style license (see LICENSE)
4-
import os
5-
64
from datadog_checks.dev import get_docker_hostname
75

8-
HERE = os.path.dirname(os.path.abspath(__file__))
9-
106
CONTAINER_NAME = 'nextcloud-standalone'
117
USER = 'admin'
128
PASSWORD = 'admin'
139
HOST = get_docker_hostname()
14-
PORT = '8080'
15-
VALID_URL = 'http://{}:{}/ocs/v2.php/apps/serverinfo/api/v1/info?format=json'.format(HOST, PORT)
10+
PORT = 8080
11+
VALID_URL = 'http://{}:{}/ocs/v2.php/apps/serverinfo/api/v1/info'.format(HOST, PORT)
1612
INVALID_URL = 'http://{}:{}/ocs/v2.php'.format(HOST, PORT)
1713

1814
BASE_CONFIG = {'url': VALID_URL, 'username': USER, 'password': PASSWORD}
Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
version: '3.5'
2-
31
services:
42
nextcloud-standalone:
5-
image: "nextcloud:14.0.14"
3+
image: "nextcloud:latest"
64
ports:
75
- 8080:80
86
container_name: nextcloud-standalone

nextcloud/tests/conftest.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,23 @@
44

55
import pytest
66

7-
from datadog_checks.dev import WaitFor, docker_run
7+
from datadog_checks.dev import docker_run, get_here
8+
from datadog_checks.dev.conditions import WaitFor, WaitForPortListening
89

9-
from .common import BASE_CONFIG, CONTAINER_NAME, HERE, HOST, INVALID_URL, PASSWORD, USER, VALID_URL
10+
from .common import BASE_CONFIG, CONTAINER_NAME, HOST, INVALID_URL, PASSWORD, PORT, USER, VALID_URL
1011

1112

1213
@pytest.fixture(scope="session")
1314
def dd_environment():
1415
"""
15-
Spin up and initialize couchbase
16+
Spin up and initialize Nextcloud
1617
"""
17-
18+
compose_file = os.path.join(get_here(), 'compose', CONTAINER_NAME)
1819
with docker_run(
19-
compose_file=os.path.join(HERE, 'compose', CONTAINER_NAME),
20+
compose_file=compose_file,
2021
env_vars={'NEXTCLOUD_ADMIN_USER': USER, 'NEXTCLOUD_ADMIN_PASSWORD': PASSWORD},
2122
conditions=[
23+
WaitForPortListening(HOST, PORT),
2224
WaitFor(nextcloud_container, attempts=15),
2325
WaitFor(nextcloud_install, attempts=15),
2426
WaitFor(nextcloud_add_trusted_domain, attempts=15),
@@ -47,6 +49,13 @@ def invalid_url_instance():
4749
return invalid_url_instance
4850

4951

52+
@pytest.fixture
53+
def apps_stats_instance():
54+
instance = deepcopy(BASE_CONFIG)
55+
instance['apps_stats'] = True
56+
return instance
57+
58+
5059
def nextcloud_container():
5160
"""
5261
Wait for nextcloud to start

0 commit comments

Comments
 (0)