forked from elastic/elasticsearch
/
Exporter.java
221 lines (183 loc) · 8.6 KB
/
Exporter.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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
/*
* 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.exporter;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Setting.Property;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.settings.SettingsException;
import org.elasticsearch.common.time.DateFormatter;
import org.elasticsearch.license.XPackLicenseState;
import org.elasticsearch.xpack.monitoring.exporter.http.HttpExporter;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;
public abstract class Exporter implements AutoCloseable {
public static Setting.AffixSettingDependency TYPE_DEPENDENCY = () -> Exporter.TYPE_SETTING;
private static final Setting.AffixSetting<Boolean> ENABLED_SETTING =
Setting.affixKeySetting("xpack.monitoring.exporters.","enabled",
key -> Setting.boolSetting(key, true, Property.Dynamic, Property.NodeScope), TYPE_DEPENDENCY);
public static final Setting.AffixSetting<String> TYPE_SETTING = Setting.affixKeySetting(
"xpack.monitoring.exporters.",
"type",
key -> Setting.simpleString(
key,
new Setting.Validator<String>() {
@Override
public void validate(final String value) {
}
@Override
public void validate(final String value, final Map<Setting<?>, Object> settings) {
switch (value) {
case "":
break;
case "http":
// if the type is http, then hosts must be set
final String namespace = TYPE_SETTING.getNamespace(TYPE_SETTING.getConcreteSetting(key));
final Setting<List<String>> hostsSetting = HttpExporter.HOST_SETTING.getConcreteSettingForNamespace(namespace);
@SuppressWarnings("unchecked") final List<String> hosts = (List<String>) settings.get(hostsSetting);
if (hosts.isEmpty()) {
throw new SettingsException("host list for [" + hostsSetting.getKey() + "] is empty");
}
break;
case "local":
break;
default:
throw new SettingsException(
"type [" + value + "] for key [" + key + "] is invalid, only [http] and [local] are allowed");
}
}
@Override
public Iterator<Setting<?>> settings() {
final String namespace =
Exporter.TYPE_SETTING.getNamespace(Exporter.TYPE_SETTING.getConcreteSetting(key));
final List<Setting<?>> settings =
Collections.singletonList(HttpExporter.HOST_SETTING.getConcreteSettingForNamespace(namespace));
return settings.iterator();
}
},
Property.Dynamic,
Property.NodeScope));
/**
* Every {@code Exporter} adds the ingest pipeline to bulk requests, but they should, at the exporter level, allow that to be disabled.
* <p>
* Note: disabling it obviously loses any benefit of using it, but it does allow clusters that don't run with ingest to not use it.
*/
public static final Setting.AffixSetting<Boolean> USE_INGEST_PIPELINE_SETTING =
Setting.affixKeySetting("xpack.monitoring.exporters.","use_ingest",
key -> Setting.boolSetting(key, true, Property.Dynamic, Property.NodeScope), TYPE_DEPENDENCY);
/**
* Every {@code Exporter} allows users to explicitly disable cluster alerts.
*/
public static final Setting.AffixSetting<Boolean> CLUSTER_ALERTS_MANAGEMENT_SETTING =
Setting.affixKeySetting("xpack.monitoring.exporters.", "cluster_alerts.management.enabled",
key -> Setting.boolSetting(key, true, Property.Dynamic, Property.NodeScope), TYPE_DEPENDENCY);
/**
* Every {@code Exporter} allows users to explicitly disable specific cluster alerts.
* <p>
* When cluster alerts management is enabled, this should delete anything blacklisted here in addition to not creating it.
*/
public static final Setting.AffixSetting<List<String>> CLUSTER_ALERTS_BLACKLIST_SETTING = Setting
.affixKeySetting("xpack.monitoring.exporters.", "cluster_alerts.management.blacklist",
key -> Setting.listSetting(key, Collections.emptyList(), Function.identity(), Property.Dynamic, Property.NodeScope),
TYPE_DEPENDENCY);
/**
* Every {@code Exporter} allows users to use a different index time format.
*/
static final Setting.AffixSetting<DateFormatter> INDEX_NAME_TIME_FORMAT_SETTING =
Setting.affixKeySetting("xpack.monitoring.exporters.","index.name.time_format",
key -> new Setting<DateFormatter>(
key,
Exporter.INDEX_FORMAT,
DateFormatter::forPattern,
Property.Dynamic,
Property.NodeScope), TYPE_DEPENDENCY);
private static final String INDEX_FORMAT = "yyyy.MM.dd";
protected final Config config;
private AtomicBoolean closed = new AtomicBoolean(false);
public Exporter(Config config) {
this.config = config;
}
public String name() {
return config.name;
}
public Config config() {
return config;
}
/** Returns true if only one instance of this exporter should be allowed. */
public boolean isSingleton() {
return false;
}
/**
* Opens up a new export bulk.
*
* @param listener Returns {@code null} to indicate that this exporter is not ready to export the docs.
*/
public abstract void openBulk(ActionListener<ExportBulk> listener);
protected final boolean isClosed() {
return closed.get();
}
@Override
public void close() {
if (closed.compareAndSet(false, true)) {
doClose();
}
}
protected abstract void doClose();
protected static DateFormatter dateTimeFormatter(final Config config) {
Setting<DateFormatter> setting = INDEX_NAME_TIME_FORMAT_SETTING.getConcreteSettingForNamespace(config.name);
return setting.get(config.settings());
}
public static List<Setting.AffixSetting<?>> getSettings() {
return Arrays.asList(USE_INGEST_PIPELINE_SETTING, CLUSTER_ALERTS_MANAGEMENT_SETTING, TYPE_SETTING, ENABLED_SETTING,
INDEX_NAME_TIME_FORMAT_SETTING, CLUSTER_ALERTS_BLACKLIST_SETTING);
}
public static class Config {
private final String name;
private final String type;
private final boolean enabled;
private final Settings settings;
private final ClusterService clusterService;
private final XPackLicenseState licenseState;
public Config(String name, String type, Settings settings,
ClusterService clusterService, XPackLicenseState licenseState) {
this.name = name;
this.type = type;
this.settings = settings;
this.clusterService = clusterService;
this.licenseState = licenseState;
this.enabled = ENABLED_SETTING.getConcreteSettingForNamespace(name).get(settings);
}
public String name() {
return name;
}
public String type() {
return type;
}
public boolean enabled() {
return enabled;
}
public Settings settings() {
return settings;
}
public ClusterService clusterService() {
return clusterService;
}
public XPackLicenseState licenseState() {
return licenseState;
}
}
/** A factory for constructing {@link Exporter} instances.*/
public interface Factory {
/** Create an exporter with the given configuration. */
Exporter create(Config config);
}
}