diff --git a/apm-dist-es7/src/main/assembly/binary-es7.xml b/apm-dist-es7/src/main/assembly/binary-es7.xml
index d6be958b9..2a2711928 100644
--- a/apm-dist-es7/src/main/assembly/binary-es7.xml
+++ b/apm-dist-es7/src/main/assembly/binary-es7.xml
@@ -50,7 +50,8 @@
component-libraries.ymlgateways.ymlservice-apdex-threshold.yml
- endpoint_name_grouping.yml
+ endpoint-name-grouping.yml
+ ui-initialized-templates.ymloal/core.oaloal/java-agent.oaloal/dotnet-agent.oal
diff --git a/apm-dist/src/main/assembly/binary.xml b/apm-dist/src/main/assembly/binary.xml
index 1161c1c52..00dc189db 100644
--- a/apm-dist/src/main/assembly/binary.xml
+++ b/apm-dist/src/main/assembly/binary.xml
@@ -50,7 +50,8 @@
component-libraries.ymlgateways.ymlservice-apdex-threshold.yml
- endpoint_name_grouping.yml
+ ui-initialized-templates.yml
+ endpoint-name-grouping.ymloal/core.oaloal/java-agent.oaloal/dotnet-agent.oal
diff --git a/docs/en/setup/backend/dynamic-config.md b/docs/en/setup/backend/dynamic-config.md
index b9ce01edc..8f4419332 100755
--- a/docs/en/setup/backend/dynamic-config.md
+++ b/docs/en/setup/backend/dynamic-config.md
@@ -10,7 +10,7 @@ Right now, SkyWalking supports following dynamic configurations.
|receiver-trace.default.uninstrumentedGateways| The uninstrumented gateways, override `gateways.yml`. | same as [`gateways.yml`](uninstrumented-gateways.md#configuration-format) |
|alarm.default.alarm-settings| The alarm settings, will override `alarm-settings.yml`. | same as [`alarm-settings.yml`](backend-alarm.md) |
|core.default.apdexThreshold| The apdex threshold settings, will override `service-apdex-threshold.yml`. | same as [`service-apdex-threshold.yml`](apdex-threshold.md) |
-|core.default.endpoint-name-grouping| The endpoint name grouping setting, will override `endpoint_name_grouping.yml`. | same as [`endpoint_name_grouping.yml`](endpoint-grouping-rules.md) |
+|core.default.endpoint-name-grouping| The endpoint name grouping setting, will override `endpoint-name-grouping.yml`. | same as [`endpoint-name-grouping.yml`](endpoint-grouping-rules.md) |
This feature depends on upstream service, so it is **DISABLED** by default.
diff --git a/docs/en/setup/backend/endpoint-grouping-rules.md b/docs/en/setup/backend/endpoint-grouping-rules.md
index e44e6df70..dd623beac 100644
--- a/docs/en/setup/backend/endpoint-grouping-rules.md
+++ b/docs/en/setup/backend/endpoint-grouping-rules.md
@@ -6,7 +6,7 @@ There are some special cases, especially when people use REST style URI, the app
such as putting order id in the URI, like `/prod/ORDER123` and `/prod/ORDER123`. But logically, people expect they could
have an endpoint name like `prod/{order-id}`. This is the feature of parameterized endpoint grouping designed for.
-Current, user could set up grouping rules through the static YAML file, named `endpoint_name_grouping.yml`,
+Current, user could set up grouping rules through the static YAML file, named `endpoint-name-grouping.yml`,
or use [Dynamic Configuration](dynamic-config.md) to initial and update the endpoint grouping rule.
## Configuration Format
diff --git a/oap-server/server-bootstrap/pom.xml b/oap-server/server-bootstrap/pom.xml
index 20b25f83e..c0d1f0994 100644
--- a/oap-server/server-bootstrap/pom.xml
+++ b/oap-server/server-bootstrap/pom.xml
@@ -242,7 +242,8 @@
component-libraries.ymlgateways.ymlservice-apdex-threshold.yml
- endpoint_name_grouping.yml
+ endpoint-name-grouping.yml
+ ui-initialized-templates.ymloal/core.oaloal/java-agent.oaloal/dotnet-agent.oal
diff --git a/oap-server/server-bootstrap/src/main/resources/endpoint_name_grouping.yml b/oap-server/server-bootstrap/src/main/resources/endpoint-name-grouping.yml
similarity index 100%
rename from oap-server/server-bootstrap/src/main/resources/endpoint_name_grouping.yml
rename to oap-server/server-bootstrap/src/main/resources/endpoint-name-grouping.yml
diff --git a/oap-server/server-bootstrap/src/main/resources/ui-initialized-templates.yml b/oap-server/server-bootstrap/src/main/resources/ui-initialized-templates.yml
new file mode 100644
index 000000000..76585b41b
--- /dev/null
+++ b/oap-server/server-bootstrap/src/main/resources/ui-initialized-templates.yml
@@ -0,0 +1,34 @@
+# 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.
+
+# UI templates initialized file includes the default template when the SkyWalking OAP starts up at the first time.
+#
+# Also, SkyWalking would detect the existing templates in the database, once they are missing, all templates in this file
+# could be added automatically.
+
+#templates:
+# - name: "APM (Agent based)"
+# # The type includes DASHBOARD, TOPOLOGY_INSTANCE, TOPOLOGY_ENDPOINT.
+# # DASHBOARD type templates could have multiple definitions, by using different names.
+# # TOPOLOGY_INSTANCE, TOPOLOGY_ENDPOINT type templates should be defined once, as they are used in the topology page only.
+# type: "DASHBOARD"
+# # Configuration could be defined through UI, and use `export` to format in the standard JSON.
+# configuration: |-
+# JSON format exported from UI.
+# # Activated as the DASHBOARD type, makes this templates added into the UI page automatically.
+# # False means providing a basic template, user needs to add it manually.
+# activated: true
+# # True means wouldn't show up on the dashboard. Only keeps the definition in the storage.
+# disabled: false
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/CoreModule.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/CoreModule.java
index dc74e59a7..e796aca8d 100755
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/CoreModule.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/CoreModule.java
@@ -28,6 +28,7 @@ import org.apache.skywalking.oap.server.core.config.ConfigService;
import org.apache.skywalking.oap.server.core.config.DownSamplingConfigService;
import org.apache.skywalking.oap.server.core.config.IComponentLibraryCatalogService;
import org.apache.skywalking.oap.server.core.config.NamingControl;
+import org.apache.skywalking.oap.server.core.management.ui.template.UITemplateManagementService;
import org.apache.skywalking.oap.server.core.oal.rt.OALEngineLoaderService;
import org.apache.skywalking.oap.server.core.profile.ProfileTaskMutationService;
import org.apache.skywalking.oap.server.core.query.AggregationQueryService;
@@ -46,8 +47,8 @@ import org.apache.skywalking.oap.server.core.server.GRPCHandlerRegister;
import org.apache.skywalking.oap.server.core.server.JettyHandlerRegister;
import org.apache.skywalking.oap.server.core.source.SourceReceiver;
import org.apache.skywalking.oap.server.core.storage.model.IModelManager;
-import org.apache.skywalking.oap.server.core.storage.model.ModelManipulator;
import org.apache.skywalking.oap.server.core.storage.model.ModelCreator;
+import org.apache.skywalking.oap.server.core.storage.model.ModelManipulator;
import org.apache.skywalking.oap.server.core.worker.IWorkerInstanceGetter;
import org.apache.skywalking.oap.server.core.worker.IWorkerInstanceSetter;
import org.apache.skywalking.oap.server.library.module.ModuleDefine;
@@ -82,10 +83,15 @@ public class CoreModule extends ModuleDefine {
addQueryService(classes);
addProfileService(classes);
addOALService(classes);
+ addManagementService(classes);
classes.add(CommandService.class);
- return classes.toArray(new Class[] {});
+ return classes.toArray(new Class[]{});
+ }
+
+ private void addManagementService(List classes) {
+ classes.add(UITemplateManagementService.class);
}
private void addProfileService(List classes) {
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/CoreModuleProvider.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/CoreModuleProvider.java
index cd6430b49..6aeba0f64 100755
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/CoreModuleProvider.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/CoreModuleProvider.java
@@ -28,6 +28,7 @@ import org.apache.skywalking.oap.server.core.analysis.DisableRegister;
import org.apache.skywalking.oap.server.core.analysis.StreamAnnotationListener;
import org.apache.skywalking.oap.server.core.analysis.meter.MeterSystem;
import org.apache.skywalking.oap.server.core.analysis.metrics.ApdexMetrics;
+import org.apache.skywalking.oap.server.core.analysis.worker.ManagementStreamProcessor;
import org.apache.skywalking.oap.server.core.analysis.worker.MetricsStreamProcessor;
import org.apache.skywalking.oap.server.core.analysis.worker.TopNStreamProcessor;
import org.apache.skywalking.oap.server.core.annotation.AnnotationScan;
@@ -45,6 +46,8 @@ import org.apache.skywalking.oap.server.core.config.IComponentLibraryCatalogServ
import org.apache.skywalking.oap.server.core.config.NamingControl;
import org.apache.skywalking.oap.server.core.config.group.EndpointNameGrouping;
import org.apache.skywalking.oap.server.core.config.group.EndpointNameGroupingRuleWatcher;
+import org.apache.skywalking.oap.server.core.management.ui.template.UITemplateInitializer;
+import org.apache.skywalking.oap.server.core.management.ui.template.UITemplateManagementService;
import org.apache.skywalking.oap.server.core.oal.rt.OALEngineLoaderService;
import org.apache.skywalking.oap.server.core.profile.ProfileTaskMutationService;
import org.apache.skywalking.oap.server.core.query.AggregationQueryService;
@@ -87,6 +90,7 @@ import org.apache.skywalking.oap.server.library.module.ServiceNotProvidedExcepti
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.jetty.JettyServer;
+import org.apache.skywalking.oap.server.library.util.ResourceUtils;
import org.apache.skywalking.oap.server.telemetry.TelemetryModule;
/**
@@ -139,14 +143,14 @@ public class CoreModuleProvider extends ModuleProvider {
}
EndpointNameGrouping endpointNameGrouping = new EndpointNameGrouping();
this.registerServiceImplementation(NamingControl.class, new NamingControl(
- moduleConfig.getServiceNameMaxLength(),
- moduleConfig.getInstanceNameMaxLength(),
- moduleConfig.getEndpointNameMaxLength(),
- endpointNameGrouping
+ moduleConfig.getServiceNameMaxLength(),
+ moduleConfig.getInstanceNameMaxLength(),
+ moduleConfig.getEndpointNameMaxLength(),
+ endpointNameGrouping
));
try {
endpointNameGroupingRuleWatcher = new EndpointNameGroupingRuleWatcher(
- this, endpointNameGrouping);
+ this, endpointNameGrouping);
} catch (FileNotFoundException e) {
throw new ModuleStartException(e.getMessage(), e);
}
@@ -174,8 +178,8 @@ public class CoreModuleProvider extends ModuleProvider {
if (moduleConfig.isGRPCSslEnabled()) {
grpcServer = new GRPCServer(moduleConfig.getGRPCHost(), moduleConfig.getGRPCPort(),
- Paths.get(moduleConfig.getGRPCSslCertChainPath()).toFile(),
- Paths.get(moduleConfig.getGRPCSslKeyPath()).toFile()
+ Paths.get(moduleConfig.getGRPCSslCertChainPath()).toFile(),
+ Paths.get(moduleConfig.getGRPCSslKeyPath()).toFile()
);
} else {
grpcServer = new GRPCServer(moduleConfig.getGRPCHost(), moduleConfig.getGRPCPort());
@@ -195,13 +199,13 @@ public class CoreModuleProvider extends ModuleProvider {
grpcServer.initialize();
jettyServer = new JettyServer(
- moduleConfig.getRestHost(), moduleConfig.getRestPort(), moduleConfig.getRestContextPath(), moduleConfig
- .getJettySelectors());
+ moduleConfig.getRestHost(), moduleConfig.getRestPort(), moduleConfig.getRestContextPath(), moduleConfig
+ .getJettySelectors());
jettyServer.initialize();
this.registerServiceImplementation(ConfigService.class, new ConfigService(moduleConfig));
this.registerServiceImplementation(
- DownSamplingConfigService.class, new DownSamplingConfigService(moduleConfig.getDownsampling()));
+ DownSamplingConfigService.class, new DownSamplingConfigService(moduleConfig.getDownsampling()));
this.registerServiceImplementation(GRPCHandlerRegister.class, new GRPCHandlerRegisterImpl(grpcServer));
this.registerServiceImplementation(JettyHandlerRegister.class, new JettyHandlerRegisterImpl(jettyServer));
@@ -220,7 +224,7 @@ public class CoreModuleProvider extends ModuleProvider {
this.registerServiceImplementation(ModelManipulator.class, storageModels);
this.registerServiceImplementation(
- NetworkAddressAliasCache.class, new NetworkAddressAliasCache(moduleConfig));
+ NetworkAddressAliasCache.class, new NetworkAddressAliasCache(moduleConfig));
this.registerServiceImplementation(TopologyQueryService.class, new TopologyQueryService(getManager()));
this.registerServiceImplementation(MetricsMetadataQueryService.class, new MetricsMetadataQueryService());
@@ -234,9 +238,9 @@ public class CoreModuleProvider extends ModuleProvider {
// add profile service implementations
this.registerServiceImplementation(
- ProfileTaskMutationService.class, new ProfileTaskMutationService(getManager()));
+ ProfileTaskMutationService.class, new ProfileTaskMutationService(getManager()));
this.registerServiceImplementation(
- ProfileTaskQueryService.class, new ProfileTaskQueryService(getManager(), moduleConfig));
+ ProfileTaskQueryService.class, new ProfileTaskQueryService(getManager(), moduleConfig));
this.registerServiceImplementation(ProfileTaskCache.class, new ProfileTaskCache(getManager(), moduleConfig));
this.registerServiceImplementation(CommandService.class, new CommandService(getManager()));
@@ -248,14 +252,17 @@ public class CoreModuleProvider extends ModuleProvider {
if (moduleConfig.isGRPCSslEnabled()) {
this.remoteClientManager = new RemoteClientManager(getManager(), moduleConfig.getRemoteTimeout(),
- Paths.get(moduleConfig.getGRPCSslTrustedCAPath())
- .toFile()
+ Paths.get(moduleConfig.getGRPCSslTrustedCAPath())
+ .toFile()
);
} else {
this.remoteClientManager = new RemoteClientManager(getManager(), moduleConfig.getRemoteTimeout());
}
this.registerServiceImplementation(RemoteClientManager.class, remoteClientManager);
+ // Management
+ this.registerServiceImplementation(UITemplateManagementService.class, new UITemplateManagementService(getManager()));
+
MetricsStreamProcessor.getInstance().setEnableDatabaseSession(moduleConfig.isEnableDatabaseSession());
TopNStreamProcessor.getInstance().setTopNWorkerReportCycle(moduleConfig.getTopNReportPeriod());
apdexThresholdConfig = new ApdexThresholdConfig(this);
@@ -276,24 +283,24 @@ public class CoreModuleProvider extends ModuleProvider {
}
if (CoreModuleConfig.Role.Mixed.name()
- .equalsIgnoreCase(
- moduleConfig.getRole())
- || CoreModuleConfig.Role.Aggregator.name()
- .equalsIgnoreCase(
- moduleConfig.getRole())) {
+ .equalsIgnoreCase(
+ moduleConfig.getRole())
+ || CoreModuleConfig.Role.Aggregator.name()
+ .equalsIgnoreCase(
+ moduleConfig.getRole())) {
RemoteInstance gRPCServerInstance = new RemoteInstance(
- new Address(moduleConfig.getGRPCHost(), moduleConfig.getGRPCPort(), true));
+ new Address(moduleConfig.getGRPCHost(), moduleConfig.getGRPCPort(), true));
this.getManager()
- .find(ClusterModule.NAME)
- .provider()
- .getService(ClusterRegister.class)
- .registerRemote(gRPCServerInstance);
+ .find(ClusterModule.NAME)
+ .provider()
+ .getService(ClusterRegister.class)
+ .registerRemote(gRPCServerInstance);
}
DynamicConfigurationService dynamicConfigurationService = getManager().find(ConfigurationModule.NAME)
- .provider()
- .getService(
- DynamicConfigurationService.class);
+ .provider()
+ .getService(
+ DynamicConfigurationService.class);
dynamicConfigurationService.registerConfigChangeWatcher(apdexThresholdConfig);
dynamicConfigurationService.registerConfigChangeWatcher(endpointNameGroupingRuleWatcher);
}
@@ -314,13 +321,23 @@ public class CoreModuleProvider extends ModuleProvider {
}
CacheUpdateTimer.INSTANCE.start(getManager(), moduleConfig.getMetricsDataTTL());
+
+ try {
+ new UITemplateInitializer(ResourceUtils.read("ui-initialized-templates.yml"))
+ .read()
+ .forEach(uiTemplate -> {
+ ManagementStreamProcessor.getInstance().in(uiTemplate);
+ });
+ } catch (FileNotFoundException e) {
+ throw new ModuleStartException(e.getMessage(), e);
+ }
}
@Override
public String[] requiredModules() {
- return new String[] {
- TelemetryModule.NAME,
- ConfigurationModule.NAME
+ return new String[]{
+ TelemetryModule.NAME,
+ ConfigurationModule.NAME
};
}
}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/DownSampling.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/DownSampling.java
index 98a4ece51..93e0b7489 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/DownSampling.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/DownSampling.java
@@ -19,7 +19,7 @@ package org.apache.skywalking.oap.server.core.analysis;
public enum DownSampling {
/**
- * None downsampling is for inventory
+ * None downsampling is for un-time-series data.
*/
None(0, ""),
/**
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/Stream.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/Stream.java
index ea312d2b2..5de708688 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/Stream.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/Stream.java
@@ -24,7 +24,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Map;
import org.apache.skywalking.oap.server.core.analysis.worker.MetricsStreamProcessor;
-import org.apache.skywalking.oap.server.core.analysis.worker.NoneStreamingProcessor;
+import org.apache.skywalking.oap.server.core.analysis.worker.NoneStreamProcessor;
import org.apache.skywalking.oap.server.core.analysis.worker.RecordStreamProcessor;
import org.apache.skywalking.oap.server.core.analysis.worker.TopNStreamProcessor;
import org.apache.skywalking.oap.server.core.source.ScopeDeclaration;
@@ -33,7 +33,7 @@ import org.apache.skywalking.oap.server.core.storage.StorageBuilder;
/**
* Stream annotation represents a metadata definition. Include the key values of the distributed streaming calculation.
* See {@link MetricsStreamProcessor}, {@link RecordStreamProcessor}, {@link TopNStreamProcessor} and {@link
- * NoneStreamingProcessor} for more details.
+ * NoneStreamProcessor} for more details.
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@@ -55,7 +55,7 @@ public @interface Stream {
/**
* @return the stream processor type, see {@link MetricsStreamProcessor}, {@link RecordStreamProcessor}, {@link
- * TopNStreamProcessor} and {@link NoneStreamingProcessor} for more details.
+ * TopNStreamProcessor} and {@link NoneStreamProcessor} for more details.
*/
Class extends StreamProcessor> processor();
}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/StreamAnnotationListener.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/StreamAnnotationListener.java
index 4c75c7836..052ea509e 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/StreamAnnotationListener.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/StreamAnnotationListener.java
@@ -20,8 +20,9 @@ package org.apache.skywalking.oap.server.core.analysis;
import java.lang.annotation.Annotation;
import org.apache.skywalking.oap.server.core.UnexpectedException;
+import org.apache.skywalking.oap.server.core.analysis.worker.ManagementStreamProcessor;
import org.apache.skywalking.oap.server.core.analysis.worker.MetricsStreamProcessor;
-import org.apache.skywalking.oap.server.core.analysis.worker.NoneStreamingProcessor;
+import org.apache.skywalking.oap.server.core.analysis.worker.NoneStreamProcessor;
import org.apache.skywalking.oap.server.core.analysis.worker.RecordStreamProcessor;
import org.apache.skywalking.oap.server.core.analysis.worker.TopNStreamProcessor;
import org.apache.skywalking.oap.server.core.annotation.AnnotationListener;
@@ -56,14 +57,16 @@ public class StreamAnnotationListener implements AnnotationListener {
MetricsStreamProcessor.getInstance().create(moduleDefineHolder, stream, aClass);
} else if (stream.processor().equals(TopNStreamProcessor.class)) {
TopNStreamProcessor.getInstance().create(moduleDefineHolder, stream, aClass);
- } else if (stream.processor().equals(NoneStreamingProcessor.class)) {
- NoneStreamingProcessor.getInstance().create(moduleDefineHolder, stream, aClass);
+ } else if (stream.processor().equals(NoneStreamProcessor.class)) {
+ NoneStreamProcessor.getInstance().create(moduleDefineHolder, stream, aClass);
+ } else if (stream.processor().equals(ManagementStreamProcessor.class)) {
+ ManagementStreamProcessor.getInstance().create(moduleDefineHolder, stream, aClass);
} else {
throw new UnexpectedException("Unknown stream processor.");
}
} else {
throw new UnexpectedException(
- "Stream annotation listener could only parse the class present stream annotation.");
+ "Stream annotation listener could only parse the class present stream annotation.");
}
}
}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/management/ManagementData.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/management/ManagementData.java
new file mode 100644
index 000000000..9e35b8a8a
--- /dev/null
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/management/ManagementData.java
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ *
+ */
+
+package org.apache.skywalking.oap.server.core.analysis.management;
+
+import org.apache.skywalking.oap.server.core.storage.StorageData;
+
+/**
+ * ManagementData provides the basic CRUD operations.
+ */
+public abstract class ManagementData implements StorageData {
+}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/worker/ManagementPersistentWorker.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/worker/ManagementPersistentWorker.java
new file mode 100644
index 000000000..8e413817c
--- /dev/null
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/worker/ManagementPersistentWorker.java
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ *
+ */
+
+package org.apache.skywalking.oap.server.core.analysis.worker;
+
+import java.io.IOException;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.skywalking.oap.server.core.analysis.management.ManagementData;
+import org.apache.skywalking.oap.server.core.storage.IManagementDAO;
+import org.apache.skywalking.oap.server.core.storage.model.Model;
+import org.apache.skywalking.oap.server.core.worker.AbstractWorker;
+import org.apache.skywalking.oap.server.library.module.ModuleDefineHolder;
+
+@Slf4j
+public class ManagementPersistentWorker extends AbstractWorker {
+ private final Model model;
+ private final IManagementDAO configDAO;
+
+ public ManagementPersistentWorker(ModuleDefineHolder moduleDefineHolder, Model model, IManagementDAO configDAO) {
+ super(moduleDefineHolder);
+ this.model = model;
+ this.configDAO = configDAO;
+ }
+
+ @Override
+ public void in(ManagementData managementData) {
+ try {
+ configDAO.insert(model, managementData);
+ } catch (IOException e) {
+ log.error(e.getMessage(), e);
+ }
+ }
+}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/worker/ManagementStreamProcessor.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/worker/ManagementStreamProcessor.java
new file mode 100644
index 000000000..8a44a4da0
--- /dev/null
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/worker/ManagementStreamProcessor.java
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ *
+ */
+
+package org.apache.skywalking.oap.server.core.analysis.worker;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.skywalking.oap.server.core.CoreModule;
+import org.apache.skywalking.oap.server.core.UnexpectedException;
+import org.apache.skywalking.oap.server.core.analysis.DisableRegister;
+import org.apache.skywalking.oap.server.core.analysis.DownSampling;
+import org.apache.skywalking.oap.server.core.analysis.Stream;
+import org.apache.skywalking.oap.server.core.analysis.StreamProcessor;
+import org.apache.skywalking.oap.server.core.analysis.management.ManagementData;
+import org.apache.skywalking.oap.server.core.storage.IManagementDAO;
+import org.apache.skywalking.oap.server.core.storage.StorageDAO;
+import org.apache.skywalking.oap.server.core.storage.StorageException;
+import org.apache.skywalking.oap.server.core.storage.StorageModule;
+import org.apache.skywalking.oap.server.core.storage.annotation.Storage;
+import org.apache.skywalking.oap.server.core.storage.model.Model;
+import org.apache.skywalking.oap.server.core.storage.model.ModelCreator;
+import org.apache.skywalking.oap.server.library.module.ModuleDefineHolder;
+
+/**
+ * ManagementProcessor represents the UI/CLI interactive process. They are management data, which size is not huge and
+ * time serious.
+ *
+ * @since 8.0.0
+ */
+public class ManagementStreamProcessor implements StreamProcessor {
+ private static final ManagementStreamProcessor PROCESSOR = new ManagementStreamProcessor();
+ private Map, ManagementPersistentWorker> workers = new HashMap<>();
+
+ public static ManagementStreamProcessor getInstance() {
+ return PROCESSOR;
+ }
+
+ @Override
+ public void in(final ManagementData managementData) {
+ final ManagementPersistentWorker worker = workers.get(managementData.getClass());
+ if (worker != null) {
+ worker.in(managementData);
+ }
+ }
+
+ @Override
+ public void create(final ModuleDefineHolder moduleDefineHolder, final Stream stream, final Class extends ManagementData> streamClass) throws StorageException {
+ if (DisableRegister.INSTANCE.include(stream.name())) {
+ return;
+ }
+
+ StorageDAO storageDAO = moduleDefineHolder.find(StorageModule.NAME).provider().getService(StorageDAO.class);
+ IManagementDAO managementDAO;
+ try {
+ managementDAO = storageDAO.newManagementDao(stream.builder().newInstance());
+ } catch (InstantiationException | IllegalAccessException e) {
+ throw new UnexpectedException("Create " + stream.builder()
+ .getSimpleName() + " none stream record DAO failure.", e);
+ }
+
+ ModelCreator modelSetter = moduleDefineHolder.find(CoreModule.NAME).provider().getService(ModelCreator.class);
+ Model model = modelSetter.add(streamClass, stream.scopeId(), new Storage(stream.name(), DownSampling.None), false);
+
+ final ManagementPersistentWorker persistentWorker = new ManagementPersistentWorker(moduleDefineHolder, model, managementDAO);
+ workers.put(streamClass, persistentWorker);
+ }
+}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/worker/NoneStreamPersistentWorker.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/worker/NoneStreamPersistentWorker.java
index 59c729c0c..865d38a43 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/worker/NoneStreamPersistentWorker.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/worker/NoneStreamPersistentWorker.java
@@ -19,21 +19,18 @@
package org.apache.skywalking.oap.server.core.analysis.worker;
import java.io.IOException;
+import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.oap.server.core.analysis.config.NoneStream;
import org.apache.skywalking.oap.server.core.storage.INoneStreamDAO;
import org.apache.skywalking.oap.server.core.storage.model.Model;
import org.apache.skywalking.oap.server.core.worker.AbstractWorker;
import org.apache.skywalking.oap.server.library.module.ModuleDefineHolder;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
/**
- * None persistent use {@link INoneStreamDAO#insert(Model, NoneStream)} on get new data
+ * None persistent use {@link INoneStreamDAO#insert(Model, NoneStream)} on saving new data
*/
+@Slf4j
public class NoneStreamPersistentWorker extends AbstractWorker {
-
- private static final Logger logger = LoggerFactory.getLogger(NoneStreamPersistentWorker.class);
-
private final Model model;
private final INoneStreamDAO configDAO;
@@ -48,7 +45,7 @@ public class NoneStreamPersistentWorker extends AbstractWorker {
try {
configDAO.insert(model, noneStream);
} catch (IOException e) {
- logger.error(e.getMessage(), e);
+ log.error(e.getMessage(), e);
}
}
}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/worker/NoneStreamingProcessor.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/worker/NoneStreamProcessor.java
similarity index 94%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/worker/NoneStreamingProcessor.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/worker/NoneStreamProcessor.java
index cda63c2ee..8878d44b5 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/worker/NoneStreamingProcessor.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/worker/NoneStreamProcessor.java
@@ -40,13 +40,13 @@ import org.apache.skywalking.oap.server.library.module.ModuleDefineHolder;
* none streaming is designed for user operation configuration in UI interface. It uses storage (synchronization)
* similar to Inventory and supports TTL deletion mode similar to the record.
*/
-public class NoneStreamingProcessor implements StreamProcessor {
+public class NoneStreamProcessor implements StreamProcessor {
- private static final NoneStreamingProcessor PROCESSOR = new NoneStreamingProcessor();
+ private static final NoneStreamProcessor PROCESSOR = new NoneStreamProcessor();
private Map, NoneStreamPersistentWorker> workers = new HashMap<>();
- public static NoneStreamingProcessor getInstance() {
+ public static NoneStreamProcessor getInstance() {
return PROCESSOR;
}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/config/group/EndpointNameGroupingRuleWatcher.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/config/group/EndpointNameGroupingRuleWatcher.java
index 19b27ee09..cfb307fc0 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/config/group/EndpointNameGroupingRuleWatcher.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/config/group/EndpointNameGroupingRuleWatcher.java
@@ -40,7 +40,7 @@ public class EndpointNameGroupingRuleWatcher extends ConfigChangeWatcher {
// This is just a place holder text representing the original text.
ruleSetting = "SkyWalking endpoint rule";
grouping.setEndpointGroupingRule(new EndpointGroupingRuleReader(
- ResourceUtils.read("endpoint_name_grouping.yml")).read());
+ ResourceUtils.read("endpoint-name-grouping.yml")).read());
}
@Override
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/management/ui/template/UITemplate.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/management/ui/template/UITemplate.java
new file mode 100644
index 000000000..376dedcb1
--- /dev/null
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/management/ui/template/UITemplate.java
@@ -0,0 +1,92 @@
+/*
+ * 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.
+ *
+ */
+
+package org.apache.skywalking.oap.server.core.management.ui.template;
+
+import java.util.HashMap;
+import java.util.Map;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.skywalking.oap.server.core.analysis.Stream;
+import org.apache.skywalking.oap.server.core.analysis.management.ManagementData;
+import org.apache.skywalking.oap.server.core.analysis.worker.ManagementStreamProcessor;
+import org.apache.skywalking.oap.server.core.source.ScopeDeclaration;
+import org.apache.skywalking.oap.server.core.storage.StorageBuilder;
+import org.apache.skywalking.oap.server.core.storage.annotation.Column;
+
+import static org.apache.skywalking.oap.server.core.source.DefaultScopeDefine.UI_TEMPLATE;
+
+@Setter
+@Getter
+@ScopeDeclaration(id = UI_TEMPLATE, name = "UITemplate")
+@Stream(name = UITemplate.INDEX_NAME, scopeId = UI_TEMPLATE, builder = UITemplate.Builder.class, processor = ManagementStreamProcessor.class)
+@EqualsAndHashCode(of = {
+ "name"
+}, callSuper = false)
+public class UITemplate extends ManagementData {
+ public static final String INDEX_NAME = "ui_template";
+ public static final String NAME = "name";
+ public static final String TYPE = "type";
+ public static final String CONFIGURATION = "configuration";
+ public static final String ACTIVATED = "activated";
+ public static final String DISABLED = "disabled";
+
+ @Column(columnName = NAME)
+ private String name;
+ @Column(columnName = TYPE, storageOnly = true)
+ private String type;
+ /**
+ * Configuration in JSON format.
+ */
+ @Column(columnName = CONFIGURATION, storageOnly = true, length = 1_000_000)
+ private String configuration;
+ @Column(columnName = ACTIVATED, storageOnly = true)
+ private int activated;
+ @Column(columnName = DISABLED)
+ private int disabled;
+
+ @Override
+ public String id() {
+ return name;
+ }
+
+ public static class Builder implements StorageBuilder {
+ @Override
+ public UITemplate map2Data(final Map dbMap) {
+ UITemplate uiTemplate = new UITemplate();
+ uiTemplate.setName((String) dbMap.get(NAME));
+ uiTemplate.setType((String) dbMap.get(TYPE));
+ uiTemplate.setConfiguration((String) dbMap.get(CONFIGURATION));
+ uiTemplate.setActivated(((Number) dbMap.get(ACTIVATED)).intValue());
+ uiTemplate.setDisabled(((Number) dbMap.get(DISABLED)).intValue());
+ return uiTemplate;
+ }
+
+ @Override
+ public Map data2Map(final UITemplate storageData) {
+ final HashMap map = new HashMap<>();
+ map.put(NAME, storageData.getName());
+ map.put(TYPE, storageData.getType());
+ map.put(CONFIGURATION, storageData.getConfiguration());
+ map.put(ACTIVATED, storageData.getActivated());
+ map.put(DISABLED, storageData.getDisabled());
+ return map;
+ }
+ }
+}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/management/ui/template/UITemplateInitializer.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/management/ui/template/UITemplateInitializer.java
new file mode 100644
index 000000000..4ec82ae6b
--- /dev/null
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/management/ui/template/UITemplateInitializer.java
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ *
+ */
+
+package org.apache.skywalking.oap.server.core.management.ui.template;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import org.apache.skywalking.apm.util.StringUtil;
+import org.apache.skywalking.oap.server.core.query.enumeration.TemplateType;
+import org.apache.skywalking.oap.server.library.util.BooleanUtils;
+import org.yaml.snakeyaml.Yaml;
+
+/**
+ * UITemplateInitializer load the template from the config file in YAML format. The template definition is by JSON format in default,
+ * but it depends on the UI implementation only.
+ */
+public class UITemplateInitializer {
+ private Map yamlData;
+
+ public UITemplateInitializer(InputStream inputStream) {
+ Yaml yaml = new Yaml();
+ yamlData = yaml.loadAs(inputStream, Map.class);
+ }
+
+ public UITemplateInitializer(Reader io) {
+ Yaml yaml = new Yaml();
+ yamlData = yaml.loadAs(io, Map.class);
+ }
+
+ public List read() {
+ List uiTemplates = new ArrayList<>();
+ if (Objects.nonNull(yamlData)) {
+ List templates = (List) yamlData.get("templates");
+ if (templates != null) {
+ templates.forEach(templateObj -> {
+ final Map template = (Map) templateObj;
+ UITemplate newTemplate = new UITemplate();
+ final String name = (String) template.get("name");
+ if (StringUtil.isEmpty(name)) {
+ throw new IllegalArgumentException("template name shouldn't be null");
+ }
+ newTemplate.setName(name);
+ final String type = (String) template.getOrDefault("type", TemplateType.DASHBOARD.name());
+ TemplateType.forName(type); // for checking.
+ newTemplate.setType(type);
+ final String configuration = (String) template.get("configuration");
+ if (StringUtil.isEmpty(configuration)) {
+ throw new IllegalArgumentException("template configuration shouldn't be null");
+ }
+ newTemplate.setConfiguration(configuration);
+ newTemplate.setActivated(
+ BooleanUtils.booleanToValue(
+ // The template should be activated in default, it is just an option.
+ (Boolean) template.getOrDefault("activated", false)
+ )
+ );
+ newTemplate.setDisabled(
+ BooleanUtils.booleanToValue(
+ // The template should be available in default.
+ (Boolean) template.getOrDefault("disabled", false)
+ )
+ );
+ if (uiTemplates.contains(newTemplate)) {
+ throw new IllegalArgumentException("Template " + newTemplate.getName() + " name conflicts");
+ }
+ uiTemplates.add(newTemplate);
+ });
+ }
+ }
+ return uiTemplates;
+ }
+}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/management/ui/template/UITemplateManagementService.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/management/ui/template/UITemplateManagementService.java
new file mode 100644
index 000000000..63e462026
--- /dev/null
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/management/ui/template/UITemplateManagementService.java
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ *
+ */
+
+package org.apache.skywalking.oap.server.core.management.ui.template;
+
+import java.io.IOException;
+import java.util.List;
+import lombok.RequiredArgsConstructor;
+import org.apache.skywalking.oap.server.core.query.input.DashboardSetting;
+import org.apache.skywalking.oap.server.core.query.type.DashboardConfiguration;
+import org.apache.skywalking.oap.server.core.query.type.TemplateChangeStatus;
+import org.apache.skywalking.oap.server.core.storage.StorageModule;
+import org.apache.skywalking.oap.server.core.storage.management.UITemplateManagementDAO;
+import org.apache.skywalking.oap.server.library.module.ModuleManager;
+import org.apache.skywalking.oap.server.library.module.Service;
+
+@RequiredArgsConstructor
+public class UITemplateManagementService implements Service {
+ private final ModuleManager moduleManager;
+ private UITemplateManagementDAO uiTemplateManagementDAO;
+
+ private UITemplateManagementDAO getUITemplateManagementDAO() {
+ if (uiTemplateManagementDAO == null) {
+ this.uiTemplateManagementDAO = moduleManager.find(StorageModule.NAME)
+ .provider()
+ .getService(UITemplateManagementDAO.class);
+ }
+ return uiTemplateManagementDAO;
+ }
+
+ public List getAllTemplates(Boolean includingDisabled) throws IOException {
+ return getUITemplateManagementDAO().getAllTemplates(includingDisabled);
+ }
+
+ public TemplateChangeStatus addTemplate(DashboardSetting setting) throws IOException {
+ return getUITemplateManagementDAO().addTemplate(setting);
+ }
+
+ public TemplateChangeStatus changeTemplate(DashboardSetting setting) throws IOException {
+ return getUITemplateManagementDAO().changeTemplate(setting);
+ }
+
+ public TemplateChangeStatus disableTemplate(String name) throws IOException {
+ return getUITemplateManagementDAO().disableTemplate(name);
+ }
+}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/ProfileTaskMutationService.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/ProfileTaskMutationService.java
index 202d4c734..b2601ab62 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/ProfileTaskMutationService.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/ProfileTaskMutationService.java
@@ -21,11 +21,12 @@ package org.apache.skywalking.oap.server.core.profile;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeUnit;
+import lombok.RequiredArgsConstructor;
import org.apache.skywalking.apm.network.constants.ProfileConstants;
import org.apache.skywalking.apm.util.StringUtil;
import org.apache.skywalking.oap.server.core.analysis.DownSampling;
import org.apache.skywalking.oap.server.core.analysis.TimeBucket;
-import org.apache.skywalking.oap.server.core.analysis.worker.NoneStreamingProcessor;
+import org.apache.skywalking.oap.server.core.analysis.worker.NoneStreamProcessor;
import org.apache.skywalking.oap.server.core.query.type.ProfileTaskCreationResult;
import org.apache.skywalking.oap.server.core.query.type.ProfileTask;
import org.apache.skywalking.oap.server.core.storage.StorageModule;
@@ -34,15 +35,11 @@ import org.apache.skywalking.oap.server.library.module.ModuleManager;
import org.apache.skywalking.oap.server.library.module.Service;
import org.apache.skywalking.oap.server.library.util.CollectionUtils;
+@RequiredArgsConstructor
public class ProfileTaskMutationService implements Service {
-
private final ModuleManager moduleManager;
private IProfileTaskQueryDAO profileTaskQueryDAO;
- public ProfileTaskMutationService(ModuleManager moduleManager) {
- this.moduleManager = moduleManager;
- }
-
private IProfileTaskQueryDAO getProfileTaskDAO() {
if (profileTaskQueryDAO == null) {
this.profileTaskQueryDAO = moduleManager.find(StorageModule.NAME)
@@ -97,7 +94,7 @@ public class ProfileTaskMutationService implements Service {
task.setCreateTime(createTime);
task.setMaxSamplingCount(maxSamplingCount);
task.setTimeBucket(TimeBucket.getRecordTimeBucket(taskEndTime));
- NoneStreamingProcessor.getInstance().in(task);
+ NoneStreamProcessor.getInstance().in(task);
return ProfileTaskCreationResult.builder().id(task.id()).build();
}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/ProfileTaskRecord.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/ProfileTaskRecord.java
index 6ec2fff5c..816c67748 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/ProfileTaskRecord.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/ProfileTaskRecord.java
@@ -25,7 +25,7 @@ import lombok.Setter;
import org.apache.skywalking.oap.server.core.Const;
import org.apache.skywalking.oap.server.core.analysis.Stream;
import org.apache.skywalking.oap.server.core.analysis.config.NoneStream;
-import org.apache.skywalking.oap.server.core.analysis.worker.NoneStreamingProcessor;
+import org.apache.skywalking.oap.server.core.analysis.worker.NoneStreamProcessor;
import org.apache.skywalking.oap.server.core.source.ScopeDeclaration;
import org.apache.skywalking.oap.server.core.storage.StorageBuilder;
import org.apache.skywalking.oap.server.core.storage.annotation.Column;
@@ -38,7 +38,7 @@ import static org.apache.skywalking.oap.server.core.source.DefaultScopeDefine.PR
@Getter
@Setter
@ScopeDeclaration(id = PROFILE_TASK, name = "ProfileTask")
-@Stream(name = ProfileTaskRecord.INDEX_NAME, scopeId = PROFILE_TASK, builder = ProfileTaskRecord.Builder.class, processor = NoneStreamingProcessor.class)
+@Stream(name = ProfileTaskRecord.INDEX_NAME, scopeId = PROFILE_TASK, builder = ProfileTaskRecord.Builder.class, processor = NoneStreamProcessor.class)
public class ProfileTaskRecord extends NoneStream {
public static final String INDEX_NAME = "profile_task";
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/enumeration/TemplateType.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/enumeration/TemplateType.java
new file mode 100644
index 000000000..2d21c1348
--- /dev/null
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/enumeration/TemplateType.java
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ *
+ */
+
+package org.apache.skywalking.oap.server.core.query.enumeration;
+
+public enum TemplateType {
+ DASHBOARD,
+ TOPOLOGY_SERVICE,
+ TOPOLOGY_INSTANCE,
+ TOPOLOGY_ENDPOINT,
+ TOPOLOGY_SERVICE_RELATION,
+ TOPOLOGY_SERVICE_INSTANCE_RELATION;
+
+ public static TemplateType forName(String name) {
+ return Enum.valueOf(TemplateType.class, name.toUpperCase());
+ }
+}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/DashboardSetting.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/DashboardSetting.java
new file mode 100644
index 000000000..f9464d856
--- /dev/null
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/DashboardSetting.java
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ *
+ */
+
+package org.apache.skywalking.oap.server.core.query.input;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.skywalking.oap.server.core.management.ui.template.UITemplate;
+import org.apache.skywalking.oap.server.core.query.enumeration.TemplateType;
+import org.apache.skywalking.oap.server.library.util.BooleanUtils;
+
+@Setter
+@Getter
+public class DashboardSetting {
+ private String name;
+ private TemplateType type;
+ private String configuration;
+ private boolean active;
+
+ public UITemplate toEntity() {
+ UITemplate uiTemplate = new UITemplate();
+ uiTemplate.setName(this.getName());
+ uiTemplate.setConfiguration(this.getConfiguration());
+ uiTemplate.setType(this.getType().name());
+ uiTemplate.setActivated(BooleanUtils.booleanToValue(this.isActive()));
+ uiTemplate.setDisabled(BooleanUtils.FALSE);
+ return uiTemplate;
+ }
+}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/DashboardConfiguration.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/DashboardConfiguration.java
new file mode 100644
index 000000000..e4e2788b8
--- /dev/null
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/DashboardConfiguration.java
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ *
+ */
+
+package org.apache.skywalking.oap.server.core.query.type;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.skywalking.oap.server.core.management.ui.template.UITemplate;
+import org.apache.skywalking.oap.server.core.query.enumeration.TemplateType;
+import org.apache.skywalking.oap.server.library.util.BooleanUtils;
+
+@Setter
+@Getter
+public class DashboardConfiguration {
+ private String name;
+ private TemplateType type;
+ /**
+ * Configuration in JSON format.
+ */
+ private String configuration;
+ private boolean activated;
+ private boolean disabled;
+
+ public DashboardConfiguration fromEntity(UITemplate templateEntity) {
+ this.setName(templateEntity.getName());
+ this.setType(TemplateType.forName(templateEntity.getType()));
+ this.setConfiguration(templateEntity.getConfiguration());
+ this.setActivated(BooleanUtils.valueToBoolean(templateEntity.getActivated()));
+ this.setDisabled(BooleanUtils.valueToBoolean(templateEntity.getDisabled()));
+
+ return this;
+ }
+}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/TemplateChangeStatus.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/TemplateChangeStatus.java
new file mode 100644
index 000000000..8282672da
--- /dev/null
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/TemplateChangeStatus.java
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ *
+ */
+
+package org.apache.skywalking.oap.server.core.query.type;
+
+import lombok.Builder;
+import lombok.Getter;
+import lombok.Setter;
+
+@Setter
+@Getter
+@Builder
+public class TemplateChangeStatus {
+ private boolean status;
+ private String message;
+}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/source/DefaultScopeDefine.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/source/DefaultScopeDefine.java
index 499d51f1b..4883446c7 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/source/DefaultScopeDefine.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/source/DefaultScopeDefine.java
@@ -66,6 +66,7 @@ public class DefaultScopeDefine {
public static final int SERVICE_META = 29;
public static final int SERVICE_INSTANCE_UPDATE = 30;
public static final int NETWORK_ADDRESS_ALIAS = 31;
+ public static final int UI_TEMPLATE = 32;
/**
* Catalog of scope, the metrics processor could use this to group all generated metrics by oal rt.
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/IManagementDAO.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/IManagementDAO.java
new file mode 100644
index 000000000..98c912ef6
--- /dev/null
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/IManagementDAO.java
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ *
+ */
+
+package org.apache.skywalking.oap.server.core.storage;
+
+import java.io.IOException;
+import org.apache.skywalking.oap.server.core.analysis.management.ManagementData;
+import org.apache.skywalking.oap.server.core.storage.model.Model;
+
+/**
+ * Use synchronize storage to insert storage data
+ */
+public interface IManagementDAO extends DAO {
+ void insert(Model model, ManagementData storageData) throws IOException;
+}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/INoneStreamDAO.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/INoneStreamDAO.java
index 64d4da00d..685ef7cf4 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/INoneStreamDAO.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/INoneStreamDAO.java
@@ -26,7 +26,5 @@ import org.apache.skywalking.oap.server.core.storage.model.Model;
* Use synchronize storage to insert none stream data
*/
public interface INoneStreamDAO extends DAO {
-
void insert(Model model, NoneStream noneStream) throws IOException;
-
}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/StorageDAO.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/StorageDAO.java
index 7ee4dfcb8..8f5c722be 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/StorageDAO.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/StorageDAO.java
@@ -19,6 +19,7 @@
package org.apache.skywalking.oap.server.core.storage;
import org.apache.skywalking.oap.server.core.analysis.config.NoneStream;
+import org.apache.skywalking.oap.server.core.analysis.management.ManagementData;
import org.apache.skywalking.oap.server.core.analysis.metrics.Metrics;
import org.apache.skywalking.oap.server.core.analysis.record.Record;
import org.apache.skywalking.oap.server.library.module.Service;
@@ -33,4 +34,6 @@ public interface StorageDAO extends Service {
IRecordDAO newRecordDao(StorageBuilder storageBuilder);
INoneStreamDAO newNoneStreamDao(StorageBuilder storageBuilder);
+
+ IManagementDAO newManagementDao(StorageBuilder storageBuilder);
}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/StorageModule.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/StorageModule.java
index 39dff1f41..1b5b9cd5c 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/StorageModule.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/StorageModule.java
@@ -19,6 +19,7 @@
package org.apache.skywalking.oap.server.core.storage;
import org.apache.skywalking.oap.server.core.storage.cache.INetworkAddressAliasDAO;
+import org.apache.skywalking.oap.server.core.storage.management.UITemplateManagementDAO;
import org.apache.skywalking.oap.server.core.storage.profile.IProfileTaskLogQueryDAO;
import org.apache.skywalking.oap.server.core.storage.profile.IProfileTaskQueryDAO;
import org.apache.skywalking.oap.server.core.storage.profile.IProfileThreadSnapshotQueryDAO;
@@ -46,22 +47,23 @@ public class StorageModule extends ModuleDefine {
@Override
public Class[] services() {
- return new Class[] {
- IBatchDAO.class,
- StorageDAO.class,
- IHistoryDeleteDAO.class,
- INetworkAddressAliasDAO.class,
- ITopologyQueryDAO.class,
- IMetricsQueryDAO.class,
- ITraceQueryDAO.class,
- IMetadataQueryDAO.class,
- IAggregationQueryDAO.class,
- IAlarmQueryDAO.class,
- ITopNRecordsQueryDAO.class,
- ILogQueryDAO.class,
- IProfileTaskQueryDAO.class,
- IProfileTaskLogQueryDAO.class,
- IProfileThreadSnapshotQueryDAO.class
+ return new Class[]{
+ IBatchDAO.class,
+ StorageDAO.class,
+ IHistoryDeleteDAO.class,
+ INetworkAddressAliasDAO.class,
+ ITopologyQueryDAO.class,
+ IMetricsQueryDAO.class,
+ ITraceQueryDAO.class,
+ IMetadataQueryDAO.class,
+ IAggregationQueryDAO.class,
+ IAlarmQueryDAO.class,
+ ITopNRecordsQueryDAO.class,
+ ILogQueryDAO.class,
+ IProfileTaskQueryDAO.class,
+ IProfileTaskLogQueryDAO.class,
+ IProfileThreadSnapshotQueryDAO.class,
+ UITemplateManagementDAO.class
};
}
}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/annotation/Column.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/annotation/Column.java
index 83c6e529c..370e1321a 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/annotation/Column.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/annotation/Column.java
@@ -61,6 +61,10 @@ public @interface Column {
/**
* @return the length of this column, this is only for {@link String} column. The usage of this depends on the
* storage implementation.
+ *
+ * Notice, different lengths may cause different types.
+ * Such as, over 16383 would make the type in MySQL to be MEDIUMTEXT, due to database varchar max=16383
+ *
* @since 7.1.0
*/
int length() default 200;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/management/UITemplateManagementDAO.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/management/UITemplateManagementDAO.java
new file mode 100644
index 000000000..aee1bbbdf
--- /dev/null
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/management/UITemplateManagementDAO.java
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ *
+ */
+
+package org.apache.skywalking.oap.server.core.storage.management;
+
+import java.io.IOException;
+import java.util.List;
+import org.apache.skywalking.oap.server.core.query.input.DashboardSetting;
+import org.apache.skywalking.oap.server.core.query.type.DashboardConfiguration;
+import org.apache.skywalking.oap.server.core.query.type.TemplateChangeStatus;
+import org.apache.skywalking.oap.server.core.storage.DAO;
+
+/**
+ * UI Template management, including CRUD.
+ */
+public interface UITemplateManagementDAO extends DAO {
+ List getAllTemplates(Boolean includingDisabled) throws IOException;
+
+ TemplateChangeStatus addTemplate(DashboardSetting setting) throws IOException;
+
+ TemplateChangeStatus changeTemplate(DashboardSetting setting) throws IOException;
+
+ TemplateChangeStatus disableTemplate(String name) throws IOException;
+}
diff --git a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/CoreModuleTest.java b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/CoreModuleTest.java
index c0756b41c..ba3facc5a 100644
--- a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/CoreModuleTest.java
+++ b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/CoreModuleTest.java
@@ -26,6 +26,6 @@ public class CoreModuleTest {
public void testOpenServiceList() {
CoreModule coreModule = new CoreModule();
- Assert.assertEquals(30, coreModule.services().length);
+ Assert.assertEquals(31, coreModule.services().length);
}
}
diff --git a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/config/group/EndpointGroupingRuleReaderTest.java b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/config/group/EndpointGroupingRuleReaderTest.java
index 93b482513..e1e199be7 100644
--- a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/config/group/EndpointGroupingRuleReaderTest.java
+++ b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/config/group/EndpointGroupingRuleReaderTest.java
@@ -28,7 +28,7 @@ public class EndpointGroupingRuleReaderTest {
EndpointGroupingRuleReader reader = new EndpointGroupingRuleReader(this.getClass()
.getClassLoader()
.getResourceAsStream(
- "endpoint_name_grouping.yml"));
+ "endpoint-name-grouping.yml"));
final EndpointGroupingRule rule = reader.read();
StringFormatGroup.FormatResult formatResult = rule.format("serviceA", "/prod/123");
diff --git a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/management/ui/template/UITemplateInitializerTest.java b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/management/ui/template/UITemplateInitializerTest.java
new file mode 100644
index 000000000..219328516
--- /dev/null
+++ b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/management/ui/template/UITemplateInitializerTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ *
+ */
+
+package org.apache.skywalking.oap.server.core.management.ui.template;
+
+import java.util.List;
+import org.apache.skywalking.oap.server.library.util.BooleanUtils;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class UITemplateInitializerTest {
+ @Test
+ public void testReadFile() {
+ UITemplateInitializer initializer = new UITemplateInitializer(this.getClass()
+ .getClassLoader()
+ .getResourceAsStream(
+ "ui-initialized-templates.yml"));
+ final List uiTemplates = initializer.read();
+
+ Assert.assertEquals(2, uiTemplates.size());
+ UITemplate uiTemplate = uiTemplates.get(0);
+ Assert.assertEquals("APM (Agent based)", uiTemplate.getName());
+ Assert.assertTrue(uiTemplate.getConfiguration().length() > 0);
+ Assert.assertEquals(BooleanUtils.TRUE, uiTemplate.getActivated());
+ Assert.assertEquals(BooleanUtils.FALSE, uiTemplate.getDisabled());
+
+ uiTemplate = uiTemplates.get(1);
+ Assert.assertEquals("APM (Service Mesh)", uiTemplate.getName());
+ Assert.assertTrue(uiTemplate.getConfiguration().length() > 0);
+ Assert.assertEquals(BooleanUtils.FALSE, uiTemplate.getActivated());
+ Assert.assertEquals(BooleanUtils.TRUE, uiTemplate.getDisabled());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testTemplateConflict() {
+ UITemplateInitializer initializer = new UITemplateInitializer(this.getClass()
+ .getClassLoader()
+ .getResourceAsStream(
+ "ui-initialized-templates-conflict.yml"));
+ final List uiTemplates = initializer.read();
+ }
+}
diff --git a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/management/ui/template/UITemplateTest.java b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/management/ui/template/UITemplateTest.java
new file mode 100644
index 000000000..da25400ef
--- /dev/null
+++ b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/management/ui/template/UITemplateTest.java
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ *
+ */
+
+package org.apache.skywalking.oap.server.core.management.ui.template;
+
+import org.apache.skywalking.oap.server.core.query.enumeration.TemplateType;
+import org.apache.skywalking.oap.server.library.util.BooleanUtils;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class UITemplateTest {
+ @Test
+ public void testSerialization() {
+ UITemplate uiTemplate = new UITemplate();
+ uiTemplate.setName("name");
+ uiTemplate.setConfiguration("configuration");
+ uiTemplate.setType(TemplateType.DASHBOARD.name());
+ uiTemplate.setActivated(BooleanUtils.TRUE);
+ uiTemplate.setDisabled(BooleanUtils.FALSE);
+
+ final UITemplate.Builder builder = new UITemplate.Builder();
+ final UITemplate uiTemplate2 = builder.map2Data(builder.data2Map(uiTemplate));
+
+ Assert.assertEquals(uiTemplate, uiTemplate2);
+
+ uiTemplate2.setConfiguration("configuration2");
+ uiTemplate.setType(TemplateType.TOPOLOGY_ENDPOINT.name());
+ uiTemplate.setActivated(BooleanUtils.FALSE);
+ uiTemplate.setDisabled(BooleanUtils.TRUE);
+ // Equals method is only for `name` field.
+ Assert.assertEquals(uiTemplate, uiTemplate2);
+ }
+}
diff --git a/oap-server/server-core/src/test/resources/endpoint_name_grouping.yml b/oap-server/server-core/src/test/resources/endpoint-name-grouping.yml
similarity index 100%
rename from oap-server/server-core/src/test/resources/endpoint_name_grouping.yml
rename to oap-server/server-core/src/test/resources/endpoint-name-grouping.yml
diff --git a/oap-server/server-core/src/test/resources/ui-initialized-templates-conflict.yml b/oap-server/server-core/src/test/resources/ui-initialized-templates-conflict.yml
new file mode 100644
index 000000000..9f55a1c4e
--- /dev/null
+++ b/oap-server/server-core/src/test/resources/ui-initialized-templates-conflict.yml
@@ -0,0 +1,51 @@
+# 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.
+
+# UI templates initialized file includes the default template when the SkyWalking OAP starts up at the first time.
+#
+# Also, SkyWalking would detect the existing templates in the database, once they are missing, all templates in this file
+# could be added automatically.
+
+templates:
+ - name: "APM"
+ # The type includes DASHBOARD, TOPOLOGY_INSTANCE, TOPOLOGY_ENDPOINT.
+ # DASHBOARD type templates could have multiple definitions, by using different names.
+ # TOPOLOGY_INSTANCE, TOPOLOGY_ENDPOINT type templates should be defined once, as they are used in the topology page only.
+ type: "DASHBOARD"
+ # Configuration could be defined through UI, and use `export` to format in the standard JSON.
+ configuration: |-
+ ui exported definition in JSONsdfsd
+ sdjfkasld
+ sdfui
+ skdfj:dafjisa
+ adifaosi
+ # Activated as the DASHBOARD type, makes this templates added into the UI page automatically.
+ # False means providing a basic template, user needs to add it manually.
+ activated: true
+ # True means wouldn't show up on the dashboard. Only keeps the definition in the storage.
+ # disabled: false
+ - name: "APM"
+ # The type includes DASHBOARD, TOPOLOGY_INSTANCE, TOPOLOGY_ENDPOINT.
+ # DASHBOARD type templates could have multiple definitions, by using different names.
+ # TOPOLOGY_INSTANCE, TOPOLOGY_ENDPOINT type templates should be defined once, as they are used in the topology page only.
+ type: "DASHBOARD"
+ # Configuration could be defined through UI, and use `export` to format in the standard JSON.
+ configuration: |-
+ Mesh metrics configuration.
+ # Activated as the DASHBOARD type, makes this templates added into the UI page automatically.
+ # False means providing a basic template, user needs to add it manually.
+ # activated: true
+ # True means wouldn't show up on the dashboard. Only keeps the definition in the storage.
+ disabled: true
diff --git a/oap-server/server-core/src/test/resources/ui-initialized-templates.yml b/oap-server/server-core/src/test/resources/ui-initialized-templates.yml
new file mode 100644
index 000000000..29824914c
--- /dev/null
+++ b/oap-server/server-core/src/test/resources/ui-initialized-templates.yml
@@ -0,0 +1,51 @@
+# 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.
+
+# UI templates initialized file includes the default template when the SkyWalking OAP starts up at the first time.
+#
+# Also, SkyWalking would detect the existing templates in the database, once they are missing, all templates in this file
+# could be added automatically.
+
+templates:
+ - name: "APM (Agent based)"
+ # The type includes DASHBOARD, TOPOLOGY_INSTANCE, TOPOLOGY_ENDPOINT.
+ # DASHBOARD type templates could have multiple definitions, by using different names.
+ # TOPOLOGY_INSTANCE, TOPOLOGY_ENDPOINT type templates should be defined once, as they are used in the topology page only.
+ type: "DASHBOARD"
+ # Configuration could be defined through UI, and use `export` to format in the standard JSON.
+ configuration: |-
+ ui exported definition in JSONsdfsd
+ sdjfkasld
+ sdfui
+ skdfj:dafjisa
+ adifaosi
+ # Activated as the DASHBOARD type, makes this templates added into the UI page automatically.
+ # False means providing a basic template, user needs to add it manually.
+ activated: true
+ # True means wouldn't show up on the dashboard. Only keeps the definition in the storage.
+ # disable: false
+ - name: "APM (Service Mesh)"
+ # The type includes DASHBOARD, TOPOLOGY_INSTANCE, TOPOLOGY_ENDPOINT.
+ # DASHBOARD type templates could have multiple definitions, by using different names.
+ # TOPOLOGY_INSTANCE, TOPOLOGY_ENDPOINT type templates should be defined once, as they are used in the topology page only.
+ type: "DASHBOARD"
+ # Configuration could be defined through UI, and use `export` to format in the standard JSON.
+ configuration: |-
+ Mesh metrics configuration.
+ # Activated as the DASHBOARD type, makes this templates added into the UI page automatically.
+ # False means providing a basic template, user needs to add it manually.
+ # activated: true
+ # True means wouldn't show up on the dashboard. Only keeps the definition in the storage.
+ disabled: true
diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/GraphQLQueryProvider.java b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/GraphQLQueryProvider.java
index ddcf10309..7a5ba9136 100644
--- a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/GraphQLQueryProvider.java
+++ b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/GraphQLQueryProvider.java
@@ -34,6 +34,7 @@ import org.apache.skywalking.oap.query.graphql.resolver.Query;
import org.apache.skywalking.oap.query.graphql.resolver.TopNRecordsQuery;
import org.apache.skywalking.oap.query.graphql.resolver.TopologyQuery;
import org.apache.skywalking.oap.query.graphql.resolver.TraceQuery;
+import org.apache.skywalking.oap.query.graphql.resolver.UIConfigurationManagement;
import org.apache.skywalking.oap.server.core.CoreModule;
import org.apache.skywalking.oap.server.core.query.QueryModule;
import org.apache.skywalking.oap.server.core.server.JettyHandlerRegister;
@@ -70,46 +71,48 @@ public class GraphQLQueryProvider extends ModuleProvider {
@Override
public void prepare() throws ServiceNotProvidedException, ModuleStartException {
GraphQLSchema schema = SchemaParser.newParser()
- .file("query-protocol/common.graphqls")
- .resolvers(new Query(), new Mutation())
- .file("query-protocol/metadata.graphqls")
- .resolvers(new MetadataQuery(getManager()))
- .file("query-protocol/topology.graphqls")
- .resolvers(new TopologyQuery(getManager()))
- /**
- * Metrics v2 query protocol is an alternative metrics query(s) of original v1,
- * defined in the metric.graphql, top-n-records.graphqls, and aggregation.graphqls.
- */
- .file("query-protocol/metrics-v2.graphqls")
- .resolvers(new MetricsQuery(getManager()))
- ////////
- //Deprecated Queries
- ////////
- .file("query-protocol/metric.graphqls")
- .resolvers(new MetricQuery(getManager()))
- .file("query-protocol/aggregation.graphqls")
- .resolvers(new AggregationQuery(getManager()))
- .file("query-protocol/top-n-records.graphqls")
- .resolvers(new TopNRecordsQuery(getManager()))
- ////////
- .file("query-protocol/trace.graphqls")
- .resolvers(new TraceQuery(getManager()))
- .file("query-protocol/alarm.graphqls")
- .resolvers(new AlarmQuery(getManager()))
- .file("query-protocol/log.graphqls")
- .resolvers(new LogQuery(getManager()))
- .file("query-protocol/profile.graphqls")
- .resolvers(new ProfileQuery(getManager()), new ProfileMutation(getManager()))
- .build()
- .makeExecutableSchema();
+ .file("query-protocol/common.graphqls")
+ .resolvers(new Query(), new Mutation())
+ .file("query-protocol/metadata.graphqls")
+ .resolvers(new MetadataQuery(getManager()))
+ .file("query-protocol/topology.graphqls")
+ .resolvers(new TopologyQuery(getManager()))
+ /**
+ * Metrics v2 query protocol is an alternative metrics query(s) of original v1,
+ * defined in the metric.graphql, top-n-records.graphqls, and aggregation.graphqls.
+ */
+ .file("query-protocol/metrics-v2.graphqls")
+ .resolvers(new MetricsQuery(getManager()))
+ ////////
+ //Deprecated Queries
+ ////////
+ .file("query-protocol/metric.graphqls")
+ .resolvers(new MetricQuery(getManager()))
+ .file("query-protocol/aggregation.graphqls")
+ .resolvers(new AggregationQuery(getManager()))
+ .file("query-protocol/top-n-records.graphqls")
+ .resolvers(new TopNRecordsQuery(getManager()))
+ ////////
+ .file("query-protocol/trace.graphqls")
+ .resolvers(new TraceQuery(getManager()))
+ .file("query-protocol/alarm.graphqls")
+ .resolvers(new AlarmQuery(getManager()))
+ .file("query-protocol/log.graphqls")
+ .resolvers(new LogQuery(getManager()))
+ .file("query-protocol/profile.graphqls")
+ .resolvers(new ProfileQuery(getManager()), new ProfileMutation(getManager()))
+ .file("query-protocol/ui-configuration.graphqls")
+ .resolvers(new UIConfigurationManagement(getManager()))
+ .build()
+ .makeExecutableSchema();
this.graphQL = GraphQL.newGraphQL(schema).build();
}
@Override
public void start() throws ServiceNotProvidedException, ModuleStartException {
JettyHandlerRegister service = getManager().find(CoreModule.NAME)
- .provider()
- .getService(JettyHandlerRegister.class);
+ .provider()
+ .getService(JettyHandlerRegister.class);
service.addHandler(new GraphQLQueryHandler(config.getPath(), graphQL));
}
diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/UIConfigurationManagement.java b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/UIConfigurationManagement.java
new file mode 100644
index 000000000..72fe59575
--- /dev/null
+++ b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/UIConfigurationManagement.java
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ *
+ */
+
+package org.apache.skywalking.oap.query.graphql.resolver;
+
+import com.coxautodev.graphql.tools.GraphQLMutationResolver;
+import com.coxautodev.graphql.tools.GraphQLQueryResolver;
+import java.io.IOException;
+import java.util.List;
+import lombok.RequiredArgsConstructor;
+import org.apache.skywalking.oap.server.core.CoreModule;
+import org.apache.skywalking.oap.server.core.management.ui.template.UITemplateManagementService;
+import org.apache.skywalking.oap.server.core.query.input.DashboardSetting;
+import org.apache.skywalking.oap.server.core.query.type.DashboardConfiguration;
+import org.apache.skywalking.oap.server.core.query.type.TemplateChangeStatus;
+import org.apache.skywalking.oap.server.library.module.ModuleManager;
+
+/**
+ * UI Configuration including dashboard, topology pop up page, is based on the available templates or manual configuration.
+ * UIConfigurationManagement provides the query and operations of templates.
+ *
+ * @since 8.0.0
+ */
+@RequiredArgsConstructor
+public class UIConfigurationManagement implements GraphQLQueryResolver, GraphQLMutationResolver {
+ private final ModuleManager manager;
+ private UITemplateManagementService uiTemplateManagementService;
+
+ private UITemplateManagementService getUITemplateManagementService() {
+ if (uiTemplateManagementService == null) {
+ this.uiTemplateManagementService = manager.find(CoreModule.NAME)
+ .provider()
+ .getService(UITemplateManagementService.class);
+ }
+ return uiTemplateManagementService;
+ }
+
+ public List getAllTemplates(Boolean includingDisabled) throws IOException {
+ if (includingDisabled == null) {
+ includingDisabled = false;
+ }
+ return getUITemplateManagementService().getAllTemplates(includingDisabled);
+ }
+
+ public TemplateChangeStatus addTemplate(DashboardSetting setting) throws IOException {
+ return getUITemplateManagementService().addTemplate(setting);
+ }
+
+ public TemplateChangeStatus changeTemplate(DashboardSetting setting) throws IOException {
+ return getUITemplateManagementService().changeTemplate(setting);
+ }
+
+ public TemplateChangeStatus disableTemplate(String name) throws IOException {
+ return getUITemplateManagementService().disableTemplate(name);
+ }
+}
diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/main/resources/query-protocol b/oap-server/server-query-plugin/query-graphql-plugin/src/main/resources/query-protocol
index 3f44392c3..0b38f4e16 160000
--- a/oap-server/server-query-plugin/query-graphql-plugin/src/main/resources/query-protocol
+++ b/oap-server/server-query-plugin/query-graphql-plugin/src/main/resources/query-protocol
@@ -1 +1 @@
-Subproject commit 3f44392c3b3502b4f3066e7ec89c794bc9ffb54d
+Subproject commit 0b38f4e1620ef66e6d9121845b2a55b090d2020f
diff --git a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/StorageModuleElasticsearchProvider.java b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/StorageModuleElasticsearchProvider.java
index e5f51fb4f..9f591cbc8 100644
--- a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/StorageModuleElasticsearchProvider.java
+++ b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/StorageModuleElasticsearchProvider.java
@@ -35,6 +35,7 @@ import org.apache.skywalking.oap.server.core.storage.StorageDAO;
import org.apache.skywalking.oap.server.core.storage.StorageException;
import org.apache.skywalking.oap.server.core.storage.StorageModule;
import org.apache.skywalking.oap.server.core.storage.cache.INetworkAddressAliasDAO;
+import org.apache.skywalking.oap.server.core.storage.management.UITemplateManagementDAO;
import org.apache.skywalking.oap.server.core.storage.model.ModelCreator;
import org.apache.skywalking.oap.server.core.storage.profile.IProfileTaskLogQueryDAO;
import org.apache.skywalking.oap.server.core.storage.profile.IProfileTaskQueryDAO;
@@ -72,6 +73,7 @@ import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.Profi
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.TopNRecordsQueryEsDAO;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.TopologyQueryEsDAO;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.TraceQueryEsDAO;
+import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.UITemplateManagementEsDAO;
/**
* The storage provider for ElasticSearch 6.
@@ -112,7 +114,7 @@ public class StorageModuleElasticsearchProvider extends ModuleProvider {
if (!StringUtil.isEmpty(config.getSecretsManagementFile())) {
MultipleFilesChangeMonitor monitor = new MultipleFilesChangeMonitor(
- 10, readableContents -> {
+ 10, readableContents -> {
final byte[] secretsFileContent = readableContents.get(0);
if (secretsFileContent == null) {
return;
@@ -140,39 +142,41 @@ public class StorageModuleElasticsearchProvider extends ModuleProvider {
}
elasticSearchClient = new ElasticSearchClient(
- config.getClusterNodes(), config.getProtocol(), config.getTrustStorePath(), config
- .getTrustStorePass(), config.getUser(), config.getPassword(),
- indexNameConverters(config.getNameSpace())
+ config.getClusterNodes(), config.getProtocol(), config.getTrustStorePath(), config
+ .getTrustStorePass(), config.getUser(), config.getPassword(),
+ indexNameConverters(config.getNameSpace())
);
this.registerServiceImplementation(
- IBatchDAO.class, new BatchProcessEsDAO(elasticSearchClient, config.getBulkActions(), config
- .getFlushInterval(), config.getConcurrentRequests()));
+ IBatchDAO.class, new BatchProcessEsDAO(elasticSearchClient, config.getBulkActions(), config
+ .getFlushInterval(), config.getConcurrentRequests()));
this.registerServiceImplementation(StorageDAO.class, new StorageEsDAO(elasticSearchClient));
this.registerServiceImplementation(
- IHistoryDeleteDAO.class, new HistoryDeleteEsDAO(elasticSearchClient));
+ IHistoryDeleteDAO.class, new HistoryDeleteEsDAO(elasticSearchClient));
this.registerServiceImplementation(
- INetworkAddressAliasDAO.class, new NetworkAddressAliasEsDAO(elasticSearchClient, config
- .getResultWindowMaxSize()));
+ INetworkAddressAliasDAO.class, new NetworkAddressAliasEsDAO(elasticSearchClient, config
+ .getResultWindowMaxSize()));
this.registerServiceImplementation(ITopologyQueryDAO.class, new TopologyQueryEsDAO(elasticSearchClient));
this.registerServiceImplementation(IMetricsQueryDAO.class, new MetricsQueryEsDAO(elasticSearchClient));
this.registerServiceImplementation(
- ITraceQueryDAO.class, new TraceQueryEsDAO(elasticSearchClient, config.getSegmentQueryMaxSize()));
+ ITraceQueryDAO.class, new TraceQueryEsDAO(elasticSearchClient, config.getSegmentQueryMaxSize()));
this.registerServiceImplementation(
- IMetadataQueryDAO.class, new MetadataQueryEsDAO(elasticSearchClient, config.getMetadataQueryMaxSize()));
+ IMetadataQueryDAO.class, new MetadataQueryEsDAO(elasticSearchClient, config.getMetadataQueryMaxSize()));
this.registerServiceImplementation(IAggregationQueryDAO.class, new AggregationQueryEsDAO(elasticSearchClient));
this.registerServiceImplementation(IAlarmQueryDAO.class, new AlarmQueryEsDAO(elasticSearchClient));
this.registerServiceImplementation(ITopNRecordsQueryDAO.class, new TopNRecordsQueryEsDAO(elasticSearchClient));
this.registerServiceImplementation(ILogQueryDAO.class, new LogQueryEsDAO(elasticSearchClient));
this.registerServiceImplementation(
- IProfileTaskQueryDAO.class, new ProfileTaskQueryEsDAO(elasticSearchClient, config
- .getProfileTaskQueryMaxSize()));
+ IProfileTaskQueryDAO.class, new ProfileTaskQueryEsDAO(elasticSearchClient, config
+ .getProfileTaskQueryMaxSize()));
this.registerServiceImplementation(
- IProfileTaskLogQueryDAO.class, new ProfileTaskLogEsDAO(elasticSearchClient, config
- .getProfileTaskQueryMaxSize()));
+ IProfileTaskLogQueryDAO.class, new ProfileTaskLogEsDAO(elasticSearchClient, config
+ .getProfileTaskQueryMaxSize()));
this.registerServiceImplementation(
- IProfileThreadSnapshotQueryDAO.class, new ProfileThreadSnapshotQueryEsDAO(elasticSearchClient, config
- .getProfileTaskQueryMaxSize()));
+ IProfileThreadSnapshotQueryDAO.class, new ProfileThreadSnapshotQueryEsDAO(elasticSearchClient, config
+ .getProfileTaskQueryMaxSize()));
+ this.registerServiceImplementation(
+ UITemplateManagementDAO.class, new UITemplateManagementEsDAO(elasticSearchClient));
}
@Override
@@ -193,7 +197,7 @@ public class StorageModuleElasticsearchProvider extends ModuleProvider {
@Override
public String[] requiredModules() {
- return new String[] {CoreModule.NAME};
+ return new String[]{CoreModule.NAME};
}
public static List indexNameConverters(String namespace) {
diff --git a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/base/ManagementEsDAO.java b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/base/ManagementEsDAO.java
new file mode 100644
index 000000000..604043a1a
--- /dev/null
+++ b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/base/ManagementEsDAO.java
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ *
+ */
+
+package org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base;
+
+import java.io.IOException;
+import org.apache.skywalking.oap.server.core.analysis.management.ManagementData;
+import org.apache.skywalking.oap.server.core.storage.IManagementDAO;
+import org.apache.skywalking.oap.server.core.storage.StorageBuilder;
+import org.apache.skywalking.oap.server.core.storage.model.Model;
+import org.apache.skywalking.oap.server.library.client.elasticsearch.ElasticSearchClient;
+import org.elasticsearch.action.get.GetResponse;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+
+public class ManagementEsDAO extends EsDAO implements IManagementDAO {
+ private final StorageBuilder storageBuilder;
+
+ public ManagementEsDAO(ElasticSearchClient client, StorageBuilder storageBuilder) {
+ super(client);
+ this.storageBuilder = storageBuilder;
+ }
+
+ @Override
+ public void insert(Model model, ManagementData managementData) throws IOException {
+ String modelName = model.getName();
+ final String id = managementData.id();
+ final GetResponse response = getClient().get(modelName, id);
+ if (response.isExists()) {
+ return;
+ }
+
+ XContentBuilder builder = map2builder(storageBuilder.data2Map(managementData));
+ getClient().forceInsert(modelName, id, builder);
+ }
+}
\ No newline at end of file
diff --git a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/base/StorageEsDAO.java b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/base/StorageEsDAO.java
index b006055fc..08af9e62d 100644
--- a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/base/StorageEsDAO.java
+++ b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/base/StorageEsDAO.java
@@ -19,8 +19,10 @@
package org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base;
import org.apache.skywalking.oap.server.core.analysis.config.NoneStream;
+import org.apache.skywalking.oap.server.core.analysis.management.ManagementData;
import org.apache.skywalking.oap.server.core.analysis.metrics.Metrics;
import org.apache.skywalking.oap.server.core.analysis.record.Record;
+import org.apache.skywalking.oap.server.core.storage.IManagementDAO;
import org.apache.skywalking.oap.server.core.storage.IMetricsDAO;
import org.apache.skywalking.oap.server.core.storage.INoneStreamDAO;
import org.apache.skywalking.oap.server.core.storage.IRecordDAO;
@@ -48,4 +50,9 @@ public class StorageEsDAO extends EsDAO implements StorageDAO {
public INoneStreamDAO newNoneStreamDao(StorageBuilder storageBuilder) {
return new NoneStreamEsDAO(getClient(), storageBuilder);
}
+
+ @Override
+ public IManagementDAO newManagementDao(final StorageBuilder storageBuilder) {
+ return new ManagementEsDAO(getClient(), storageBuilder);
+ }
}
diff --git a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/UITemplateManagementEsDAO.java b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/UITemplateManagementEsDAO.java
new file mode 100644
index 000000000..f926d32aa
--- /dev/null
+++ b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/UITemplateManagementEsDAO.java
@@ -0,0 +1,129 @@
+/*
+ * 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.
+ *
+ */
+
+package org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.skywalking.oap.server.core.management.ui.template.UITemplate;
+import org.apache.skywalking.oap.server.core.query.input.DashboardSetting;
+import org.apache.skywalking.oap.server.core.query.type.DashboardConfiguration;
+import org.apache.skywalking.oap.server.core.query.type.TemplateChangeStatus;
+import org.apache.skywalking.oap.server.core.storage.management.UITemplateManagementDAO;
+import org.apache.skywalking.oap.server.library.client.elasticsearch.ElasticSearchClient;
+import org.apache.skywalking.oap.server.library.util.BooleanUtils;
+import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base.EsDAO;
+import org.elasticsearch.action.get.GetResponse;
+import org.elasticsearch.action.search.SearchResponse;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.index.query.BoolQueryBuilder;
+import org.elasticsearch.index.query.QueryBuilders;
+import org.elasticsearch.search.SearchHit;
+import org.elasticsearch.search.builder.SearchSourceBuilder;
+
+@Slf4j
+public class UITemplateManagementEsDAO extends EsDAO implements UITemplateManagementDAO {
+ public UITemplateManagementEsDAO(ElasticSearchClient client) {
+ super(client);
+ }
+
+ @Override
+ public List getAllTemplates(final Boolean includingDisabled) throws IOException {
+ SearchSourceBuilder sourceBuilder = SearchSourceBuilder.searchSource();
+
+ BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
+ if (!includingDisabled) {
+ boolQueryBuilder.must().add(QueryBuilders.termQuery(UITemplate.DISABLED, BooleanUtils.booleanToValue(includingDisabled)));
+ }
+
+ sourceBuilder.query(boolQueryBuilder);
+ //It is impossible we have 10000+ templates.
+ sourceBuilder.size(10000);
+
+ SearchResponse response = getClient().search(UITemplate.INDEX_NAME, sourceBuilder);
+
+ List configs = new ArrayList<>();
+ final UITemplate.Builder builder = new UITemplate.Builder();
+ for (SearchHit searchHit : response.getHits()) {
+ Map sourceAsMap = searchHit.getSourceAsMap();
+
+ final UITemplate uiTemplate = builder.map2Data(sourceAsMap);
+ configs.add(new DashboardConfiguration().fromEntity(uiTemplate));
+ }
+ return configs;
+ }
+
+ @Override
+ public TemplateChangeStatus addTemplate(final DashboardSetting setting) throws IOException {
+ try {
+ final UITemplate.Builder builder = new UITemplate.Builder();
+ final UITemplate uiTemplate = setting.toEntity();
+
+ final GetResponse response = getClient().get(UITemplate.INDEX_NAME, uiTemplate.id());
+ if (response.isExists()) {
+ return TemplateChangeStatus.builder().status(false).message("Template exists").build();
+ }
+
+ XContentBuilder xContentBuilder = map2builder(builder.data2Map(uiTemplate));
+ getClient().forceInsert(UITemplate.INDEX_NAME, uiTemplate.id(), xContentBuilder);
+ return TemplateChangeStatus.builder().status(true).build();
+ } catch (IOException e) {
+ log.error(e.getMessage(), e);
+ return TemplateChangeStatus.builder().status(false).message("Can't add a new template").build();
+ }
+ }
+
+ @Override
+ public TemplateChangeStatus changeTemplate(final DashboardSetting setting) throws IOException {
+ try {
+ final UITemplate.Builder builder = new UITemplate.Builder();
+ final UITemplate uiTemplate = setting.toEntity();
+
+ final GetResponse response = getClient().get(UITemplate.INDEX_NAME, uiTemplate.id());
+ if (!response.isExists()) {
+ return TemplateChangeStatus.builder().status(false).message("Can't find the template").build();
+ }
+
+ XContentBuilder xContentBuilder = map2builder(builder.data2Map(uiTemplate));
+ getClient().forceUpdate(UITemplate.INDEX_NAME, uiTemplate.id(), xContentBuilder);
+ return TemplateChangeStatus.builder().status(true).build();
+ } catch (IOException e) {
+ log.error(e.getMessage(), e);
+ return TemplateChangeStatus.builder().status(false).message("Can't find the template").build();
+ }
+ }
+
+ @Override
+ public TemplateChangeStatus disableTemplate(final String name) throws IOException {
+ final GetResponse response = getClient().get(UITemplate.INDEX_NAME, name);
+ if (response.isExists()) {
+ final UITemplate.Builder builder = new UITemplate.Builder();
+ final UITemplate uiTemplate = builder.map2Data(response.getSourceAsMap());
+ uiTemplate.setDisabled(BooleanUtils.TRUE);
+
+ XContentBuilder xContentBuilder = map2builder(builder.data2Map(uiTemplate));
+ getClient().forceUpdate(UITemplate.INDEX_NAME, uiTemplate.id(), xContentBuilder);
+ return TemplateChangeStatus.builder().status(true).build();
+ } else {
+ return TemplateChangeStatus.builder().status(false).message("Can't find the template").build();
+ }
+ }
+}
diff --git a/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/StorageModuleElasticsearch7Provider.java b/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/StorageModuleElasticsearch7Provider.java
index aa740df0c..c69d399cb 100644
--- a/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/StorageModuleElasticsearch7Provider.java
+++ b/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/StorageModuleElasticsearch7Provider.java
@@ -33,6 +33,7 @@ import org.apache.skywalking.oap.server.core.storage.StorageDAO;
import org.apache.skywalking.oap.server.core.storage.StorageException;
import org.apache.skywalking.oap.server.core.storage.StorageModule;
import org.apache.skywalking.oap.server.core.storage.cache.INetworkAddressAliasDAO;
+import org.apache.skywalking.oap.server.core.storage.management.UITemplateManagementDAO;
import org.apache.skywalking.oap.server.core.storage.model.ModelCreator;
import org.apache.skywalking.oap.server.core.storage.profile.IProfileTaskLogQueryDAO;
import org.apache.skywalking.oap.server.core.storage.profile.IProfileTaskQueryDAO;
@@ -58,6 +59,7 @@ import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.Profi
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.ProfileTaskQueryEsDAO;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.TopNRecordsQueryEsDAO;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.TopologyQueryEsDAO;
+import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.UITemplateManagementEsDAO;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch7.base.StorageEs7Installer;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch7.client.ElasticSearch7Client;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch7.dao.StorageEs7DAO;
@@ -106,7 +108,7 @@ public class StorageModuleElasticsearch7Provider extends ModuleProvider {
}
if (!StringUtil.isEmpty(config.getSecretsManagementFile())) {
MultipleFilesChangeMonitor monitor = new MultipleFilesChangeMonitor(
- 10, readableContents -> {
+ 10, readableContents -> {
final byte[] secretsFileContent = readableContents.get(0);
if (secretsFileContent == null) {
return;
@@ -134,50 +136,52 @@ public class StorageModuleElasticsearch7Provider extends ModuleProvider {
}
elasticSearch7Client = new ElasticSearch7Client(
- config.getClusterNodes(), config.getProtocol(), config.getTrustStorePath(), config
- .getTrustStorePass(), config.getUser(), config.getPassword(),
- indexNameConverters(config.getNameSpace())
+ config.getClusterNodes(), config.getProtocol(), config.getTrustStorePath(), config
+ .getTrustStorePass(), config.getUser(), config.getPassword(),
+ indexNameConverters(config.getNameSpace())
);
this.registerServiceImplementation(
- IBatchDAO.class, new BatchProcessEsDAO(elasticSearch7Client, config.getBulkActions(),
- config.getFlushInterval(), config.getConcurrentRequests()
- ));
+ IBatchDAO.class, new BatchProcessEsDAO(elasticSearch7Client, config.getBulkActions(),
+ config.getFlushInterval(), config.getConcurrentRequests()
+ ));
this.registerServiceImplementation(StorageDAO.class, new StorageEs7DAO(elasticSearch7Client));
this.registerServiceImplementation(
- IHistoryDeleteDAO.class, new HistoryDeleteEsDAO(elasticSearch7Client));
+ IHistoryDeleteDAO.class, new HistoryDeleteEsDAO(elasticSearch7Client));
this.registerServiceImplementation(
- INetworkAddressAliasDAO.class, new NetworkAddressAliasEsDAO(
- elasticSearch7Client,
- config.getResultWindowMaxSize()
- ));
+ INetworkAddressAliasDAO.class, new NetworkAddressAliasEsDAO(
+ elasticSearch7Client,
+ config.getResultWindowMaxSize()
+ ));
this.registerServiceImplementation(ITopologyQueryDAO.class, new TopologyQueryEsDAO(elasticSearch7Client));
this.registerServiceImplementation(IMetricsQueryDAO.class, new MetricsQueryEs7DAO(elasticSearch7Client));
this.registerServiceImplementation(
- ITraceQueryDAO.class, new TraceQueryEs7DAO(elasticSearch7Client, config.getSegmentQueryMaxSize()));
+ ITraceQueryDAO.class, new TraceQueryEs7DAO(elasticSearch7Client, config.getSegmentQueryMaxSize()));
this.registerServiceImplementation(
- IMetadataQueryDAO.class, new MetadataQueryEs7DAO(elasticSearch7Client, config.getMetadataQueryMaxSize()));
+ IMetadataQueryDAO.class, new MetadataQueryEs7DAO(elasticSearch7Client, config.getMetadataQueryMaxSize()));
this.registerServiceImplementation(
- IAggregationQueryDAO.class, new AggregationQueryEs7DAO(elasticSearch7Client));
+ IAggregationQueryDAO.class, new AggregationQueryEs7DAO(elasticSearch7Client));
this.registerServiceImplementation(IAlarmQueryDAO.class, new AlarmQueryEs7DAO(elasticSearch7Client));
this.registerServiceImplementation(ITopNRecordsQueryDAO.class, new TopNRecordsQueryEsDAO(elasticSearch7Client));
this.registerServiceImplementation(ILogQueryDAO.class, new LogQueryEs7DAO(elasticSearch7Client));
this.registerServiceImplementation(
- IProfileTaskQueryDAO.class, new ProfileTaskQueryEsDAO(
- elasticSearch7Client,
- config.getProfileTaskQueryMaxSize()
- ));
+ IProfileTaskQueryDAO.class, new ProfileTaskQueryEsDAO(
+ elasticSearch7Client,
+ config.getProfileTaskQueryMaxSize()
+ ));
this.registerServiceImplementation(
- IProfileTaskLogQueryDAO.class, new ProfileTaskLogEsDAO(
- elasticSearch7Client,
- config.getProfileTaskQueryMaxSize()
- ));
+ IProfileTaskLogQueryDAO.class, new ProfileTaskLogEsDAO(
+ elasticSearch7Client,
+ config.getProfileTaskQueryMaxSize()
+ ));
this.registerServiceImplementation(
- IProfileThreadSnapshotQueryDAO.class, new ProfileThreadSnapshotQueryEs7DAO(
- elasticSearch7Client,
- config.getProfileTaskQueryMaxSize()
- ));
+ IProfileThreadSnapshotQueryDAO.class, new ProfileThreadSnapshotQueryEs7DAO(
+ elasticSearch7Client,
+ config.getProfileTaskQueryMaxSize()
+ ));
+ this.registerServiceImplementation(
+ UITemplateManagementDAO.class, new UITemplateManagementEsDAO(elasticSearch7Client));
}
@Override
@@ -198,6 +202,6 @@ public class StorageModuleElasticsearch7Provider extends ModuleProvider {
@Override
public String[] requiredModules() {
- return new String[] {CoreModule.NAME};
+ return new String[]{CoreModule.NAME};
}
}
diff --git a/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/dao/StorageEs7DAO.java b/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/dao/StorageEs7DAO.java
index 60655ff37..5161e0a5d 100644
--- a/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/dao/StorageEs7DAO.java
+++ b/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/dao/StorageEs7DAO.java
@@ -19,8 +19,10 @@
package org.apache.skywalking.oap.server.storage.plugin.elasticsearch7.dao;
import org.apache.skywalking.oap.server.core.analysis.config.NoneStream;
+import org.apache.skywalking.oap.server.core.analysis.management.ManagementData;
import org.apache.skywalking.oap.server.core.analysis.metrics.Metrics;
import org.apache.skywalking.oap.server.core.analysis.record.Record;
+import org.apache.skywalking.oap.server.core.storage.IManagementDAO;
import org.apache.skywalking.oap.server.core.storage.IMetricsDAO;
import org.apache.skywalking.oap.server.core.storage.INoneStreamDAO;
import org.apache.skywalking.oap.server.core.storage.IRecordDAO;
@@ -28,6 +30,7 @@ import org.apache.skywalking.oap.server.core.storage.StorageBuilder;
import org.apache.skywalking.oap.server.core.storage.StorageDAO;
import org.apache.skywalking.oap.server.library.client.elasticsearch.ElasticSearchClient;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base.EsDAO;
+import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base.ManagementEsDAO;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base.NoneStreamEsDAO;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base.RecordEsDAO;
@@ -51,4 +54,9 @@ public class StorageEs7DAO extends EsDAO implements StorageDAO {
public INoneStreamDAO newNoneStreamDao(StorageBuilder storageBuilder) {
return new NoneStreamEsDAO(getClient(), storageBuilder);
}
+
+ @Override
+ public IManagementDAO newManagementDao(final StorageBuilder storageBuilder) {
+ return new ManagementEsDAO(getClient(), storageBuilder);
+ }
}
diff --git a/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/InfluxStorageProvider.java b/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/InfluxStorageProvider.java
index 380ca1d69..13d7edab1 100644
--- a/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/InfluxStorageProvider.java
+++ b/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/InfluxStorageProvider.java
@@ -26,6 +26,7 @@ import org.apache.skywalking.oap.server.core.storage.StorageDAO;
import org.apache.skywalking.oap.server.core.storage.StorageException;
import org.apache.skywalking.oap.server.core.storage.StorageModule;
import org.apache.skywalking.oap.server.core.storage.cache.INetworkAddressAliasDAO;
+import org.apache.skywalking.oap.server.core.storage.management.UITemplateManagementDAO;
import org.apache.skywalking.oap.server.core.storage.model.ModelCreator;
import org.apache.skywalking.oap.server.core.storage.profile.IProfileTaskLogQueryDAO;
import org.apache.skywalking.oap.server.core.storage.profile.IProfileTaskQueryDAO;
@@ -58,6 +59,7 @@ import org.apache.skywalking.oap.server.storage.plugin.influxdb.query.ProfileThr
import org.apache.skywalking.oap.server.storage.plugin.influxdb.query.TopNRecordsQuery;
import org.apache.skywalking.oap.server.storage.plugin.influxdb.query.TopologyQuery;
import org.apache.skywalking.oap.server.storage.plugin.influxdb.query.TraceQuery;
+import org.apache.skywalking.oap.server.storage.plugin.influxdb.query.UITemplateManagementDAOImpl;
@Slf4j
public class InfluxStorageProvider extends ModuleProvider {
@@ -103,12 +105,13 @@ public class InfluxStorageProvider extends ModuleProvider {
this.registerServiceImplementation(IProfileTaskQueryDAO.class, new ProfileTaskQuery(client));
this.registerServiceImplementation(
- IProfileThreadSnapshotQueryDAO.class, new ProfileThreadSnapshotQuery(client));
+ IProfileThreadSnapshotQueryDAO.class, new ProfileThreadSnapshotQuery(client));
this.registerServiceImplementation(
- IProfileTaskLogQueryDAO.class, new ProfileTaskLogQuery(client, config.getFetchTaskLogMaxSize()));
+ IProfileTaskLogQueryDAO.class, new ProfileTaskLogQuery(client, config.getFetchTaskLogMaxSize()));
this.registerServiceImplementation(
- IHistoryDeleteDAO.class, new HistoryDeleteDAO(client));
+ IHistoryDeleteDAO.class, new HistoryDeleteDAO(client));
+ this.registerServiceImplementation(UITemplateManagementDAO.class, new UITemplateManagementDAOImpl(client));
}
@Override
@@ -130,6 +133,6 @@ public class InfluxStorageProvider extends ModuleProvider {
@Override
public String[] requiredModules() {
- return new String[] {CoreModule.NAME};
+ return new String[]{CoreModule.NAME};
}
}
diff --git a/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/base/InfluxStorageDAO.java b/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/base/InfluxStorageDAO.java
index 77e69edb9..45553d09c 100644
--- a/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/base/InfluxStorageDAO.java
+++ b/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/base/InfluxStorageDAO.java
@@ -19,8 +19,10 @@
package org.apache.skywalking.oap.server.storage.plugin.influxdb.base;
import org.apache.skywalking.oap.server.core.analysis.config.NoneStream;
+import org.apache.skywalking.oap.server.core.analysis.management.ManagementData;
import org.apache.skywalking.oap.server.core.analysis.metrics.Metrics;
import org.apache.skywalking.oap.server.core.analysis.record.Record;
+import org.apache.skywalking.oap.server.core.storage.IManagementDAO;
import org.apache.skywalking.oap.server.core.storage.IMetricsDAO;
import org.apache.skywalking.oap.server.core.storage.INoneStreamDAO;
import org.apache.skywalking.oap.server.core.storage.IRecordDAO;
@@ -49,4 +51,9 @@ public class InfluxStorageDAO implements StorageDAO {
public INoneStreamDAO newNoneStreamDao(StorageBuilder storageBuilder) {
return new NoneStreamDAO(influxClient, storageBuilder);
}
+
+ @Override
+ public IManagementDAO newManagementDao(final StorageBuilder storageBuilder) {
+ return new ManagementDAO(influxClient, storageBuilder);
+ }
}
diff --git a/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/base/ManagementDAO.java b/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/base/ManagementDAO.java
new file mode 100644
index 000000000..b45bc41e5
--- /dev/null
+++ b/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/base/ManagementDAO.java
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ *
+ */
+
+package org.apache.skywalking.oap.server.storage.plugin.influxdb.base;
+
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.skywalking.oap.server.core.analysis.management.ManagementData;
+import org.apache.skywalking.oap.server.core.analysis.manual.service.ServiceTraffic;
+import org.apache.skywalking.oap.server.core.storage.IManagementDAO;
+import org.apache.skywalking.oap.server.core.storage.StorageBuilder;
+import org.apache.skywalking.oap.server.core.storage.model.Model;
+import org.apache.skywalking.oap.server.storage.plugin.influxdb.InfluxClient;
+import org.apache.skywalking.oap.server.storage.plugin.influxdb.TableMetaInfo;
+import org.influxdb.dto.QueryResult;
+import org.influxdb.querybuilder.SelectQueryImpl;
+import org.influxdb.querybuilder.WhereQueryImpl;
+
+import static org.apache.skywalking.oap.server.storage.plugin.influxdb.InfluxConstants.ID_COLUMN;
+import static org.apache.skywalking.oap.server.storage.plugin.influxdb.InfluxConstants.NAME;
+import static org.influxdb.querybuilder.BuiltQuery.QueryBuilder.eq;
+import static org.influxdb.querybuilder.BuiltQuery.QueryBuilder.select;
+
+@Slf4j
+public class ManagementDAO implements IManagementDAO {
+ private static final long STATIC_TIMESTAMP = 1_000_000;
+
+ private InfluxClient client;
+ private StorageBuilder storageBuilder;
+
+ public ManagementDAO(InfluxClient client, StorageBuilder storageBuilder) {
+ this.client = client;
+ this.storageBuilder = storageBuilder;
+ }
+
+ @Override
+ public void insert(final Model model, final ManagementData managementData) throws IOException {
+ final WhereQueryImpl query = select()
+ .column(ID_COLUMN).column(NAME)
+ .from(ServiceTraffic.INDEX_NAME)
+ .where(eq(ID_COLUMN, managementData.id()));
+ QueryResult.Series series = client.queryForSingleSeries(query);
+ if (log.isDebugEnabled()) {
+ log.debug("SQL: {} result: {}", query.getCommand(), series);
+ }
+ if (series != null && series.getValues().size() > 0) {
+ return;
+ }
+
+ final InfluxInsertRequest request = new InfluxInsertRequest(model, managementData, storageBuilder)
+ .time(STATIC_TIMESTAMP, TimeUnit.NANOSECONDS);
+ TableMetaInfo.get(model.getName()).getStorageAndTagMap().forEach((field, tag) -> {
+ request.addFieldAsTag(field, tag);
+ });
+ client.write(request.getPoint());
+ }
+}
diff --git a/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/MetadataQuery.java b/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/MetadataQuery.java
index 4c20e08e9..6b0d83828 100644
--- a/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/MetadataQuery.java
+++ b/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/MetadataQuery.java
@@ -29,6 +29,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.oap.server.core.analysis.NodeType;
import org.apache.skywalking.oap.server.core.analysis.TimeBucket;
@@ -59,15 +60,12 @@ import static org.influxdb.querybuilder.BuiltQuery.QueryBuilder.eq;
import static org.influxdb.querybuilder.BuiltQuery.QueryBuilder.gte;
import static org.influxdb.querybuilder.BuiltQuery.QueryBuilder.select;
+@RequiredArgsConstructor
@Slf4j
public class MetadataQuery implements IMetadataQueryDAO {
private static final Gson GSON = new Gson();
private final InfluxClient client;
- public MetadataQuery(final InfluxClient client) {
- this.client = client;
- }
-
@Override
public List getAllServices(final long startTimestamp, final long endTimestamp) throws IOException {
SelectSubQueryImpl subQuery = select()
diff --git a/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/UITemplateManagementDAOImpl.java b/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/UITemplateManagementDAOImpl.java
new file mode 100644
index 000000000..ddc3359e6
--- /dev/null
+++ b/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/UITemplateManagementDAOImpl.java
@@ -0,0 +1,144 @@
+/*
+ * 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.
+ *
+ */
+
+package org.apache.skywalking.oap.server.storage.plugin.influxdb.query;
+
+import com.google.common.collect.Maps;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.skywalking.oap.server.core.management.ui.template.UITemplate;
+import org.apache.skywalking.oap.server.core.query.input.DashboardSetting;
+import org.apache.skywalking.oap.server.core.query.type.DashboardConfiguration;
+import org.apache.skywalking.oap.server.core.query.type.TemplateChangeStatus;
+import org.apache.skywalking.oap.server.core.storage.management.UITemplateManagementDAO;
+import org.apache.skywalking.oap.server.library.util.BooleanUtils;
+import org.apache.skywalking.oap.server.storage.plugin.influxdb.InfluxClient;
+import org.apache.skywalking.oap.server.storage.plugin.influxdb.InfluxConstants;
+import org.influxdb.dto.Point;
+import org.influxdb.dto.QueryResult;
+import org.influxdb.querybuilder.SelectQueryImpl;
+import org.influxdb.querybuilder.WhereQueryImpl;
+
+import static org.influxdb.querybuilder.BuiltQuery.QueryBuilder.eq;
+import static org.influxdb.querybuilder.BuiltQuery.QueryBuilder.select;
+
+@RequiredArgsConstructor
+@Slf4j
+public class UITemplateManagementDAOImpl implements UITemplateManagementDAO {
+ private final InfluxClient client;
+
+ @Override
+ public List getAllTemplates(final Boolean includingDisabled) throws IOException {
+ WhereQueryImpl where = select().raw("*::field")
+ .from(client.getDatabase(), UITemplate.INDEX_NAME)
+ .where();
+ if (!includingDisabled) {
+ where.and(eq(UITemplate.DISABLED, BooleanUtils.FALSE));
+ }
+ final QueryResult.Series series = client.queryForSingleSeries(where);
+ final List configs = new ArrayList<>();
+ final UITemplate.Builder builder = new UITemplate.Builder();
+ if (Objects.nonNull(series)) {
+ List columnNames = series.getColumns();
+
+ final int size = series.getValues().size();
+ for (int offset = 0; offset < size; offset++) {
+ List