Support continuous profiling feature (#10473)

This commit is contained in:
mrproliu 2023-03-20 20:26:42 +08:00 committed by GitHub
parent 3662b01365
commit 7dcdb279ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
98 changed files with 3417 additions and 307 deletions

View File

@ -528,6 +528,28 @@ jobs:
config: test/e2e-v2/cases/profiling/ebpf/network/opensearch/e2e.yaml
env: OPENSEARCH_VERSION=2.4.0
- name: Continuous Profiling BanyanDB
config: test/e2e-v2/cases/profiling/ebpf/continuous/banyandb/e2e.yaml
- name: Continuous Profiling H2
config: test/e2e-v2/cases/profiling/ebpf/continuous/h2/e2e.yaml
- name: Continuous Profiling ES
config: test/e2e-v2/cases/profiling/ebpf/continuous/es/e2e.yaml
- name: Continuous Profiling Sharding ES
config: test/e2e-v2/cases/profiling/ebpf/continuous/es/es-sharding/e2e.yaml
- name: Continuous Profiling MySQL
config: test/e2e-v2/cases/profiling/ebpf/continuous/mysql/e2e.yaml
- name: Continuous Profiling Postgres
config: test/e2e-v2/cases/profiling/ebpf/continuous/postgres/e2e.yaml
- name: Continuous Profiling OpenSearch 1.1.0
config: test/e2e-v2/cases/profiling/ebpf/continuous/opensearch/e2e.yaml
env: OPENSEARCH_VERSION=1.1.0
- name: Continuous Profiling OpenSearch 1.3.6
config: test/e2e-v2/cases/profiling/ebpf/continuous/opensearch/e2e.yaml
env: OPENSEARCH_VERSION=1.3.6
- name: Continuous Profiling OpenSearch 2.4.0
config: test/e2e-v2/cases/profiling/ebpf/continuous/opensearch/e2e.yaml
env: OPENSEARCH_VERSION=2.4.0
- name: Kafka Basic
config: test/e2e-v2/cases/kafka/simple-so11y/e2e.yaml
- name: Kafka Profiling

View File

@ -0,0 +1,49 @@
/*
* 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.network.trace.component.command;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import java.util.List;
import java.util.Map;
@Data
public class ContinuousProfilingPolicy {
@SerializedName("ServiceName")
private String serviceName;
@SerializedName("UUID")
private String uuid;
@SerializedName("Profiling")
private Map<String, Map<String, Item>> profiling;
@Data
public static class Item {
@SerializedName("Threshold")
private String threshold;
@SerializedName("Period")
private int period;
@SerializedName("Count")
private int count;
@SerializedName("URIList")
private List<String> uriList;
@SerializedName("URIRegex")
private String uriRegex;
}
}

View File

@ -0,0 +1,45 @@
/*
* 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.network.trace.component.command;
import com.google.gson.Gson;
import org.apache.skywalking.apm.network.common.v3.Command;
import org.apache.skywalking.apm.network.common.v3.KeyStringValuePair;
import java.util.List;
public class ContinuousProfilingPolicyCommand extends BaseCommand implements Serializable {
public static final String NAME = "ContinuousProfilingPolicyQuery";
private static final Gson GSON = new Gson();
private List<ContinuousProfilingPolicy> policies;
public ContinuousProfilingPolicyCommand(String serialNumber, List<ContinuousProfilingPolicy> policies) {
super(NAME, serialNumber);
this.policies = policies;
}
@Override
public Command.Builder serialize() {
final Command.Builder builder = commandBuilder();
builder.addArgs(KeyStringValuePair.newBuilder()
.setKey("ServiceWithPolicyJSON").setValue(GSON.toJson(policies)).build());
return builder;
}
}

View File

@ -0,0 +1,41 @@
/*
* 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.network.trace.component.command;
import org.apache.skywalking.apm.network.common.v3.Command;
import org.apache.skywalking.apm.network.common.v3.KeyStringValuePair;
public class ContinuousProfilingReportCommand extends BaseCommand implements Serializable {
public static final String NAME = "ContinuousProfilingReportTask";
private final String taskId;
public ContinuousProfilingReportCommand(String serialNumber, String taskId) {
super(NAME, serialNumber);
this.taskId = taskId;
}
@Override
public Command.Builder serialize() {
final Command.Builder builder = commandBuilder();
builder.addArgs(KeyStringValuePair.newBuilder()
.setKey("TaskId").setValue(taskId).build());
return builder;
}
}

@ -1 +1 @@
Subproject commit 9c7a0bf8e0c2195280adf65f50cbd3161dd588ff
Subproject commit 0da9c8b3e111fb51c9f8854cae16d4519462ecfe

View File

@ -14,6 +14,8 @@
* [Breaking Change] Enhance JDBC storage through merging tables and managing day-based table rolling.
* [Breaking Change] Sharding-MySQL implementations and tests get removed due to we have the day-based rolling mechanism by default
* Fix otel k8s-cluster rule add namespace dimension for MAL aggregation calculation(Deployment Status,Deployment Spec Replicas)
* Support continuous profiling feature.
* Support collect process level related metrics.
#### Documentation

View File

@ -247,6 +247,8 @@ They extract level relevant labels from metric labels, then informs the meter-sy
extracts instance level labels from the second array argument, extracts layer from `Layer` argument, `propertiesExtractor` is an optional closure that extracts instance properties from `tags`, e.g. `{ tags -> ['pod': tags.pod, 'namespace': tags.namespace] }`.
- `endpoint([svc_label1, svc_label2...], [ep_label1, ep_label2...])` extracts service level labels from the first array argument,
extracts endpoint level labels from the second array argument, extracts layer from `Layer` argument.
- `process([svc_label1, svc_label2...], [ins_label1, ins_label2...], [ps_label1, ps_label2...], layer_lable)` extracts service level labels from the first array argument,
extracts instance level labels from the second array argument, extracts process level labels from the third array argument, extracts layer label from fourse argument.
- `serviceRelation(DetectPoint, [source_svc_label1...], [dest_svc_label1...], Layer)` DetectPoint including `DetectPoint.CLIENT` and `DetectPoint.SERVER`,
extracts `sourceService` labels from the first array argument, extracts `destService` labels from the second array argument, extracts layer from `Layer` argument.
- `processRelation(detect_point_label, [service_label1...], [instance_label1...], source_process_id_label, dest_process_id_label, component_label)` extracts `DetectPoint` labels from first argument, the label value should be `client` or `server`.

View File

@ -0,0 +1,49 @@
/*
* 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.meter.analyzer.dsl.EntityDescription;
import com.google.common.collect.ImmutableList;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.ToString;
import org.apache.skywalking.oap.server.core.analysis.meter.ScopeType;
import java.util.List;
@Getter
@RequiredArgsConstructor
@ToString
public class ProcessEntityDescription implements EntityDescription {
private final ScopeType scopeType = ScopeType.PROCESS;
private final List<String> serviceKeys;
private final List<String> serviceInstanceKeys;
private final List<String> processKeys;
private final String layerKey;
private final String delimiter;
@Override
public List<String> getLabelKeys() {
return ImmutableList.<String>builder()
.addAll(serviceKeys)
.addAll(serviceInstanceKeys)
.addAll(processKeys)
.add(layerKey)
.build();
}
}

View File

@ -28,6 +28,7 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.skywalking.oap.meter.analyzer.dsl.EntityDescription.EndpointEntityDescription;
import org.apache.skywalking.oap.meter.analyzer.dsl.EntityDescription.EntityDescription;
import org.apache.skywalking.oap.meter.analyzer.dsl.EntityDescription.InstanceEntityDescription;
import org.apache.skywalking.oap.meter.analyzer.dsl.EntityDescription.ProcessEntityDescription;
import org.apache.skywalking.oap.meter.analyzer.dsl.EntityDescription.ProcessRelationEntityDescription;
import org.apache.skywalking.oap.meter.analyzer.dsl.EntityDescription.ServiceEntityDescription;
import org.apache.skywalking.oap.meter.analyzer.dsl.EntityDescription.ServiceRelationEntityDescription;
@ -477,6 +478,23 @@ public class SampleFamily {
return createMeterSamples(new EndpointEntityDescription(serviceKeys, endpointKeys, layer, Const.POINT));
}
public SampleFamily process(List<String> serviceKeys, List<String> serviceInstanceKeys, List<String> processKeys, String layerKey) {
Preconditions.checkArgument(serviceKeys.size() > 0);
Preconditions.checkArgument(serviceInstanceKeys.size() > 0);
Preconditions.checkArgument(processKeys.size() > 0);
ExpressionParsingContext.get().ifPresent(ctx -> {
ctx.scopeType = ScopeType.PROCESS;
ctx.scopeLabels.addAll(serviceKeys);
ctx.scopeLabels.addAll(serviceInstanceKeys);
ctx.scopeLabels.addAll(processKeys);
ctx.scopeLabels.add(layerKey);
});
if (this == EMPTY) {
return EMPTY;
}
return createMeterSamples(new ProcessEntityDescription(serviceKeys, serviceInstanceKeys, processKeys, layerKey, Const.POINT));
}
public SampleFamily serviceRelation(DetectPoint detectPoint, List<String> sourceServiceKeys, List<String> destServiceKeys, Layer layer) {
Preconditions.checkArgument(sourceServiceKeys.size() > 0);
Preconditions.checkArgument(destServiceKeys.size() > 0);
@ -668,6 +686,14 @@ public class SampleFamily {
InternalOps.dim(samples, endpointEntityDescription.getEndpointKeys(), endpointEntityDescription.getDelimiter()),
endpointEntityDescription.getLayer()
);
case PROCESS:
final ProcessEntityDescription processEntityDescription = (ProcessEntityDescription) entityDescription;
return MeterEntity.newProcess(
InternalOps.dim(samples, processEntityDescription.getServiceKeys(), processEntityDescription.getDelimiter()),
InternalOps.dim(samples, processEntityDescription.getServiceInstanceKeys(), processEntityDescription.getDelimiter()),
InternalOps.dim(samples, processEntityDescription.getProcessKeys(), processEntityDescription.getDelimiter()),
InternalOps.dim(samples, List.of(processEntityDescription.getLayerKey()), processEntityDescription.getDelimiter())
);
case SERVICE_RELATION:
ServiceRelationEntityDescription serviceRelationEntityDescription = (ServiceRelationEntityDescription) entityDescription;
return MeterEntity.newServiceRelation(

View File

@ -20,7 +20,6 @@ package org.apache.skywalking.oap.server.exporter.provider;
import lombok.Setter;
import org.apache.skywalking.oap.server.core.analysis.IDManager;
import org.apache.skywalking.oap.server.core.analysis.metrics.MetricsEntityMetaInfo;
import org.apache.skywalking.oap.server.core.analysis.metrics.MetricsMetaInfo;
import org.apache.skywalking.oap.server.core.source.DefaultScopeDefine;
@ -76,9 +75,6 @@ public class MetricFormatter {
endpointRelationDefine.getDestServiceId());
return endpointRelationDefine.getSource() + " in " + sourceService.getName()
+ " to " + endpointRelationDefine.getDest() + " in " + destService.getName();
} else if (DefaultScopeDefine.inProcessCatalog(scope)) {
final MetricsEntityMetaInfo entity = meta.getEntity();
return entity.getProcessName() + " in " + entity.getInstanceName() + " of " + entity.getServiceName();
} else if (scope == DefaultScopeDefine.ALL) {
return "";
} else {

View File

@ -24,7 +24,6 @@ import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.oap.server.core.alarm.AlarmCallback;
import org.apache.skywalking.oap.server.core.alarm.EndpointRelationMetaInAlarm;
import org.apache.skywalking.oap.server.core.alarm.ProcessMetaInAlarm;
import org.apache.skywalking.oap.server.core.alarm.ServiceInstanceRelationMetaInAlarm;
import org.apache.skywalking.oap.server.core.alarm.ServiceRelationMetaInAlarm;
import org.apache.skywalking.oap.server.core.alarm.EndpointMetaInAlarm;
@ -42,7 +41,6 @@ import org.apache.skywalking.oap.server.core.alarm.provider.wechat.WechatHookCal
import org.apache.skywalking.oap.server.core.alarm.provider.welink.WeLinkHookCallback;
import org.apache.skywalking.oap.server.core.analysis.IDManager;
import org.apache.skywalking.oap.server.core.analysis.metrics.Metrics;
import org.apache.skywalking.oap.server.core.analysis.metrics.MetricsEntityMetaInfo;
import org.apache.skywalking.oap.server.core.analysis.metrics.MetricsMetaInfo;
import org.apache.skywalking.oap.server.core.analysis.metrics.WithMetadata;
import org.apache.skywalking.oap.server.core.source.DefaultScopeDefine;
@ -68,8 +66,7 @@ public class NotifyHandler implements MetricsNotify {
if (!DefaultScopeDefine.inServiceCatalog(scope) && !DefaultScopeDefine.inServiceInstanceCatalog(scope)
&& !DefaultScopeDefine.inEndpointCatalog(scope) && !DefaultScopeDefine.inServiceRelationCatalog(scope)
&& !DefaultScopeDefine.inServiceInstanceRelationCatalog(scope) && !DefaultScopeDefine.inEndpointRelationCatalog(scope)
&& !DefaultScopeDefine.inProcessCatalog(scope)) {
&& !DefaultScopeDefine.inServiceInstanceRelationCatalog(scope) && !DefaultScopeDefine.inEndpointRelationCatalog(scope)) {
return;
}
@ -155,16 +152,6 @@ public class NotifyHandler implements MetricsNotify {
endpointRelationMetaInAlarm.setName(endpointRelationDefine.getSource() + " in " + sourceService.getName()
+ " to " + endpointRelationDefine.getDest() + " in " + destService.getName());
metaInAlarm = endpointRelationMetaInAlarm;
} else if (DefaultScopeDefine.inProcessCatalog(scope)) {
final String processId = meta.getId();
final MetricsEntityMetaInfo entity = meta.getEntity();
ProcessMetaInAlarm processMetaInAlarm = new ProcessMetaInAlarm();
processMetaInAlarm.setMetricsName(meta.getMetricsName());
processMetaInAlarm.setId(processId);
processMetaInAlarm.setName(entity.getProcessName() + " in " + entity.getInstanceName()
+ " of " + entity.getServiceName());
metaInAlarm = processMetaInAlarm;
} else {
return;
}

View File

@ -23,14 +23,12 @@ import org.apache.skywalking.oap.server.core.alarm.AlarmMessage;
import org.apache.skywalking.oap.server.core.alarm.EndpointMetaInAlarm;
import org.apache.skywalking.oap.server.core.alarm.EndpointRelationMetaInAlarm;
import org.apache.skywalking.oap.server.core.alarm.MetaInAlarm;
import org.apache.skywalking.oap.server.core.alarm.ProcessMetaInAlarm;
import org.apache.skywalking.oap.server.core.alarm.ServiceInstanceMetaInAlarm;
import org.apache.skywalking.oap.server.core.alarm.ServiceInstanceRelationMetaInAlarm;
import org.apache.skywalking.oap.server.core.alarm.ServiceMetaInAlarm;
import org.apache.skywalking.oap.server.core.alarm.ServiceRelationMetaInAlarm;
import org.apache.skywalking.oap.server.core.analysis.IDManager;
import org.apache.skywalking.oap.server.core.analysis.metrics.Metrics;
import org.apache.skywalking.oap.server.core.analysis.metrics.MetricsEntityMetaInfo;
import org.apache.skywalking.oap.server.core.analysis.metrics.MetricsMetaInfo;
import org.apache.skywalking.oap.server.core.analysis.metrics.WithMetadata;
import org.apache.skywalking.oap.server.core.source.DefaultScopeDefine;
@ -248,37 +246,6 @@ public class NotifyHandlerTest {
assertEquals(DefaultScopeDefine.ENDPOINT_RELATION, metaInAlarm.getScopeId());
}
@Test
public void testNotifyWithProcessCatalog() {
String metricsName = "process-metrics";
String serviceName = "test-service";
String instanceName = "test-instance";
String processName = "test-process";
when(metadata.getMetricsName()).thenReturn(metricsName);
when(DefaultScopeDefine.inProcessCatalog(0)).thenReturn(true);
final String processId = IDManager.ProcessID.buildId(
IDManager.ServiceInstanceID.buildId(IDManager.ServiceID.buildId(serviceName, true), instanceName),
processName
);
when(metadata.getId()).thenReturn(processId);
when(metadata.getEntity()).thenReturn(MetricsEntityMetaInfo.buildProcess(serviceName, instanceName, processName));
ArgumentCaptor<MetaInAlarm> metaCaptor = ArgumentCaptor.forClass(MetaInAlarm.class);
notifyHandler.notify(metrics);
verify(rule).in(metaCaptor.capture(), any());
MetaInAlarm metaInAlarm = metaCaptor.getValue();
assertTrue(metaInAlarm instanceof ProcessMetaInAlarm);
assertEquals(metricsName, metaInAlarm.getMetricsName());
assertEquals("cf4be92893026c77c539266f47f2aa22f1e53ff64fc64803f5814293ff10a56f", metaInAlarm.getId0());
assertEquals("", metaInAlarm.getId1());
assertEquals(DefaultScopeDefine.PROCESS_CATALOG_NAME, metaInAlarm.getScope());
assertEquals("test-process in test-instance of test-service", metaInAlarm.getName());
assertEquals(DefaultScopeDefine.PROCESS, metaInAlarm.getScopeId());
}
@Test
public void dontNotify() {

View File

@ -30,6 +30,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.management.ui.template.UITemplateManagementService;
import org.apache.skywalking.oap.server.core.oal.rt.OALEngineLoaderService;
import org.apache.skywalking.oap.server.core.profiling.continuous.ContinuousProfilingMutationService;
import org.apache.skywalking.oap.server.core.profiling.continuous.ContinuousProfilingQueryService;
import org.apache.skywalking.oap.server.core.profiling.ebpf.EBPFProfilingMutationService;
import org.apache.skywalking.oap.server.core.profiling.ebpf.EBPFProfilingQueryService;
import org.apache.skywalking.oap.server.core.profiling.trace.ProfileTaskMutationService;
@ -102,6 +104,8 @@ public class CoreModule extends ModuleDefine {
private void addEBPFProfilingService(List<Class> classes) {
classes.add(EBPFProfilingMutationService.class);
classes.add(EBPFProfilingQueryService.class);
classes.add(ContinuousProfilingMutationService.class);
classes.add(ContinuousProfilingQueryService.class);
}
private void addManagementService(List<Class> classes) {

View File

@ -52,6 +52,8 @@ import org.apache.skywalking.oap.server.core.management.ui.template.UITemplateIn
import org.apache.skywalking.oap.server.core.management.ui.template.UITemplateManagementService;
import org.apache.skywalking.oap.server.core.oal.rt.DisableOALDefine;
import org.apache.skywalking.oap.server.core.oal.rt.OALEngineLoaderService;
import org.apache.skywalking.oap.server.core.profiling.continuous.ContinuousProfilingMutationService;
import org.apache.skywalking.oap.server.core.profiling.continuous.ContinuousProfilingQueryService;
import org.apache.skywalking.oap.server.core.profiling.ebpf.EBPFProfilingMutationService;
import org.apache.skywalking.oap.server.core.profiling.ebpf.EBPFProfilingQueryService;
import org.apache.skywalking.oap.server.core.profiling.trace.ProfileTaskMutationService;
@ -296,6 +298,10 @@ public class CoreModuleProvider extends ModuleProvider {
EBPFProfilingQueryService.class,
new EBPFProfilingQueryService(getManager(), moduleConfig, this.storageModels)
);
this.registerServiceImplementation(
ContinuousProfilingMutationService.class, new ContinuousProfilingMutationService(getManager()));
this.registerServiceImplementation(
ContinuousProfilingQueryService.class, new ContinuousProfilingQueryService(getManager()));
this.registerServiceImplementation(CommandService.class, new CommandService(getManager()));

View File

@ -42,6 +42,7 @@ public class MeterEntity {
private String instanceName;
private Map<String, String> instanceProperties;
private String endpointName;
private String processName;
private String sourceServiceName;
private String destServiceName;
private String sourceProcessId;
@ -64,6 +65,8 @@ public class MeterEntity {
IDManager.ServiceID.buildId(serviceName, true), instanceName);
case ENDPOINT:
return IDManager.EndpointID.buildId(IDManager.ServiceID.buildId(serviceName, true), endpointName);
case PROCESS:
return IDManager.ProcessID.buildId(IDManager.ServiceInstanceID.buildId(IDManager.ServiceID.buildId(serviceName, true), instanceName), processName);
case SERVICE_RELATION:
return IDManager.ServiceID.buildRelationId(new IDManager.ServiceID.ServiceRelationDefine(
sourceServiceId(),
@ -139,6 +142,16 @@ public class MeterEntity {
return meterEntity;
}
public static MeterEntity newProcess(String serviceName, String instanceName, String processName, String layerName) {
final MeterEntity meterEntity = new MeterEntity();
meterEntity.scopeType = ScopeType.PROCESS;
meterEntity.serviceName = NAMING_CONTROL.formatServiceName(serviceName);
meterEntity.instanceName = NAMING_CONTROL.formatInstanceName(instanceName);
meterEntity.processName = processName;
meterEntity.layer = Layer.nameOf(layerName);
return meterEntity;
}
public static MeterEntity newServiceRelation(String sourceServiceName,
String destServiceName,
DetectPoint detectPoint, Layer layer) {

View File

@ -25,6 +25,7 @@ public enum ScopeType {
SERVICE(DefaultScopeDefine.SERVICE),
SERVICE_INSTANCE(DefaultScopeDefine.SERVICE_INSTANCE),
ENDPOINT(DefaultScopeDefine.ENDPOINT),
PROCESS(DefaultScopeDefine.PROCESS),
SERVICE_RELATION(DefaultScopeDefine.SERVICE_RELATION),
PROCESS_RELATION(DefaultScopeDefine.PROCESS_RELATION);

View File

@ -23,10 +23,18 @@ import java.util.Objects;
import java.util.UUID;
import java.util.stream.Collectors;
import com.google.gson.Gson;
import org.apache.skywalking.oap.server.core.analysis.IDManager;
import org.apache.skywalking.oap.server.core.profiling.continuous.storage.ContinuousProfilingPolicy;
import org.apache.skywalking.oap.server.core.profiling.continuous.storage.ContinuousProfilingPolicyConfiguration;
import org.apache.skywalking.oap.server.core.profiling.ebpf.storage.EBPFProfilingTargetType;
import org.apache.skywalking.oap.server.core.profiling.ebpf.storage.EBPFProfilingTaskRecord;
import org.apache.skywalking.oap.server.core.profiling.ebpf.storage.EBPFProfilingTriggerType;
import org.apache.skywalking.oap.server.core.query.type.EBPFProfilingTask;
import org.apache.skywalking.oap.server.core.query.type.EBPFProfilingTaskExtension;
import org.apache.skywalking.oap.server.library.util.CollectionUtils;
import org.apache.skywalking.oap.server.library.util.StringUtil;
import org.apache.skywalking.oap.server.network.trace.component.command.ContinuousProfilingReportCommand;
import org.apache.skywalking.oap.server.network.trace.component.command.ContinuousProfilingPolicyCommand;
import org.apache.skywalking.oap.server.network.trace.component.command.EBPFProfilingTaskCommand;
import org.apache.skywalking.oap.server.network.trace.component.command.EBPFProfilingTaskExtensionConfig;
import org.apache.skywalking.oap.server.network.trace.component.command.ProfileTaskCommand;
@ -38,6 +46,7 @@ import org.apache.skywalking.oap.server.library.module.Service;
* CommandService represents the command creation factory. All commands for downstream agents should be created here.
*/
public class CommandService implements Service {
private static final Gson GSON = new Gson();
private final ModuleManager moduleManager;
public CommandService(final ModuleManager moduleManager) {
@ -54,20 +63,55 @@ public class CommandService implements Service {
/**
* Used to notify the eBPF Profiling task to the eBPF agent side
*/
public EBPFProfilingTaskCommand newEBPFProfilingTaskCommand(EBPFProfilingTask task, List<String> processId) {
public EBPFProfilingTaskCommand newEBPFProfilingTaskCommand(EBPFProfilingTaskRecord task, List<String> processId) {
final String serialNumber = UUID.randomUUID().toString();
EBPFProfilingTaskCommand.FixedTrigger fixedTrigger = null;
if (Objects.equals(task.getTriggerType(), EBPFProfilingTriggerType.FIXED_TIME)) {
if (Objects.equals(task.getTriggerType(), EBPFProfilingTriggerType.FIXED_TIME.value())) {
fixedTrigger = new EBPFProfilingTaskCommand.FixedTrigger(task.getFixedTriggerDuration());
}
return new EBPFProfilingTaskCommand(serialNumber, task.getTaskId(), processId, task.getTaskStartTime(),
task.getLastUpdateTime(), task.getTriggerType().name(), fixedTrigger, task.getTargetType().name(),
convertExtension(task));
return new EBPFProfilingTaskCommand(serialNumber, task.getLogicalId(), processId, task.getStartTime(),
task.getLastUpdateTime(), EBPFProfilingTriggerType.valueOf(task.getTriggerType()).name(), fixedTrigger,
EBPFProfilingTargetType.valueOf(task.getTargetType()).name(),
convertExtension(task));
}
private EBPFProfilingTaskExtensionConfig convertExtension(EBPFProfilingTask task) {
EBPFProfilingTaskExtension extensionConfig = task.getExtensionConfig();
if (extensionConfig == null || CollectionUtils.isEmpty(extensionConfig.getNetworkSamplings())) {
public ContinuousProfilingPolicyCommand newContinuousProfilingServicePolicyCommand(List<ContinuousProfilingPolicy> policy) {
return new ContinuousProfilingPolicyCommand(UUID.randomUUID().toString(),
policy.stream().map(this::convertContinuesProfilingPolicy).collect(Collectors.toList()));
}
public ContinuousProfilingReportCommand newContinuousProfilingReportCommand(String taskId) {
return new ContinuousProfilingReportCommand(UUID.randomUUID().toString(), taskId);
}
private org.apache.skywalking.oap.server.network.trace.component.command.ContinuousProfilingPolicy convertContinuesProfilingPolicy(ContinuousProfilingPolicy policy) {
final org.apache.skywalking.oap.server.network.trace.component.command.ContinuousProfilingPolicy result = new org.apache.skywalking.oap.server.network.trace.component.command.ContinuousProfilingPolicy();
result.setServiceName(IDManager.ServiceID.analysisId(policy.getServiceId()).getName());
result.setUuid(policy.getUuid());
if (StringUtil.isNotEmpty(policy.getConfigurationJson())) {
final ContinuousProfilingPolicyConfiguration configuration = ContinuousProfilingPolicyConfiguration.parseFromJSON(policy.getConfigurationJson());
result.setProfiling(configuration.getTargetCheckers().entrySet().stream().collect(Collectors.toMap(
c -> c.getKey().name(),
c -> c.getValue().entrySet().stream().collect(Collectors.toMap(i -> i.getKey().name(), i -> {
final org.apache.skywalking.oap.server.network.trace.component.command.ContinuousProfilingPolicy.Item item = new org.apache.skywalking.oap.server.network.trace.component.command.ContinuousProfilingPolicy.Item();
item.setThreshold(i.getValue().getThreshold());
item.setPeriod(i.getValue().getPeriod());
item.setCount(i.getValue().getCount());
item.setUriList(i.getValue().getUriList());
item.setUriRegex(i.getValue().getUriRegex());
return item;
}
)))));
}
return result;
}
private EBPFProfilingTaskExtensionConfig convertExtension(EBPFProfilingTaskRecord task) {
if (StringUtil.isEmpty(task.getExtensionConfigJson())) {
return null;
}
EBPFProfilingTaskExtension extensionConfig = GSON.fromJson(task.getExtensionConfigJson(), EBPFProfilingTaskExtension.class);
if (CollectionUtils.isEmpty(extensionConfig.getNetworkSamplings())) {
return null;
}
EBPFProfilingTaskExtensionConfig config = new EBPFProfilingTaskExtensionConfig();

View File

@ -0,0 +1,176 @@
/*
* 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.profiling.continuous;
import com.google.common.hash.Hashing;
import com.google.gson.Gson;
import lombok.RequiredArgsConstructor;
import org.apache.skywalking.oap.server.core.profiling.continuous.storage.ContinuousProfilingMonitorType;
import org.apache.skywalking.oap.server.core.profiling.continuous.storage.ContinuousProfilingPolicy;
import org.apache.skywalking.oap.server.core.profiling.continuous.storage.ContinuousProfilingPolicyConfiguration;
import org.apache.skywalking.oap.server.core.profiling.continuous.storage.ContinuousProfilingTargetType;
import org.apache.skywalking.oap.server.core.query.input.ContinuousProfilingPolicyItemCreation;
import org.apache.skywalking.oap.server.core.query.input.ContinuousProfilingPolicyCreation;
import org.apache.skywalking.oap.server.core.query.input.ContinuousProfilingPolicyTargetCreation;
import org.apache.skywalking.oap.server.core.query.type.ContinuousProfilingSetResult;
import org.apache.skywalking.oap.server.core.storage.StorageModule;
import org.apache.skywalking.oap.server.core.storage.profiling.continuous.IContinuousProfilingPolicyDAO;
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;
import org.apache.skywalking.oap.server.library.util.StringUtil;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashSet;
import java.util.List;
@RequiredArgsConstructor
public class ContinuousProfilingMutationService implements Service {
private static final Gson GSON = new Gson();
private final ModuleManager moduleManager;
private IContinuousProfilingPolicyDAO policyDAO;
public IContinuousProfilingPolicyDAO getPolicyDAO() {
if (policyDAO == null) {
this.policyDAO = moduleManager.find(StorageModule.NAME)
.provider().getService(IContinuousProfilingPolicyDAO.class);
}
return policyDAO;
}
public ContinuousProfilingSetResult setContinuousProfilingPolicy(ContinuousProfilingPolicyCreation request) throws IOException {
// validate the service id
if (StringUtil.isEmpty(request.getServiceId())) {
return buildError("the service id cannot be empty");
}
// validate the targets
if (CollectionUtils.isNotEmpty(request.getTargets())) {
String validateTarget = validateTargets(request.getTargets());
if (StringUtil.isNotEmpty(validateTarget)) {
return buildError(validateTarget);
}
}
// build and save the management data
final ContinuousProfilingPolicyConfiguration configuration = ContinuousProfilingPolicyConfiguration.buildFromRequest(request);
final String configurationJSON = GSON.toJson(configuration);
final ContinuousProfilingPolicy policy = new ContinuousProfilingPolicy();
policy.setServiceId(request.getServiceId());
policy.setUuid(Hashing.sha512().hashString(configurationJSON, StandardCharsets.UTF_8).toString());
policy.setConfigurationJson(configurationJSON);
getPolicyDAO().savePolicy(policy);
return buildSaveSuccess();
}
private String validateTargets(List<ContinuousProfilingPolicyTargetCreation> targets) {
final HashSet<ContinuousProfilingTargetType> targetCache = new HashSet<>();
for (ContinuousProfilingPolicyTargetCreation target : targets) {
// same target type cannot have multiple
final ContinuousProfilingTargetType targetType = target.getTargetType();
if (targetCache.contains(targetType)) {
return "contains multiple same target type: " + targetType;
}
targetCache.add(targetType);
final HashSet<ContinuousProfilingMonitorType> monitorTypeCache = new HashSet<>();
for (ContinuousProfilingPolicyItemCreation item : target.getCheckItems()) {
// save check type cannot have multiple in each target
if (monitorTypeCache.contains(item.getType())) {
return "contains multiple same monitor type " + item.getType() + " in " + targetType;
}
monitorTypeCache.add(item.getType());
// validate each item
String itemCheck = validatePolicyItem(item);
if (StringUtil.isNotEmpty(itemCheck)) {
return "check " + item.getType() + " in " + targetType + " error: " + itemCheck;
}
}
}
return null;
}
private String validatePolicyItem(ContinuousProfilingPolicyItemCreation item) {
String timeWindowsValidate = validatePolicyItemWindows(item);
if (StringUtil.isNotEmpty(timeWindowsValidate)) {
return timeWindowsValidate;
}
try {
switch (item.getType()) {
case PROCESS_CPU:
final int cpuPercent = Integer.parseInt(item.getThreshold());
if (cpuPercent < 0 || cpuPercent > 100) {
return "the process CPU percent should in [0-100]";
}
break;
case PROCESS_THREAD_COUNT:
final int threadCount = Integer.parseInt(item.getThreshold());
if (threadCount < 0) {
return "the process thread count must bigger than zero";
}
break;
case SYSTEM_LOAD:
final int systemLoad = Integer.parseInt(item.getThreshold());
if (systemLoad < 0) {
return "the system load must bigger than zero";
}
break;
case HTTP_ERROR_RATE:
final int httpErrorRate = Integer.parseInt(item.getThreshold());
if (httpErrorRate < 0 || httpErrorRate > 100) {
return "the HTTP error rate should in [0-100]";
}
break;
case HTTP_AVG_RESPONSE_TIME:
final int httpAvgResponseTime = Integer.parseInt(item.getThreshold());
if (httpAvgResponseTime < 0) {
return "the HTTP average response time must bigger than zero";
}
break;
}
} catch (NumberFormatException e) {
return "parsing threshold error";
}
return null;
}
private String validatePolicyItemWindows(ContinuousProfilingPolicyItemCreation item) {
if (item.getPeriod() <= 0) {
return "period must bigger than zero";
}
if (item.getCount() < 0) {
return "count must bigger than zero";
}
if (item.getCount() > item.getPeriod()) {
return "count must be small than period";
}
return null;
}
private ContinuousProfilingSetResult buildError(String message) {
return ContinuousProfilingSetResult.builder().status(false).errorReason(message).build();
}
private ContinuousProfilingSetResult buildSaveSuccess() {
return ContinuousProfilingSetResult.builder().status(true).build();
}
}

View File

@ -0,0 +1,85 @@
/*
* 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.profiling.continuous;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.oap.server.core.profiling.continuous.storage.ContinuousProfilingPolicy;
import org.apache.skywalking.oap.server.core.profiling.continuous.storage.ContinuousProfilingPolicyConfiguration;
import org.apache.skywalking.oap.server.core.profiling.continuous.storage.ContinuousProfilingTargetType;
import org.apache.skywalking.oap.server.core.query.type.ContinuousProfilingPolicyItem;
import org.apache.skywalking.oap.server.core.query.type.ContinuousProfilingPolicyTarget;
import org.apache.skywalking.oap.server.core.storage.StorageModule;
import org.apache.skywalking.oap.server.core.storage.profiling.continuous.IContinuousProfilingPolicyDAO;
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;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
@Slf4j
@RequiredArgsConstructor
public class ContinuousProfilingQueryService implements Service {
private final ModuleManager moduleManager;
private IContinuousProfilingPolicyDAO policyDAO;
public IContinuousProfilingPolicyDAO getPolicyDAO() {
if (policyDAO == null) {
this.policyDAO = moduleManager.find(StorageModule.NAME)
.provider().getService(IContinuousProfilingPolicyDAO.class);
}
return policyDAO;
}
public List<ContinuousProfilingPolicyTarget> queryContinuousProfilingServiceTargets(String serviceId) throws IOException {
final List<ContinuousProfilingPolicy> policies = getPolicyDAO().queryPolicies(Arrays.asList(serviceId));
if (CollectionUtils.isEmpty(policies)) {
return Collections.emptyList();
}
final ContinuousProfilingPolicy policy = policies.get(0);
final ContinuousProfilingPolicyConfiguration configuration =
ContinuousProfilingPolicyConfiguration.parseFromJSON(policy.getConfigurationJson());
return configuration.getTargetCheckers().entrySet().stream().map(targetEntry -> {
final ContinuousProfilingTargetType type = targetEntry.getKey();
final List<ContinuousProfilingPolicyItem> items = targetEntry.getValue().entrySet().stream().map(checker -> {
final ContinuousProfilingPolicyItem result = new ContinuousProfilingPolicyItem();
final ContinuousProfilingPolicyConfiguration.CheckItem item = checker.getValue();
result.setType(checker.getKey());
result.setThreshold(item.getThreshold());
result.setPeriod(item.getPeriod());
result.setCount(item.getCount());
result.setUriList(item.getUriList());
result.setUriRegex(item.getUriRegex());
return result;
}).collect(Collectors.toList());
return ContinuousProfilingPolicyTarget.builder()
.type(type)
.checkItems(items)
.build();
}).collect(Collectors.toList());
}
}

View File

@ -0,0 +1,75 @@
/*
* 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.profiling.continuous.storage;
import org.apache.skywalking.apm.network.ebpf.profiling.v3.ContinuousProfilingTriggeredMonitorType;
import org.apache.skywalking.oap.server.core.UnexpectedException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;
public enum ContinuousProfilingMonitorType {
UNKNOWN(0, null),
PROCESS_CPU(1, ContinuousProfilingTriggeredMonitorType.ProcessCPU),
PROCESS_THREAD_COUNT(2, ContinuousProfilingTriggeredMonitorType.ProcessThreadCount),
SYSTEM_LOAD(3, ContinuousProfilingTriggeredMonitorType.SystemLoad),
HTTP_ERROR_RATE(4, ContinuousProfilingTriggeredMonitorType.HTTPErrorRate),
HTTP_AVG_RESPONSE_TIME(5, ContinuousProfilingTriggeredMonitorType.HTTPAvgResponseTime);
private final int value;
private final ContinuousProfilingTriggeredMonitorType causeType;
private static final Map<Integer, ContinuousProfilingMonitorType> DICTIONARY = new HashMap<>();
private static final Map<ContinuousProfilingTriggeredMonitorType, ContinuousProfilingMonitorType> CAUSE_DICTIONARY = new HashMap<>();
static {
DICTIONARY.putAll(Arrays.stream(ContinuousProfilingMonitorType.values()).collect(Collectors.toMap(ContinuousProfilingMonitorType::value, Function.identity())));
CAUSE_DICTIONARY.putAll(Arrays.stream(ContinuousProfilingMonitorType.values()).filter(s -> Objects.nonNull(s.causeType))
.collect(Collectors.toMap(s -> s.causeType, Function.identity())));
}
ContinuousProfilingMonitorType(int value, ContinuousProfilingTriggeredMonitorType causeType) {
this.value = value;
this.causeType = causeType;
}
public static ContinuousProfilingMonitorType valueOf(int value) {
ContinuousProfilingMonitorType type = DICTIONARY.get(value);
if (type == null) {
throw new UnexpectedException("Unknown ContinuousProfilingTargetType value");
}
return type;
}
public static ContinuousProfilingMonitorType valueOf(ContinuousProfilingTriggeredMonitorType causeType) {
ContinuousProfilingMonitorType type = CAUSE_DICTIONARY.get(causeType);
if (type == null) {
throw new UnexpectedException("Unknown ContinuousProfilingTargetType value");
}
return type;
}
public int value() {
return this.value;
}
}

View File

@ -0,0 +1,80 @@
/*
* 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.profiling.continuous.storage;
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.StorageID;
import org.apache.skywalking.oap.server.core.storage.annotation.Column;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Entity;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Storage;
import org.apache.skywalking.oap.server.core.storage.type.StorageBuilder;
import static org.apache.skywalking.oap.server.core.source.DefaultScopeDefine.CONTINUOUS_PROFILING_POLICY;
@Setter
@Getter
@ScopeDeclaration(id = CONTINUOUS_PROFILING_POLICY, name = "ContinuousProfilingPolicy")
@Stream(name = ContinuousProfilingPolicy.INDEX_NAME, scopeId = CONTINUOUS_PROFILING_POLICY,
builder = ContinuousProfilingPolicy.Builder.class, processor = ManagementStreamProcessor.class)
@EqualsAndHashCode(of = {
"serviceId"
}, callSuper = false)
public class ContinuousProfilingPolicy extends ManagementData {
public static final String INDEX_NAME = "continuous_profiling_policy";
public static final String SERVICE_ID = "service_id";
public static final String UUID = "uuid";
public static final String CONFIGURATION_JSON = "configuration_json";
@Column(name = SERVICE_ID)
private String serviceId;
@Column(name = CONFIGURATION_JSON, storageOnly = true, length = 5000)
private String configurationJson;
@Column(name = UUID)
private String uuid;
@Override
public StorageID id() {
return new StorageID().append(SERVICE_ID, serviceId);
}
public static class Builder implements StorageBuilder<ContinuousProfilingPolicy> {
@Override
public ContinuousProfilingPolicy storage2Entity(Convert2Entity converter) {
final ContinuousProfilingPolicy policy = new ContinuousProfilingPolicy();
policy.setServiceId((String) converter.get(SERVICE_ID));
policy.setUuid((String) converter.get(UUID));
policy.setConfigurationJson((String) converter.get(CONFIGURATION_JSON));
return policy;
}
@Override
public void entity2Storage(ContinuousProfilingPolicy entity, Convert2Storage converter) {
converter.accept(SERVICE_ID, entity.getServiceId());
converter.accept(UUID, entity.getUuid());
converter.accept(CONFIGURATION_JSON, entity.getConfigurationJson());
}
}
}

View File

@ -0,0 +1,83 @@
/*
* 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.profiling.continuous.storage;
import com.google.gson.Gson;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.skywalking.oap.server.core.query.input.ContinuousProfilingPolicyItemCreation;
import org.apache.skywalking.oap.server.core.query.input.ContinuousProfilingPolicyCreation;
import org.apache.skywalking.oap.server.core.query.input.ContinuousProfilingPolicyTargetCreation;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Data
public class ContinuousProfilingPolicyConfiguration {
private static Gson GSON = new Gson();
// one target have multiple checkers
private Map<ContinuousProfilingTargetType, Map<ContinuousProfilingMonitorType, CheckItem>> targetCheckers;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class CheckItem {
private String threshold;
private int period;
private int count;
private List<String> uriList;
private String uriRegex;
}
public String toJSON() {
return GSON.toJson(this);
}
public static ContinuousProfilingPolicyConfiguration buildFromRequest(ContinuousProfilingPolicyCreation request) {
final ContinuousProfilingPolicyConfiguration data = new ContinuousProfilingPolicyConfiguration();
for (ContinuousProfilingPolicyTargetCreation target : request.getTargets()) {
final ContinuousProfilingTargetType targetType = target.getTargetType();
Map<ContinuousProfilingMonitorType, CheckItem> items = data.targetCheckers.computeIfAbsent(targetType, k -> new HashMap<>());
for (ContinuousProfilingPolicyItemCreation itemRequest : target.getCheckItems()) {
final CheckItem item = new CheckItem();
item.setThreshold(itemRequest.getThreshold());
item.setPeriod(itemRequest.getPeriod());
item.setCount(itemRequest.getCount());
item.setUriList(itemRequest.getUriList());
item.setUriRegex(itemRequest.getUriRegex());
items.put(itemRequest.getType(), item);
}
}
return data;
}
public static ContinuousProfilingPolicyConfiguration parseFromJSON(String json) {
return GSON.fromJson(json, ContinuousProfilingPolicyConfiguration.class);
}
public ContinuousProfilingPolicyConfiguration() {
this.targetCheckers = new HashMap<>();
}
}

View File

@ -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.profiling.continuous.storage;
import org.apache.skywalking.oap.server.core.UnexpectedException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
public enum ContinuousProfilingTargetType {
UNKNOWN(0),
ON_CPU(1),
OFF_CPU(2),
NETWORK(3);
private final int value;
private static final Map<Integer, ContinuousProfilingTargetType> DICTIONARY = new HashMap<>();
static {
DICTIONARY.putAll(Arrays.stream(ContinuousProfilingTargetType.values()).collect(Collectors.toMap(ContinuousProfilingTargetType::value, type -> type)));
}
ContinuousProfilingTargetType(int value) {
this.value = value;
}
public static ContinuousProfilingTargetType valueOf(int value) {
ContinuousProfilingTargetType type = DICTIONARY.get(value);
if (type == null) {
throw new UnexpectedException("Unknown ContinuousProfilingTargetType value");
}
return type;
}
public int value() {
return this.value;
}
}

View File

@ -34,7 +34,6 @@ import org.apache.skywalking.oap.server.core.query.input.EBPFNetworkSamplingRule
import org.apache.skywalking.oap.server.core.query.input.EBPFProfilingNetworkTaskRequest;
import org.apache.skywalking.oap.server.core.query.input.EBPFProfilingTaskFixedTimeCreationRequest;
import org.apache.skywalking.oap.server.core.query.type.EBPFNetworkKeepProfilingResult;
import org.apache.skywalking.oap.server.core.query.type.EBPFProfilingTask;
import org.apache.skywalking.oap.server.core.query.type.EBPFProfilingTaskCreationResult;
import org.apache.skywalking.oap.server.core.query.type.EBPFProfilingTaskExtension;
import org.apache.skywalking.oap.server.core.storage.StorageModule;
@ -165,18 +164,23 @@ public class EBPFProfilingMutationService implements Service {
}
public EBPFNetworkKeepProfilingResult keepEBPFNetworkProfiling(String taskId) throws IOException {
final EBPFProfilingTask task = getProcessProfilingTaskDAO().queryById(taskId);
final List<EBPFProfilingTaskRecord> tasks = getProcessProfilingTaskDAO().getTaskRecord(taskId);
// task not exists
if (task == null) {
if (CollectionUtils.isEmpty(tasks)) {
return buildKeepProfilingError("profiling task not exists");
}
// combine all tasks
final EBPFProfilingTaskRecord task = tasks.get(0);
for (int i = 1; i < tasks.size(); i++) {
task.combine(tasks.get(i));
}
// target type not "NETWORK"
if (!Objects.equals(task.getTargetType(), EBPFProfilingTargetType.NETWORK)) {
return buildKeepProfilingError("current task is not a \"NETWORK\" task");
}
// task already finished
final Calendar taskTime = Calendar.getInstance();
taskTime.setTimeInMillis(task.getTaskStartTime());
taskTime.setTimeInMillis(task.getStartTime());
taskTime.add(Calendar.SECOND, (int) task.getFixedTriggerDuration());
final Calendar now = Calendar.getInstance();
final long sec = TimeUnit.MILLISECONDS.toSeconds(taskTime.getTimeInMillis() - now.getTimeInMillis());
@ -189,12 +193,12 @@ public class EBPFProfilingMutationService implements Service {
// copy the task and extend the task time
final EBPFProfilingTaskRecord record = new EBPFProfilingTaskRecord();
record.setLogicalId(task.getTaskId());
record.setLogicalId(task.getLogicalId());
record.setServiceId(task.getServiceId());
record.setProcessLabelsJson(Const.EMPTY_STRING);
record.setInstanceId(task.getServiceInstanceId());
record.setStartTime(task.getTaskStartTime());
record.setTriggerType(task.getTriggerType().value());
record.setInstanceId(task.getInstanceId());
record.setStartTime(task.getStartTime());
record.setTriggerType(task.getTriggerType());
record.setFixedTriggerDuration(task.getFixedTriggerDuration() + NETWORK_PROFILING_DURATION);
record.setTargetType(EBPFProfilingTargetType.NETWORK.value());
record.setCreateTime(now.getTimeInMillis());
@ -256,12 +260,12 @@ public class EBPFProfilingMutationService implements Service {
}
// query exist processes
final List<EBPFProfilingTask> tasks = getProcessProfilingTaskDAO().queryTasksByTargets(
request.getServiceId(), null, Arrays.asList(request.getTargetType()), request.getStartTime(), 0);
final List<EBPFProfilingTaskRecord> tasks = getProcessProfilingTaskDAO().queryTasksByTargets(
request.getServiceId(), null, Arrays.asList(request.getTargetType()), EBPFProfilingTriggerType.FIXED_TIME, request.getStartTime(), 0);
if (CollectionUtils.isNotEmpty(tasks)) {
final EBPFProfilingTask mostRecentTask = tasks.stream()
.min(Comparator.comparingLong(EBPFProfilingTask::getTaskStartTime)).get();
if (mostRecentTask.getTaskStartTime() < calculateStartTime(request)) {
final EBPFProfilingTaskRecord mostRecentTask = tasks.stream()
.min(Comparator.comparingLong(EBPFProfilingTaskRecord::getStartTime)).get();
if (mostRecentTask.getStartTime() < calculateStartTime(request)) {
return "Task's time range overlaps with other tasks";
}
}

View File

@ -30,6 +30,8 @@ import org.apache.skywalking.oap.server.core.analysis.manual.process.ProcessTraf
import org.apache.skywalking.oap.server.core.analysis.metrics.Metrics;
import org.apache.skywalking.oap.server.core.profiling.ebpf.analyze.EBPFProfilingAnalyzer;
import org.apache.skywalking.oap.server.core.profiling.ebpf.storage.EBPFProfilingTargetType;
import org.apache.skywalking.oap.server.core.profiling.ebpf.storage.EBPFProfilingTaskRecord;
import org.apache.skywalking.oap.server.core.profiling.ebpf.storage.EBPFProfilingTriggerType;
import org.apache.skywalking.oap.server.core.query.enumeration.ProfilingSupportStatus;
import org.apache.skywalking.oap.server.core.query.type.Attribute;
import org.apache.skywalking.oap.server.core.query.type.EBPFProfilingAnalyzation;
@ -37,6 +39,8 @@ import org.apache.skywalking.oap.server.core.query.type.EBPFProfilingAnalyzeAggr
import org.apache.skywalking.oap.server.core.query.type.EBPFProfilingAnalyzeTimeRange;
import org.apache.skywalking.oap.server.core.query.type.EBPFProfilingSchedule;
import org.apache.skywalking.oap.server.core.query.type.EBPFProfilingTask;
import org.apache.skywalking.oap.server.core.query.type.EBPFProfilingTaskContinuousProfiling;
import org.apache.skywalking.oap.server.core.query.type.EBPFProfilingTaskExtension;
import org.apache.skywalking.oap.server.core.query.type.EBPFProfilingTaskPrepare;
import org.apache.skywalking.oap.server.core.query.type.Process;
import org.apache.skywalking.oap.server.core.storage.IMetricsDAO;
@ -57,11 +61,11 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;
@Slf4j
@ -173,22 +177,46 @@ public class EBPFProfilingQueryService implements Service {
return prepare;
}
public List<EBPFProfilingTask> queryEBPFProfilingTasks(String serviceId, String serviceInstanceId, List<EBPFProfilingTargetType> targets) throws IOException {
public List<EBPFProfilingTask> queryEBPFProfilingTasks(String serviceId, String serviceInstanceId, List<EBPFProfilingTargetType> targets, EBPFProfilingTriggerType triggerType) throws IOException {
if (CollectionUtils.isEmpty(targets)) {
targets = Arrays.asList(EBPFProfilingTargetType.values());
}
final List<EBPFProfilingTask> tasks = getTaskDAO().queryTasksByTargets(serviceId, serviceInstanceId, targets, 0, 0);
final List<EBPFProfilingTaskRecord> tasks = getTaskDAO().queryTasksByTargets(serviceId, serviceInstanceId, targets, triggerType, 0, 0);
// combine same id tasks
final LinkedHashMap<String, EBPFProfilingTask> tmpMap = new LinkedHashMap<>();
for (EBPFProfilingTask task : tasks) {
final EBPFProfilingTask p = tmpMap.get(task.getTaskId());
if (p == null) {
tmpMap.put(task.getTaskId(), task);
continue;
}
p.combine(task);
final Map<String, EBPFProfilingTaskRecord> records = tasks.stream().collect(Collectors.toMap(EBPFProfilingTaskRecord::getLogicalId, Function.identity(), EBPFProfilingTaskRecord::combine));
return records.values().stream().map(this::parseTask).collect(Collectors.toList());
}
private EBPFProfilingTask parseTask(EBPFProfilingTaskRecord record) {
final EBPFProfilingTask result = new EBPFProfilingTask();
result.setTaskId(record.getLogicalId());
result.setServiceId(record.getServiceId());
result.setServiceName(IDManager.ServiceID.analysisId(record.getServiceId()).getName());
if (StringUtil.isNotEmpty(record.getProcessLabelsJson())) {
result.setProcessLabels(GSON.<List<String>>fromJson(record.getProcessLabelsJson(), ArrayList.class));
} else {
result.setProcessLabels(Collections.emptyList());
}
return new ArrayList<>(tmpMap.values());
if (StringUtil.isNotEmpty(record.getInstanceId())) {
result.setServiceInstanceId(record.getInstanceId());
result.setServiceInstanceName(IDManager.ServiceInstanceID.analysisId(record.getInstanceId()).getName());
}
result.setTaskStartTime(record.getStartTime());
result.setTriggerType(EBPFProfilingTriggerType.valueOf(record.getTriggerType()));
result.setFixedTriggerDuration(record.getFixedTriggerDuration());
result.setTargetType(EBPFProfilingTargetType.valueOf(record.getTargetType()));
result.setCreateTime(record.getCreateTime());
result.setLastUpdateTime(record.getLastUpdateTime());
if (StringUtil.isNotEmpty(record.getExtensionConfigJson())) {
result.setExtensionConfig(GSON.fromJson(record.getExtensionConfigJson(), EBPFProfilingTaskExtension.class));
}
if (StringUtil.isNotEmpty(record.getContinuousProfilingJson())) {
final EBPFProfilingTaskContinuousProfiling continuousProfiling = GSON.fromJson(record.getContinuousProfilingJson(), EBPFProfilingTaskContinuousProfiling.class);
result.setProcessId(continuousProfiling.getProcessId());
result.setProcessName(continuousProfiling.getProcessName());
result.setContinuousProfilingCauses(continuousProfiling.getCauses());
}
return result;
}
public List<EBPFProfilingSchedule> queryEBPFProfilingSchedules(String taskId) throws Exception {

View File

@ -19,10 +19,12 @@
package org.apache.skywalking.oap.server.core.profiling.ebpf.storage;
import org.apache.skywalking.oap.server.core.UnexpectedException;
import org.apache.skywalking.oap.server.core.profiling.continuous.storage.ContinuousProfilingTargetType;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
/**
@ -30,29 +32,38 @@ import java.util.stream.Collectors;
*/
public enum EBPFProfilingTargetType {
UNKNOWN(0),
UNKNOWN(0, null),
ON_CPU(1),
ON_CPU(1, ContinuousProfilingTargetType.ON_CPU),
OFF_CPU(2),
OFF_CPU(2, ContinuousProfilingTargetType.OFF_CPU),
NETWORK(3),
NETWORK(3, ContinuousProfilingTargetType.NETWORK),
;
private final int value;
private final ContinuousProfilingTargetType continuousProfilingTargetType;
private static final Map<Integer, EBPFProfilingTargetType> DICTIONARY = new HashMap<>();
private static final Map<ContinuousProfilingTargetType, EBPFProfilingTargetType> CONTINUOUS_PROFILING_TARGET_DICTIONARY = new HashMap<>();
static {
Arrays.stream(EBPFProfilingTargetType.values()).collect(Collectors.toMap(EBPFProfilingTargetType::value, type -> type)).forEach(DICTIONARY::put);
Arrays.stream(EBPFProfilingTargetType.values()).filter(s -> Objects.nonNull(s.getContinuousProfilingTargetType()))
.collect(Collectors.toMap(EBPFProfilingTargetType::getContinuousProfilingTargetType, type -> type)).forEach(CONTINUOUS_PROFILING_TARGET_DICTIONARY::put);
}
EBPFProfilingTargetType(int value) {
EBPFProfilingTargetType(int value, ContinuousProfilingTargetType continuousProfilingTargetType) {
this.value = value;
this.continuousProfilingTargetType = continuousProfilingTargetType;
}
public int value() {
return value;
}
public ContinuousProfilingTargetType getContinuousProfilingTargetType() {
return continuousProfilingTargetType;
}
public static EBPFProfilingTargetType valueOf(int value) {
EBPFProfilingTargetType type = DICTIONARY.get(value);
if (type == null) {
@ -60,4 +71,12 @@ public enum EBPFProfilingTargetType {
}
return type;
}
public static EBPFProfilingTargetType valueOf(ContinuousProfilingTargetType value) {
EBPFProfilingTargetType type = CONTINUOUS_PROFILING_TARGET_DICTIONARY.get(value);
if (type == null) {
throw new UnexpectedException("Unknown ContinuousProfilingTargetType value: " + value);
}
return type;
}
}

View File

@ -55,9 +55,11 @@ public class EBPFProfilingTaskRecord extends NoneStream {
public static final String CREATE_TIME = "create_time";
public static final String LAST_UPDATE_TIME = "last_update_time";
public static final String EXTENSION_CONFIG_JSON = "extension_config_json";
public static final String CONTINUOUS_PROFILING_JSON = "continuous_profiling_json";
public static final int PROCESS_LABELS_JSON_MAX_LENGTH = 1000;
public static final int EXTENSION_CONFIG_JSON_MAX_LENGTH = 1000;
public static final int CONTINOUS_PROFILING_JSON_MAX_LENGTH = 1000;
@Column(name = LOGICAL_ID)
private String logicalId;
@ -82,6 +84,8 @@ public class EBPFProfilingTaskRecord extends NoneStream {
private long lastUpdateTime;
@Column(name = EXTENSION_CONFIG_JSON, length = EXTENSION_CONFIG_JSON_MAX_LENGTH, storageOnly = true)
private String extensionConfigJson;
@Column(name = CONTINUOUS_PROFILING_JSON, length = CONTINOUS_PROFILING_JSON_MAX_LENGTH, storageOnly = true)
private String continuousProfilingJson;
@Override
public StorageID id() {
@ -108,6 +112,20 @@ public class EBPFProfilingTaskRecord extends NoneStream {
.hash().toString();
}
/**
* combine the same task
* @param task have same {@link #logicalId}
*/
public EBPFProfilingTaskRecord combine(EBPFProfilingTaskRecord task) {
if (task.getFixedTriggerDuration() > this.getFixedTriggerDuration()) {
this.setFixedTriggerDuration(task.getFixedTriggerDuration());
}
if (task.getLastUpdateTime() > this.getLastUpdateTime()) {
this.setLastUpdateTime(task.getLastUpdateTime());
}
return this;
}
public static class Builder implements StorageBuilder<EBPFProfilingTaskRecord> {
@Override
@ -125,6 +143,7 @@ public class EBPFProfilingTaskRecord extends NoneStream {
record.setLastUpdateTime(((Number) converter.get(LAST_UPDATE_TIME)).longValue());
record.setTimeBucket(((Number) converter.get(TIME_BUCKET)).longValue());
record.setExtensionConfigJson((String) converter.get(EXTENSION_CONFIG_JSON));
record.setContinuousProfilingJson((String) converter.get(CONTINUOUS_PROFILING_JSON));
return record;
}
@ -142,6 +161,7 @@ public class EBPFProfilingTaskRecord extends NoneStream {
converter.accept(LAST_UPDATE_TIME, storageData.getLastUpdateTime());
converter.accept(TIME_BUCKET, storageData.getTimeBucket());
converter.accept(EXTENSION_CONFIG_JSON, storageData.getExtensionConfigJson());
converter.accept(CONTINUOUS_PROFILING_JSON, storageData.getContinuousProfilingJson());
}
}
}

View File

@ -36,6 +36,11 @@ public enum EBPFProfilingTriggerType {
* Appoint the task start time
*/
FIXED_TIME(1),
/**
* Trigger by the reach the continuous profiling policy
*/
CONTINUOUS_PROFILING(2)
;
private final int value;
private static final Map<Integer, EBPFProfilingTriggerType> DICTIONARY = new HashMap<>();

View File

@ -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.input;
import lombok.Data;
import java.util.List;
@Data
public class ContinuousProfilingPolicyCreation {
// service of the policy
private String serviceId;
// target of the policy
private List<ContinuousProfilingPolicyTargetCreation> targets;
}

View File

@ -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.query.input;
import lombok.Data;
import org.apache.skywalking.oap.server.core.profiling.continuous.storage.ContinuousProfilingMonitorType;
import java.util.List;
@Data
public class ContinuousProfilingPolicyItemCreation {
// define the monitor type to collect metrics
private ContinuousProfilingMonitorType type;
// threshold of policy, which decide by the monitor type
private String threshold;
// the length of time to evaluate the metrics
private int period;
// how many times after the metrics match the threshold, will trigger profiling
private int count;
// the URI path/regex filter when monitor the HTTP related types
private List<String> uriList;
private String uriRegex;
}

View File

@ -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.input;
import lombok.Data;
import org.apache.skywalking.oap.server.core.profiling.continuous.storage.ContinuousProfilingTargetType;
import java.util.List;
@Data
public class ContinuousProfilingPolicyTargetCreation {
// policy profiling target
private ContinuousProfilingTargetType targetType;
// target check thresholds
private List<ContinuousProfilingPolicyItemCreation> checkItems;
}

View File

@ -87,6 +87,8 @@ public class Entity {
return Objects.nonNull(serviceName) && Objects.nonNull(serviceInstanceName) && Objects.nonNull(normal);
case Endpoint:
return Objects.nonNull(serviceName) && Objects.nonNull(endpointName) && Objects.nonNull(normal);
case Process:
return Objects.nonNull(serviceName) && Objects.nonNull(serviceInstanceName) && Objects.nonNull(processName) && Objects.nonNull(normal);
case ServiceRelation:
return Objects.nonNull(serviceName) && Objects.nonNull(destServiceName)
&& Objects.nonNull(normal) && Objects.nonNull(destNormal);
@ -123,6 +125,8 @@ public class Entity {
IDManager.ServiceID.buildId(serviceName, normal), serviceInstanceName);
case Endpoint:
return IDManager.EndpointID.buildId(IDManager.ServiceID.buildId(serviceName, normal), endpointName);
case Process:
return IDManager.ProcessID.buildId(IDManager.ServiceInstanceID.buildId(IDManager.ServiceID.buildId(serviceName, normal), serviceInstanceName), processName);
case ServiceRelation:
return IDManager.ServiceID.buildRelationId(
new IDManager.ServiceID.ServiceRelationDefine(

View File

@ -0,0 +1,37 @@
/*
* 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.Data;
import org.apache.skywalking.oap.server.core.profiling.continuous.storage.ContinuousProfilingMonitorType;
import java.util.List;
/**
* Continuous profiling policy threshold item
*/
@Data
public class ContinuousProfilingPolicyItem {
private ContinuousProfilingMonitorType type;
private String threshold;
private Integer period;
private Integer count;
private List<String> uriList;
private String uriRegex;
}

View File

@ -0,0 +1,36 @@
/*
* 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.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.skywalking.oap.server.core.profiling.continuous.storage.ContinuousProfilingTargetType;
import java.util.List;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ContinuousProfilingPolicyTarget {
private ContinuousProfilingTargetType type;
private List<ContinuousProfilingPolicyItem> checkItems;
}

View File

@ -0,0 +1,33 @@
/*
* 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.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ContinuousProfilingSetResult {
private boolean status;
private String errorReason;
}

View File

@ -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.query.type;
import lombok.Data;
/**
* Continuous profiling single value based cause
*/
@Data
public class ContinuousProfilingSingleValueCause {
private long threshold;
private long current;
}

View File

@ -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.type;
import lombok.Data;
import org.apache.skywalking.oap.server.core.profiling.continuous.storage.ContinuousProfilingMonitorType;
/**
* Continuous profiling task single trigger casus
*/
@Data
public class ContinuousProfilingTriggeredCause {
private ContinuousProfilingMonitorType type;
private ContinuousProfilingSingleValueCause singleValue;
private ContinuousProfilingURICause uri;
}

View File

@ -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.type;
import lombok.Data;
/**
* Continuous profiling task URI-based cause
*/
@Data
public class ContinuousProfilingURICause {
private String uriRegex;
private String uriPath;
private long threshold;
private long current;
}

View File

@ -33,6 +33,8 @@ public class EBPFProfilingTask {
private String serviceInstanceId;
private String serviceInstanceName;
private List<String> processLabels;
private String processId;
private String processName;
private long taskStartTime;
private EBPFProfilingTriggerType triggerType;
private long fixedTriggerDuration;
@ -40,18 +42,6 @@ public class EBPFProfilingTask {
private long createTime;
private long lastUpdateTime;
private EBPFProfilingTaskExtension extensionConfig;
private List<ContinuousProfilingTriggeredCause> continuousProfilingCauses;
/**
* combine the same task
* @param task have same {@link #taskId}
*/
public EBPFProfilingTask combine(EBPFProfilingTask task) {
if (task.getFixedTriggerDuration() > this.getFixedTriggerDuration()) {
this.setFixedTriggerDuration(task.getFixedTriggerDuration());
}
if (task.getLastUpdateTime() > this.getLastUpdateTime()) {
this.setLastUpdateTime(task.getLastUpdateTime());
}
return this;
}
}

View File

@ -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.query.type;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
* Continuous profiling task configuration
*/
@Data
public class EBPFProfilingTaskContinuousProfiling {
private String processId;
private String processName;
private List<ContinuousProfilingTriggeredCause> causes;
public EBPFProfilingTaskContinuousProfiling() {
this.causes = new ArrayList<>();
}
}

View File

@ -123,6 +123,8 @@ public class DefaultScopeDefine {
public static final int SAMPLED_STATUS_4XX_TRACE = 66;
public static final int SAMPLED_STATUS_5XX_TRACE = 67;
public static final int CONTINUOUS_PROFILING_POLICY = 68;
/**
* Catalog of scope, the metrics processor could use this to group all generated metrics by oal rt.
*/

View File

@ -28,8 +28,9 @@ import org.apache.skywalking.oap.server.core.query.enumeration.ProfilingSupportS
import java.util.List;
import static org.apache.skywalking.oap.server.core.source.DefaultScopeDefine.PROCESS;
import static org.apache.skywalking.oap.server.core.source.DefaultScopeDefine.PROCESS_CATALOG_NAME;
@ScopeDeclaration(id = PROCESS, name = "Process")
@ScopeDeclaration(id = PROCESS, name = "Process", catalog = PROCESS_CATALOG_NAME)
@ScopeDefaultColumn.VirtualColumnDefinition(fieldName = "entityId", columnName = "entity_id", isID = true, type = String.class)
public class Process extends Source {
private volatile String entityId;

View File

@ -20,6 +20,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.profiling.continuous.IContinuousProfilingPolicyDAO;
import org.apache.skywalking.oap.server.core.storage.profiling.ebpf.IServiceLabelDAO;
import org.apache.skywalking.oap.server.core.storage.profiling.trace.IProfileTaskLogQueryDAO;
import org.apache.skywalking.oap.server.core.storage.profiling.trace.IProfileTaskQueryDAO;
@ -79,6 +80,7 @@ public class StorageModule extends ModuleDefine {
IEBPFProfilingTaskDAO.class,
IEBPFProfilingScheduleDAO.class,
IEBPFProfilingDataDAO.class,
IContinuousProfilingPolicyDAO.class,
IServiceLabelDAO.class,
ITagAutoCompleteQueryDAO.class,
IZipkinQueryDAO.class,

View File

@ -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.profiling.continuous;
import org.apache.skywalking.oap.server.core.profiling.continuous.storage.ContinuousProfilingPolicy;
import org.apache.skywalking.oap.server.core.storage.DAO;
import java.io.IOException;
import java.util.List;
public interface IContinuousProfilingPolicyDAO extends DAO {
/**
* save the policy, insert if not absent
*/
void savePolicy(ContinuousProfilingPolicy policy) throws IOException;
/**
* query policies from services
*/
List<ContinuousProfilingPolicy> queryPolicies(List<String> serviceIdList) throws IOException;
}

View File

@ -20,7 +20,7 @@ package org.apache.skywalking.oap.server.core.storage.profiling.ebpf;
import org.apache.skywalking.oap.server.core.profiling.ebpf.storage.EBPFProfilingTargetType;
import org.apache.skywalking.oap.server.core.profiling.ebpf.storage.EBPFProfilingTaskRecord;
import org.apache.skywalking.oap.server.core.query.type.EBPFProfilingTask;
import org.apache.skywalking.oap.server.core.profiling.ebpf.storage.EBPFProfilingTriggerType;
import org.apache.skywalking.oap.server.core.storage.DAO;
import java.io.IOException;
@ -35,21 +35,21 @@ public interface IEBPFProfilingTaskDAO extends DAO {
* Query profiling task through service id list
* @param serviceIdList cannot be empty
*/
List<EBPFProfilingTask> queryTasksByServices(List<String> serviceIdList,
List<EBPFProfilingTaskRecord> queryTasksByServices(List<String> serviceIdList, EBPFProfilingTriggerType triggerType,
long taskStartTime, long latestUpdateTime) throws IOException;
/**
* Query profiling task through target types
* @param targetTypes cannot be empty
*/
List<EBPFProfilingTask> queryTasksByTargets(String serviceId, String serviceInstanceId,
List<EBPFProfilingTaskRecord> queryTasksByTargets(String serviceId, String serviceInstanceId,
List<EBPFProfilingTargetType> targetTypes,
EBPFProfilingTriggerType triggerType,
long taskStartTime, long latestUpdateTime) throws IOException;
/**
* Query profiling task
* Query profiling task by logical ID
* @param id {@link EBPFProfilingTaskRecord#getLogicalId()}
* @return use {@link EBPFProfilingTask#combine(EBPFProfilingTask)} to combine all task result
*/
EBPFProfilingTask queryById(String id) throws IOException;
List<EBPFProfilingTaskRecord> getTaskRecord(String id) throws IOException;
}

View File

@ -26,6 +26,6 @@ public class CoreModuleTest {
public void testOpenServiceList() {
CoreModule coreModule = new CoreModule();
Assertions.assertEquals(38, coreModule.services().length);
Assertions.assertEquals(40, coreModule.services().length);
}
}

View File

@ -26,6 +26,8 @@ import java.util.Collections;
import org.apache.skywalking.oap.query.graphql.resolver.AggregationQuery;
import org.apache.skywalking.oap.query.graphql.resolver.AlarmQuery;
import org.apache.skywalking.oap.query.graphql.resolver.BrowserLogQuery;
import org.apache.skywalking.oap.query.graphql.resolver.ContinuousProfilingMutation;
import org.apache.skywalking.oap.query.graphql.resolver.ContinuousProfilingQuery;
import org.apache.skywalking.oap.query.graphql.resolver.EBPFProcessProfilingMutation;
import org.apache.skywalking.oap.query.graphql.resolver.EBPFProcessProfilingQuery;
import org.apache.skywalking.oap.query.graphql.resolver.EventQuery;
@ -132,6 +134,8 @@ public class GraphQLQueryProvider extends ModuleProvider {
.resolvers(metadataQueryV2)
.file("query-protocol/ebpf-profiling.graphqls")
.resolvers(new EBPFProcessProfilingQuery(getManager()), new EBPFProcessProfilingMutation(getManager()))
.file("query-protocol/continuous-profiling.graphqls")
.resolvers(new ContinuousProfilingQuery(getManager()), new ContinuousProfilingMutation(getManager()))
.file("query-protocol/record.graphqls")
.resolvers(new RecordsQuery(getManager()));

View File

@ -0,0 +1,52 @@
/*
* 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 graphql.kickstart.tools.GraphQLMutationResolver;
import org.apache.skywalking.oap.server.core.CoreModule;
import org.apache.skywalking.oap.server.core.profiling.continuous.ContinuousProfilingMutationService;
import org.apache.skywalking.oap.server.core.query.input.ContinuousProfilingPolicyCreation;
import org.apache.skywalking.oap.server.core.query.type.ContinuousProfilingSetResult;
import org.apache.skywalking.oap.server.library.module.ModuleManager;
import java.io.IOException;
public class ContinuousProfilingMutation implements GraphQLMutationResolver {
private final ModuleManager moduleManager;
private ContinuousProfilingMutationService mutationService;
public ContinuousProfilingMutation(ModuleManager moduleManager) {
this.moduleManager = moduleManager;
}
private ContinuousProfilingMutationService getMutationService() {
if (mutationService == null) {
this.mutationService = moduleManager.find(CoreModule.NAME)
.provider()
.getService(ContinuousProfilingMutationService.class);
}
return mutationService;
}
public ContinuousProfilingSetResult setContinuousProfilingPolicy(ContinuousProfilingPolicyCreation request) throws IOException {
return getMutationService().setContinuousProfilingPolicy(request);
}
}

View File

@ -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.
*
*/
package org.apache.skywalking.oap.query.graphql.resolver;
import graphql.kickstart.tools.GraphQLQueryResolver;
import org.apache.skywalking.oap.server.core.CoreModule;
import org.apache.skywalking.oap.server.core.profiling.continuous.ContinuousProfilingQueryService;
import org.apache.skywalking.oap.server.core.query.type.ContinuousProfilingPolicyTarget;
import org.apache.skywalking.oap.server.library.module.ModuleManager;
import java.io.IOException;
import java.util.List;
public class ContinuousProfilingQuery implements GraphQLQueryResolver {
private final ModuleManager moduleManager;
private ContinuousProfilingQueryService queryService;
public ContinuousProfilingQuery(ModuleManager moduleManager) {
this.moduleManager = moduleManager;
}
private ContinuousProfilingQueryService getQueryService() {
if (queryService == null) {
queryService = this.moduleManager.find(CoreModule.NAME)
.provider().getService(ContinuousProfilingQueryService.class);
}
return queryService;
}
public List<ContinuousProfilingPolicyTarget> queryContinuousProfilingServiceTargets(String serviceId) throws IOException {
return getQueryService().queryContinuousProfilingServiceTargets(serviceId);
}
}

View File

@ -22,6 +22,7 @@ import graphql.kickstart.tools.GraphQLQueryResolver;
import org.apache.skywalking.oap.server.core.CoreModule;
import org.apache.skywalking.oap.server.core.profiling.ebpf.EBPFProfilingQueryService;
import org.apache.skywalking.oap.server.core.profiling.ebpf.storage.EBPFProfilingTargetType;
import org.apache.skywalking.oap.server.core.profiling.ebpf.storage.EBPFProfilingTriggerType;
import org.apache.skywalking.oap.server.core.query.type.EBPFProfilingAnalyzation;
import org.apache.skywalking.oap.server.core.query.type.EBPFProfilingAnalyzeAggregateType;
import org.apache.skywalking.oap.server.core.query.type.EBPFProfilingAnalyzeTimeRange;
@ -59,11 +60,14 @@ public class EBPFProcessProfilingQuery implements GraphQLQueryResolver {
return getQueryService().queryPrepareCreateEBPFProfilingTaskData(serviceId);
}
public List<EBPFProfilingTask> queryEBPFProfilingTasks(String serviceId, String serviceInstanceId, List<EBPFProfilingTargetType> targets) throws IOException {
public List<EBPFProfilingTask> queryEBPFProfilingTasks(String serviceId, String serviceInstanceId, List<EBPFProfilingTargetType> targets, EBPFProfilingTriggerType triggerType) throws IOException {
if (StringUtil.isEmpty(serviceId) && StringUtil.isEmpty(serviceInstanceId)) {
throw new IllegalArgumentException("please provide the service id or instance id");
}
return getQueryService().queryEBPFProfilingTasks(serviceId, serviceInstanceId, targets);
if (triggerType == null) {
triggerType = EBPFProfilingTriggerType.FIXED_TIME;
}
return getQueryService().queryEBPFProfilingTasks(serviceId, serviceInstanceId, targets, triggerType);
}
public List<EBPFProfilingSchedule> queryEBPFProfilingSchedules(String taskId) throws Exception {

@ -1 +1 @@
Subproject commit 450328c6445d4dc50a868a0b797a14755f1d82cc
Subproject commit 4749946962b9c685111876d1abe8c745d3cf3253

View File

@ -0,0 +1,33 @@
/*
* 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.receiver.ebpf.provider;
import lombok.Getter;
import lombok.Setter;
import org.apache.skywalking.oap.server.library.module.ModuleConfig;
@Getter
public class EBPFReceiverModuleConfig extends ModuleConfig {
/**
* The continuous profiling policy cache time, Unit is second. Default value is 60 seconds.
*/
@Setter
private int continuousPolicyCacheTimeout = 60;
}

View File

@ -25,12 +25,15 @@ import org.apache.skywalking.oap.server.library.module.ModuleProvider;
import org.apache.skywalking.oap.server.library.module.ModuleStartException;
import org.apache.skywalking.oap.server.library.module.ServiceNotProvidedException;
import org.apache.skywalking.oap.server.receiver.ebpf.module.EBPFReceiverModule;
import org.apache.skywalking.oap.server.receiver.ebpf.provider.handler.ContinuousProfilingServiceHandler;
import org.apache.skywalking.oap.server.receiver.ebpf.provider.handler.EBPFProcessServiceHandler;
import org.apache.skywalking.oap.server.receiver.ebpf.provider.handler.EBPFProfilingServiceHandler;
import org.apache.skywalking.oap.server.receiver.sharing.server.SharingServerModule;
public class EBPFReceiverProvider extends ModuleProvider {
private EBPFReceiverModuleConfig config;
@Override
public String name() {
return "default";
@ -42,8 +45,18 @@ public class EBPFReceiverProvider extends ModuleProvider {
}
@Override
public ConfigCreator newConfigCreator() {
return null;
public ConfigCreator<EBPFReceiverModuleConfig> newConfigCreator() {
return new ConfigCreator<EBPFReceiverModuleConfig>() {
@Override
public Class<EBPFReceiverModuleConfig> type() {
return EBPFReceiverModuleConfig.class;
}
@Override
public void onInitialized(EBPFReceiverModuleConfig initialized) {
config = initialized;
}
};
}
@Override
@ -57,6 +70,7 @@ public class EBPFReceiverProvider extends ModuleProvider {
.getService(GRPCHandlerRegister.class);
grpcHandlerRegister.addHandler(new EBPFProcessServiceHandler(getManager()));
grpcHandlerRegister.addHandler(new EBPFProfilingServiceHandler(getManager()));
grpcHandlerRegister.addHandler(new ContinuousProfilingServiceHandler(getManager(), this.config));
}
@Override

View File

@ -0,0 +1,266 @@
/*
* 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.receiver.ebpf.provider.handler;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.gson.Gson;
import io.grpc.stub.StreamObserver;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.apm.network.common.v3.Commands;
import org.apache.skywalking.apm.network.ebpf.profiling.v3.ContinuousProfilingCause;
import org.apache.skywalking.apm.network.ebpf.profiling.v3.ContinuousProfilingPolicyQuery;
import org.apache.skywalking.apm.network.ebpf.profiling.v3.ContinuousProfilingReport;
import org.apache.skywalking.apm.network.ebpf.profiling.v3.ContinuousProfilingServiceGrpc;
import org.apache.skywalking.apm.network.ebpf.profiling.v3.ContinuousProfilingServicePolicyQuery;
import org.apache.skywalking.oap.server.core.Const;
import org.apache.skywalking.oap.server.core.CoreModule;
import org.apache.skywalking.oap.server.core.analysis.IDManager;
import org.apache.skywalking.oap.server.core.analysis.worker.NoneStreamProcessor;
import org.apache.skywalking.oap.server.core.command.CommandService;
import org.apache.skywalking.oap.server.core.profiling.continuous.storage.ContinuousProfilingMonitorType;
import org.apache.skywalking.oap.server.core.profiling.continuous.storage.ContinuousProfilingPolicy;
import org.apache.skywalking.oap.server.core.profiling.ebpf.storage.EBPFProfilingTargetType;
import org.apache.skywalking.oap.server.core.profiling.ebpf.storage.EBPFProfilingTaskRecord;
import org.apache.skywalking.oap.server.core.profiling.ebpf.storage.EBPFProfilingTriggerType;
import org.apache.skywalking.oap.server.core.query.input.EBPFNetworkDataCollectingSettings;
import org.apache.skywalking.oap.server.core.query.input.EBPFNetworkSamplingRule;
import org.apache.skywalking.oap.server.core.query.type.ContinuousProfilingSingleValueCause;
import org.apache.skywalking.oap.server.core.query.type.ContinuousProfilingTriggeredCause;
import org.apache.skywalking.oap.server.core.query.type.ContinuousProfilingURICause;
import org.apache.skywalking.oap.server.core.query.type.EBPFProfilingTaskContinuousProfiling;
import org.apache.skywalking.oap.server.core.query.type.EBPFProfilingTaskExtension;
import org.apache.skywalking.oap.server.core.storage.StorageModule;
import org.apache.skywalking.oap.server.core.storage.profiling.continuous.IContinuousProfilingPolicyDAO;
import org.apache.skywalking.oap.server.library.module.ModuleManager;
import org.apache.skywalking.oap.server.library.server.grpc.GRPCHandler;
import org.apache.skywalking.oap.server.library.util.CollectionUtils;
import org.apache.skywalking.oap.server.library.util.StringUtil;
import org.apache.skywalking.oap.server.network.trace.component.command.ContinuousProfilingPolicyCommand;
import org.apache.skywalking.oap.server.receiver.ebpf.provider.EBPFReceiverModuleConfig;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@Slf4j
public class ContinuousProfilingServiceHandler extends ContinuousProfilingServiceGrpc.ContinuousProfilingServiceImplBase implements GRPCHandler {
private static final Gson GSON = new Gson();
private IContinuousProfilingPolicyDAO policyDAO;
private final CommandService commandService;
private final Cache<String, PolicyWrapper> policyCache;
public ContinuousProfilingServiceHandler(ModuleManager moduleManager, EBPFReceiverModuleConfig config) {
this.policyDAO = moduleManager.find(StorageModule.NAME).provider().getService(IContinuousProfilingPolicyDAO.class);
this.commandService = moduleManager.find(CoreModule.NAME).provider().getService(CommandService.class);
this.policyCache = CacheBuilder.newBuilder()
.expireAfterWrite(config.getContinuousPolicyCacheTimeout(), TimeUnit.SECONDS)
.build();
}
@Override
public void queryPolicies(ContinuousProfilingPolicyQuery request, StreamObserver<Commands> responseObserver) {
final Map<String, String> policiesQuery = request.getPoliciesList().stream()
.collect(Collectors.toMap(s -> IDManager.ServiceID.buildId(s.getServiceName(), true), ContinuousProfilingServicePolicyQuery::getUuid, (s1, s2) -> s1));
if (CollectionUtils.isEmpty(policiesQuery)) {
responseObserver.onNext(Commands.newBuilder().build());
responseObserver.onCompleted();
return;
}
try {
final List<String> serviceIdList = new ArrayList<>(policiesQuery.keySet());
final HashMap<String, ContinuousProfilingPolicy> policiesInDB = new HashMap<>();
// query from the cache first
for (ListIterator<String> serviceIdIt = serviceIdList.listIterator(); serviceIdIt.hasNext(); ) {
final String serviceId = serviceIdIt.next();
final PolicyWrapper wrapper = this.policyCache.getIfPresent(serviceId);
if (wrapper == null) {
continue;
}
serviceIdIt.remove();
if (wrapper.policy != null) {
policiesInDB.put(serviceId, wrapper.policy);
}
}
// query the policies which not in the cache
final List<ContinuousProfilingPolicy> queriedFromDB = policyDAO.queryPolicies(serviceIdList);
for (ContinuousProfilingPolicy dbPolicy : queriedFromDB) {
policiesInDB.put(dbPolicy.getServiceId(), dbPolicy);
this.policyCache.put(dbPolicy.getServiceId(), new PolicyWrapper(dbPolicy));
serviceIdList.remove(dbPolicy.getServiceId());
}
// Also add the cache if the service haven't policy
for (String serviceId : serviceIdList) {
this.policyCache.put(serviceId, new PolicyWrapper(null));
}
final ArrayList<ContinuousProfilingPolicy> updatePolicies = new ArrayList<>();
for (Map.Entry<String, String> entry : policiesQuery.entrySet()) {
final String serviceId = entry.getKey();
final ContinuousProfilingPolicy policyInDB = policiesInDB.get(serviceId);
// policy not exist in DB or uuid not same
// needs to send commands to downstream
if (policyInDB == null && StringUtil.isNotEmpty(entry.getValue())) {
final ContinuousProfilingPolicy emptyPolicy = new ContinuousProfilingPolicy();
emptyPolicy.setServiceId(entry.getKey());
emptyPolicy.setUuid("");
updatePolicies.add(emptyPolicy);
} else if (policyInDB != null && !Objects.equals(policyInDB.getUuid(), entry.getValue())) {
updatePolicies.add(policyInDB);
}
}
if (CollectionUtils.isEmpty(updatePolicies)) {
sendEmptyCommands(responseObserver);
return;
}
final ContinuousProfilingPolicyCommand command = commandService.newContinuousProfilingServicePolicyCommand(updatePolicies);
final Commands.Builder builder = Commands.newBuilder();
builder.addCommands(command.serialize());
responseObserver.onNext(builder.build());
responseObserver.onCompleted();
return;
} catch (Exception e) {
log.warn("query continuous profiling service policies failure", e);
}
sendEmptyCommands(responseObserver);
}
private void sendEmptyCommands(StreamObserver<Commands> responseObserver) {
responseObserver.onNext(Commands.newBuilder().build());
responseObserver.onCompleted();
}
@Override
public void reportProfilingTask(ContinuousProfilingReport request, StreamObserver<Commands> responseObserver) {
// set up the task record
final long currentTime = System.currentTimeMillis();
final EBPFProfilingTaskRecord task = new EBPFProfilingTaskRecord();
final String serviceId = IDManager.ServiceID.buildId(request.getServiceName(), true);
final String instanceId = IDManager.ServiceInstanceID.buildId(serviceId, request.getInstanceName());
final String processId = IDManager.ProcessID.buildId(instanceId, request.getProcessName());
task.setServiceId(serviceId);
task.setProcessLabelsJson(Const.EMPTY_STRING);
task.setInstanceId(instanceId);
task.setStartTime(currentTime);
task.setTriggerType(EBPFProfilingTriggerType.CONTINUOUS_PROFILING.value());
task.setFixedTriggerDuration(request.getDuration());
task.setCreateTime(currentTime);
task.setLastUpdateTime(currentTime);
final EBPFProfilingTaskContinuousProfiling continuousProfiling = new EBPFProfilingTaskContinuousProfiling();
continuousProfiling.setProcessId(processId);
continuousProfiling.setProcessName(request.getProcessName());
continuousProfiling.setCauses(request.getCausesList().stream().map(this::parseTaskCause).collect(Collectors.toList()));
settingTargetTask(request, task, continuousProfiling);
task.setContinuousProfilingJson(GSON.toJson(continuousProfiling));
task.generateLogicalId();
// save the profiling task
NoneStreamProcessor.getInstance().in(task);
final Commands.Builder builder = Commands.newBuilder();
builder.addCommands(commandService.newContinuousProfilingReportCommand(task.getLogicalId()).serialize());
responseObserver.onNext(builder.build());
responseObserver.onCompleted();
}
private void settingTargetTask(ContinuousProfilingReport request, EBPFProfilingTaskRecord task, EBPFProfilingTaskContinuousProfiling continuousProfiling) {
switch (request.getTargetTaskCase()) {
case ONCPU:
task.setTargetType(EBPFProfilingTargetType.ON_CPU.value());
break;
case OFFCPU:
task.setTargetType(EBPFProfilingTargetType.OFF_CPU.value());
break;
case NETWORK:
task.setTargetType(EBPFProfilingTargetType.NETWORK.value());
final EBPFProfilingTaskExtension networkExtension = new EBPFProfilingTaskExtension();
networkExtension.setNetworkSamplings(request.getNetwork().getSamplingURIRegexesList().stream().map(uri -> {
final EBPFNetworkSamplingRule rule = new EBPFNetworkSamplingRule();
rule.setMinDuration(0);
rule.setWhen4xx(true);
rule.setWhen5xx(true);
final EBPFNetworkDataCollectingSettings setting = new EBPFNetworkDataCollectingSettings();
setting.setRequireCompleteRequest(true);
setting.setRequireCompleteResponse(true);
rule.setSettings(setting);
return rule;
}).collect(Collectors.toList()));
task.setExtensionConfigJson(GSON.toJson(networkExtension));
break;
default:
throw new IllegalArgumentException("the continuous profiling task type cannot recognized");
}
}
private ContinuousProfilingTriggeredCause parseTaskCause(ContinuousProfilingCause cause) {
final ContinuousProfilingTriggeredCause result = new ContinuousProfilingTriggeredCause();
result.setType(ContinuousProfilingMonitorType.valueOf(cause.getType()));
switch (cause.getCauseCase()) {
case SINGLEVALUE:
final ContinuousProfilingSingleValueCause singleValue = new ContinuousProfilingSingleValueCause();
singleValue.setThreshold(thresholdToLong(cause.getSingleValue().getThreshold()));
singleValue.setCurrent(thresholdToLong(cause.getSingleValue().getCurrent()));
result.setSingleValue(singleValue);
break;
case URI:
final ContinuousProfilingURICause uriCause = new ContinuousProfilingURICause();
switch (cause.getUri().getUriCase()) {
case PATH:
uriCause.setUriPath(cause.getUri().getPath());
break;
case REGEX:
uriCause.setUriRegex(cause.getUri().getRegex());
break;
default:
throw new IllegalArgumentException("the uri case not set");
}
uriCause.setThreshold(thresholdToLong(cause.getUri().getThreshold()));
uriCause.setCurrent(thresholdToLong(cause.getUri().getCurrent()));
result.setUri(uriCause);
break;
}
return result;
}
private long thresholdToLong(double val) {
return (long) (val * 100);
}
@AllArgsConstructor
private static class PolicyWrapper {
final ContinuousProfilingPolicy policy;
}
}

View File

@ -19,6 +19,7 @@
package org.apache.skywalking.oap.server.receiver.ebpf.provider.handler;
import com.google.common.base.Joiner;
import com.google.gson.Gson;
import io.grpc.Status;
import io.grpc.stub.StreamObserver;
import io.vavr.Tuple;
@ -35,8 +36,9 @@ import org.apache.skywalking.oap.server.core.CoreModule;
import org.apache.skywalking.oap.server.core.command.CommandService;
import org.apache.skywalking.oap.server.core.profiling.ebpf.storage.EBPFProfilingStackType;
import org.apache.skywalking.oap.server.core.profiling.ebpf.storage.EBPFProfilingTargetType;
import org.apache.skywalking.oap.server.core.profiling.ebpf.storage.EBPFProfilingTaskRecord;
import org.apache.skywalking.oap.server.core.profiling.ebpf.storage.EBPFProfilingTriggerType;
import org.apache.skywalking.oap.server.core.query.enumeration.ProfilingSupportStatus;
import org.apache.skywalking.oap.server.core.query.type.EBPFProfilingTask;
import org.apache.skywalking.oap.server.core.query.type.Process;
import org.apache.skywalking.oap.server.core.source.EBPFProfilingData;
import org.apache.skywalking.oap.server.core.source.EBPFProcessProfilingSchedule;
@ -47,6 +49,7 @@ import org.apache.skywalking.oap.server.core.storage.query.IMetadataQueryDAO;
import org.apache.skywalking.oap.server.library.module.ModuleManager;
import org.apache.skywalking.oap.server.library.server.grpc.GRPCHandler;
import org.apache.skywalking.oap.server.library.util.CollectionUtils;
import org.apache.skywalking.oap.server.library.util.StringUtil;
import org.apache.skywalking.oap.server.network.trace.component.command.EBPFProfilingTaskCommand;
import java.io.IOException;
@ -64,6 +67,7 @@ import java.util.stream.Collectors;
*/
@Slf4j
public class EBPFProfilingServiceHandler extends EBPFProfilingServiceGrpc.EBPFProfilingServiceImplBase implements GRPCHandler {
private static final Gson GSON = new Gson();
public static final List<EBPFProfilingStackType> COMMON_STACK_TYPE_ORDER = Arrays.asList(
EBPFProfilingStackType.KERNEL_SPACE, EBPFProfilingStackType.USER_SPACE);
@ -94,10 +98,10 @@ public class EBPFProfilingServiceHandler extends EBPFProfilingServiceGrpc.EBPFPr
// fetch tasks from process id list
final List<String> serviceIdList = processes.stream().map(Process::getServiceId).distinct().collect(Collectors.toList());
final List<EBPFProfilingTask> tasks = taskDAO.queryTasksByServices(serviceIdList, 0, latestUpdateTime);
final List<EBPFProfilingTaskRecord> tasks = taskDAO.queryTasksByServices(serviceIdList, EBPFProfilingTriggerType.FIXED_TIME, 0, latestUpdateTime);
final Commands.Builder builder = Commands.newBuilder();
tasks.stream().collect(Collectors.toMap(EBPFProfilingTask::getTaskId, Function.identity(), EBPFProfilingTask::combine))
tasks.stream().collect(Collectors.toMap(EBPFProfilingTaskRecord::getLogicalId, Function.identity(), EBPFProfilingTaskRecord::combine))
.values().stream().flatMap(t -> this.buildProfilingCommands(t, processes).stream())
.map(EBPFProfilingTaskCommand::serialize).forEach(builder::addCommands);
responseObserver.onNext(builder.build());
@ -110,9 +114,9 @@ public class EBPFProfilingServiceHandler extends EBPFProfilingServiceGrpc.EBPFPr
responseObserver.onCompleted();
}
private List<EBPFProfilingTaskCommand> buildProfilingCommands(EBPFProfilingTask task, List<Process> processes) {
if (EBPFProfilingTargetType.NETWORK.equals(task.getTargetType())) {
final List<String> processIdList = processes.stream().filter(p -> Objects.equals(p.getInstanceId(), task.getServiceInstanceId())).map(Process::getId).collect(Collectors.toList());
private List<EBPFProfilingTaskCommand> buildProfilingCommands(EBPFProfilingTaskRecord task, List<Process> processes) {
if (EBPFProfilingTargetType.NETWORK.value() == task.getTargetType()) {
final List<String> processIdList = processes.stream().filter(p -> Objects.equals(p.getInstanceId(), task.getInstanceId())).map(Process::getId).collect(Collectors.toList());
if (CollectionUtils.isEmpty(processIdList)) {
return Collections.emptyList();
}
@ -127,8 +131,12 @@ public class EBPFProfilingServiceHandler extends EBPFProfilingServiceGrpc.EBPFPr
}
// If the task doesn't require a label or the process match all labels in task
if (CollectionUtils.isEmpty(task.getProcessLabels())
|| process.getLabels().containsAll(task.getProcessLabels())) {
List<String> processLabels = Collections.emptyList();
if (StringUtil.isNotEmpty(task.getProcessLabelsJson())) {
processLabels = GSON.<List<String>>fromJson(task.getProcessLabelsJson(), ArrayList.class);
}
if (CollectionUtils.isEmpty(processLabels)
|| process.getLabels().containsAll(processLabels)) {
commands.add(commandService.newEBPFProfilingTaskCommand(task, Collections.singletonList(process.getId())));
}
}

View File

@ -231,7 +231,7 @@ agent-analyzer:
# Nginx and Envoy agents can't get the real remote address.
# Exit spans with the component in the list would not generate the client-side instance relation metrics.
noUpstreamRealAddressAgents: ${SW_NO_UPSTREAM_REAL_ADDRESS:6000,9000}
meterAnalyzerActiveFiles: ${SW_METER_ANALYZER_ACTIVE_FILES:datasource,threadpool,satellite,go-runtime,python-runtime} # Which files could be meter analyzed, files split by ","
meterAnalyzerActiveFiles: ${SW_METER_ANALYZER_ACTIVE_FILES:datasource,threadpool,satellite,go-runtime,python-runtime,continuous-profiling} # Which files could be meter analyzed, files split by ","
slowCacheReadThreshold: ${SW_SLOW_CACHE_SLOW_READ_THRESHOLD:default:20,redis:10} # The slow cache write operation thresholds. Unit ms.
slowCacheWriteThreshold: ${SW_SLOW_CACHE_SLOW_WRITE_THRESHOLD:default:20,redis:10} # The slow cache write operation thresholds. Unit ms.
@ -527,6 +527,8 @@ receiver-event:
receiver-ebpf:
selector: ${SW_RECEIVER_EBPF:default}
default:
# The continuous profiling policy cache time, Unit is second.
continuousPolicyCacheTimeout: ${SW_CONTINUOUS_POLICY_CACHE_TIMEOUT:60}
receiver-telegraf:
selector: ${SW_RECEIVER_TELEGRAF:default}

View File

@ -0,0 +1,28 @@
# 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.
expSuffix: process(['service'], ['instance'], ['process_name'], 'layer')
metricPrefix: continuous_profiling
metricsRules:
- name: process_cpu
exp: rover_con_p_process_cpu.avg(["service", "instance", "process_name", "layer"]).multiply(10000)
- name: process_thread_count
exp: rover_con_p_process_thread_count.avg(["service", "instance", "process_name", "layer"])
- name: system_load
exp: rover_con_p_system_load.avg(["service", "instance", "process_name", "layer"]).multiply(100)
- name: http_error_rate
exp: rover_con_p_http_error_rate.avg(["service", "instance", "process_name", "layer", "uri"]).multiply(100)
- name: http_avg_response_time
exp: rover_con_p_http_avg_response_time.avg(["service", "instance", "process_name", "layer", "uri"])

View File

@ -30,6 +30,7 @@ import org.apache.skywalking.oap.server.core.storage.cache.INetworkAddressAliasD
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.model.ModelInstaller;
import org.apache.skywalking.oap.server.core.storage.profiling.continuous.IContinuousProfilingPolicyDAO;
import org.apache.skywalking.oap.server.core.storage.profiling.ebpf.IEBPFProfilingDataDAO;
import org.apache.skywalking.oap.server.core.storage.profiling.ebpf.IEBPFProfilingScheduleDAO;
import org.apache.skywalking.oap.server.core.storage.profiling.ebpf.IEBPFProfilingTaskDAO;
@ -64,6 +65,7 @@ import org.apache.skywalking.oap.server.storage.plugin.banyandb.measure.BanyanDB
import org.apache.skywalking.oap.server.storage.plugin.banyandb.measure.BanyanDBTopologyQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.banyandb.stream.BanyanDBAlarmQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.banyandb.stream.BanyanDBBrowserLogQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.banyandb.stream.BanyanDBContinuousProfilingPolicyDAO;
import org.apache.skywalking.oap.server.storage.plugin.banyandb.stream.BanyanDBEBPFProfilingDataDAO;
import org.apache.skywalking.oap.server.storage.plugin.banyandb.stream.BanyanDBEBPFProfilingTaskDAO;
import org.apache.skywalking.oap.server.storage.plugin.banyandb.stream.BanyanDBHistoryDeleteDAO;
@ -149,6 +151,7 @@ public class BanyanDBStorageProvider extends ModuleProvider {
this.registerServiceImplementation(IEBPFProfilingDataDAO.class, new BanyanDBEBPFProfilingDataDAO(client));
this.registerServiceImplementation(
IEBPFProfilingScheduleDAO.class, new BanyanDBEBPFProfilingScheduleQueryDAO(client));
this.registerServiceImplementation(IContinuousProfilingPolicyDAO.class, new BanyanDBContinuousProfilingPolicyDAO(client));
this.registerServiceImplementation(IServiceLabelDAO.class, new BanyanDBServiceLabelDAO(client));
this.registerServiceImplementation(ITagAutoCompleteQueryDAO.class, new BanyanDBTagAutocompleteQueryDAO(client));

View File

@ -0,0 +1,80 @@
/*
* 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.banyandb.stream;
import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.banyandb.v1.client.TagAndValue;
import org.apache.skywalking.banyandb.v1.client.metadata.Property;
import org.apache.skywalking.oap.server.core.profiling.continuous.storage.ContinuousProfilingPolicy;
import org.apache.skywalking.oap.server.core.storage.profiling.continuous.IContinuousProfilingPolicyDAO;
import org.apache.skywalking.oap.server.storage.plugin.banyandb.BanyanDBStorageClient;
import java.io.IOException;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
@Slf4j
public class BanyanDBContinuousProfilingPolicyDAO extends AbstractBanyanDBDAO implements IContinuousProfilingPolicyDAO {
private static final String GROUP = "sw";
public BanyanDBContinuousProfilingPolicyDAO(BanyanDBStorageClient client) {
super(client);
}
@Override
public void savePolicy(ContinuousProfilingPolicy policy) throws IOException {
try {
this.getClient().define(applyAll(policy));
} catch (IOException e) {
log.error("fail to save policy", e);
}
}
public Property applyAll(ContinuousProfilingPolicy policy) {
return Property.create(GROUP, ContinuousProfilingPolicy.INDEX_NAME, policy.id().build())
.addTag(TagAndValue.newStringTag(ContinuousProfilingPolicy.UUID, policy.getUuid()))
.addTag(TagAndValue.newStringTag(ContinuousProfilingPolicy.CONFIGURATION_JSON, policy.getConfigurationJson()))
.build();
}
@Override
public List<ContinuousProfilingPolicy> queryPolicies(List<String> serviceIdList) throws IOException {
return serviceIdList.stream().map(s -> {
try {
return getClient().queryProperty(GROUP, ContinuousProfilingPolicy.INDEX_NAME, s);
} catch (IOException e) {
log.warn("query policy error", e);
return null;
}
}).filter(Objects::nonNull).map(properties -> {
final ContinuousProfilingPolicy policy = new ContinuousProfilingPolicy();
policy.setServiceId(properties.id());
for (TagAndValue<?> tag : properties.tags()) {
if (tag.getTagName().equals(ContinuousProfilingPolicy.CONFIGURATION_JSON)) {
policy.setConfigurationJson((String) tag.getValue());
} else if (tag.getTagName().equals(ContinuousProfilingPolicy.UUID)) {
policy.setUuid((String) tag.getValue());
}
}
return policy;
}).collect(Collectors.toList());
}
}

View File

@ -19,17 +19,13 @@
package org.apache.skywalking.oap.server.storage.plugin.banyandb.stream;
import com.google.common.collect.ImmutableSet;
import com.google.gson.Gson;
import org.apache.skywalking.banyandb.v1.client.AbstractQuery;
import org.apache.skywalking.banyandb.v1.client.RowEntity;
import org.apache.skywalking.banyandb.v1.client.StreamQuery;
import org.apache.skywalking.banyandb.v1.client.StreamQueryResponse;
import org.apache.skywalking.oap.server.core.analysis.IDManager;
import org.apache.skywalking.oap.server.core.profiling.ebpf.storage.EBPFProfilingTargetType;
import org.apache.skywalking.oap.server.core.profiling.ebpf.storage.EBPFProfilingTaskRecord;
import org.apache.skywalking.oap.server.core.profiling.ebpf.storage.EBPFProfilingTriggerType;
import org.apache.skywalking.oap.server.core.query.type.EBPFProfilingTask;
import org.apache.skywalking.oap.server.core.query.type.EBPFProfilingTaskExtension;
import org.apache.skywalking.oap.server.core.storage.profiling.ebpf.IEBPFProfilingTaskDAO;
import org.apache.skywalking.oap.server.library.util.CollectionUtils;
import org.apache.skywalking.oap.server.library.util.StringUtil;
@ -38,7 +34,6 @@ import org.apache.skywalking.oap.server.storage.plugin.banyandb.BanyanDBStorageC
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@ -55,17 +50,17 @@ public class BanyanDBEBPFProfilingTaskDAO extends AbstractBanyanDBDAO implements
EBPFProfilingTaskRecord.TARGET_TYPE,
EBPFProfilingTaskRecord.CREATE_TIME,
EBPFProfilingTaskRecord.LAST_UPDATE_TIME,
EBPFProfilingTaskRecord.EXTENSION_CONFIG_JSON);
private static final Gson GSON = new Gson();
EBPFProfilingTaskRecord.EXTENSION_CONFIG_JSON,
EBPFProfilingTaskRecord.CONTINUOUS_PROFILING_JSON);
public BanyanDBEBPFProfilingTaskDAO(BanyanDBStorageClient client) {
super(client);
}
@Override
public List<EBPFProfilingTask> queryTasksByServices(List<String> serviceIdList, long taskStartTime, long latestUpdateTime) throws IOException {
List<EBPFProfilingTask> tasks = new ArrayList<>();
public List<EBPFProfilingTaskRecord> queryTasksByServices(List<String> serviceIdList, EBPFProfilingTriggerType triggerType,
long taskStartTime, long latestUpdateTime) throws IOException {
List<EBPFProfilingTaskRecord> tasks = new ArrayList<>();
for (final String serviceId : serviceIdList) {
StreamQueryResponse resp = query(EBPFProfilingTaskRecord.INDEX_NAME, TAGS,
new QueryBuilder<StreamQuery>() {
@ -73,6 +68,9 @@ public class BanyanDBEBPFProfilingTaskDAO extends AbstractBanyanDBDAO implements
protected void apply(StreamQuery query) {
query.and(eq(EBPFProfilingTaskRecord.SERVICE_ID, serviceId));
appendTimeQuery(this, query, taskStartTime, latestUpdateTime);
if (triggerType != null) {
query.and(eq(EBPFProfilingTaskRecord.TRIGGER_TYPE, triggerType.value()));
}
query.setOrderBy(new AbstractQuery.OrderBy(EBPFProfilingTaskRecord.CREATE_TIME, AbstractQuery.Sort.DESC));
}
});
@ -83,8 +81,9 @@ public class BanyanDBEBPFProfilingTaskDAO extends AbstractBanyanDBDAO implements
}
@Override
public List<EBPFProfilingTask> queryTasksByTargets(String serviceId, String serviceInstanceId, List<EBPFProfilingTargetType> targetTypes, long taskStartTime, long latestUpdateTime) throws IOException {
List<EBPFProfilingTask> tasks = new ArrayList<>();
public List<EBPFProfilingTaskRecord> queryTasksByTargets(String serviceId, String serviceInstanceId, List<EBPFProfilingTargetType> targetTypes,
EBPFProfilingTriggerType triggerType, long taskStartTime, long latestUpdateTime) throws IOException {
List<EBPFProfilingTaskRecord> tasks = new ArrayList<>();
for (final EBPFProfilingTargetType targetType : targetTypes) {
StreamQueryResponse resp = query(EBPFProfilingTaskRecord.INDEX_NAME, TAGS,
new QueryBuilder<StreamQuery>() {
@ -96,6 +95,9 @@ public class BanyanDBEBPFProfilingTaskDAO extends AbstractBanyanDBDAO implements
if (StringUtil.isNotEmpty(serviceInstanceId)) {
query.and(eq(EBPFProfilingTaskRecord.INSTANCE_ID, serviceInstanceId));
}
if (CollectionUtils.isNotEmpty(targetTypes)) {
query.and(eq(EBPFProfilingTaskRecord.TRIGGER_TYPE, triggerType.value()));
}
query.and(eq(EBPFProfilingTaskRecord.TARGET_TYPE, targetType.value()));
appendTimeQuery(this, query, taskStartTime, latestUpdateTime);
query.setOrderBy(new AbstractQuery.OrderBy(EBPFProfilingTaskRecord.CREATE_TIME, AbstractQuery.Sort.DESC));
@ -108,7 +110,7 @@ public class BanyanDBEBPFProfilingTaskDAO extends AbstractBanyanDBDAO implements
}
@Override
public EBPFProfilingTask queryById(String id) throws IOException {
public List<EBPFProfilingTaskRecord> getTaskRecord(String id) throws IOException {
StreamQueryResponse resp = query(EBPFProfilingTaskRecord.INDEX_NAME, TAGS,
new QueryBuilder<StreamQuery>() {
@Override
@ -116,16 +118,7 @@ public class BanyanDBEBPFProfilingTaskDAO extends AbstractBanyanDBDAO implements
query.and(eq(EBPFProfilingTaskRecord.LOGICAL_ID, id));
}
});
final List<EBPFProfilingTask> tasks = resp.getElements().stream().map(this::buildTask).collect(Collectors.toList());
if (CollectionUtils.isEmpty(tasks)) {
return null;
}
EBPFProfilingTask result = tasks.get(0);
for (int i = 1; i < tasks.size(); i++) {
result = result.combine(tasks.get(i));
}
return result;
return resp.getElements().stream().map(this::buildTask).collect(Collectors.toList());
}
private void appendTimeQuery(QueryBuilder<StreamQuery> builder, StreamQuery query, long taskStartTime, long latestUpdateTime) {
@ -137,34 +130,10 @@ public class BanyanDBEBPFProfilingTaskDAO extends AbstractBanyanDBDAO implements
}
}
private EBPFProfilingTask buildTask(final RowEntity rowEntity) {
private EBPFProfilingTaskRecord buildTask(final RowEntity rowEntity) {
final EBPFProfilingTaskRecord.Builder builder = new EBPFProfilingTaskRecord.Builder();
final EBPFProfilingTaskRecord record = builder.storage2Entity(new BanyanDBConverter.StorageToStream(
return builder.storage2Entity(new BanyanDBConverter.StorageToStream(
EBPFProfilingTaskRecord.INDEX_NAME,
rowEntity));
final EBPFProfilingTask task = new EBPFProfilingTask();
task.setTaskId(record.getLogicalId());
task.setServiceId(record.getServiceId());
task.setServiceName(IDManager.ServiceID.analysisId(record.getServiceId()).getName());
if (StringUtil.isNotEmpty(record.getProcessLabelsJson())) {
task.setProcessLabels(GSON.<List<String>>fromJson(record.getProcessLabelsJson(), ArrayList.class));
} else {
task.setProcessLabels(Collections.emptyList());
}
if (StringUtil.isNotEmpty(record.getInstanceId())) {
task.setServiceInstanceId(record.getInstanceId());
task.setServiceInstanceName(IDManager.ServiceInstanceID.analysisId(record.getInstanceId()).getName());
}
task.setTaskStartTime(record.getStartTime());
task.setTriggerType(EBPFProfilingTriggerType.valueOf(record.getTriggerType()));
task.setFixedTriggerDuration(record.getFixedTriggerDuration());
task.setTargetType(EBPFProfilingTargetType.valueOf(record.getTargetType()));
task.setCreateTime(record.getCreateTime());
task.setLastUpdateTime(record.getLastUpdateTime());
if (StringUtil.isNotEmpty(record.getExtensionConfigJson())) {
task.setExtensionConfig(GSON.fromJson(record.getExtensionConfigJson(), EBPFProfilingTaskExtension.class));
}
return task;
}
}

View File

@ -32,6 +32,7 @@ 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.profiling.continuous.IContinuousProfilingPolicyDAO;
import org.apache.skywalking.oap.server.core.storage.profiling.ebpf.IEBPFProfilingDataDAO;
import org.apache.skywalking.oap.server.core.storage.profiling.ebpf.IEBPFProfilingScheduleDAO;
import org.apache.skywalking.oap.server.core.storage.profiling.ebpf.IEBPFProfilingTaskDAO;
@ -69,6 +70,7 @@ import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.cache.Netwo
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.AggregationQueryEsDAO;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.AlarmQueryEsDAO;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.BrowserLogQueryEsDAO;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.ContinuousProfilingPolicyEsDAO;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.EBPFProfilingDataEsDAO;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.EBPFProfilingScheduleEsDAO;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.EBPFProfilingTaskEsDAO;
@ -229,6 +231,10 @@ public class StorageModuleElasticsearchProvider extends ModuleProvider {
IEBPFProfilingDataDAO.class,
new EBPFProfilingDataEsDAO(elasticSearchClient, config)
);
this.registerServiceImplementation(
IContinuousProfilingPolicyDAO.class,
new ContinuousProfilingPolicyEsDAO(elasticSearchClient)
);
this.registerServiceImplementation(
IServiceLabelDAO.class,
new ServiceLabelEsDAO(elasticSearchClient, config)

View File

@ -0,0 +1,78 @@
/*
* 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 org.apache.skywalking.library.elasticsearch.requests.search.Query;
import org.apache.skywalking.library.elasticsearch.requests.search.Search;
import org.apache.skywalking.library.elasticsearch.requests.search.SearchBuilder;
import org.apache.skywalking.library.elasticsearch.response.search.SearchHit;
import org.apache.skywalking.library.elasticsearch.response.search.SearchResponse;
import org.apache.skywalking.oap.server.core.profiling.continuous.storage.ContinuousProfilingPolicy;
import org.apache.skywalking.oap.server.core.storage.profiling.continuous.IContinuousProfilingPolicyDAO;
import org.apache.skywalking.oap.server.library.client.elasticsearch.ElasticSearchClient;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base.ElasticSearchConverter;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base.EsDAO;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base.IndexController;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class ContinuousProfilingPolicyEsDAO extends EsDAO implements IContinuousProfilingPolicyDAO {
public ContinuousProfilingPolicyEsDAO(ElasticSearchClient client) {
super(client);
}
@Override
public void savePolicy(ContinuousProfilingPolicy policy) throws IOException {
final ContinuousProfilingPolicy.Builder builder = new ContinuousProfilingPolicy.Builder();
final ElasticSearchConverter.ToStorage toStorage = new ElasticSearchConverter.ToStorage(ContinuousProfilingPolicy.INDEX_NAME);
builder.entity2Storage(policy, toStorage);
final boolean exist = getClient().existDoc(ContinuousProfilingPolicy.INDEX_NAME, policy.id().build());
if (exist) {
getClient().forceUpdate(ContinuousProfilingPolicy.INDEX_NAME, policy.id().build(), toStorage.obtain());
} else {
getClient().forceInsert(ContinuousProfilingPolicy.INDEX_NAME, policy.id().build(), toStorage.obtain());
}
}
@Override
public List<ContinuousProfilingPolicy> queryPolicies(List<String> serviceIdList) throws IOException {
final String index =
IndexController.LogicIndicesRegister.getPhysicalTableName(ContinuousProfilingPolicy.INDEX_NAME);
final SearchBuilder search = Search.builder()
.query(Query.terms(ContinuousProfilingPolicy.SERVICE_ID, serviceIdList))
.size(serviceIdList.size());
return buildPolicies(getClient().search(index, search.build()));
}
private List<ContinuousProfilingPolicy> buildPolicies(SearchResponse response) {
List<ContinuousProfilingPolicy> policies = new ArrayList<>();
for (SearchHit hit : response.getHits()) {
final Map<String, Object> sourceAsMap = hit.getSource();
final ContinuousProfilingPolicy.Builder builder = new ContinuousProfilingPolicy.Builder();
policies.add(builder.storage2Entity(new ElasticSearchConverter.ToEntity(ContinuousProfilingPolicy.INDEX_NAME, sourceAsMap)));
}
return policies;
}
}

View File

@ -18,7 +18,6 @@
package org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query;
import com.google.gson.Gson;
import org.apache.skywalking.library.elasticsearch.requests.search.BoolQueryBuilder;
import org.apache.skywalking.library.elasticsearch.requests.search.Query;
import org.apache.skywalking.library.elasticsearch.requests.search.Search;
@ -26,12 +25,9 @@ import org.apache.skywalking.library.elasticsearch.requests.search.SearchBuilder
import org.apache.skywalking.library.elasticsearch.requests.search.Sort;
import org.apache.skywalking.library.elasticsearch.response.search.SearchHit;
import org.apache.skywalking.library.elasticsearch.response.search.SearchResponse;
import org.apache.skywalking.oap.server.core.analysis.IDManager;
import org.apache.skywalking.oap.server.core.profiling.ebpf.storage.EBPFProfilingTargetType;
import org.apache.skywalking.oap.server.core.profiling.ebpf.storage.EBPFProfilingTaskRecord;
import org.apache.skywalking.oap.server.core.profiling.ebpf.storage.EBPFProfilingTriggerType;
import org.apache.skywalking.oap.server.core.query.type.EBPFProfilingTask;
import org.apache.skywalking.oap.server.core.query.type.EBPFProfilingTaskExtension;
import org.apache.skywalking.oap.server.core.storage.profiling.ebpf.IEBPFProfilingTaskDAO;
import org.apache.skywalking.oap.server.library.client.elasticsearch.ElasticSearchClient;
import org.apache.skywalking.oap.server.library.util.CollectionUtils;
@ -42,15 +38,11 @@ import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base.EsDAO;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base.IndexController;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class EBPFProfilingTaskEsDAO extends EsDAO implements IEBPFProfilingTaskDAO {
private static final Gson GSON = new Gson();
private final int taskMaxSize;
public EBPFProfilingTaskEsDAO(ElasticSearchClient client, StorageModuleElasticsearchConfig config) {
@ -59,7 +51,7 @@ public class EBPFProfilingTaskEsDAO extends EsDAO implements IEBPFProfilingTaskD
}
@Override
public List<EBPFProfilingTask> queryTasksByServices(List<String> serviceIdList, long taskStartTime, long latestUpdateTime) throws IOException {
public List<EBPFProfilingTaskRecord> queryTasksByServices(List<String> serviceIdList, EBPFProfilingTriggerType triggerType, long taskStartTime, long latestUpdateTime) throws IOException {
final String index =
IndexController.LogicIndicesRegister.getPhysicalTableName(EBPFProfilingTaskRecord.INDEX_NAME);
final BoolQueryBuilder query = Query.bool();
@ -76,6 +68,9 @@ public class EBPFProfilingTaskEsDAO extends EsDAO implements IEBPFProfilingTaskD
if (latestUpdateTime > 0) {
query.must(Query.range(EBPFProfilingTaskRecord.LAST_UPDATE_TIME).gt(latestUpdateTime));
}
if (triggerType != null) {
query.must(Query.term(EBPFProfilingTaskRecord.TRIGGER_TYPE, triggerType.value()));
}
final SearchBuilder search = Search.builder().query(query)
.sort(EBPFProfilingTaskRecord.CREATE_TIME, Sort.Order.DESC)
@ -86,7 +81,8 @@ public class EBPFProfilingTaskEsDAO extends EsDAO implements IEBPFProfilingTaskD
}
@Override
public List<EBPFProfilingTask> queryTasksByTargets(String serviceId, String serviceInstanceId, List<EBPFProfilingTargetType> targetTypes, long taskStartTime, long latestUpdateTime) throws IOException {
public List<EBPFProfilingTaskRecord> queryTasksByTargets(String serviceId, String serviceInstanceId, List<EBPFProfilingTargetType> targetTypes,
EBPFProfilingTriggerType triggerType, long taskStartTime, long latestUpdateTime) throws IOException {
final String index =
IndexController.LogicIndicesRegister.getPhysicalTableName(EBPFProfilingTaskRecord.INDEX_NAME);
final BoolQueryBuilder query = Query.bool();
@ -101,6 +97,9 @@ public class EBPFProfilingTaskEsDAO extends EsDAO implements IEBPFProfilingTaskD
query.must(Query.terms(EBPFProfilingTaskRecord.TARGET_TYPE, targetTypes.stream()
.map(EBPFProfilingTargetType::value).collect(Collectors.toList())));
}
if (triggerType != null) {
query.must(Query.term(EBPFProfilingTaskRecord.TRIGGER_TYPE, triggerType.value()));
}
if (taskStartTime > 0) {
query.must(Query.range(EBPFProfilingTaskRecord.START_TIME).gte(taskStartTime));
}
@ -117,7 +116,7 @@ public class EBPFProfilingTaskEsDAO extends EsDAO implements IEBPFProfilingTaskD
}
@Override
public EBPFProfilingTask queryById(String id) throws IOException {
public List<EBPFProfilingTaskRecord> getTaskRecord(String id) throws IOException {
final String index =
IndexController.LogicIndicesRegister.getPhysicalTableName(EBPFProfilingTaskRecord.INDEX_NAME);
final BoolQueryBuilder query = Query.bool().must(Query.term(EBPFProfilingTaskRecord.LOGICAL_ID, id));
@ -125,44 +124,12 @@ public class EBPFProfilingTaskEsDAO extends EsDAO implements IEBPFProfilingTaskD
final SearchBuilder search = Search.builder().query(query).size(taskMaxSize);
final SearchResponse response = getClient().search(index, search.build());
final List<EBPFProfilingTask> tasks = response.getHits().getHits().stream().map(this::parseTask).collect(Collectors.toList());
if (CollectionUtils.isEmpty(tasks)) {
return null;
}
EBPFProfilingTask result = tasks.get(0);
for (int i = 1; i < tasks.size(); i++) {
result = result.combine(tasks.get(i));
}
return result;
return response.getHits().getHits().stream().map(this::parseTask).collect(Collectors.toList());
}
private EBPFProfilingTask parseTask(final SearchHit hit) {
private EBPFProfilingTaskRecord parseTask(final SearchHit hit) {
final Map<String, Object> sourceAsMap = hit.getSource();
final EBPFProfilingTaskRecord.Builder builder = new EBPFProfilingTaskRecord.Builder();
final EBPFProfilingTaskRecord record = builder.storage2Entity(new ElasticSearchConverter.ToEntity(EBPFProfilingTaskRecord.INDEX_NAME, sourceAsMap));
final EBPFProfilingTask task = new EBPFProfilingTask();
task.setTaskId(record.getLogicalId());
task.setServiceId(record.getServiceId());
task.setServiceName(IDManager.ServiceID.analysisId(record.getServiceId()).getName());
if (StringUtil.isNotEmpty(record.getProcessLabelsJson())) {
task.setProcessLabels(GSON.<List<String>>fromJson(record.getProcessLabelsJson(), ArrayList.class));
} else {
task.setProcessLabels(Collections.emptyList());
}
if (StringUtil.isNotEmpty(record.getInstanceId())) {
task.setServiceInstanceId(record.getInstanceId());
task.setServiceInstanceName(IDManager.ServiceInstanceID.analysisId(record.getInstanceId()).getName());
}
task.setTaskStartTime(record.getStartTime());
task.setTriggerType(EBPFProfilingTriggerType.valueOf(record.getTriggerType()));
task.setFixedTriggerDuration(record.getFixedTriggerDuration());
task.setTargetType(EBPFProfilingTargetType.valueOf(record.getTargetType()));
task.setCreateTime(record.getCreateTime());
task.setLastUpdateTime(record.getLastUpdateTime());
if (StringUtil.isNotEmpty(record.getExtensionConfigJson())) {
task.setExtensionConfig(GSON.fromJson(record.getExtensionConfigJson(), EBPFProfilingTaskExtension.class));
}
return task;
return builder.storage2Entity(new ElasticSearchConverter.ToEntity(EBPFProfilingTaskRecord.INDEX_NAME, sourceAsMap));
}
}

View File

@ -29,6 +29,7 @@ import org.apache.skywalking.oap.server.core.storage.cache.INetworkAddressAliasD
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.model.ModelInstaller;
import org.apache.skywalking.oap.server.core.storage.profiling.continuous.IContinuousProfilingPolicyDAO;
import org.apache.skywalking.oap.server.core.storage.profiling.ebpf.IEBPFProfilingDataDAO;
import org.apache.skywalking.oap.server.core.storage.profiling.ebpf.IEBPFProfilingScheduleDAO;
import org.apache.skywalking.oap.server.core.storage.profiling.ebpf.IEBPFProfilingTaskDAO;
@ -58,6 +59,7 @@ import org.apache.skywalking.oap.server.storage.plugin.jdbc.common.dao.JDBCAggre
import org.apache.skywalking.oap.server.storage.plugin.jdbc.common.dao.JDBCAlarmQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.common.dao.JDBCBatchDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.common.dao.JDBCBrowserLogQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.common.dao.JDBCContinuousProfilingPolicyDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.common.dao.JDBCEBPFProfilingDataDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.common.dao.JDBCEBPFProfilingScheduleDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.common.dao.JDBCEBPFProfilingTaskDAO;
@ -199,6 +201,9 @@ public abstract class JDBCStorageProvider extends ModuleProvider {
this.registerServiceImplementation(
IEBPFProfilingDataDAO.class,
new JDBCEBPFProfilingDataDAO(jdbcClient, tableHelper));
this.registerServiceImplementation(
IContinuousProfilingPolicyDAO.class,
new JDBCContinuousProfilingPolicyDAO(jdbcClient, tableHelper));
this.registerServiceImplementation(
IServiceLabelDAO.class,
new JDBCServiceLabelQueryDAO(jdbcClient, tableHelper));

View File

@ -0,0 +1,98 @@
/*
* 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.jdbc.common.dao;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import org.apache.skywalking.oap.server.core.profiling.continuous.storage.ContinuousProfilingPolicy;
import org.apache.skywalking.oap.server.core.storage.profiling.continuous.IContinuousProfilingPolicyDAO;
import org.apache.skywalking.oap.server.core.storage.type.HashMapConverter;
import org.apache.skywalking.oap.server.library.client.jdbc.hikaricp.JDBCClient;
import org.apache.skywalking.oap.server.library.util.CollectionUtils;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.SQLExecutor;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.TableMetaInfo;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.common.JDBCTableInstaller;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.common.TableHelper;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@AllArgsConstructor
public class JDBCContinuousProfilingPolicyDAO extends JDBCSQLExecutor implements IContinuousProfilingPolicyDAO {
private final JDBCClient jdbcClient;
private final TableHelper tableHelper;
@Override
public void savePolicy(ContinuousProfilingPolicy policy) throws IOException {
final List<ContinuousProfilingPolicy> existingPolicy = queryPolicies(Arrays.asList(policy.getServiceId()));
SQLExecutor sqlExecutor;
final var model = TableMetaInfo.get(ContinuousProfilingPolicy.INDEX_NAME);
if (CollectionUtils.isNotEmpty(existingPolicy)) {
sqlExecutor = getUpdateExecutor(model, policy, 0, new ContinuousProfilingPolicy.Builder(), null);
} else {
sqlExecutor = getInsertExecutor(model, policy, 0,
new ContinuousProfilingPolicy.Builder(), new HashMapConverter.ToStorage(), null);
}
try (Connection connection = jdbcClient.getConnection()) {
sqlExecutor.invoke(connection);
} catch (SQLException e) {
throw new IOException(e);
}
}
@SneakyThrows
@Override
public List<ContinuousProfilingPolicy> queryPolicies(List<String> serviceIdList) throws IOException {
final var tables = tableHelper.getTablesWithinTTL(ContinuousProfilingPolicy.INDEX_NAME);
List<Object> condition = new ArrayList<>();
condition.add(ContinuousProfilingPolicy.INDEX_NAME);
condition.addAll(serviceIdList);
StringBuilder whereQuery = new StringBuilder()
.append(" where ")
.append(JDBCTableInstaller.TABLE_COLUMN).append(" = ?")
.append(" and ").append(ContinuousProfilingPolicy.SERVICE_ID)
.append(" in ").append(serviceIdList.stream().map(s -> "?").collect(Collectors.joining(",", "(", ")")));
final var results = new ArrayList<ContinuousProfilingPolicy>();
for (String table : tables) {
results.addAll(jdbcClient.executeQuery("select * from " + table + whereQuery, this::buildPolicies, condition.toArray(new Object[0])));
}
return results;
}
private List<ContinuousProfilingPolicy> buildPolicies(ResultSet resultSet) throws SQLException {
List<ContinuousProfilingPolicy> policies = new ArrayList<>();
while (resultSet.next()) {
final ContinuousProfilingPolicy policy = new ContinuousProfilingPolicy();
policy.setServiceId(resultSet.getString(ContinuousProfilingPolicy.SERVICE_ID));
policy.setUuid(resultSet.getString(ContinuousProfilingPolicy.UUID));
policy.setConfigurationJson(resultSet.getString(ContinuousProfilingPolicy.CONFIGURATION_JSON));
policies.add(policy);
}
return policies;
}
}

View File

@ -18,15 +18,12 @@
package org.apache.skywalking.oap.server.storage.plugin.jdbc.common.dao;
import com.google.gson.Gson;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.apache.skywalking.oap.server.core.analysis.IDManager;
import org.apache.skywalking.oap.server.core.profiling.ebpf.storage.EBPFProfilingTargetType;
import org.apache.skywalking.oap.server.core.profiling.ebpf.storage.EBPFProfilingTaskRecord;
import org.apache.skywalking.oap.server.core.profiling.ebpf.storage.EBPFProfilingTriggerType;
import org.apache.skywalking.oap.server.core.query.type.EBPFProfilingTask;
import org.apache.skywalking.oap.server.core.query.type.EBPFProfilingTaskExtension;
import org.apache.skywalking.oap.server.core.storage.StorageData;
import org.apache.skywalking.oap.server.core.storage.profiling.ebpf.IEBPFProfilingTaskDAO;
import org.apache.skywalking.oap.server.library.client.jdbc.hikaricp.JDBCClient;
import org.apache.skywalking.oap.server.library.util.StringUtil;
@ -34,40 +31,21 @@ import org.apache.skywalking.oap.server.storage.plugin.jdbc.common.JDBCTableInst
import org.apache.skywalking.oap.server.storage.plugin.jdbc.common.SQLAndParameters;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.common.TableHelper;
import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
@RequiredArgsConstructor
public class JDBCEBPFProfilingTaskDAO implements IEBPFProfilingTaskDAO {
private static final Gson GSON = new Gson();
public class JDBCEBPFProfilingTaskDAO extends JDBCSQLExecutor implements IEBPFProfilingTaskDAO {
private final JDBCClient jdbcClient;
private final TableHelper tableHelper;
@Override
@SneakyThrows
public List<EBPFProfilingTask> queryTasksByServices(List<String> serviceIdList, long taskStartTime, long latestUpdateTime) {
final var tables = tableHelper.getTablesWithinTTL(EBPFProfilingTaskRecord.INDEX_NAME);
final var results = new ArrayList<EBPFProfilingTask>();
for (final var table : tables) {
final var sqlAndParameters = buildSQLForQueryTasksByServices(serviceIdList, taskStartTime, latestUpdateTime, table);
results.addAll(
jdbcClient.executeQuery(
sqlAndParameters.sql(),
this::buildTasks,
sqlAndParameters.parameters()
)
);
}
return results;
}
protected SQLAndParameters buildSQLForQueryTasksByServices(
final List<String> serviceIdList,
EBPFProfilingTriggerType triggerType,
final long taskStartTime,
final long latestUpdateTime,
final String table) {
@ -88,6 +66,10 @@ public class JDBCEBPFProfilingTaskDAO implements IEBPFProfilingTaskDAO {
appendCondition(conditionSql, parameters,
EBPFProfilingTaskRecord.LAST_UPDATE_TIME, ">", latestUpdateTime);
}
if (triggerType != null) {
appendCondition(conditionSql, parameters,
EBPFProfilingTaskRecord.TRIGGER_TYPE, "=", triggerType.value());
}
if (conditionSql.length() > 0) {
sql.append(" where ").append(conditionSql);
@ -95,15 +77,36 @@ public class JDBCEBPFProfilingTaskDAO implements IEBPFProfilingTaskDAO {
return new SQLAndParameters(sql.toString(), parameters);
}
@SneakyThrows
@Override
public List<EBPFProfilingTaskRecord> queryTasksByServices(List<String> serviceIdList, EBPFProfilingTriggerType triggerType, long taskStartTime, long latestUpdateTime) throws IOException {
final var tables = tableHelper.getTablesWithinTTL(EBPFProfilingTaskRecord.INDEX_NAME);
final var results = new ArrayList<EBPFProfilingTaskRecord>();
for (final var table : tables) {
final var sqlAndParameters = buildSQLForQueryTasksByServices(serviceIdList, triggerType, taskStartTime, latestUpdateTime, table);
results.addAll(
jdbcClient.executeQuery(
sqlAndParameters.sql(),
this::buildTasks,
sqlAndParameters.parameters()
)
);
}
return results;
}
@Override
@SneakyThrows
public List<EBPFProfilingTask> queryTasksByTargets(String serviceId, String serviceInstanceId, List<EBPFProfilingTargetType> targetTypes, long taskStartTime, long latestUpdateTime) {
final var results = new ArrayList<EBPFProfilingTask>();
public List<EBPFProfilingTaskRecord> queryTasksByTargets(String serviceId, String serviceInstanceId, List<EBPFProfilingTargetType> targetTypes,
EBPFProfilingTriggerType triggerType, long taskStartTime, long latestUpdateTime) throws IOException {
final var results = new ArrayList<EBPFProfilingTaskRecord>();
final var tables = tableHelper.getTablesWithinTTL(EBPFProfilingTaskRecord.INDEX_NAME);
for (final var table : tables) {
final var sqlAndParameters = buildSQLForQueryTasksByTargets(
serviceId, serviceInstanceId, targetTypes, taskStartTime, latestUpdateTime, table
serviceId, serviceInstanceId, targetTypes, triggerType, taskStartTime, latestUpdateTime, table
);
results.addAll(
jdbcClient.executeQuery(
@ -116,10 +119,30 @@ public class JDBCEBPFProfilingTaskDAO implements IEBPFProfilingTaskDAO {
return results;
}
@Override
@SneakyThrows
public List<EBPFProfilingTaskRecord> getTaskRecord(String id) throws IOException {
final List<EBPFProfilingTaskRecord> results = new ArrayList<>();
final var tables = tableHelper.getTablesWithinTTL(EBPFProfilingTaskRecord.INDEX_NAME);
for (final var table : tables) {
String sql = "select * from " + table +
" where " + JDBCTableInstaller.TABLE_COLUMN + " = ?" +
EBPFProfilingTaskRecord.LOGICAL_ID + " = ?";
results.addAll(jdbcClient.executeQuery(
sql,
this::buildTasks,
EBPFProfilingTaskRecord.INDEX_NAME, id
));
}
return results;
}
protected SQLAndParameters buildSQLForQueryTasksByTargets(
final String serviceId,
final String serviceInstanceId,
final List<EBPFProfilingTargetType> targetTypes,
EBPFProfilingTriggerType triggerType,
final long taskStartTime,
final long latestUpdateTime,
final String table) {
@ -147,6 +170,10 @@ public class JDBCEBPFProfilingTaskDAO implements IEBPFProfilingTaskDAO {
appendCondition(conditions, parameters,
EBPFProfilingTaskRecord.LAST_UPDATE_TIME, ">", latestUpdateTime);
}
if (triggerType != null) {
appendCondition(conditions, parameters,
EBPFProfilingTaskRecord.TRIGGER_TYPE, "=", triggerType.value());
}
if (conditions.length() > 0) {
sql.append(" where ").append(conditions);
@ -155,60 +182,11 @@ public class JDBCEBPFProfilingTaskDAO implements IEBPFProfilingTaskDAO {
return new SQLAndParameters(sql.toString(), parameters);
}
@Override
@SneakyThrows
public EBPFProfilingTask queryById(String id) {
final var tables = tableHelper.getTablesWithinTTL(EBPFProfilingTaskRecord.INDEX_NAME);
for (final var table : tables) {
final var sql = new StringBuilder();
sql.append("select * from ").append(table)
.append(" where ").append(JDBCTableInstaller.TABLE_COLUMN).append(" = ?")
.append(EBPFProfilingTaskRecord.LOGICAL_ID).append(" = ?");
final var result = jdbcClient.executeQuery(
sql.toString(),
resultSet -> buildTasks(resultSet).stream().reduce(EBPFProfilingTask::combine).orElse(null),
EBPFProfilingTaskRecord.INDEX_NAME, id
);
if (result != null) {
return result;
}
}
return null;
}
private List<EBPFProfilingTask> buildTasks(ResultSet resultSet) throws SQLException {
List<EBPFProfilingTask> tasks = new ArrayList<>();
while (resultSet.next()) {
EBPFProfilingTask task = new EBPFProfilingTask();
task.setTaskId(resultSet.getString(EBPFProfilingTaskRecord.LOGICAL_ID));
final String serviceId = resultSet.getString(EBPFProfilingTaskRecord.SERVICE_ID);
task.setServiceId(serviceId);
task.setServiceName(IDManager.ServiceID.analysisId(serviceId).getName());
final String processLabelString = resultSet.getString(EBPFProfilingTaskRecord.PROCESS_LABELS_JSON);
if (StringUtil.isNotEmpty(processLabelString)) {
task.setProcessLabels(GSON.<List<String>>fromJson(processLabelString, ArrayList.class));
} else {
task.setProcessLabels(Collections.emptyList());
}
if (StringUtil.isNotEmpty(resultSet.getString(EBPFProfilingTaskRecord.INSTANCE_ID))) {
task.setServiceInstanceId(resultSet.getString(EBPFProfilingTaskRecord.INSTANCE_ID));
task.setServiceInstanceName(IDManager.ServiceInstanceID.analysisId(task.getServiceInstanceId()).getName());
}
task.setTaskStartTime(resultSet.getLong(EBPFProfilingTaskRecord.START_TIME));
task.setTriggerType(EBPFProfilingTriggerType.valueOf(
resultSet.getInt(EBPFProfilingTaskRecord.TRIGGER_TYPE)));
task.setFixedTriggerDuration(resultSet.getInt(EBPFProfilingTaskRecord.FIXED_TRIGGER_DURATION));
task.setTargetType(EBPFProfilingTargetType.valueOf(
resultSet.getInt(EBPFProfilingTaskRecord.TARGET_TYPE)));
task.setCreateTime(resultSet.getLong(EBPFProfilingTaskRecord.CREATE_TIME));
task.setLastUpdateTime(resultSet.getLong(EBPFProfilingTaskRecord.LAST_UPDATE_TIME));
String extensionConfigJson = resultSet.getString(EBPFProfilingTaskRecord.EXTENSION_CONFIG_JSON);
if (StringUtil.isNotEmpty(extensionConfigJson)) {
task.setExtensionConfig(GSON.fromJson(extensionConfigJson, EBPFProfilingTaskExtension.class));
}
tasks.add(task);
private List<EBPFProfilingTaskRecord> buildTasks(ResultSet resultSet) throws SQLException {
List<EBPFProfilingTaskRecord> tasks = new ArrayList<>();
StorageData data;
while ((data = toStorageData(resultSet, EBPFProfilingTaskRecord.INDEX_NAME, new EBPFProfilingTaskRecord.Builder())) != null) {
tasks.add((EBPFProfilingTaskRecord) data);
}
return tasks;
}

View File

@ -0,0 +1,23 @@
# 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.
FROM golang:1.17
WORKDIR /
COPY sqrt.go /sqrt.go
RUN go build -o sqrt sqrt.go
CMD ["/sqrt"]

View File

@ -0,0 +1,58 @@
# 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.
version: '2.1'
services:
banyandb:
extends:
file: ../docker-compose.yml
service: banyandb
networks:
- e2e
oap:
extends:
file: ../docker-compose.yml
service: oap
networks:
- e2e
environment:
SW_STORAGE: banyandb
depends_on:
banyandb:
condition: service_healthy
ports:
- 12800
sqrt:
extends:
file: ../docker-compose.yml
service: sqrt
networks:
- e2e
rover:
extends:
file: ../docker-compose.yml
service: rover
networks:
- e2e
depends_on:
oap:
condition: service_healthy
networks:
e2e:

View File

@ -0,0 +1,37 @@
# 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.
# This file is used to show how to write configuration files and can be used to test.
setup:
env: compose
file: docker-compose.yml
timeout: 20m
init-system-environment: ../../../../../script/env
steps:
- name: set PATH
command: export PATH=/tmp/skywalking-infra-e2e/bin:$PATH
- name: install yq
command: bash test/e2e-v2/script/prepare/setup-e2e-shell/install.sh yq
- name: install swctl
command: bash test/e2e-v2/script/prepare/setup-e2e-shell/install.sh swctl
verify:
retry:
count: 20
interval: 10s
cases:
- includes:
- ../profiling-cases.yaml

View File

@ -0,0 +1,62 @@
# 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.
version: '2.1'
services:
oap:
extends:
file: ../../../../script/docker-compose/base-compose.yml
service: oap
banyandb:
extends:
file: ../../../../script/docker-compose/base-compose.yml
service: banyandb
sqrt:
build:
context: .
dockerfile: Dockerfile.sqrt
networks:
- e2e
rover:
image: "ghcr.io/apache/skywalking-rover/skywalking-rover:${SW_ROVER_COMMIT}"
networks:
- e2e
privileged: true
pid: host
environment:
ROVER_LOGGER_LEVEL: DEBUG
ROVER_HOST_MAPPING: /host
ROVER_BACKEND_ADDR: oap:11800
ROVER_PROCESS_DISCOVERY_HEARTBEAT_PERIOD: 2s
ROVER_PROCESS_DISCOVERY_VM_ACTIVE: "true"
ROVER_PROCESS_DISCOVERY_SCAN_MODE: REGEX
ROVER_PROCESS_DISCOVERY_REGEX_SCANNER_MATCH_CMD: sqrt
ROVER_PROCESS_DISCOVERY_REGEX_SCANNER_LAYER: OS_LINUX
ROVER_PROCESS_DISCOVERY_REGEX_SCANNER_SERVICE_NAME: sqrt
ROVER_PROCESS_DISCOVERY_REGEX_SCANNER_INSTANCE_NAME: test-instance
ROVER_PROCESS_DISCOVERY_REGEX_SCANNER_PROCESS_NAME: "{{.Process.ExeName}}"
ROVER_PROFILING_ACTIVE: "true"
ROVER_PROFILING_CHECK_INTERVAL: 2s
ROVER_PROFILING_FLUSH_INTERVAL: 5s
ROVER_PROFILING_TASK_ON_CPU_DUMP_PERIOD: 9ms
volumes:
- /:/host
networks:
e2e:

View File

@ -0,0 +1,66 @@
# 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.
version: '2.1'
services:
es:
image: elastic/elasticsearch:7.15.0
expose:
- 9200
networks:
- e2e
environment:
- discovery.type=single-node
- cluster.routing.allocation.disk.threshold_enabled=false
healthcheck:
test: [ "CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/9200" ]
interval: 5s
timeout: 60s
retries: 120
oap:
extends:
file: ../docker-compose.yml
service: oap
networks:
- e2e
environment:
SW_STORAGE: elasticsearch
depends_on:
es:
condition: service_healthy
ports:
- 12800
sqrt:
extends:
file: ../docker-compose.yml
service: sqrt
networks:
- e2e
rover:
extends:
file: ../docker-compose.yml
service: rover
networks:
- e2e
depends_on:
oap:
condition: service_healthy
networks:
e2e:

View File

@ -0,0 +1,37 @@
# 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.
# This file is used to show how to write configuration files and can be used to test.
setup:
env: compose
file: docker-compose.yml
timeout: 20m
init-system-environment: ../../../../../script/env
steps:
- name: set PATH
command: export PATH=/tmp/skywalking-infra-e2e/bin:$PATH
- name: install yq
command: bash test/e2e-v2/script/prepare/setup-e2e-shell/install.sh yq
- name: install swctl
command: bash test/e2e-v2/script/prepare/setup-e2e-shell/install.sh swctl
verify:
retry:
count: 20
interval: 10s
cases:
- includes:
- ../profiling-cases.yaml

View File

@ -0,0 +1,67 @@
# 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.
version: '2.1'
services:
es:
image: elastic/elasticsearch:7.15.0
expose:
- 9200
networks:
- e2e
environment:
- discovery.type=single-node
- cluster.routing.allocation.disk.threshold_enabled=false
healthcheck:
test: [ "CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/9200" ]
interval: 5s
timeout: 60s
retries: 120
oap:
extends:
file: ../../docker-compose.yml
service: oap
networks:
- e2e
environment:
SW_STORAGE: elasticsearch
SW_STORAGE_ES_LOGIC_SHARDING: "true"
depends_on:
es:
condition: service_healthy
ports:
- 12800
sqrt:
extends:
file: ../../docker-compose.yml
service: sqrt
networks:
- e2e
rover:
extends:
file: ../../docker-compose.yml
service: rover
networks:
- e2e
depends_on:
oap:
condition: service_healthy
networks:
e2e:

View File

@ -0,0 +1,37 @@
# 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.
# This file is used to show how to write configuration files and can be used to test.
setup:
env: compose
file: docker-compose.yml
timeout: 20m
init-system-environment: ../../../../../../script/env
steps:
- name: set PATH
command: export PATH=/tmp/skywalking-infra-e2e/bin:$PATH
- name: install yq
command: bash test/e2e-v2/script/prepare/setup-e2e-shell/install.sh yq
- name: install swctl
command: bash test/e2e-v2/script/prepare/setup-e2e-shell/install.sh swctl
verify:
retry:
count: 20
interval: 10s
cases:
- includes:
- ../../profiling-cases.yaml

View File

@ -0,0 +1,22 @@
# 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.
{{- contains . }}
- id: {{ b64enc "sqrt" }}.1_{{ b64enc "test-instance" }}
name: test-instance
attributes: []
language: UNKNOWN
instanceuuid: {{ notEmpty .instanceuuid }}
{{- end }}

View File

@ -0,0 +1,19 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
{{- contains . }}
- key: {{ notEmpty .key }}
value: {{ ge .value 1 }}
{{- end }}

View File

@ -0,0 +1,17 @@
# 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.
status: true
errorreason: null

View File

@ -0,0 +1,37 @@
# 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.
{{- contains . }}
- id: {{ notEmpty .id }}
name: sqrt
serviceid: {{ b64enc "sqrt" }}.1
servicename: sqrt
instanceid: {{ b64enc "sqrt" }}.1_{{ b64enc "test-instance" }}
instancename: test-instance
agentid: {{ notEmpty .agentid }}
detecttype: VM
attributes:
{{- contains .attributes }}
- name: host_ip
value: {{ notEmpty .value }}
- name: pid
value: {{ notEmpty .value }}
- name: command_line
value: /sqrt
- name: support_ebpf_profiling
value: "true"
{{- end }}
labels: []
{{- end }}

View File

@ -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.
tip: null
trees:
{{- contains .trees }}
- elements:
{{- contains .elements }}
- id: "{{ notEmpty .id }}"
parentid: "{{ notEmpty .parentid }}"
symbol: "main.sqrtGolang"
stacktype: USER_SPACE
dumpcount: {{ gt .dumpcount 0 }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,40 @@
# 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.
{{- contains . }}
- scheduleid: {{ notEmpty .scheduleid }}
taskid: {{ notEmpty .taskid }}
process:
id: {{ notEmpty .process.id }}
name: sqrt
serviceid: {{ b64enc "sqrt" }}.1
servicename: sqrt
instanceid: {{ b64enc "sqrt" }}.1_{{ b64enc "test-instance" }}
instancename: test-instance
agentid: {{ notEmpty .process.agentid }}
detecttype: VM
attributes:
{{- contains .process.attributes }}
- name: host_ip
value: {{ notEmpty .value }}
- name: pid
value: {{ notEmpty .value }}
- name: command_line
value: /sqrt
{{- end }}
labels: []
starttime: {{ gt .starttime 0 }}
endtime: {{ gt .endtime 0 }}
{{- end }}

View File

@ -0,0 +1,23 @@
# 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.
- type: ON_CPU
checkitems:
- type: PROCESS_CPU
threshold: "10"
period: 10
count: 3
urilist: []
uriregex: null

View File

@ -0,0 +1,24 @@
# 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.
{{- contains . }}
- id: {{ b64enc "sqrt" }}.1
name: sqrt
group: ""
shortname: sqrt
layers:
- OS_LINUX
normal: true
{{- end }}

View File

@ -0,0 +1,36 @@
# 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.
{{- contains . }}
- taskid: {{ notEmpty .taskid }}
serviceid: {{ b64enc "sqrt" }}.1
servicename: sqrt
serviceinstanceid: {{ b64enc "sqrt" }}.1_{{ b64enc "test-instance" }}
serviceinstancename: test-instance
processlabels: []
processid: {{ notEmpty .processid }}
processname: sqrt
taskstarttime: {{ ge .taskstarttime 1 }}
triggertype: CONTINUOUS_PROFILING
fixedtriggerduration: 600
continuousprofilingcauses:
- type: PROCESS_CPU
singlevalue:
threshold: 1000
current: {{ ge (index .continuousprofilingcauses 0).singlevalue.current 1 }}
uri: null
targettype: ON_CPU
createtime: {{ ge .createtime 1 }}
{{- end }}

View File

@ -0,0 +1,66 @@
# 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.
version: '2.1'
services:
h2db:
build:
context: ""
dockerfile: ../../../../../script/dockerfile/Dockerfile.h2
networks:
- e2e
expose:
- 1521
healthcheck:
test: ["CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/1521"]
interval: 5s
timeout: 60s
retries: 120
oap:
extends:
file: ../docker-compose.yml
service: oap
networks:
- e2e
environment:
SW_STORAGE: h2
SW_STORAGE_H2_URL: jdbc:h2:tcp://h2db:1521/skywalking-oap-db;DATABASE_TO_UPPER=FALSE
depends_on:
h2db:
condition: service_healthy
ports:
- 12800
sqrt:
extends:
file: ../docker-compose.yml
service: sqrt
networks:
- e2e
rover:
extends:
file: ../docker-compose.yml
service: rover
networks:
- e2e
depends_on:
oap:
condition: service_healthy
networks:
e2e:

View File

@ -0,0 +1,37 @@
# 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.
# This file is used to show how to write configuration files and can be used to test.
setup:
env: compose
file: docker-compose.yml
timeout: 20m
init-system-environment: ../../../../../script/env
steps:
- name: set PATH
command: export PATH=/tmp/skywalking-infra-e2e/bin:$PATH
- name: install yq
command: bash test/e2e-v2/script/prepare/setup-e2e-shell/install.sh yq
- name: install swctl
command: bash test/e2e-v2/script/prepare/setup-e2e-shell/install.sh swctl
verify:
retry:
count: 20
interval: 10s
cases:
- includes:
- ../profiling-cases.yaml

View File

@ -0,0 +1,68 @@
# 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.
version: '2.1'
services:
mysql:
image: mysql/mysql-server:8.0.13
networks:
- e2e
expose:
- 3306
environment:
- MYSQL_ROOT_PASSWORD=root@1234
- MYSQL_DATABASE=swtest
- MYSQL_ROOT_HOST=%
healthcheck:
test: [ "CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/3306" ]
interval: 5s
timeout: 60s
retries: 120
oap:
extends:
file: ../docker-compose.yml
service: oap
networks:
- e2e
environment:
SW_STORAGE: mysql
entrypoint: ['sh', '-c', '/download-mysql.sh /skywalking/oap-libs && /skywalking/docker-entrypoint.sh']
ports:
- 12800
depends_on:
mysql:
condition: service_healthy
sqrt:
extends:
file: ../docker-compose.yml
service: sqrt
networks:
- e2e
rover:
extends:
file: ../docker-compose.yml
service: rover
networks:
- e2e
depends_on:
oap:
condition: service_healthy
networks:
e2e:

View File

@ -0,0 +1,37 @@
# 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.
# This file is used to show how to write configuration files and can be used to test.
setup:
env: compose
file: docker-compose.yml
timeout: 20m
init-system-environment: ../../../../../script/env
steps:
- name: set PATH
command: export PATH=/tmp/skywalking-infra-e2e/bin:$PATH
- name: install yq
command: bash test/e2e-v2/script/prepare/setup-e2e-shell/install.sh yq
- name: install swctl
command: bash test/e2e-v2/script/prepare/setup-e2e-shell/install.sh swctl
verify:
retry:
count: 20
interval: 10s
cases:
- includes:
- ../profiling-cases.yaml

View File

@ -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.
version: '2.1'
services:
opensearch:
image: opensearchproject/opensearch:${OPENSEARCH_VERSION}
expose:
- 9200
networks:
- e2e
environment:
- discovery.type=single-node
- cluster.routing.allocation.disk.threshold_enabled=false
- plugins.security.ssl.http.enabled=false
healthcheck:
test: [ "CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/9200" ]
interval: 5s
timeout: 60s
retries: 120
oap:
extends:
file: ../docker-compose.yml
service: oap
networks:
- e2e
environment:
SW_STORAGE: elasticsearch
SW_STORAGE_ES_CLUSTER_NODES: opensearch:9200
SW_ES_USER: admin
SW_ES_PASSWORD: admin
SW_STORAGE_ES_LOGIC_SHARDING: "true"
depends_on:
opensearch:
condition: service_healthy
ports:
- 12800
sqrt:
extends:
file: ../docker-compose.yml
service: sqrt
networks:
- e2e
rover:
extends:
file: ../docker-compose.yml
service: rover
networks:
- e2e
depends_on:
oap:
condition: service_healthy
networks:
e2e:

View File

@ -0,0 +1,37 @@
# 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.
# This file is used to show how to write configuration files and can be used to test.
setup:
env: compose
file: docker-compose.yml
timeout: 20m
init-system-environment: ../../../../../script/env
steps:
- name: set PATH
command: export PATH=/tmp/skywalking-infra-e2e/bin:$PATH
- name: install yq
command: bash test/e2e-v2/script/prepare/setup-e2e-shell/install.sh yq
- name: install swctl
command: bash test/e2e-v2/script/prepare/setup-e2e-shell/install.sh swctl
verify:
retry:
count: 20
interval: 10s
cases:
- includes:
- ../profiling-cases.yaml

View File

@ -0,0 +1,41 @@
# 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.
# Policy config
# policy: the policy config list
# - type: the profiling target type when reached the threshold, support: "ON_CPU", "OFF_CPU", "NETWORK"
# checks: define the thresholds, when any configuration item reaches the threshold, it will trigger profiling task
# - type: monitoring type, please see the below monitoring type with threshold description
# threshold: monitor threshold, please see the below monitoring type with threshold description
# period: the length of time to evaluate the metrics
# count: how many times after the metrics match the threshold, will trigger profiling
# uriList: the URI paths filter when monitor the HTTP related types
# uriRegex: the URI regex filter when monitor the HTTP related types
# Monitoring type with threshold
# PROCESS_CPU: Monitoring Process CPU percent, threshold value in [0-100]
# PROCESS_THREAD_COUNT: Monitoring process thread count, threshold value must bigger than zero
# SYSTEM_LOAD: Monitoring current system load, threshold value must bigger than zero
# HTTP_ERROR_RATE: Monitoring the process HTTP response error(status>=500) percent, threshold value in [0-100]
# HTTP_AVG_RESPONSE_TIME: Monitoring the process HTTP response duration(ms), threshold value must be bigger than zero
policy:
- type: ON_CPU
checkers:
- type: PROCESS_CPU
threshold: 10
period: 10
count: 3

View File

@ -0,0 +1,67 @@
# 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.
version: '2.1'
services:
postgres:
image: postgres:13
networks:
- e2e
expose:
- 5432
environment:
- POSTGRES_PASSWORD=123456
- POSTGRES_DB=skywalking
healthcheck:
test: [ "CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/5432" ]
interval: 5s
timeout: 60s
retries: 120
oap:
extends:
file: ../docker-compose.yml
service: oap
networks:
- e2e
environment:
SW_STORAGE: postgresql
SW_JDBC_URL: "jdbc:postgresql://postgres:5432/skywalking"
depends_on:
postgres:
condition: service_healthy
ports:
- 12800
sqrt:
extends:
file: ../docker-compose.yml
service: sqrt
networks:
- e2e
rover:
extends:
file: ../docker-compose.yml
service: rover
networks:
- e2e
depends_on:
oap:
condition: service_healthy
networks:
e2e:

View File

@ -0,0 +1,37 @@
# 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.
# This file is used to show how to write configuration files and can be used to test.
setup:
env: compose
file: docker-compose.yml
timeout: 20m
init-system-environment: ../../../../../script/env
steps:
- name: set PATH
command: export PATH=/tmp/skywalking-infra-e2e/bin:$PATH
- name: install yq
command: bash test/e2e-v2/script/prepare/setup-e2e-shell/install.sh yq
- name: install swctl
command: bash test/e2e-v2/script/prepare/setup-e2e-shell/install.sh swctl
verify:
retry:
count: 20
interval: 10s
cases:
- includes:
- ../profiling-cases.yaml

View File

@ -0,0 +1,55 @@
# 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.
# This file is used to show how to write configuration files and can be used to test.
cases:
# metadata
- query: swctl --base-url=http://${oap_host}:${oap_12800}/graphql --display yaml service ls
expected: expected/service.yml
- query: swctl --base-url=http://${oap_host}:${oap_12800}/graphql --display yaml instance ls --service-name sqrt
expected: expected/instance.yml
- query: swctl --base-url=http://${oap_host}:${oap_12800}/graphql --display yaml process ls --service-name sqrt --instance-name test-instance
expected: expected/process.yml
# policy setting
- query: |
swctl --base-url=http://${oap_host}:${oap_12800}/graphql --display yaml profiling continuous set --service-name sqrt --config test/e2e-v2/cases/profiling/ebpf/continuous/policy.yaml
expected: expected/policy-set.yml
- query: swctl --base-url=http://${oap_host}:${oap_12800}/graphql --display yaml profiling continuous ls --service-name sqrt
expected: expected/query-policy.yml
# check profiling metrics
- query: |
swctl --base-url=http://${oap_host}:${oap_12800}/graphql --display yaml metrics linear \
--service-name sqrt --instance-name test-instance --process-name sqrt --name continuous_profiling_process_cpu |yq e 'to_entries' -
expected: expected/metrics-has-value.yml
# check triggered profiling task
- query: |
swctl --base-url=http://${oap_host}:${oap_12800}/graphql --display yaml profiling ebpf list --service-name sqrt --trigger CONTINUOUS_PROFILING
expected: expected/trigger-task.yml
- query: |
swctl --base-url=http://${oap_host}:${oap_12800}/graphql --display yaml profiling ebpf schedules --task-id=$( \
swctl --base-url=http://${oap_host}:${oap_12800}/graphql --display yaml profiling ebpf list --service-name sqrt --trigger CONTINUOUS_PROFILING|yq e '.[0].taskid' -
)
expected: expected/profiling-schedule-list.yml
- query: |
taskid=$(swctl --base-url=http://${oap_host}:${oap_12800}/graphql --display yaml profiling ebpf list --service-name sqrt --trigger CONTINUOUS_PROFILING|yq e '.[0].taskid' -)
scheduleid=$(swctl --base-url=http://${oap_host}:${oap_12800}/graphql --display yaml profiling ebpf schedules --task-id=$taskid |yq e '.[0].scheduleid' -);
start=$(swctl --base-url=http://${oap_host}:${oap_12800}/graphql --display yaml profiling ebpf schedules --task-id=$taskid | yq e '.[0].starttime' -)
end=$(swctl --base-url=http://${oap_host}:${oap_12800}/graphql --display yaml profiling ebpf schedules --task-id=$taskid | yq e '.[0].endtime' -)
swctl --base-url=http://${oap_host}:${oap_12800}/graphql --display yaml profiling ebpf analysis --schedule-id=$scheduleid --time-ranges=$start-$end
expected: expected/profiling-analysis.yml

View File

@ -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 main
import (
"math"
)
//go:noinline
func sqrtGolang() {
for {
math.Sqrt(10000)
}
}
func main() {
sqrtGolang()
}

View File

@ -152,4 +152,17 @@ profiling:
# The default body encoding when sampling the request
default_request_encoding: ${ROVER_PROFILING_TASK_NETWORK_PROTOCOL_ANALYZE_SAMPLING_HTTP_DEFAULT_REQUEST_ENCODING:UTF-8}
# The default body encoding when sampling the response
default_response_encoding: ${ROVER_PROFILING_TASK_NETWORK_PROTOCOL_ANALYZE_SAMPLING_HTTP_DEFAULT_RESPONSE_ENCODING:UTF-8}
default_response_encoding: ${ROVER_PROFILING_TASK_NETWORK_PROTOCOL_ANALYZE_SAMPLING_HTTP_DEFAULT_RESPONSE_ENCODING:UTF-8}
# continuous profiling config
continuous:
# continuous related meters prefix name
meter_prefix: ${ROVER_PROFILING_CONTINUOUS_METER_PREFIX:rover_con_p}
# The interval of fetch metrics from the system, such as Process CPU, System Load, etc.
fetch_interval: ${ROVER_PROFILING_CONTINUOUS_FETCH_INTERVAL:1s}
# The interval of check metrics is reach the thresholds
check_interval: ${ROVER_PROFILING_CONTINUOUS_CHECK_INTERVAL:5s}
trigger:
# the duration of the profiling task
execute_duration: ${ROVER_PROFILING_CONTINUOUS_TRIGGER_EXECUTE_DURATION:10m}
# the minimal duration between the execution of the same profiling task
silence_duration: ${ROVER_PROFILING_CONTINUOUS_TRIGGER_SILENCE_DURATION:20m}

View File

@ -19,6 +19,8 @@
servicename: file
serviceinstanceid: null
serviceinstancename: null
processid: null
processname: null
processlabels:
{{- contains .processlabels }}
- e2e-label1
@ -29,4 +31,5 @@
fixedtriggerduration: 60
targettype: OFF_CPU
createtime: {{ gt .createtime 0 }}
continuousprofilingcauses: []
{{- end }}

View File

@ -19,6 +19,8 @@
servicename: sqrt
serviceinstanceid: null
serviceinstancename: null
processid: null
processname: null
processlabels:
{{- contains .processlabels }}
- e2e-label1
@ -29,4 +31,5 @@
fixedtriggerduration: 60
targettype: ON_CPU
createtime: {{ gt .createtime 0 }}
continuousprofilingcauses: []
{{- end }}

View File

@ -22,7 +22,7 @@ SW_AGENT_PYTHON_COMMIT=c76a6ec51a478ac91abb20ec8f22a99b8d4d6a58
SW_AGENT_CLIENT_JS_COMMIT=af0565a67d382b683c1dbd94c379b7080db61449
SW_AGENT_CLIENT_JS_TEST_COMMIT=4f1eb1dcdbde3ec4a38534bf01dded4ab5d2f016
SW_KUBERNETES_COMMIT_SHA=b670c41d94a82ddefcf466d54bab5c492d88d772
SW_ROVER_COMMIT=8550199e98c9f5a4b2058878a0a899ffb73fe461
SW_ROVER_COMMIT=fc8d074c6d34ecfee585a7097cbd5aef1ca680a5
SW_BANYANDB_COMMIT=adbd3e87df7f84e5d1904fcf40476d2e81842058
SW_CTL_COMMIT=0883266bfaa36612927b69e35781b64ea181758d
SW_CTL_COMMIT=838e222da5ab81b383c5bc8526e5d30002d836f9