-
Notifications
You must be signed in to change notification settings - Fork 24.3k
/
ClusterStatsCollector.java
147 lines (129 loc) · 6.72 KB
/
ClusterStatsCollector.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.xpack.monitoring.collector.cluster;
import org.apache.logging.log4j.message.ParameterizedMessage;
import org.apache.logging.log4j.util.Supplier;
import org.elasticsearch.ElasticsearchSecurityException;
import org.elasticsearch.Version;
import org.elasticsearch.action.admin.cluster.stats.ClusterStatsResponse;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.client.Client;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.Index;
import org.elasticsearch.index.IndexNotFoundException;
import org.elasticsearch.license.License;
import org.elasticsearch.license.LicenseService;
import org.elasticsearch.license.LicenseUtils;
import org.elasticsearch.license.XPackLicenseState;
import org.elasticsearch.xpack.core.XPackFeatureSet;
import org.elasticsearch.xpack.core.action.XPackUsageRequestBuilder;
import org.elasticsearch.xpack.core.monitoring.exporter.MonitoringDoc;
import org.elasticsearch.xpack.monitoring.collector.Collector;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import static org.elasticsearch.xpack.core.XPackSettings.SECURITY_ENABLED;
import static org.elasticsearch.xpack.core.XPackSettings.TRANSPORT_SSL_ENABLED;
/**
* Collector for cluster stats.
* <p>
* This collector runs on the master node. It collect data about the current
* license and also retrieves the cluster stats.
* <p>
* the license and cluster stats are indexed in the data index in a "cluster_info"
* document; the cluster stats are also indexed in the timestamped index in a
* "cluster_stats" document.
*/
public class ClusterStatsCollector extends Collector {
/**
* Timeout value when collecting the cluster stats information (default to 10s)
*/
public static final Setting<TimeValue> CLUSTER_STATS_TIMEOUT = collectionTimeoutSetting("cluster.stats.timeout");
private final Settings settings;
private final IndexNameExpressionResolver indexNameExpressionResolver;
private final LicenseService licenseService;
private final Client client;
public ClusterStatsCollector(final Settings settings,
final ClusterService clusterService,
final XPackLicenseState licenseState,
final Client client,
final LicenseService licenseService) {
this(settings, clusterService, licenseState, client, licenseService, new IndexNameExpressionResolver(settings));
}
ClusterStatsCollector(final Settings settings,
final ClusterService clusterService,
final XPackLicenseState licenseState,
final Client client,
final LicenseService licenseService,
final IndexNameExpressionResolver indexNameExpressionResolver) {
super(ClusterStatsMonitoringDoc.TYPE, clusterService, CLUSTER_STATS_TIMEOUT, licenseState);
this.settings = settings;
this.client = client;
this.licenseService = licenseService;
this.indexNameExpressionResolver = Objects.requireNonNull(indexNameExpressionResolver);
}
@Override
protected boolean shouldCollect(final boolean isElectedMaster) {
// This collector can always collect data on the master node
return isElectedMaster;
}
@Override
protected Collection<MonitoringDoc> doCollect(final MonitoringDoc.Node node,
final long interval,
final ClusterState clusterState) throws Exception {
final Supplier<ClusterStatsResponse> clusterStatsSupplier =
() -> client.admin().cluster().prepareClusterStats().get(getCollectionTimeout());
final Supplier<List<XPackFeatureSet.Usage>> usageSupplier =
() -> new XPackUsageRequestBuilder(client).get().getUsages();
final ClusterStatsResponse clusterStats = clusterStatsSupplier.get();
final String clusterName = clusterService.getClusterName().value();
final String clusterUuid = clusterUuid(clusterState);
final String version = Version.CURRENT.toString();
final License license = licenseService.getLicense();
final List<XPackFeatureSet.Usage> xpackUsage = collect(usageSupplier);
final boolean apmIndicesExist = doAPMIndicesExist(clusterState);
// if they have any other type of license, then they are either okay or already know
final boolean clusterNeedsTLSEnabled = license.operationMode() == License.OperationMode.TRIAL &&
settings.hasValue(SECURITY_ENABLED.getKey()) &&
SECURITY_ENABLED.get(settings) &&
TRANSPORT_SSL_ENABLED.get(settings) == false;
// Adds a cluster stats document
return Collections.singleton(
new ClusterStatsMonitoringDoc(clusterUuid, timestamp(), interval, node, clusterName, version, clusterStats.getStatus(),
license, apmIndicesExist, xpackUsage, clusterStats, clusterState,
clusterNeedsTLSEnabled));
}
boolean doAPMIndicesExist(final ClusterState clusterState) {
try {
final Index[] indices =
indexNameExpressionResolver.concreteIndices(clusterState, IndicesOptions.lenientExpandOpen(), "apm-*");
return indices.length > 0;
} catch (IndexNotFoundException | IllegalArgumentException e) {
return false;
}
}
@Nullable
private <T> T collect(final Supplier<T> supplier) {
try {
return supplier.get();
} catch (ElasticsearchSecurityException e) {
if (LicenseUtils.isLicenseExpiredException(e)) {
logger.trace((Supplier<?>) () -> new ParameterizedMessage("collector [{}] - " +
"unable to collect data because of expired license", name()), e);
} else {
throw e;
}
}
return null;
}
}