Skip to content

Commit

Permalink
Composable index templates for ES 7.8
Browse files Browse the repository at this point in the history
  • Loading branch information
Chanatan Charnkijtawarush authored and Chanatan Charnkijtawarush committed Aug 22, 2020
1 parent 90e7178 commit c3cf802
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 4 deletions.
2 changes: 2 additions & 0 deletions zipkin-server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,8 @@ The following apply when `STORAGE_TYPE` is set to `elasticsearch`:
Options are BASIC, HEADERS, BODY
* `ES_SSL_NO_VERIFY`: When true, disables the verification of server's key certificate chain.
This is not appropriate for production. Defaults to false.
* `ES_TEMPLATE_PRIORITY`: The priority value of the composable index templates. This is only applicable
for ES version 7.8 or above. Defaults to 0.

Example usage:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
* enabled: true
* http-logging: HEADERS
* interval: 3s
* priority: 0
* }</pre>
*/
@ConfigurationProperties("zipkin.storage.elasticsearch")
Expand Down Expand Up @@ -212,6 +213,8 @@ public void setInterval(Duration interval) {

private HealthCheck healthCheck = new HealthCheck();

private String priority;

public String getPipeline() {
return pipeline;
}
Expand Down Expand Up @@ -346,6 +349,10 @@ public void setSsl(Ssl ssl) {
this.ssl = ssl;
}

public String getPriority() { return priority; }

public void setPriority(String priority) { this.priority = priority; }

public ElasticsearchStorage.Builder toBuilder(LazyHttpClient httpClient) {
ElasticsearchStorage.Builder builder = ElasticsearchStorage.newBuilder(httpClient);
if (index != null) builder.index(index);
Expand All @@ -360,6 +367,7 @@ public ElasticsearchStorage.Builder toBuilder(LazyHttpClient httpClient) {
if (maxRequests != null) {
log.warning("ES_MAX_REQUESTS is no longer honored. Use STORAGE_THROTTLE_ENABLED instead");
}
if (priority != null) builder.templatePriority(priority);
return builder;
}

Expand Down
1 change: 1 addition & 0 deletions zipkin-server/src/main/resources/zipkin-server-shared.yml
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ zipkin:
health-check:
enabled: ${ES_HEALTH_CHECK_ENABLED:true}
interval: ${ES_HEALTH_CHECK_INTERVAL:3s}
priority: ${ES_TEMPLATE_PRIORITY:0}
mysql:
jdbc-url: ${MYSQL_JDBC_URL:}
host: ${MYSQL_HOST:localhost}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ public static Builder newBuilder(LazyHttpClient lazyHttpClient) {
.flushOnWrites(false)
.autocompleteKeys(Collections.emptyList())
.autocompleteTtl((int) TimeUnit.HOURS.toMillis(1))
.autocompleteCardinality(5 * 4000); // Ex. 5 site tags with cardinality 4000 each
.autocompleteCardinality(5 * 4000)
.templatePriority("0"); // Ex. 5 site tags with cardinality 4000 each
}

abstract Builder toBuilder();
Expand Down Expand Up @@ -162,6 +163,15 @@ public final Builder dateSeparator(char dateSeparator) {
/** False disables automatic index template installation. */
public abstract Builder ensureTemplates(boolean ensureTemplates);

/**
* Only valid when the destination is Elasticsearch >= 7.8. Indicates the index template
* priority in case of multiple matching templates. The template with highest priority is used.
* Default to 0.
*
* <p>See https://www.elastic.co/guide/en/elasticsearch/reference/7.8/_index_template_and_settings_priority.html
*/
public abstract Builder templatePriority(String priority);

/** {@inheritDoc} */
@Override public abstract Builder strictTraceId(boolean strictTraceId);

Expand Down Expand Up @@ -213,6 +223,8 @@ public final Builder dateSeparator(char dateSeparator) {

public abstract int namesLookback();

abstract String templatePriority();

@Override public SpanStore spanStore() {
ensureIndexTemplates();
return new ElasticsearchSpanStore(this);
Expand Down Expand Up @@ -337,12 +349,17 @@ IndexTemplates versionSpecificTemplates(float version) {
indexReplicas(),
indexShards(),
searchEnabled(),
strictTraceId()
strictTraceId(),
templatePriority()
).get(version);
}

String buildUrl(IndexTemplates templates, String type) {
String indexPrefix = indexNameFormatter().index() + templates.indexTypeDelimiter();

if (version() >= 7.8f) {
return "/_index_template/" + indexPrefix + type + "_template";
}
return "/_template/" + indexPrefix + type + "_template";
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,18 @@ final class VersionSpecificTemplates {
*/
static final String KEYWORD = "{ \"type\": \"keyword\", \"norms\": false }";

final String indexPrefix;
final String indexPrefix, templatePriority;
final int indexReplicas, indexShards;
final boolean searchEnabled, strictTraceId;

VersionSpecificTemplates(String indexPrefix, int indexReplicas, int indexShards,
boolean searchEnabled, boolean strictTraceId) {
boolean searchEnabled, boolean strictTraceId, String templatePriority) {
this.indexPrefix = indexPrefix;
this.indexReplicas = indexReplicas;
this.indexShards = indexShards;
this.searchEnabled = searchEnabled;
this.strictTraceId = strictTraceId;
this.templatePriority = templatePriority;
}

String indexPattern(String type, float version) {
Expand All @@ -66,10 +67,35 @@ String indexProperties(float version) {
return result + ",\n \"index.mapper.dynamic\": false\n";
}

String indexTemplate(float version) {
if (version >= 7.8f) {
return "\"template\": {\n";
}

return "";
}

String indexTemplateClosing(float version) {
if (version >= 7.8f) {
return "},\n";
}

return "";
}

String templatePriority(float version) {
if (version >= 7.8f) {
return "\"priority\": " + templatePriority + "\n";
}

return "";
}

/** Templatized due to version differences. Only fields used in search are declared */
String spanIndexTemplate(float version) {
String result = "{\n"
+ " " + indexPattern(TYPE_SPAN, version) + ",\n"
+ indexTemplate(version)
+ " \"settings\": {\n"
+ indexProperties(version);

Expand Down Expand Up @@ -141,6 +167,8 @@ String spanIndexTemplate(float version) {
+ " \"_q\": " + KEYWORD + "\n"
+ " }\n")
+ " }\n"
+ indexTemplateClosing(version)
+ templatePriority(version)
+ "}");
}
return result
Expand All @@ -152,19 +180,24 @@ String spanIndexTemplate(float version) {
+ " \"tags\": { \"enabled\": false }\n"
+ " }\n")
+ " }\n"
+ indexTemplateClosing(version)
+ templatePriority(version)
+ "}");
}

/** Templatized due to version differences. Only fields used in search are declared */
String dependencyTemplate(float version) {
return "{\n"
+ " " + indexPattern(TYPE_DEPENDENCY, version) + ",\n"
+ indexTemplate(version)
+ " \"settings\": {\n"
+ indexProperties(version)
+ " },\n"
+ " \"mappings\": {\n"
+ maybeWrap(TYPE_DEPENDENCY, version, " \"enabled\": false\n")
+ " }\n"
+ indexTemplateClosing(version)
+ templatePriority(version)
+ "}";
}

Expand All @@ -173,6 +206,7 @@ String dependencyTemplate(float version) {
String autocompleteTemplate(float version) {
return "{\n"
+ " " + indexPattern(TYPE_AUTOCOMPLETE, version) + ",\n"
+ indexTemplate(version)
+ " \"settings\": {\n"
+ indexProperties(version)
+ " },\n"
Expand All @@ -184,6 +218,8 @@ String autocompleteTemplate(float version) {
+ " \"tagValue\": " + KEYWORD + "\n"
+ " }\n")
+ " }\n"
+ indexTemplateClosing(version)
+ templatePriority(version)
+ "}";
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,26 @@ class ElasticsearchStorageTest {
String.format("ElasticsearchStorage{initialEndpoints=%s, index=zipkin}", server.httpUri()));
}

@Test void check_composable_indexTemplate() throws Exception {
server.enqueue(AggregatedHttpResponse.of(
HttpStatus.OK, MediaType.JSON_UTF_8, "{\"version\":{\"number\":\"7.8.0\"}}"));
server.enqueue(SUCCESS_RESPONSE); // get span template
server.enqueue(SUCCESS_RESPONSE); // get dependency template
server.enqueue(SUCCESS_RESPONSE); // get autocomplete template
server.enqueue(SUCCESS_RESPONSE); // cluster health

storage.check();

server.takeRequest(); // get version

assertThat(server.takeRequest().request().path()) // get span template
.startsWith("/_index_template/zipkin-span_template");
assertThat(server.takeRequest().request().path()) // // get dependency template
.startsWith("/_index_template/zipkin-dependency_template");
assertThat(server.takeRequest().request().path()) // get autocomplete template
.startsWith("/_index_template/zipkin-autocomplete_template");
}

ElasticsearchStorage.Builder newBuilder() {
return ElasticsearchStorage.newBuilder(new LazyHttpClient() {
@Override public WebClient get() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,24 @@ class VersionSpecificTemplatesTest {
+ " }");
}

@Test void version78() {
IndexTemplates template = storage.versionSpecificTemplates(7.8f);

assertThat(template.version()).isEqualTo(7.8f);
assertThat(template.autocomplete())
.withFailMessage("Starting at v7.x, we delimit index and type with hyphen")
.contains("\"index_patterns\": \"zipkin-autocomplete-*\"");
assertThat(template.span())
.contains("\"template\": {\n")
.contains("\"priority\": 0\n");
assertThat(template.autocomplete())
.contains("\"template\": {\n")
.contains("\"priority\": 0\n");
assertThat(template.dependency())
.contains("\"template\": {\n")
.contains("\"priority\": 0\n");
}

@Test void searchEnabled_minimalSpanIndexing_6x() {
storage.close();
storage = ElasticsearchStorage.newBuilder(() -> mock(WebClient.class))
Expand Down

0 comments on commit c3cf802

Please sign in to comment.