Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/en/changes/changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
* Add Ztunnel component in the topology.
* [Break Change] Change `compomentId` to `componentIds` in the K8SServiceRelation Scope.
* Adapt the mesh metrics if detect the ambient mesh in the eBPF access log receiver.
* Add JSON format support for the `/debugging/config/dump` status API.
* Enhance status APIs to support multiple `accept` header values, e.g. `Accept: application/json; charset=utf-8`.

#### UI

Expand Down
24 changes: 24 additions & 0 deletions docs/en/debugging/config_dump.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,30 @@ core.default.serviceCacheRefreshInterval=10

All booting configurations with their runtime values are listed, including the selected provider for each module.

This API also provides the response in JSON format, which is more friendly for programmatic usage.

```shell
> curl -X GET 'http://127.0.0.1:12800/debugging/config/dump' \
-H 'Accept: application/json'

// The following JSON is manually formatted for better readability.

{
"core.default.autocompleteTagKeysQueryMaxSize":"100",
"receiver-sharing-server.default.gRPCPort":"0",
"aws-firehose.default.port":"12801",
"core.default.restPort":"12800",
"receiver-sharing-server.default.gRPCSslCertChainPath":"",
"agent-analyzer.default.meterAnalyzerActiveFiles":"datasource,threadpool,satellite,go-runtime,python-runtime,continuous-profiling,java-agent,go-agent",
"agent-analyzer.default.traceSamplingPolicySettingsFile":"trace-sampling-policy-settings.yml",
"core.default.gRPCSslTrustedCAPath":"",
"configuration-discovery.default.disableMessageDigest":"false",
"core.default.serviceNameMaxLength":"70",
"aws-firehose.default.tlsCertChainPath":"",
....
}
```

## Protect The Secrets

Some of the configurations contain sensitive values, such as username, password, token, etc. These values would be
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@

package org.apache.skywalking.oap.server.core.status;

import com.google.gson.Gson;
import io.vavr.Tuple2;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import lombok.Getter;
Expand Down Expand Up @@ -84,20 +87,18 @@ public void registerWatcher(ServerStatusWatcher watcher) {
/**
* @return a complete list of booting configurations with effected values.
* @since 9.7.0
* @since 10.3.0 return ConfigList instead of String, to support raw configurations.
*/
public String dumpBootingConfigurations(String keywords4MaskingSecretsOfConfig) {
public ConfigList dumpBootingConfigurations(String keywords4MaskingSecretsOfConfig) {
ConfigList configList = new ConfigList();
if (configurations == null || configurations.isEmpty()) {
return "No available booting configurations.";
return configList;
}
final String[] keywords = keywords4MaskingSecretsOfConfig.split(",");
StringBuilder configList = new StringBuilder();
for (ApplicationConfiguration.ModuleConfiguration configuration : configurations) {
final String moduleName = configuration.getModuleName();
if (configuration.getProviders().size() == 1) {
configList.append(moduleName)
.append(".provider=")
.append(configuration.getProviders().keySet().iterator().next())
.append("\n");
configList.add(moduleName + ".provider", configuration.getProviders().keySet().iterator().next());
}
configuration.getProviders().forEach(
(providerName, providerConfiguration) ->
Expand All @@ -108,19 +109,41 @@ public String dumpBootingConfigurations(String keywords4MaskingSecretsOfConfig)
value = "******";
}
}

configList.append(moduleName)
.append(".")
.append(providerName)
.append(".")
.append(key)
.append("=")
.append(value)
.append("\n");
configList.add(moduleName + "." + providerName + "." + key, value.toString());
}
)
);
}
return configList.toString();
return configList;
}

public static class ConfigList {
private final static Gson GSON = new Gson();
private List<Tuple2> configurations = new ArrayList<>(200);

public void add(String key, String value) {
configurations.add(new Tuple2<>(key, value));
}

@Override
public String toString() {
StringBuilder configList = new StringBuilder();
for (Tuple2 tuple : configurations) {
configList.append(tuple._1)
.append("=")
.append(tuple._2)
.append("\n");
}
return configList.toString();
}

public String toJsonString() {
return GSON.toJson(configurations.stream()
.collect(
java.util.stream.Collectors.toMap(
tuple -> tuple._1.toString(),
tuple -> tuple._2.toString()
)));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import com.linecorp.armeria.common.AggregatedHttpResponse;
import com.linecorp.armeria.common.HttpHeaderNames;
import com.linecorp.armeria.common.HttpRequest;
import com.linecorp.armeria.server.annotation.Default;
import com.linecorp.armeria.server.annotation.ExceptionHandler;
import com.linecorp.armeria.server.annotation.Get;
Expand All @@ -38,7 +40,6 @@
import java.util.stream.Collectors;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.oap.server.core.query.mqe.ExpressionResult;
import org.apache.skywalking.oap.query.debug.log.DebuggingQueryLogsRsp;
import org.apache.skywalking.oap.query.debug.mqe.DebuggingMQERsp;
import org.apache.skywalking.oap.query.debug.topology.DebuggingQueryEndpointTopologyRsp;
Expand Down Expand Up @@ -67,6 +68,7 @@
import org.apache.skywalking.oap.server.core.query.input.LogQueryCondition;
import org.apache.skywalking.oap.server.core.query.input.TraceQueryCondition;
import org.apache.skywalking.oap.server.core.query.input.TraceScopeCondition;
import org.apache.skywalking.oap.server.core.query.mqe.ExpressionResult;
import org.apache.skywalking.oap.server.core.query.type.EndpointTopology;
import org.apache.skywalking.oap.server.core.query.type.Logs;
import org.apache.skywalking.oap.server.core.query.type.Pagination;
Expand All @@ -77,8 +79,8 @@
import org.apache.skywalking.oap.server.core.query.type.Trace;
import org.apache.skywalking.oap.server.core.query.type.TraceBrief;
import org.apache.skywalking.oap.server.core.query.type.TraceState;
import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTrace;
import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingSpan;
import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTrace;
import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTraceContext;
import org.apache.skywalking.oap.server.core.status.ServerStatusService;
import org.apache.skywalking.oap.server.library.module.ModuleManager;
Expand Down Expand Up @@ -109,8 +111,13 @@ public DebuggingHTTPHandler(final ModuleManager manager, final StatusQueryConfig
}

@Get("/debugging/config/dump")
public String dumpConfigurations() {
return serverStatusService.dumpBootingConfigurations(config.getKeywords4MaskingSecretsOfConfig());
public String dumpConfigurations(HttpRequest request) {
final String acceptHeader = request.headers().get(HttpHeaderNames.ACCEPT);
if (acceptHeader != null && acceptHeader.toLowerCase().contains("application/json")) {
return serverStatusService.dumpBootingConfigurations(config.getKeywords4MaskingSecretsOfConfig())
.toJsonString();
}
return serverStatusService.dumpBootingConfigurations(config.getKeywords4MaskingSecretsOfConfig()).toString();
}

@SneakyThrows
Expand Down Expand Up @@ -150,7 +157,8 @@ public String execExpression(@Param("dumpDBRsp") boolean dumpStorageRsp,
duration.setEnd(endTime);
duration.setStep(Step.valueOf(step));
coldStage.ifPresent(duration::setColdStage);
ExpressionResult expressionResult = mqeQuery.execExpression(expression, entity, duration, true, dumpStorageRsp).join();
ExpressionResult expressionResult = mqeQuery.execExpression(expression, entity, duration, true, dumpStorageRsp)
.join();
DebuggingTrace execTrace = expressionResult.getDebuggingTrace();
DebuggingMQERsp result = new DebuggingMQERsp(
expressionResult.getType(), expressionResult.getResults(), expressionResult.getError(),
Expand Down Expand Up @@ -279,8 +287,10 @@ public String queryZipkinTraces(@Param("serviceName") Optional<String> serviceNa
);
List<List<Span>> traces = new ArrayList<>();
if (response.status().code() == 200) {
traces = new Gson().fromJson(response.contentUtf8(), new TypeToken<ArrayList<ArrayList<Span>>>() {
}.getType());
traces = new Gson().fromJson(
response.contentUtf8(), new TypeToken<ArrayList<ArrayList<Span>>>() {
}.getType()
);
}
DebuggingZipkinQueryTracesRsp result = new DebuggingZipkinQueryTracesRsp(
traces, transformTrace(traceContext.getExecTrace()));
Expand All @@ -300,11 +310,15 @@ public String getZipkinTraceById(@Param("traceId") String traceId) {
AggregatedHttpResponse response = zipkinQueryHandler.getTraceById(traceId);
List<Span> trace = new ArrayList<>();
if (response.status().code() == 200) {
trace = new Gson().fromJson(response.contentUtf8(), new TypeToken<ArrayList<Span>>() {
}.getType());
trace = new Gson().fromJson(
response.contentUtf8(), new TypeToken<ArrayList<Span>>() {
}.getType()
);
}
DebuggingZipkinQueryTraceRsp result = new DebuggingZipkinQueryTraceRsp(trace, transformTrace(
traceContext.getExecTrace()));
DebuggingZipkinQueryTraceRsp result = new DebuggingZipkinQueryTraceRsp(
trace, transformTrace(
traceContext.getExecTrace())
);
return transToYAMLStringZipkin(result);
} finally {
traceContext.stopTrace();
Expand All @@ -315,10 +329,10 @@ public String getZipkinTraceById(@Param("traceId") String traceId) {
@SneakyThrows
@Get("/debugging/query/topology/getGlobalTopology")
public String getGlobalTopology(@Param("startTime") String startTime,
@Param("endTime") String endTime,
@Param("step") String step,
@Param("coldStage") Optional<Boolean> coldStage,
@Param("serviceLayer") Optional<String> serviceLayer) {
@Param("endTime") String endTime,
@Param("step") String step,
@Param("coldStage") Optional<Boolean> coldStage,
@Param("serviceLayer") Optional<String> serviceLayer) {
Duration duration = new Duration();
duration.setStart(startTime);
duration.setEnd(endTime);
Expand All @@ -333,11 +347,11 @@ public String getGlobalTopology(@Param("startTime") String startTime,
@SneakyThrows
@Get("/debugging/query/topology/getServicesTopology")
public String getServicesTopology(@Param("startTime") String startTime,
@Param("endTime") String endTime,
@Param("step") String step,
@Param("coldStage") Optional<Boolean> coldStage,
@Param("serviceLayer") String serviceLayer,
@Param("services") String services) {
@Param("endTime") String endTime,
@Param("step") String step,
@Param("coldStage") Optional<Boolean> coldStage,
@Param("serviceLayer") String serviceLayer,
@Param("services") String services) {
Duration duration = new Duration();
duration.setStart(startTime);
duration.setEnd(endTime);
Expand Down Expand Up @@ -367,9 +381,12 @@ public String getServiceInstanceTopology(@Param("startTime") String startTime,
duration.setEnd(endTime);
duration.setStep(Step.valueOf(step));
coldStage.ifPresent(duration::setColdStage);
String clientServiceId = IDManager.ServiceID.buildId(clientService, Layer.nameOf(clientServiceLayer).isNormal());
String serverServiceId = IDManager.ServiceID.buildId(serverService, Layer.nameOf(serverServiceLayer).isNormal());
ServiceInstanceTopology topology = topologyQuery.getServiceInstanceTopology(clientServiceId, serverServiceId, duration, true).join();
String clientServiceId = IDManager.ServiceID.buildId(
clientService, Layer.nameOf(clientServiceLayer).isNormal());
String serverServiceId = IDManager.ServiceID.buildId(
serverService, Layer.nameOf(serverServiceLayer).isNormal());
ServiceInstanceTopology topology = topologyQuery.getServiceInstanceTopology(
clientServiceId, serverServiceId, duration, true).join();
DebuggingQueryInstanceTopologyRsp result = new DebuggingQueryInstanceTopologyRsp(
topology.getNodes(), topology.getCalls(), transformTrace(topology.getDebuggingTrace()));
return transToYAMLString(result);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ private TTLStatusQuery getTTLStatusQuery() {

@Get("/status/config/ttl")
public HttpResponse affectedTTLConfigurations(HttpRequest request) {
if ("application/json".equalsIgnoreCase(request.headers().get(HttpHeaderNames.ACCEPT))) {
final String acceptHeader = request.headers().get(HttpHeaderNames.ACCEPT);
if (acceptHeader != null && acceptHeader.toLowerCase().contains("application/json")) {
return HttpResponse.of(MediaType.JSON_UTF_8, getTTLStatusQuery().getTTL().generateTTLDefinitionAsJSONStr());
}
return HttpResponse.of(MediaType.PLAIN_TEXT_UTF_8, getTTLStatusQuery().getTTL().generateTTLDefinition());
Expand Down
Loading