From a6f354cca1478c6a0ee73792fbb7d614cf834645 Mon Sep 17 00:00:00 2001 From: mrproliu <741550557@qq.com> Date: Tue, 10 Oct 2023 20:49:57 +0800 Subject: [PATCH] Adaptation enhancements for various features in v3 (#3573) --- zipkin-server/health-query-plugin/pom.xml | 21 +++ .../query/health/HealthQueryConfig.java | 86 +++++++++ .../query/health/HealthQueryModule.java | 30 ++++ .../query/health/HealthQueryProvider.java | 100 +++++++++++ .../zipkin/server/query/health/JsonUtil.java | 45 +++++ .../query/health/ZipkinHealthHandler.java | 110 ++++++++++++ ...ing.oap.server.library.module.ModuleDefine | 19 ++ ...g.oap.server.library.module.ModuleProvider | 19 ++ zipkin-server/http-query-plugin/pom.xml | 23 +++ .../server/query/http/HTTPQueryConfig.java | 163 ++++++++++++++++++ .../server/query/http/HTTPQueryHandler.java | 132 ++++++++++++++ .../server/query/http/HTTPQueryProvider.java | 103 +++++++++++ ...g.oap.server.library.module.ModuleProvider | 19 ++ zipkin-server/pom.xml | 2 + .../zipkin/http/ZipkinHTTPReceiverConfig.java | 13 ++ .../http/ZipkinHTTPReceiverProvider.java | 48 ++++-- .../receiver/zipkin/http/ITHTTPReceiver.java | 24 +-- .../zipkin/server/core/CoreModuleConfig.java | 76 +++++++- .../server/core/CoreModuleProvider.java | 22 ++- .../core/services/ZipkinConfigService.java | 2 +- zipkin-server/server-starter/pom.xml | 11 +- .../main/java/zipkin/server/ZipkinServer.java | 22 +++ .../config/ApplicationConfigLoader.java | 7 +- .../src/main/resources/application.yml | 65 ++++--- .../src/main/resources/log4j2.xml | 6 +- .../src/main/resources/zipkin.txt | 28 +++ 26 files changed, 1131 insertions(+), 65 deletions(-) create mode 100644 zipkin-server/health-query-plugin/pom.xml create mode 100644 zipkin-server/health-query-plugin/src/main/java/zipkin/server/query/health/HealthQueryConfig.java create mode 100644 zipkin-server/health-query-plugin/src/main/java/zipkin/server/query/health/HealthQueryModule.java create mode 100644 zipkin-server/health-query-plugin/src/main/java/zipkin/server/query/health/HealthQueryProvider.java create mode 100644 zipkin-server/health-query-plugin/src/main/java/zipkin/server/query/health/JsonUtil.java create mode 100644 zipkin-server/health-query-plugin/src/main/java/zipkin/server/query/health/ZipkinHealthHandler.java create mode 100644 zipkin-server/health-query-plugin/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleDefine create mode 100755 zipkin-server/health-query-plugin/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider create mode 100644 zipkin-server/http-query-plugin/pom.xml create mode 100644 zipkin-server/http-query-plugin/src/main/java/zipkin/server/query/http/HTTPQueryConfig.java create mode 100644 zipkin-server/http-query-plugin/src/main/java/zipkin/server/query/http/HTTPQueryHandler.java create mode 100644 zipkin-server/http-query-plugin/src/main/java/zipkin/server/query/http/HTTPQueryProvider.java create mode 100755 zipkin-server/http-query-plugin/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider create mode 100644 zipkin-server/server-starter/src/main/resources/zipkin.txt diff --git a/zipkin-server/health-query-plugin/pom.xml b/zipkin-server/health-query-plugin/pom.xml new file mode 100644 index 00000000000..d16e9add651 --- /dev/null +++ b/zipkin-server/health-query-plugin/pom.xml @@ -0,0 +1,21 @@ + + + 4.0.0 + + zipkin-server-parent + io.zipkin + 2.24.4-SNAPSHOT + + + health-query-plugin + + + + io.zipkin + zipkin-server-core + ${project.version} + + + \ No newline at end of file diff --git a/zipkin-server/health-query-plugin/src/main/java/zipkin/server/query/health/HealthQueryConfig.java b/zipkin-server/health-query-plugin/src/main/java/zipkin/server/query/health/HealthQueryConfig.java new file mode 100644 index 00000000000..3ba094e0454 --- /dev/null +++ b/zipkin-server/health-query-plugin/src/main/java/zipkin/server/query/health/HealthQueryConfig.java @@ -0,0 +1,86 @@ +/* + * Copyright 2015-2023 The OpenZipkin Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ +package zipkin.server.query.health; + +import org.apache.skywalking.oap.server.library.module.ModuleConfig; + +public class HealthQueryConfig extends ModuleConfig { + private String restHost; + private int restPort; + private String restContextPath; + private int restMaxThreads = 200; + private long restIdleTimeOut = 30000; + private int restAcceptQueueSize = 0; + /** + * The maximum size in bytes allowed for request headers. + * Use -1 to disable it. + */ + private int restMaxRequestHeaderSize = 8192; + + public String getRestHost() { + return restHost; + } + + public void setRestHost(String restHost) { + this.restHost = restHost; + } + + public int getRestPort() { + return restPort; + } + + public void setRestPort(int restPort) { + this.restPort = restPort; + } + + public String getRestContextPath() { + return restContextPath; + } + + public void setRestContextPath(String restContextPath) { + this.restContextPath = restContextPath; + } + + public int getRestMaxThreads() { + return restMaxThreads; + } + + public void setRestMaxThreads(int restMaxThreads) { + this.restMaxThreads = restMaxThreads; + } + + public long getRestIdleTimeOut() { + return restIdleTimeOut; + } + + public void setRestIdleTimeOut(long restIdleTimeOut) { + this.restIdleTimeOut = restIdleTimeOut; + } + + public int getRestAcceptQueueSize() { + return restAcceptQueueSize; + } + + public void setRestAcceptQueueSize(int restAcceptQueueSize) { + this.restAcceptQueueSize = restAcceptQueueSize; + } + + public int getRestMaxRequestHeaderSize() { + return restMaxRequestHeaderSize; + } + + public void setRestMaxRequestHeaderSize(int restMaxRequestHeaderSize) { + this.restMaxRequestHeaderSize = restMaxRequestHeaderSize; + } +} diff --git a/zipkin-server/health-query-plugin/src/main/java/zipkin/server/query/health/HealthQueryModule.java b/zipkin-server/health-query-plugin/src/main/java/zipkin/server/query/health/HealthQueryModule.java new file mode 100644 index 00000000000..e12896279ee --- /dev/null +++ b/zipkin-server/health-query-plugin/src/main/java/zipkin/server/query/health/HealthQueryModule.java @@ -0,0 +1,30 @@ +/* + * Copyright 2015-2023 The OpenZipkin Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package zipkin.server.query.health; + +import org.apache.skywalking.oap.server.library.module.ModuleDefine; + +public class HealthQueryModule extends ModuleDefine { + public static final String NAME = "query-health"; + + public HealthQueryModule() { + super(NAME); + } + + @Override + public Class[] services() { + return new Class[0]; + } +} diff --git a/zipkin-server/health-query-plugin/src/main/java/zipkin/server/query/health/HealthQueryProvider.java b/zipkin-server/health-query-plugin/src/main/java/zipkin/server/query/health/HealthQueryProvider.java new file mode 100644 index 00000000000..005c67e2629 --- /dev/null +++ b/zipkin-server/health-query-plugin/src/main/java/zipkin/server/query/health/HealthQueryProvider.java @@ -0,0 +1,100 @@ +/* + * Copyright 2015-2023 The OpenZipkin Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package zipkin.server.query.health; + +import com.linecorp.armeria.common.HttpMethod; +import org.apache.skywalking.oap.server.core.CoreModule; +import org.apache.skywalking.oap.server.core.server.HTTPHandlerRegister; +import org.apache.skywalking.oap.server.library.module.ModuleConfig; +import org.apache.skywalking.oap.server.library.module.ModuleDefine; +import org.apache.skywalking.oap.server.library.module.ModuleProvider; +import org.apache.skywalking.oap.server.library.module.ModuleStartException; +import org.apache.skywalking.oap.server.library.module.ServiceNotProvidedException; +import org.apache.skywalking.oap.server.library.server.http.HTTPServer; +import org.apache.skywalking.oap.server.library.server.http.HTTPServerConfig; + +import java.util.Collections; + +public class HealthQueryProvider extends ModuleProvider { + private HealthQueryConfig moduleConfig; + private HTTPServer httpServer; + @Override + public String name() { + return "zipkin"; + } + + @Override + public Class module() { + return HealthQueryModule.class; + } + + @Override + public ConfigCreator newConfigCreator() { + return new ConfigCreator() { + @Override + public Class type() { + return HealthQueryConfig.class; + } + + @Override + public void onInitialized(HealthQueryConfig initialized) { + moduleConfig = initialized; + } + }; + } + + @Override + public void prepare() throws ServiceNotProvidedException, ModuleStartException { + if (moduleConfig.getRestPort() > 0) { + HTTPServerConfig httpServerConfig = HTTPServerConfig.builder() + .host(moduleConfig.getRestHost()) + .port(moduleConfig.getRestPort()) + .contextPath(moduleConfig.getRestContextPath()) + .idleTimeOut(moduleConfig.getRestIdleTimeOut()) + .maxThreads(moduleConfig.getRestMaxThreads()) + .acceptQueueSize(moduleConfig.getRestAcceptQueueSize()) + .maxRequestHeaderSize(moduleConfig.getRestMaxRequestHeaderSize()) + .build(); + httpServer = new HTTPServer(httpServerConfig); + httpServer.initialize(); + } + } + + @Override + public void start() throws ServiceNotProvidedException, ModuleStartException { + if (httpServer != null) { + httpServer.addHandler(new ZipkinHealthHandler(getManager()), + Collections.singletonList(HttpMethod.GET)); + } else { + getManager().find(CoreModule.NAME).provider() + .getService(HTTPHandlerRegister.class).addHandler( + new ZipkinHealthHandler(getManager()), + Collections.singletonList(HttpMethod.GET) + ); + } + } + + @Override + public void notifyAfterCompleted() throws ServiceNotProvidedException, ModuleStartException { + if (httpServer != null) { + httpServer.start(); + } + } + + @Override + public String[] requiredModules() { + return new String[0]; + } +} diff --git a/zipkin-server/health-query-plugin/src/main/java/zipkin/server/query/health/JsonUtil.java b/zipkin-server/health-query-plugin/src/main/java/zipkin/server/query/health/JsonUtil.java new file mode 100644 index 00000000000..b885037fe45 --- /dev/null +++ b/zipkin-server/health-query-plugin/src/main/java/zipkin/server/query/health/JsonUtil.java @@ -0,0 +1,45 @@ +/* + * Copyright 2015-2019 The OpenZipkin Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ +package zipkin.server.query.health; + +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.util.DefaultIndenter; +import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; + +import java.io.IOException; +import java.io.Writer; + +/** + * Utilities for working with JSON. + */ +public final class JsonUtil { + + static final JsonFactory JSON_FACTORY = new JsonFactory(); + static final DefaultPrettyPrinter.Indenter TWOSPACES_LF_INDENTER = + new DefaultIndenter(" ", "\n"); + + /** + * Creates a new {@link JsonGenerator} with pretty-printing enabled forcing {@code '\n'} + * between lines, as opposed to Jackson's default which uses the system line separator. + */ + public static JsonGenerator createGenerator(Writer writer) throws IOException { + JsonGenerator generator = JSON_FACTORY.createGenerator(writer); + DefaultPrettyPrinter prettyPrinter = new DefaultPrettyPrinter(); + prettyPrinter.indentArraysWith(TWOSPACES_LF_INDENTER); + prettyPrinter.indentObjectsWith(TWOSPACES_LF_INDENTER); + generator.setPrettyPrinter(prettyPrinter); + return generator; + } +} diff --git a/zipkin-server/health-query-plugin/src/main/java/zipkin/server/query/health/ZipkinHealthHandler.java b/zipkin-server/health-query-plugin/src/main/java/zipkin/server/query/health/ZipkinHealthHandler.java new file mode 100644 index 00000000000..0ac958c94f4 --- /dev/null +++ b/zipkin-server/health-query-plugin/src/main/java/zipkin/server/query/health/ZipkinHealthHandler.java @@ -0,0 +1,110 @@ +/* + * Copyright 2015-2023 The OpenZipkin Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ +package zipkin.server.query.health; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.linecorp.armeria.common.HttpResponse; +import com.linecorp.armeria.common.HttpStatus; +import com.linecorp.armeria.common.MediaType; +import com.linecorp.armeria.server.ServiceRequestContext; +import com.linecorp.armeria.server.annotation.Get; +import io.vavr.collection.Stream; +import org.apache.skywalking.oap.server.library.module.ModuleManager; +import org.apache.skywalking.oap.server.library.module.ModuleServiceHolder; +import org.apache.skywalking.oap.server.telemetry.TelemetryModule; +import org.apache.skywalking.oap.server.telemetry.api.MetricFamily; +import org.apache.skywalking.oap.server.telemetry.api.MetricsCollector; +import org.apache.skywalking.oap.server.telemetry.api.MetricsCreator; + +import java.io.IOException; +import java.io.StringWriter; +import java.util.Map; +import java.util.stream.Collectors; + +public class ZipkinHealthHandler { + static final String STATUS_UP = "UP", STATUS_DOWN = "DOWN"; + + final MetricsCollector collector; + final private MetricsCreator metricsCreator; + + public static final MediaType MEDIA_TYPE_ACTUATOR = + MediaType.parse("application/vnd.spring-boot.actuator.v2+json;charset=UTF-8"); + + public ZipkinHealthHandler(ModuleManager moduleManager) { + ModuleServiceHolder telemetry = moduleManager.find(TelemetryModule.NAME).provider(); + metricsCreator = telemetry.getService(MetricsCreator.class); + collector = telemetry.getService(MetricsCollector.class); + } + + @Get("/actuator/health") + public HttpResponse getActuatorHealth(ServiceRequestContext ctx) { + return newHealthResponse(MEDIA_TYPE_ACTUATOR); + } + + @Get("/health") + public HttpResponse getHealth(ServiceRequestContext ctx) { + return newHealthResponse(MediaType.JSON_UTF_8); + } + + HttpResponse newHealthResponse(MediaType mediaType) { + final Map componentsHealth = Stream.ofAll(collector.collect()) + .flatMap(metricFamily -> metricFamily.samples) + .filter(sample -> metricsCreator.isHealthCheckerMetrics(sample.name)) + .collect(Collectors.toMap(t -> t, t -> t.value > 0 ? STATUS_DOWN : STATUS_UP, (a, b) -> b)); + + String overallStatus = STATUS_UP; + for (String health : componentsHealth.values()) { + if (STATUS_DOWN.equals(health)) { + overallStatus = STATUS_DOWN; + break; + } + } + + final String healthJson; + try { + healthJson = writeJson(overallStatus, componentsHealth); + } catch (IOException e) { + // Can't have an exception writing to a string. + throw new Error(e); + } + return newHealthResponse(overallStatus, mediaType, healthJson); + } + + static HttpResponse newHealthResponse(String status, MediaType mediaType, String healthJson) { + HttpStatus code = status.equals(STATUS_UP) ? HttpStatus.OK : HttpStatus.SERVICE_UNAVAILABLE; + return HttpResponse.of(code, mediaType, healthJson); + } + + static String writeJson(String overallStatus, Map healths) throws IOException { + StringWriter writer = new StringWriter(); + try (JsonGenerator generator = JsonUtil.createGenerator(writer)) { + generator.writeStartObject(); + generator.writeStringField("status", overallStatus); + generator.writeObjectFieldStart("zipkin"); + generator.writeStringField("status", overallStatus); + generator.writeObjectFieldStart("details"); + + for (Map.Entry health : healths.entrySet()) { + generator.writeObjectFieldStart(health.getKey().name); + generator.writeStringField("status", health.getValue()); + generator.writeEndObject(); // .zipkin.details.healthName + } + + generator.writeEndObject(); // .zipkin.details + generator.writeEndObject(); // .zipkin + generator.writeEndObject(); // . + } + return writer.toString(); + } +} diff --git a/zipkin-server/health-query-plugin/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleDefine b/zipkin-server/health-query-plugin/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleDefine new file mode 100644 index 00000000000..7ebf10eb635 --- /dev/null +++ b/zipkin-server/health-query-plugin/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleDefine @@ -0,0 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# + +zipkin.server.query.health.HealthQueryModule \ No newline at end of file diff --git a/zipkin-server/health-query-plugin/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider b/zipkin-server/health-query-plugin/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider new file mode 100755 index 00000000000..17bea87ef10 --- /dev/null +++ b/zipkin-server/health-query-plugin/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider @@ -0,0 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# + +zipkin.server.query.health.HealthQueryProvider \ No newline at end of file diff --git a/zipkin-server/http-query-plugin/pom.xml b/zipkin-server/http-query-plugin/pom.xml new file mode 100644 index 00000000000..f4371f49179 --- /dev/null +++ b/zipkin-server/http-query-plugin/pom.xml @@ -0,0 +1,23 @@ + + + 4.0.0 + + zipkin-server-parent + io.zipkin + 2.24.4-SNAPSHOT + + + http-query-plugin + Zipkin HTTP Query + + + + org.apache.skywalking + zipkin-query-plugin + ${skywalking.version} + + + + \ No newline at end of file diff --git a/zipkin-server/http-query-plugin/src/main/java/zipkin/server/query/http/HTTPQueryConfig.java b/zipkin-server/http-query-plugin/src/main/java/zipkin/server/query/http/HTTPQueryConfig.java new file mode 100644 index 00000000000..fd336dec3a0 --- /dev/null +++ b/zipkin-server/http-query-plugin/src/main/java/zipkin/server/query/http/HTTPQueryConfig.java @@ -0,0 +1,163 @@ +/* + * Copyright 2015-2023 The OpenZipkin Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package zipkin.server.query.http; + +import org.apache.skywalking.oap.query.zipkin.ZipkinQueryConfig; +import org.apache.skywalking.oap.server.library.module.ModuleConfig; + +public class HTTPQueryConfig extends ModuleConfig { + private String restHost; + private int restPort; + private String restContextPath; + private int restMaxThreads = 200; + private long restIdleTimeOut = 30000; + private int restAcceptQueueSize = 0; + /** + * The maximum size in bytes allowed for request headers. + * Use -1 to disable it. + */ + private int restMaxRequestHeaderSize = 8192; + + private boolean strictTraceId = true; + private long lookback = 86400000L; + private int namesMaxAge = 300; + private int uiQueryLimit = 10; + private String uiEnvironment = ""; + private long uiDefaultLookback = 900000L; + private boolean uiSearchEnabled = true; + + public ZipkinQueryConfig toSkyWalkingConfig() { + final ZipkinQueryConfig result = new ZipkinQueryConfig(); + result.setLookback(lookback); + result.setNamesMaxAge(namesMaxAge); + result.setUiQueryLimit(uiQueryLimit); + result.setUiEnvironment(uiEnvironment); + result.setUiDefaultLookback(uiDefaultLookback); + result.setUiSearchEnabled(uiSearchEnabled); + return result; + } + + public long getLookback() { + return lookback; + } + + public void setLookback(long lookback) { + this.lookback = lookback; + } + + public int getNamesMaxAge() { + return namesMaxAge; + } + + public void setNamesMaxAge(int namesMaxAge) { + this.namesMaxAge = namesMaxAge; + } + + public int getUiQueryLimit() { + return uiQueryLimit; + } + + public void setUiQueryLimit(int uiQueryLimit) { + this.uiQueryLimit = uiQueryLimit; + } + + public String getUiEnvironment() { + return uiEnvironment; + } + + public void setUiEnvironment(String uiEnvironment) { + this.uiEnvironment = uiEnvironment; + } + + public long getUiDefaultLookback() { + return uiDefaultLookback; + } + + public void setUiDefaultLookback(long uiDefaultLookback) { + this.uiDefaultLookback = uiDefaultLookback; + } + + public boolean getUiSearchEnabled() { + return uiSearchEnabled; + } + + public void setUiSearchEnabled(boolean uiSearchEnabled) { + this.uiSearchEnabled = uiSearchEnabled; + } + + public boolean getStrictTraceId() { + return strictTraceId; + } + + public void setStrictTraceId(boolean strictTraceId) { + this.strictTraceId = strictTraceId; + } + + public String getRestHost() { + return restHost; + } + + public void setRestHost(String restHost) { + this.restHost = restHost; + } + + public int getRestPort() { + return restPort; + } + + public void setRestPort(int restPort) { + this.restPort = restPort; + } + + public String getRestContextPath() { + return restContextPath; + } + + public void setRestContextPath(String restContextPath) { + this.restContextPath = restContextPath; + } + + public int getRestMaxThreads() { + return restMaxThreads; + } + + public void setRestMaxThreads(int restMaxThreads) { + this.restMaxThreads = restMaxThreads; + } + + public long getRestIdleTimeOut() { + return restIdleTimeOut; + } + + public void setRestIdleTimeOut(long restIdleTimeOut) { + this.restIdleTimeOut = restIdleTimeOut; + } + + public int getRestAcceptQueueSize() { + return restAcceptQueueSize; + } + + public void setRestAcceptQueueSize(int restAcceptQueueSize) { + this.restAcceptQueueSize = restAcceptQueueSize; + } + + public int getRestMaxRequestHeaderSize() { + return restMaxRequestHeaderSize; + } + + public void setRestMaxRequestHeaderSize(int restMaxRequestHeaderSize) { + this.restMaxRequestHeaderSize = restMaxRequestHeaderSize; + } +} diff --git a/zipkin-server/http-query-plugin/src/main/java/zipkin/server/query/http/HTTPQueryHandler.java b/zipkin-server/http-query-plugin/src/main/java/zipkin/server/query/http/HTTPQueryHandler.java new file mode 100644 index 00000000000..e3ae7ae5950 --- /dev/null +++ b/zipkin-server/http-query-plugin/src/main/java/zipkin/server/query/http/HTTPQueryHandler.java @@ -0,0 +1,132 @@ +/* + * Copyright 2015-2023 The OpenZipkin Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package zipkin.server.query.http; + +import com.linecorp.armeria.common.AggregatedHttpResponse; +import com.linecorp.armeria.common.HttpData; +import com.linecorp.armeria.common.HttpStatus; +import com.linecorp.armeria.common.MediaType; +import com.linecorp.armeria.common.ResponseHeaders; +import org.apache.skywalking.oap.query.zipkin.handler.ZipkinQueryHandler; +import org.apache.skywalking.oap.server.core.storage.StorageModule; +import org.apache.skywalking.oap.server.core.storage.query.IZipkinQueryDAO; +import org.apache.skywalking.oap.server.library.module.ModuleManager; +import org.apache.skywalking.oap.server.library.util.CollectionUtils; +import org.apache.skywalking.oap.server.library.util.StringUtil; +import zipkin2.Span; +import zipkin2.codec.SpanBytesEncoder; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import static com.linecorp.armeria.common.HttpStatus.BAD_REQUEST; +import static com.linecorp.armeria.common.HttpStatus.NOT_FOUND; +import static com.linecorp.armeria.common.MediaType.ANY_TEXT_TYPE; + +public class HTTPQueryHandler extends ZipkinQueryHandler { + private final HTTPQueryConfig config; + private final ModuleManager moduleManager; + + private IZipkinQueryDAO zipkinQueryDAO; + public HTTPQueryHandler(HTTPQueryConfig config, ModuleManager moduleManager) { + super(config.toSkyWalkingConfig(), moduleManager); + this.config = config; + this.moduleManager = moduleManager; + } + + @Override + public AggregatedHttpResponse getTraceById(String traceId) throws IOException { + if (StringUtil.isEmpty(traceId)) { + return AggregatedHttpResponse.of(BAD_REQUEST, ANY_TEXT_TYPE, "traceId is empty or null"); + } + final String normalized = Span.normalizeTraceId(traceId.trim()); + List result; + if (!config.getStrictTraceId() && normalized.length() == 32) { + result = getZipkinQueryDAO().getTraces(new HashSet<>(Arrays.asList(normalized, normalized.substring(16)))) + .stream().flatMap(List::stream).collect(Collectors.toList()); + } else { + result = getZipkinQueryDAO().getTrace(normalized); + } + if (CollectionUtils.isEmpty(result)) { + return AggregatedHttpResponse.of(NOT_FOUND, ANY_TEXT_TYPE, traceId + " not found"); + } + return response(SpanBytesEncoder.JSON_V2.encodeList(result)); + } + + @Override + public AggregatedHttpResponse getTracesByIds(String traceIds) throws IOException { + if (StringUtil.isEmpty(traceIds)) { + return AggregatedHttpResponse.of(BAD_REQUEST, ANY_TEXT_TYPE, "traceIds is empty or null"); + } + + Set normalizeTraceIds = new LinkedHashSet<>(); + for (String traceId : traceIds.split(",", 1000)) { + // make sure we have a 16 or 32 character trace ID + traceId = Span.normalizeTraceId(traceId); + // Unless we are strict, truncate the trace ID to 64bit (encoded as 16 characters) + if (!config.getStrictTraceId() && traceId.length() == 32) traceId = traceId.substring(16); + normalizeTraceIds.add(traceId); + } + return response(encodeTraces(getZipkinQueryDAO().getTraces(normalizeTraceIds))); + } + + private byte[] encodeTraces(List> traces) { + if (CollectionUtils.isEmpty(traces)) { + return new byte[] { + '[', + ']' + }; + } + List encodedTraces = new ArrayList<>(traces.size()); + int tracesSize = traces.size(); + int length = 0; + for (List trace : traces) { + byte[] traceByte = SpanBytesEncoder.JSON_V2.encodeList(trace); + encodedTraces.add(traceByte); + length += traceByte.length; + } + //bytes length = length + '[' + ']' + join ',' + byte[] allByteArray = new byte[length + 2 + traces.size() - 1]; + ByteBuffer buff = ByteBuffer.wrap(allByteArray); + buff.put((byte) '['); + for (int i = 0; i < tracesSize; i++) { + buff.put(encodedTraces.get(i)); + if (i < tracesSize - 1) + buff.put((byte) ','); + } + buff.put((byte) ']'); + return buff.array(); + } + + private AggregatedHttpResponse response(byte[] body) { + return AggregatedHttpResponse.of(ResponseHeaders.builder(HttpStatus.OK) + .contentType(MediaType.JSON) + .build(), HttpData.wrap(body)); + } + + private IZipkinQueryDAO getZipkinQueryDAO() { + if (zipkinQueryDAO == null) { + zipkinQueryDAO = moduleManager.find(StorageModule.NAME).provider().getService(IZipkinQueryDAO.class); + } + return zipkinQueryDAO; + } +} diff --git a/zipkin-server/http-query-plugin/src/main/java/zipkin/server/query/http/HTTPQueryProvider.java b/zipkin-server/http-query-plugin/src/main/java/zipkin/server/query/http/HTTPQueryProvider.java new file mode 100644 index 00000000000..4e62c90104c --- /dev/null +++ b/zipkin-server/http-query-plugin/src/main/java/zipkin/server/query/http/HTTPQueryProvider.java @@ -0,0 +1,103 @@ +/* + * Copyright 2015-2023 The OpenZipkin Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package zipkin.server.query.http; + +import com.linecorp.armeria.common.HttpMethod; +import org.apache.skywalking.oap.query.zipkin.ZipkinQueryModule; +import org.apache.skywalking.oap.server.core.CoreModule; +import org.apache.skywalking.oap.server.core.server.HTTPHandlerRegister; +import org.apache.skywalking.oap.server.library.module.ModuleConfig; +import org.apache.skywalking.oap.server.library.module.ModuleDefine; +import org.apache.skywalking.oap.server.library.module.ModuleProvider; +import org.apache.skywalking.oap.server.library.module.ModuleStartException; +import org.apache.skywalking.oap.server.library.module.ServiceNotProvidedException; +import org.apache.skywalking.oap.server.library.server.http.HTTPServer; +import org.apache.skywalking.oap.server.library.server.http.HTTPServerConfig; + +import java.util.Collections; + +public class HTTPQueryProvider extends ModuleProvider { + private HTTPQueryConfig moduleConfig; + private HTTPServer httpServer; + @Override + public String name() { + return "zipkin"; + } + + @Override + public Class module() { + return ZipkinQueryModule.class; + } + + @Override + public ConfigCreator newConfigCreator() { + return new ConfigCreator() { + @Override + public Class type() { + return HTTPQueryConfig.class; + } + + @Override + public void onInitialized(HTTPQueryConfig initialized) { + moduleConfig = initialized; + } + }; + } + + @Override + public void prepare() throws ServiceNotProvidedException, ModuleStartException { + if (moduleConfig.getRestPort() > 0) { + HTTPServerConfig httpServerConfig = HTTPServerConfig.builder() + .host(moduleConfig.getRestHost()) + .port(moduleConfig.getRestPort()) + .contextPath(moduleConfig.getRestContextPath()) + .idleTimeOut(moduleConfig.getRestIdleTimeOut()) + .maxThreads(moduleConfig.getRestMaxThreads()) + .acceptQueueSize(moduleConfig.getRestAcceptQueueSize()) + .maxRequestHeaderSize(moduleConfig.getRestMaxRequestHeaderSize()) + .build(); + httpServer = new HTTPServer(httpServerConfig); + httpServer.initialize(); + } + } + + @Override + public void start() throws ServiceNotProvidedException, ModuleStartException { + if (httpServer != null) { + httpServer.addHandler(new HTTPQueryHandler(moduleConfig, getManager()), + Collections.singletonList(HttpMethod.GET)); + } else { + getManager().find(CoreModule.NAME).provider() + .getService(HTTPHandlerRegister.class).addHandler( + new HTTPQueryHandler(moduleConfig, getManager()), + Collections.singletonList(HttpMethod.GET) + ); + } + } + + @Override + public void notifyAfterCompleted() throws ServiceNotProvidedException, ModuleStartException { + if (httpServer != null) { + httpServer.start(); + } + } + + @Override + public String[] requiredModules() { + return new String[] { + CoreModule.NAME, + }; + } +} diff --git a/zipkin-server/http-query-plugin/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider b/zipkin-server/http-query-plugin/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider new file mode 100755 index 00000000000..b642e8fe737 --- /dev/null +++ b/zipkin-server/http-query-plugin/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider @@ -0,0 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# + +zipkin.server.query.http.HTTPQueryProvider \ No newline at end of file diff --git a/zipkin-server/pom.xml b/zipkin-server/pom.xml index 4ce2185032f..d812118a243 100644 --- a/zipkin-server/pom.xml +++ b/zipkin-server/pom.xml @@ -67,6 +67,8 @@ receiver-zipkin-activemq receiver-zipkin-rabbitmq receiver-zipkin-scribe + http-query-plugin + health-query-plugin diff --git a/zipkin-server/receiver-zipkin-http/src/main/java/zipkin/server/receiver/zipkin/http/ZipkinHTTPReceiverConfig.java b/zipkin-server/receiver-zipkin-http/src/main/java/zipkin/server/receiver/zipkin/http/ZipkinHTTPReceiverConfig.java index eb6bbababa5..4d9ca221525 100644 --- a/zipkin-server/receiver-zipkin-http/src/main/java/zipkin/server/receiver/zipkin/http/ZipkinHTTPReceiverConfig.java +++ b/zipkin-server/receiver-zipkin-http/src/main/java/zipkin/server/receiver/zipkin/http/ZipkinHTTPReceiverConfig.java @@ -23,6 +23,11 @@ public class ZipkinHTTPReceiverConfig extends ModuleConfig { private int restMaxThreads = 200; private long restIdleTimeOut = 30000; private int restAcceptQueueSize = 0; + /** + * The maximum size in bytes allowed for request headers. + * Use -1 to disable it. + */ + private int restMaxRequestHeaderSize = 8192; public String getRestHost() { return restHost; @@ -71,4 +76,12 @@ public int getRestAcceptQueueSize() { public void setRestAcceptQueueSize(int restAcceptQueueSize) { this.restAcceptQueueSize = restAcceptQueueSize; } + + public int getRestMaxRequestHeaderSize() { + return restMaxRequestHeaderSize; + } + + public void setRestMaxRequestHeaderSize(int restMaxRequestHeaderSize) { + this.restMaxRequestHeaderSize = restMaxRequestHeaderSize; + } } diff --git a/zipkin-server/receiver-zipkin-http/src/main/java/zipkin/server/receiver/zipkin/http/ZipkinHTTPReceiverProvider.java b/zipkin-server/receiver-zipkin-http/src/main/java/zipkin/server/receiver/zipkin/http/ZipkinHTTPReceiverProvider.java index 00f05393f71..78e10fb6379 100644 --- a/zipkin-server/receiver-zipkin-http/src/main/java/zipkin/server/receiver/zipkin/http/ZipkinHTTPReceiverProvider.java +++ b/zipkin-server/receiver-zipkin-http/src/main/java/zipkin/server/receiver/zipkin/http/ZipkinHTTPReceiverProvider.java @@ -17,6 +17,7 @@ import com.linecorp.armeria.common.HttpMethod; import org.apache.skywalking.oap.server.core.CoreModule; import org.apache.skywalking.oap.server.core.config.ConfigService; +import org.apache.skywalking.oap.server.core.server.HTTPHandlerRegister; import org.apache.skywalking.oap.server.library.module.ModuleConfig; import org.apache.skywalking.oap.server.library.module.ModuleDefine; import org.apache.skywalking.oap.server.library.module.ModuleProvider; @@ -32,7 +33,7 @@ public class ZipkinHTTPReceiverProvider extends ModuleProvider { private ZipkinHTTPReceiverConfig moduleConfig; - private SpanForward spanForward; + private ZipkinSpanHTTPHandler httpHandler; private HTTPServer httpServer; @Override @@ -62,33 +63,40 @@ public void onInitialized(ZipkinHTTPReceiverConfig initialized) { @Override public void prepare() throws ServiceNotProvidedException, ModuleStartException { + if (moduleConfig.getRestPort() > 0) { + HTTPServerConfig httpServerConfig = HTTPServerConfig.builder() + .host(moduleConfig.getRestHost()) + .port(moduleConfig.getRestPort()) + .contextPath(moduleConfig.getRestContextPath()) + .idleTimeOut(moduleConfig.getRestIdleTimeOut()) + .maxThreads(moduleConfig.getRestMaxThreads()) + .acceptQueueSize(moduleConfig.getRestAcceptQueueSize()) + .maxRequestHeaderSize(moduleConfig.getRestMaxRequestHeaderSize()) + .build(); + httpServer = new HTTPServer(httpServerConfig); + httpServer.initialize(); + } } @Override public void start() throws ServiceNotProvidedException, ModuleStartException { final ConfigService service = getManager().find(CoreModule.NAME).provider().getService(ConfigService.class); - this.spanForward = new SpanForward(((ZipkinConfigService)service).toZipkinReceiverConfig(), getManager()); + final SpanForward spanForward = new SpanForward(((ZipkinConfigService)service).toZipkinReceiverConfig(), getManager()); + httpHandler = new ZipkinSpanHTTPHandler(spanForward, getManager()); - HTTPServerConfig httpServerConfig = HTTPServerConfig.builder() - .host(moduleConfig.getRestHost()) - .port(moduleConfig.getRestPort()) - .contextPath(moduleConfig.getRestContextPath()) - .idleTimeOut(moduleConfig.getRestIdleTimeOut()) - .maxThreads(moduleConfig.getRestMaxThreads()) - .acceptQueueSize(moduleConfig.getRestAcceptQueueSize()) - .build(); - - httpServer = new HTTPServer(httpServerConfig); - httpServer.initialize(); + if (httpServer != null) { + httpServer.addHandler(httpHandler, Arrays.asList(HttpMethod.POST, HttpMethod.GET)); + } else { + final HTTPHandlerRegister httpRegister = getManager().find(CoreModule.NAME).provider().getService(HTTPHandlerRegister.class); + httpRegister.addHandler(httpHandler, Arrays.asList(HttpMethod.POST, HttpMethod.GET)); + } } @Override public void notifyAfterCompleted() throws ServiceNotProvidedException, ModuleStartException { - httpServer.addHandler( - new ZipkinSpanHTTPHandler(this.spanForward, getManager()), - Arrays.asList(HttpMethod.POST, HttpMethod.GET) - ); - httpServer.start(); + if (httpServer != null) { + httpServer.start(); + } } @Override @@ -97,4 +105,8 @@ public String[] requiredModules() { CoreModule.NAME, }; } + + public ZipkinSpanHTTPHandler getHttpHandler() { + return httpHandler; + } } diff --git a/zipkin-server/receiver-zipkin-http/src/test/java/zipkin/server/receiver/zipkin/http/ITHTTPReceiver.java b/zipkin-server/receiver-zipkin-http/src/test/java/zipkin/server/receiver/zipkin/http/ITHTTPReceiver.java index dfaaf677fbe..a6ef6ec0e95 100644 --- a/zipkin-server/receiver-zipkin-http/src/test/java/zipkin/server/receiver/zipkin/http/ITHTTPReceiver.java +++ b/zipkin-server/receiver-zipkin-http/src/test/java/zipkin/server/receiver/zipkin/http/ITHTTPReceiver.java @@ -17,8 +17,12 @@ import org.apache.skywalking.oap.server.core.CoreModule; import org.apache.skywalking.oap.server.core.CoreModuleProvider; import org.apache.skywalking.oap.server.core.config.ConfigService; +import org.apache.skywalking.oap.server.core.server.HTTPHandlerRegister; +import org.apache.skywalking.oap.server.core.server.HTTPHandlerRegisterImpl; import org.apache.skywalking.oap.server.library.module.ModuleManager; import org.apache.skywalking.oap.server.library.module.ModuleStartException; +import org.apache.skywalking.oap.server.library.server.http.HTTPServer; +import org.apache.skywalking.oap.server.library.server.http.HTTPServerConfig; import org.apache.skywalking.oap.server.receiver.zipkin.trace.SpanForward; import org.apache.skywalking.oap.server.telemetry.TelemetryModule; import org.apache.skywalking.oap.server.telemetry.api.MetricsCreator; @@ -66,26 +70,23 @@ public class ITHTTPReceiver { @BeforeEach public void setup() throws ModuleStartException { - final ZipkinHTTPReceiverConfig config = new ZipkinHTTPReceiverConfig(); - config.setRestHost("0.0.0.0"); - config.setRestPort(port); - config.setRestContextPath("/"); - config.setRestIdleTimeOut(1000); - config.setRestMaxThreads(2); - config.setRestAcceptQueueSize(10); - - moduleManager = setupModuleManager(); + final HTTPServer httpServer = new HTTPServer(HTTPServerConfig.builder().host("0.0.0.0").port(port).contextPath("/").build()); + httpServer.initialize(); + moduleManager = setupModuleManager(httpServer); final ZipkinHTTPReceiverProvider provider = new ZipkinHTTPReceiverProvider(); provider.setManager(moduleManager); + final ZipkinHTTPReceiverConfig config = new ZipkinHTTPReceiverConfig(); + config.setRestPort(-1); Whitebox.setInternalState(provider, ZipkinHTTPReceiverConfig.class, config); provider.prepare(); provider.start(); + httpServer.start(); doAnswer(invocationOnMock -> { spans.add(invocationOnMock.getArgument(0, ArrayList.class)); return null; }).when(forward).send(any()); - Whitebox.setInternalState(provider, SpanForward.class, forward); + Whitebox.setInternalState(provider.getHttpHandler(), SpanForward.class, forward); provider.notifyAfterCompleted(); } @@ -115,13 +116,14 @@ public void test() throws Exception { assertThat(spans.take()).containsExactly(CLIENT_SPAN); } - private ModuleManager setupModuleManager() { + private ModuleManager setupModuleManager(HTTPServer httpServer) { ModuleManager moduleManager = Mockito.mock(ModuleManager.class); CoreModule coreModule = Mockito.spy(CoreModule.class); CoreModuleProvider moduleProvider = Mockito.mock(CoreModuleProvider.class); Whitebox.setInternalState(coreModule, "loadedProvider", moduleProvider); Mockito.when(moduleManager.find(CoreModule.NAME)).thenReturn(coreModule); + Mockito.when(coreModule.provider().getService(HTTPHandlerRegister.class)).thenReturn(new HTTPHandlerRegisterImpl(httpServer)); TelemetryModule telemetryModule = Mockito.spy(TelemetryModule.class); NoneTelemetryProvider noneTelemetryProvider = Mockito.mock(NoneTelemetryProvider.class); diff --git a/zipkin-server/server-core/src/main/java/zipkin/server/core/CoreModuleConfig.java b/zipkin-server/server-core/src/main/java/zipkin/server/core/CoreModuleConfig.java index 3edc980af90..3c99c1ba98c 100644 --- a/zipkin-server/server-core/src/main/java/zipkin/server/core/CoreModuleConfig.java +++ b/zipkin-server/server-core/src/main/java/zipkin/server/core/CoreModuleConfig.java @@ -27,6 +27,18 @@ public class CoreModuleConfig extends ModuleConfig { private int gRPCThreadPoolQueueSize; private int gRPCMaxConcurrentCallsPerConnection; private int gRPCMaxMessageSize; + + private String restHost; + private int restPort; + private String restContextPath; + private int restMaxThreads = 200; + private long restIdleTimeOut = 30000; + private int restAcceptQueueSize = 0; + /** + * The maximum size in bytes allowed for request headers. + * Use -1 to disable it. + */ + private int restMaxRequestHeaderSize = 8192; /** * The max length of the service name. @@ -71,9 +83,9 @@ public class CoreModuleConfig extends ModuleConfig { private String searchableTracesTags = DEFAULT_SEARCHABLE_TAG_KEYS; /** - * The trace sample rate precision is 1/10000, should be between 0 and 10000. + * The trace sample rate precision is 0.0001, should be between 0 and 1. */ - private int traceSampleRate = 10000; + private double traceSampleRate = 1.0f; /** * The number of threads used to prepare metrics data to the storage. @@ -175,11 +187,11 @@ public void setSearchableTracesTags(String searchableTracesTags) { this.searchableTracesTags = searchableTracesTags; } - public int getTraceSampleRate() { + public double getTraceSampleRate() { return traceSampleRate; } - public void setTraceSampleRate(int traceSampleRate) { + public void setTraceSampleRate(double traceSampleRate) { this.traceSampleRate = traceSampleRate; } @@ -286,4 +298,60 @@ public int getGRPCMaxMessageSize() { public void setGRPCMaxMessageSize(int gRPCMaxMessageSize) { this.gRPCMaxMessageSize = gRPCMaxMessageSize; } + + public String getRestHost() { + return restHost; + } + + public void setRestHost(String restHost) { + this.restHost = restHost; + } + + public int getRestPort() { + return restPort; + } + + public void setRestPort(int restPort) { + this.restPort = restPort; + } + + public String getRestContextPath() { + return restContextPath; + } + + public void setRestContextPath(String restContextPath) { + this.restContextPath = restContextPath; + } + + public int getRestMaxThreads() { + return restMaxThreads; + } + + public void setRestMaxThreads(int restMaxThreads) { + this.restMaxThreads = restMaxThreads; + } + + public long getRestIdleTimeOut() { + return restIdleTimeOut; + } + + public void setRestIdleTimeOut(long restIdleTimeOut) { + this.restIdleTimeOut = restIdleTimeOut; + } + + public int getRestAcceptQueueSize() { + return restAcceptQueueSize; + } + + public void setRestAcceptQueueSize(int restAcceptQueueSize) { + this.restAcceptQueueSize = restAcceptQueueSize; + } + + public int getRestMaxRequestHeaderSize() { + return restMaxRequestHeaderSize; + } + + public void setRestMaxRequestHeaderSize(int restMaxRequestHeaderSize) { + this.restMaxRequestHeaderSize = restMaxRequestHeaderSize; + } } diff --git a/zipkin-server/server-core/src/main/java/zipkin/server/core/CoreModuleProvider.java b/zipkin-server/server-core/src/main/java/zipkin/server/core/CoreModuleProvider.java index 83d48dd86e8..437910e6230 100644 --- a/zipkin-server/server-core/src/main/java/zipkin/server/core/CoreModuleProvider.java +++ b/zipkin-server/server-core/src/main/java/zipkin/server/core/CoreModuleProvider.java @@ -59,6 +59,7 @@ import org.apache.skywalking.oap.server.core.server.GRPCHandlerRegister; import org.apache.skywalking.oap.server.core.server.GRPCHandlerRegisterImpl; import org.apache.skywalking.oap.server.core.server.HTTPHandlerRegister; +import org.apache.skywalking.oap.server.core.server.HTTPHandlerRegisterImpl; import org.apache.skywalking.oap.server.core.source.DefaultScopeDefine; import org.apache.skywalking.oap.server.core.source.SourceReceiver; import org.apache.skywalking.oap.server.core.status.ServerStatusService; @@ -79,6 +80,8 @@ import org.apache.skywalking.oap.server.library.module.ServiceNotProvidedException; import org.apache.skywalking.oap.server.library.server.ServerException; import org.apache.skywalking.oap.server.library.server.grpc.GRPCServer; +import org.apache.skywalking.oap.server.library.server.http.HTTPServer; +import org.apache.skywalking.oap.server.library.server.http.HTTPServerConfig; import org.apache.skywalking.oap.server.telemetry.api.TelemetryRelatedContext; import zipkin.server.core.services.EmptyComponentLibraryCatalogService; import zipkin.server.core.services.EmptyHTTPHandlerRegister; @@ -97,6 +100,7 @@ public class CoreModuleProvider extends ModuleProvider { private final StorageModels storageModels; private RemoteClientManager remoteClientManager; private GRPCServer grpcServer; + private HTTPServer httpServer; public CoreModuleProvider() { this.annotationScan = new AnnotationScan(); @@ -150,6 +154,21 @@ public void prepare() throws ServiceNotProvidedException, ModuleStartException { throw new ModuleStartException(e.getMessage(), e); } + HTTPServerConfig httpServerConfig = HTTPServerConfig.builder() + .host(moduleConfig.getRestHost()) + .port(moduleConfig.getRestPort()) + .contextPath(moduleConfig.getRestContextPath()) + .idleTimeOut(moduleConfig.getRestIdleTimeOut()) + .maxThreads(moduleConfig.getRestMaxThreads()) + .acceptQueueSize( + moduleConfig.getRestAcceptQueueSize()) + .maxRequestHeaderSize( + moduleConfig.getRestMaxRequestHeaderSize()) + .build(); + httpServer = new HTTPServer(httpServerConfig); + httpServer.initialize(); + + // grpc if (moduleConfig.getGRPCSslEnabled()) { grpcServer = new GRPCServer(moduleConfig.getGRPCHost(), moduleConfig.getGRPCPort(), moduleConfig.getGRPCSslCertChainPath(), @@ -187,7 +206,7 @@ public void prepare() throws ServiceNotProvidedException, ModuleStartException { this.registerServiceImplementation(ServerStatusService.class, new ServerStatusService(getManager())); this.registerServiceImplementation(DownSamplingConfigService.class, new DownSamplingConfigService(Collections.emptyList())); this.registerServiceImplementation(GRPCHandlerRegister.class, new GRPCHandlerRegisterImpl(grpcServer)); - this.registerServiceImplementation(HTTPHandlerRegister.class, new EmptyHTTPHandlerRegister()); + this.registerServiceImplementation(HTTPHandlerRegister.class, new HTTPHandlerRegisterImpl(httpServer)); this.registerServiceImplementation(IComponentLibraryCatalogService.class, new EmptyComponentLibraryCatalogService()); this.registerServiceImplementation(SourceReceiver.class, receiver); final WorkerInstancesService instancesService = new WorkerInstancesService(); @@ -268,6 +287,7 @@ public void notifyAfterCompleted() throws ServiceNotProvidedException, ModuleSta try { if (!RunningMode.isInitMode()) { grpcServer.start(); + httpServer.start(); remoteClientManager.start(); } } catch (ServerException e) { diff --git a/zipkin-server/server-core/src/main/java/zipkin/server/core/services/ZipkinConfigService.java b/zipkin-server/server-core/src/main/java/zipkin/server/core/services/ZipkinConfigService.java index 80626499401..2b39fd77da8 100644 --- a/zipkin-server/server-core/src/main/java/zipkin/server/core/services/ZipkinConfigService.java +++ b/zipkin-server/server-core/src/main/java/zipkin/server/core/services/ZipkinConfigService.java @@ -29,7 +29,7 @@ public ZipkinConfigService(CoreModuleConfig moduleConfig, ModuleProvider provide public ZipkinReceiverConfig toZipkinReceiverConfig() { final ZipkinReceiverConfig config = new ZipkinReceiverConfig(); config.setSearchableTracesTags(moduleConfig.getSearchableTracesTags()); - config.setSampleRate(moduleConfig.getTraceSampleRate()); + config.setSampleRate((int) (moduleConfig.getTraceSampleRate() * 10000)); return config; } } diff --git a/zipkin-server/server-starter/pom.xml b/zipkin-server/server-starter/pom.xml index 7f4344dfe8b..6419d5f6773 100644 --- a/zipkin-server/server-starter/pom.xml +++ b/zipkin-server/server-starter/pom.xml @@ -85,9 +85,14 @@ - org.apache.skywalking - zipkin-query-plugin - ${skywalking.version} + io.zipkin + http-query-plugin + ${project.version} + + + io.zipkin + health-query-plugin + ${project.version} diff --git a/zipkin-server/server-starter/src/main/java/zipkin/server/ZipkinServer.java b/zipkin-server/server-starter/src/main/java/zipkin/server/ZipkinServer.java index 8dd2aa1aa8b..636e578b4aa 100644 --- a/zipkin-server/server-starter/src/main/java/zipkin/server/ZipkinServer.java +++ b/zipkin-server/server-starter/src/main/java/zipkin/server/ZipkinServer.java @@ -13,8 +13,30 @@ */ package zipkin.server; +import com.google.common.io.CharStreams; +import org.apache.skywalking.oap.server.core.version.Version; +import org.apache.skywalking.oap.server.library.util.ResourceUtils; + +import java.io.Reader; + public class ZipkinServer { public static void main(String[] args) { + printBanner(); ZipkinServerBootstrap.start(); } + + private static void printBanner() { + try (Reader applicationReader = ResourceUtils.read("zipkin.txt")) { + String banner = CharStreams.toString(applicationReader); + + banner = banner.replace("${AnsiOrange}", "\u001b[38;5;208m"); // Ansi 256 color code 208 (orange) + banner = banner.replace("${AnsiNormal}", "\u001b[0m"); + banner = banner.replace("${ProjectVersion}", Version.CURRENT.getBuildVersion()); + banner = banner.replace("${GitCommitID}", Version.CURRENT.getCommitId()); + + System.out.println(banner); + } catch (Exception ex) { + // who cares + } + } } diff --git a/zipkin-server/server-starter/src/main/java/zipkin/server/config/ApplicationConfigLoader.java b/zipkin-server/server-starter/src/main/java/zipkin/server/config/ApplicationConfigLoader.java index c47ada07e33..f27a1702d43 100644 --- a/zipkin-server/server-starter/src/main/java/zipkin/server/config/ApplicationConfigLoader.java +++ b/zipkin-server/server-starter/src/main/java/zipkin/server/config/ApplicationConfigLoader.java @@ -119,7 +119,12 @@ private void replacePropertyAndLog(final String propertyName, final Object prope private Object convertValueString(String valueString) { try { Object replaceValue = yaml.load(valueString); - if (replaceValue instanceof String || replaceValue instanceof Integer || replaceValue instanceof Long || replaceValue instanceof Boolean || replaceValue instanceof ArrayList) { + if (replaceValue instanceof String || + replaceValue instanceof Integer || + replaceValue instanceof Long || + replaceValue instanceof Boolean || + replaceValue instanceof Double || + replaceValue instanceof ArrayList) { return replaceValue; } else { return valueString; diff --git a/zipkin-server/server-starter/src/main/resources/application.yml b/zipkin-server/server-starter/src/main/resources/application.yml index 4f7a6cf5127..1ff4dd2ea63 100644 --- a/zipkin-server/server-starter/src/main/resources/application.yml +++ b/zipkin-server/server-starter/src/main/resources/application.yml @@ -32,8 +32,8 @@ core: # Defines a set of span tag keys which are searchable. # The max length of key=value should be less than 256 or will be dropped. searchableTracesTags: ${ZIPKIN_SEARCHABLE_TAG_KEYS:http.method} - # The trace sample rate precision is 1/10000, should be between 0 and 10000 - traceSampleRate: ${ZIPKIN_SAMPLE_RATE:10000} + # The trace sample rate precision is 0.0001, should be between 0 and 1 + traceSampleRate: ${ZIPKIN_SAMPLE_RATE:1} # The number of threads used to prepare metrics data to the storage. prepareThreads: ${ZIPKIN_PREPARE_THREADS:2} # The period of doing data persistence. Unit is second.Default value is 25s @@ -48,6 +48,13 @@ core: gRPCSslTrustedCAPath: ${ZIPKIN_GRPC_SSL_TRUSTED_CA_PATH:""} gRPCMaxConcurrentCallsPerConnection: ${ZIPKIN_GRPC_MAX_CONCURRENT_CALL:0} gRPCMaxMessageSize: ${ZIPKIN_GRPC_MAX_MESSAGE_SIZE:0} + restHost: ${ZIPKIN_REST_HOST:0.0.0.0} + restPort: ${ZIPKIN_REST_PORT:9411} + restContextPath: ${ZIPKIN_REST_CONTEXT_PATH:/} + restMaxThreads: ${ZIPKIN_REST_MAX_THREADS:200} + restIdleTimeOut: ${ZIPKIN_REST_IDLE_TIMEOUT:30000} + restAcceptQueueSize: ${ZIPKIN_REST_QUEUE_SIZE:0} + restMaxRequestHeaderSize: ${ZIPKIN_REST_MAX_REQUEST_HEADER_SIZE:8192} storage: selector: ${ZIPKIN_STORAGE:h2} @@ -143,12 +150,14 @@ storage: receiver-zipkin-http: selector: ${ZIPKIN_RECEIVER_ZIPKIN_HTTP:default} default: - restHost: ${ZIPKIN_RECEIVER_ZIPKIN_REST_HOST:0.0.0.0} - restPort: ${ZIPKIN_RECEIVER_ZIPKIN_REST_PORT:9411} - restContextPath: ${ZIPKIN_RECEIVER_ZIPKIN_REST_CONTEXT_PATH:/} - restMaxThreads: ${ZIPKIN_RECEIVER_ZIPKIN_REST_MAX_THREADS:200} - restIdleTimeOut: ${ZIPKIN_RECEIVER_ZIPKIN_REST_IDLE_TIMEOUT:30000} - restAcceptQueueSize: ${ZIPKIN_RECEIVER_ZIPKIN_REST_QUEUE_SIZE:0} + restHost: ${ZIPKIN_RECEIVER_HTTP_REST_HOST:0.0.0.0} + # The port number of the HTTP service, the default HTTP service in the core would be used if the value is smaller than 0. + restPort: ${ZIPKIN_RECEIVER_HTTP_REST_PORT:-1} + restContextPath: ${ZIPKIN_RECEIVER_HTTP_REST_CONTEXT_PATH:/} + restMaxThreads: ${ZIPKIN_RECEIVER_HTTP_REST_MAX_THREADS:200} + restIdleTimeOut: ${ZIPKIN_RECEIVER_HTTP_REST_IDLE_TIMEOUT:30000} + restAcceptQueueSize: ${ZIPKIN_RECEIVER_HTTP_REST_QUEUE_SIZE:0} + restMaxRequestHeaderSize: ${ZIPKIN_RECEIVER_HTTP_REST_MAX_REQUEST_HEADER_SIZE:8192} receiver-zipkin-kafka: selector: ${ZIPKIN_RECEIVER_ZIPKIN_KAFKA:-} @@ -200,24 +209,38 @@ receiver-zipkin-scribe: ## This module is for Zipkin query API and support zipkin-lens UI query-zipkin: - selector: ${ZIPKIN_QUERY_ZIPKIN:default} - default: - # For HTTP server - restHost: ${ZIPKIN_QUERY_ZIPKIN_REST_HOST:0.0.0.0} - restPort: ${ZIPKIN_QUERY_ZIPKIN_REST_PORT:9412} - restContextPath: ${ZIPKIN_QUERY_ZIPKIN_REST_CONTEXT_PATH:/zipkin} - restMaxThreads: ${ZIPKIN_QUERY_ZIPKIN_REST_MAX_THREADS:200} - restIdleTimeOut: ${ZIPKIN_QUERY_ZIPKIN_REST_IDLE_TIMEOUT:30000} - restAcceptQueueSize: ${ZIPKIN_QUERY_ZIPKIN_REST_QUEUE_SIZE:0} + selector: ${ZIPKIN_QUERY_ZIPKIN:zipkin} + zipkin: + restHost: ${ZIPKIN_QUERY_REST_HOST:0.0.0.0} + # The port number of the HTTP service, the default HTTP service in the core would be used if the value is smaller than 0. + restPort: ${ZIPKIN_QUERY_REST_PORT:-1} + restContextPath: ${ZIPKIN_QUERY_REST_CONTEXT_PATH:/} + restMaxThreads: ${ZIPKIN_QUERY_REST_MAX_THREADS:200} + restIdleTimeOut: ${ZIPKIN_QUERY_REST_IDLE_TIMEOUT:30000} + restAcceptQueueSize: ${ZIPKIN_QUERY_REST_QUEUE_SIZE:0} + restMaxRequestHeaderSize: ${ZIPKIN_QUERY_REST_MAX_REQUEST_HEADER_SIZE:8192} + strictTraceId: ${ZIPKIN_QUERY_STRICT_TRACE_ID:true} # Default look back for traces and autocompleteTags, 1 day in millis - lookback: ${ZIPKIN_QUERY_ZIPKIN_LOOKBACK:86400000} + lookback: ${ZIPKIN_QUERY_LOOKBACK:86400000} # The Cache-Control max-age (seconds) for serviceNames, remoteServiceNames and spanNames - namesMaxAge: ${ZIPKIN_QUERY_ZIPKIN_NAMES_MAX_AGE:300} + namesMaxAge: ${ZIPKIN_QUERY_NAMES_MAX_AGE:300} ## The below config are OAP support for zipkin-lens UI # Default traces query max size - uiQueryLimit: ${ZIPKIN_QUERY_ZIPKIN_UI_QUERY_LIMIT:10} + uiQueryLimit: ${ZIPKIN_QUERY_UI_QUERY_LIMIT:10} # Default look back on the UI for search traces, 15 minutes in millis - uiDefaultLookback: ${ZIPKIN_QUERY_ZIPKIN_UI_DEFAULT_LOOKBACK:900000} + uiDefaultLookback: ${ZIPKIN_QUERY_UI_DEFAULT_LOOKBACK:900000} + +query-health: + selector: ${ZIPKIN_QUERY_HEALTH:zipkin} + zipkin: + restHost: ${ZIPKIN_QUERY_HEALTH_REST_HOST:0.0.0.0} + # The port number of the HTTP service, the default HTTP service in the core would be used if the value is smaller than 0. + restPort: ${ZIPKIN_QUERY_HEALTH_REST_PORT:-1} + restContextPath: ${ZIPKIN_QUERY_HEALTH_REST_CONTEXT_PATH:/} + restMaxThreads: ${ZIPKIN_QUERY_HEALTH_REST_MAX_THREADS:200} + restIdleTimeOut: ${ZIPKIN_QUERY_HEALTH_REST_IDLE_TIMEOUT:30000} + restAcceptQueueSize: ${ZIPKIN_QUERY_HEALTH_REST_QUEUE_SIZE:0} + restMaxRequestHeaderSize: ${ZIPKIN_QUERY_HEALTH_REST_MAX_REQUEST_HEADER_SIZE:8192} telemetry: selector: ${ZIPKIN_TELEMETRY:none} diff --git a/zipkin-server/server-starter/src/main/resources/log4j2.xml b/zipkin-server/server-starter/src/main/resources/log4j2.xml index 58ea7479d55..9438e84a4b2 100644 --- a/zipkin-server/server-starter/src/main/resources/log4j2.xml +++ b/zipkin-server/server-starter/src/main/resources/log4j2.xml @@ -20,11 +20,7 @@ - - - - - + diff --git a/zipkin-server/server-starter/src/main/resources/zipkin.txt b/zipkin-server/server-starter/src/main/resources/zipkin.txt new file mode 100644 index 00000000000..a08b48dad38 --- /dev/null +++ b/zipkin-server/server-starter/src/main/resources/zipkin.txt @@ -0,0 +1,28 @@ +${AnsiOrange} + oo + oooo + oooooo + oooooooo + oooooooooo + oooooooooooo + ooooooo ooooooo + oooooo ooooooo + oooooo ooooooo + oooooo o o oooooo + oooooo oo oo oooooo + ooooooo oooo oooo ooooooo + oooooo ooooo ooooo ooooooo + oooooo oooooo oooooo ooooooo + oooooooo oo oo oooooooo + ooooooooooooo oo oo ooooooooooooo + oooooooooooo oooooooooooo + oooooooo oooooooo + oooo oooo +${AnsiNormal} + ________ ____ _ _____ _ _ + |__ /_ _| _ \| |/ /_ _| \ | | + / / | || |_) | ' / | || \| | + / /_ | || __/| . \ | || |\ | + |____|___|_| |_|\_\___|_| \_| + +:: version ${ProjectVersion} :: commit ${GitCommitID} ::