Skip to content

Commit 7d59c3f

Browse files
committed
Implement basic telemetry collection
Signed-off-by: nscuro <nscuro@protonmail.com> # Conflicts: # dev/docker-compose.yml
1 parent 8cab3ea commit 7d59c3f

File tree

13 files changed

+621
-5
lines changed

13 files changed

+621
-5
lines changed

dev/docker-compose.yml

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ services:
2222
environment:
2323
# Speed up password hashing for faster initial login (default is 14 rounds).
2424
ALPINE_BCRYPT_ROUNDS: "4"
25+
TELEMETRY_SUBMISSION_ENABLED_DEFAULT: "false"
2526
ports:
2627
- "127.0.0.1:8080:8080"
2728
volumes:
+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
---
2+
title: Telemetry
3+
category: Getting Started
4+
chapter: 1
5+
order: 14
6+
---
7+
8+
## Collected data
9+
10+
| Data | Example |
11+
|:-------------------------|:-------------------------------------|
12+
| System ID | 78701907-3044-493d-92b5-6a45e08aecd3 |
13+
| Dependency-Track version | 4.13.0 |
14+
| Database type | PostgreSQL |
15+
| Database version | 15.2 |
16+
17+
Information that could allow this data to be traced back to specific organizations,
18+
such as IP addresses, is explicitly **not** collected or stored.
19+
20+
The system ID is randomly generated upon a Dependency-Track instance's first launch.
21+
It is used to correlate multiple data points of the same system over time,
22+
but can not be traced back to actual deployments.
23+
24+
The Dependency-Track version is collected to allow the maintainers to gauge
25+
adoption of releases.
26+
27+
Database type and version are collected to gain a better understanding of which
28+
database systems are most commonly used, and which are not. It also allows to draw
29+
conclusions as to when it's safe to raise the baseline of supported database versions.
30+
31+
The insights gained from telemetry collection, excluding system IDs, will be made available to the community.
32+
33+
## Submission frequency
34+
35+
Telemetry data is first submitted one minute after application startup.
36+
From then onwards, it is submitted on a daily basis.
37+
38+
## Opting out
39+
40+
Telemetry submission can be disabled in multiple ways.
41+
42+
**Via user interface**: Administrators can disable telemetry submission in the
43+
administration panel under *Configuration* -> *Telemetry*.
44+
45+
![Telemetry preferences]({{ site.baseurl }}/images/screenshots/telemetry.png)
46+
47+
**Via REST API**: Given an API key with `SYSTEM_CONFIGURATION` permission,
48+
telemetry submission may be disabled using the `/api/v1/configProperty` endpoint.
49+
50+
```shell
51+
curl -X POST \
52+
-H 'X-Api-Key: odt_******' \
53+
-H 'Content-Type: application/json' \
54+
-d '{"groupName":"telemetry","propertyName":"submission.enabled","propertyValue":"false"}' \
55+
https://dtrack.example.com/api/v1/configProperty
56+
```
57+
58+
**Via environment variable**: *When starting a new instance for the first time*,
59+
or *when upgrading from an older version to 4.13.0 or higher*,
60+
the following environment variable can be set:
61+
62+
```
63+
TELEMETRY_SUBMISSION_ENABLED_DEFAULT=false
64+
```
65+
66+
Please note that the environment variable merely impacts the *default value* of the setting.
67+
It does not overwrite any changes made via REST API or user interface,
68+
and has no effect past the initial launch of the application.

docs/images/screenshots/telemetry.png

73 KB
Loading

pom.xml

+6
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,9 @@
750750
<artifactId>jetty-ee10-maven-plugin</artifactId>
751751
<version>${plugin.jetty.version}</version>
752752
<configuration>
753+
<systemProperties>
754+
<dev.mode.enabled>true</dev.mode.enabled>
755+
</systemProperties>
753756
<webApp>
754757
<!-- Disable classpath scanning. -->
755758
<containerIncludeJarPattern>^$</containerIncludeJarPattern>
@@ -812,6 +815,9 @@
812815
<artifactId>jetty-ee10-maven-plugin</artifactId>
813816
<version>${plugin.jetty.version}</version>
814817
<configuration>
818+
<systemProperties>
819+
<dev.mode.enabled>true</dev.mode.enabled>
820+
</systemProperties>
815821
<webApp>
816822
<!-- Disable classpath scanning. -->
817823
<containerIncludeJarPattern>^$</containerIncludeJarPattern>

src/main/java/org/dependencytrack/common/ConfigKey.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ public enum ConfigKey implements Config.Key {
4040
REPO_META_ANALYZER_CACHE_STAMPEDE_BLOCKER_LOCK_BUCKETS("repo.meta.analyzer.cacheStampedeBlocker.lock.buckets", 1000),
4141
REPO_META_ANALYZER_CACHE_STAMPEDE_BLOCKER_MAX_ATTEMPTS("repo.meta.analyzer.cacheStampedeBlocker.max.attempts", 10),
4242
SYSTEM_REQUIREMENT_CHECK_ENABLED("system.requirement.check.enabled", true),
43-
ALPINE_WORKER_POOL_DRAIN_TIMEOUT_DURATION("alpine.worker.pool.drain.timeout.duration", "PT5S");
43+
ALPINE_WORKER_POOL_DRAIN_TIMEOUT_DURATION("alpine.worker.pool.drain.timeout.duration", "PT5S"),
44+
TELEMETRY_SUBMISSION_ENABLED_DEFAULT("telemetry.submission.enabled.default", true);
45+
4446
private final String propertyName;
4547
private final Object defaultValue;
4648

src/main/java/org/dependencytrack/event/EventSubsystemInitializer.java

+3
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import org.dependencytrack.tasks.OsvDownloadTask;
4444
import org.dependencytrack.tasks.PolicyEvaluationTask;
4545
import org.dependencytrack.tasks.TaskScheduler;
46+
import org.dependencytrack.tasks.TelemetrySubmissionTask;
4647
import org.dependencytrack.tasks.VexUploadProcessingTask;
4748
import org.dependencytrack.tasks.VulnDbSyncTask;
4849
import org.dependencytrack.tasks.VulnerabilityAnalysisTask;
@@ -112,6 +113,7 @@ public void contextInitialized(final ServletContextEvent event) {
112113
EVENT_SERVICE.subscribe(NistMirrorEvent.class, NistMirrorTask.class);
113114
EVENT_SERVICE.subscribe(NistApiMirrorEvent.class, NistApiMirrorTask.class);
114115
EVENT_SERVICE.subscribe(EpssMirrorEvent.class, EpssMirrorTask.class);
116+
EVENT_SERVICE.subscribe(TelemetrySubmissionEvent.class, TelemetrySubmissionTask.class);
115117

116118
EVENT_SERVICE_ST.subscribe(IndexEvent.class, IndexTask.class);
117119

@@ -148,6 +150,7 @@ public void contextDestroyed(final ServletContextEvent event) {
148150
EVENT_SERVICE.unsubscribe(NistMirrorTask.class);
149151
EVENT_SERVICE.unsubscribe(NistApiMirrorTask.class);
150152
EVENT_SERVICE.unsubscribe(EpssMirrorTask.class);
153+
EVENT_SERVICE.unsubscribe(TelemetrySubmissionTask.class);
151154
EVENT_SERVICE.shutdown(DRAIN_TIMEOUT_DURATION);
152155

153156
EVENT_SERVICE_ST.unsubscribe(IndexTask.class);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* This file is part of Dependency-Track.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* SPDX-License-Identifier: Apache-2.0
17+
* Copyright (c) OWASP Foundation. All Rights Reserved.
18+
*/
19+
package org.dependencytrack.event;
20+
21+
import alpine.event.framework.SingletonCapableEvent;
22+
23+
import java.util.UUID;
24+
25+
/**
26+
* @since 4.13.0
27+
*/
28+
public class TelemetrySubmissionEvent extends SingletonCapableEvent {
29+
30+
private static final UUID CHAIN_IDENTIFIER = UUID.fromString("a2ca4cbf-18d9-4e25-ae87-643020637e88");
31+
32+
public TelemetrySubmissionEvent() {
33+
setChainIdentifier(CHAIN_IDENTIFIER);
34+
setSingleton(true);
35+
}
36+
37+
}

src/main/java/org/dependencytrack/model/ConfigPropertyConstants.java

+6-2
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@
1818
*/
1919
package org.dependencytrack.model;
2020

21+
import alpine.Config;
2122
import alpine.model.IConfigProperty;
2223
import alpine.model.IConfigProperty.PropertyType;
2324
import org.apache.commons.lang3.SystemUtils;
25+
import org.dependencytrack.common.ConfigKey;
2426

2527
import java.util.Arrays;
2628

@@ -120,7 +122,10 @@ public enum ConfigPropertyConstants {
120122
BOM_VALIDATION_TAGS_EXCLUSIVE("artifact", "bom.validation.tags.exclusive", "[]", PropertyType.STRING, "JSON array of tags for which BOM validation shall NOT be performed"),
121123
WELCOME_MESSAGE("general", "welcome.message.html", "%3Chtml%3E%3Ch1%3EYour%20Welcome%20Message%3C%2Fh1%3E%3C%2Fhtml%3E", PropertyType.STRING, "Custom HTML Code that is displayed before login", true),
122124
IS_WELCOME_MESSAGE("general", "welcome.message.enabled", "false", PropertyType.BOOLEAN, "Bool that says whether to show the welcome message or not", true),
123-
DEFAULT_LANGUAGE("general", "default.locale", null, PropertyType.STRING, "Determine the default Language to use", true);
125+
DEFAULT_LANGUAGE("general", "default.locale", null, PropertyType.STRING, "Determine the default Language to use", true),
126+
TELEMETRY_SUBMISSION_ENABLED("telemetry", "submission.enabled", String.valueOf(!"true".equals(System.getProperty("dev.mode.enabled")) && Config.getInstance().getPropertyAsBoolean(ConfigKey.TELEMETRY_SUBMISSION_ENABLED_DEFAULT)), PropertyType.BOOLEAN, "Whether submission of telemetry data is enabled"),
127+
TELEMETRY_LAST_SUBMISSION_DATA("telemetry", "last.submission.data", null, PropertyType.STRING, "Data of the last telemetry submission"),
128+
TELEMETRY_LAST_SUBMISSION_EPOCH_SECONDS("telemetry", "last.submission.epoch.seconds", null, PropertyType.INTEGER, "Timestamp of the last telemetry submission in epoch seconds");
124129

125130
private final String groupName;
126131
private final String propertyName;
@@ -129,7 +134,6 @@ public enum ConfigPropertyConstants {
129134
private final String description;
130135
private final Boolean isPublic;
131136

132-
133137
ConfigPropertyConstants(String groupName, String propertyName, String defaultPropertyValue, PropertyType propertyType, String description) {
134138
this.groupName = groupName;
135139
this.propertyName = propertyName;

src/main/java/org/dependencytrack/tasks/TaskScheduler.java

+7-2
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,22 @@
3636
import org.dependencytrack.event.PortfolioMetricsUpdateEvent;
3737
import org.dependencytrack.event.PortfolioVulnerabilityAnalysisEvent;
3838
import org.dependencytrack.event.RepositoryMetaEvent;
39+
import org.dependencytrack.event.TelemetrySubmissionEvent;
3940
import org.dependencytrack.event.VulnDbSyncEvent;
4041
import org.dependencytrack.event.VulnerabilityMetricsUpdateEvent;
4142
import org.dependencytrack.model.ConfigPropertyConstants;
4243
import org.dependencytrack.persistence.QueryManager;
4344

45+
import java.util.concurrent.TimeUnit;
46+
4447
import static org.dependencytrack.model.ConfigPropertyConstants.DEFECTDOJO_ENABLED;
4548
import static org.dependencytrack.model.ConfigPropertyConstants.DEFECTDOJO_SYNC_CADENCE;
4649
import static org.dependencytrack.model.ConfigPropertyConstants.FORTIFY_SSC_ENABLED;
4750
import static org.dependencytrack.model.ConfigPropertyConstants.FORTIFY_SSC_SYNC_CADENCE;
48-
import static org.dependencytrack.model.ConfigPropertyConstants.SEARCH_INDEXES_CONSISTENCY_CHECK_CADENCE;
49-
import static org.dependencytrack.model.ConfigPropertyConstants.SEARCH_INDEXES_CONSISTENCY_CHECK_ENABLED;
5051
import static org.dependencytrack.model.ConfigPropertyConstants.KENNA_ENABLED;
5152
import static org.dependencytrack.model.ConfigPropertyConstants.KENNA_SYNC_CADENCE;
53+
import static org.dependencytrack.model.ConfigPropertyConstants.SEARCH_INDEXES_CONSISTENCY_CHECK_CADENCE;
54+
import static org.dependencytrack.model.ConfigPropertyConstants.SEARCH_INDEXES_CONSISTENCY_CHECK_ENABLED;
5255
import static org.dependencytrack.model.ConfigPropertyConstants.TASK_SCHEDULER_COMPONENT_ANALYSIS_CACHE_CLEAR_CADENCE;
5356
import static org.dependencytrack.model.ConfigPropertyConstants.TASK_SCHEDULER_GHSA_MIRROR_CADENCE;
5457
import static org.dependencytrack.model.ConfigPropertyConstants.TASK_SCHEDULER_INTERNAL_COMPONENT_IDENTIFICATION_CADENCE;
@@ -109,6 +112,8 @@ private TaskScheduler() {
109112

110113
// Creates a new event that executes every 72 hours (259200000) by default after an initial 10 second (10000) delay
111114
scheduleEvent(new ClearComponentAnalysisCacheEvent(), 10000, getCadenceConfigPropertyValueInMilliseconds(qm, TASK_SCHEDULER_COMPONENT_ANALYSIS_CACHE_CLEAR_CADENCE));
115+
116+
scheduleEvent(new TelemetrySubmissionEvent(), TimeUnit.MINUTES.toMillis(1), TimeUnit.HOURS.toMillis(1));
112117
}
113118

114119
// Configurable tasks

0 commit comments

Comments
 (0)