Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support install external agent in Sermant #1706

Merged
merged 1 commit into from
Dec 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ agent.config.enhancedClassesOutputPath=
# Enable the host service instance class to be loaded by the thread context classloader during interceptor execution. If enabled, the host class is loaded by the context classloader during interceptor execution for service governance logic use. The default value is true.
agent.config.useContextLoader=true
# List of class prefixes that need be ignored when bytecode enhancement is performed.
agent.config.ignoredPrefixes=io.sermant
agent.config.ignoredPrefixes=io.sermant,io.opentelemetry
# List of interfaces that need to be ignored when bytecode enhancement is used to search for a class. If all implementation classes of an interface do not want to be bytecode enhanced, you can configure this configuration item
agent.config.ignoredInterfaces=org.springframework.cglib.proxy.Factory
# Specifies which classes in the plugins are allowed to be bytecode enhanced (classes in the plugins are not allowed to be bytecode enhanced by default)
Expand All @@ -21,6 +21,12 @@ agent.config.preFilter.enable=false
agent.config.preFilter.path=
# File name of unmatched class name, the default file is 'unmatched_class_name.txt'
agent.config.preFilter.file=
# External agent injection
agent.config.externalAgent.injection=false
# External agent name, OTEL is tested and supported. Other agents need to be tested by developers
agent.config.externalAgent.name=OTEL
# File of external agent, example: /user/opentelemetry-javaagent.jar
agent.config.externalAgent.file=
#============================= core service configuration =============================#
# Heartbeat service switch
agent.service.heartbeat.enable=false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ agent.config.enhancedClassesOutputPath=
# Enable the host service instance class to be loaded by the thread context classloader during interceptor execution. If enabled, the host class is loaded by the context classloader during interceptor execution for service governance logic use. The default value is true.
agent.config.useContextLoader=true
# List of class prefixes that need be ignored when bytecode enhancement is performed.
agent.config.ignoredPrefixes=io.sermant
agent.config.ignoredPrefixes=io.sermant,io.opentelemetry
# List of interfaces that need to be ignored when bytecode enhancement is used to search for a class. If all implementation classes of an interface do not want to be bytecode enhanced, you can configure this configuration item
agent.config.ignoredInterfaces=org.springframework.cglib.proxy.Factory
# Specifies which classes in the plugins are allowed to be bytecode enhanced (classes in the plugins are not allowed to be bytecode enhanced by default)
Expand All @@ -21,6 +21,12 @@ agent.config.preFilter.enable=false
agent.config.preFilter.path=
# File name of unmatched class name, the default file is 'unmatched_class_name.txt'
agent.config.preFilter.file=
# External agent injection
agent.config.externalAgent.injection=false
# External agent name, OTEL is tested and supported. Other agents need to be tested by developers
agent.config.externalAgent.name=OTEL
# File of external agent, example: /user/opentelemetry-javaagent.jar
agent.config.externalAgent.file=
#============================= core service configuration =============================#
# Heartbeat service switch
agent.service.heartbeat.enable=true
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2021 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (C) 2021-2024 Huawei Technologies Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -17,13 +17,15 @@
package io.sermant.core;

import io.sermant.core.classloader.ClassLoaderManager;
import io.sermant.core.command.CommandProcessor;
import io.sermant.core.common.AgentType;
import io.sermant.core.common.BootArgsIndexer;
import io.sermant.core.common.CommonConstant;
import io.sermant.core.common.LoggerFactory;
import io.sermant.core.config.ConfigManager;
import io.sermant.core.event.EventManager;
import io.sermant.core.event.collector.FrameworkEventCollector;
import io.sermant.core.ext.ExternalAgentManager;
import io.sermant.core.notification.NotificationInfo;
import io.sermant.core.notification.NotificationManager;
import io.sermant.core.notification.SermantNotificationType;
Expand All @@ -33,6 +35,7 @@
import io.sermant.core.plugin.agent.ByteEnhanceManager;
import io.sermant.core.plugin.agent.adviser.AdviserInterface;
import io.sermant.core.plugin.agent.adviser.AdviserScheduler;
import io.sermant.core.plugin.agent.config.AgentConfig;
import io.sermant.core.plugin.agent.info.EnhancementManager;
import io.sermant.core.plugin.agent.template.DefaultAdviser;
import io.sermant.core.service.ServiceManager;
Expand Down Expand Up @@ -136,6 +139,24 @@
if (NotificationManager.isEnable()) {
NotificationManager.doNotify(new NotificationInfo(SermantNotificationType.LOAD_COMPLETE, null));
}

// cache instrumentation
CommandProcessor.cacheInstrumentation(instrumentation);
daizhenyu marked this conversation as resolved.
Show resolved Hide resolved

// install external agent, such as OTEL
handleExternalAgentInstallation(instrumentation);
}

private static void handleExternalAgentInstallation(Instrumentation instrumentation) {
AgentConfig agentConfig = ConfigManager.getConfig(AgentConfig.class);
if (agentConfig.isExternalAgentInjection()) {
try {
ExternalAgentManager.installExternalAgent(false, agentConfig.getExternalAgentName(),
agentConfig.getExternalAgentFile(), null, instrumentation);
} catch (Exception e) {

Check failure on line 156 in sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/AgentCoreEntrance.java

View workflow job for this annotation

GitHub Actions / Checkstyle

[Checkstyle Check] reported by reviewdog 🐶 Catching 'Exception' is not allowed. Raw Output: /home/runner/work/Sermant/Sermant/./sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/AgentCoreEntrance.java:156:15: error: Catching 'Exception' is not allowed. (com.puppycrawl.tools.checkstyle.checks.coding.IllegalCatchCheck)
LOGGER.severe("Failed to install external agent: " + e.getMessage());
}
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2023-2023 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (C) 2023-2024 Huawei Technologies Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -43,7 +43,12 @@ public enum Command {
/**
* Enhancement query instruction
*/
CHECK_ENHANCEMENT("CHECK-ENHANCEMENT");
CHECK_ENHANCEMENT("CHECK-ENHANCEMENT"),

/**
* Install external agent instruction
*/
INSTALL_EXTERNAL_AGENT("INSTALL-EXTERNAL-AGENT");

private final String value;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2023-2023 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (C) 2023-2024 Huawei Technologies Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -19,6 +19,7 @@
import io.sermant.core.common.LoggerFactory;
import io.sermant.core.utils.StringUtils;

import java.lang.instrument.Instrumentation;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
Expand All @@ -41,12 +42,15 @@ public class CommandProcessor {

private static final String COMMAND = "command";

private static Instrumentation instrumentation;

static {
COMMAND_EXECUTOR_MAP.put(Command.INSTALL_PLUGINS.getValue(), new PluginsInstallCommandExecutor());
COMMAND_EXECUTOR_MAP.put(Command.UNINSTALL_AGENT.getValue(), new AgentUnInstallCommandExecutor());
COMMAND_EXECUTOR_MAP.put(Command.UNINSTALL_PLUGINS.getValue(), new PluginsUnInstallCommandExecutor());
COMMAND_EXECUTOR_MAP.put(Command.UPDATE_PLUGINS.getValue(), new PluginsUpdateCommandExecutor());
COMMAND_EXECUTOR_MAP.put(Command.CHECK_ENHANCEMENT.getValue(), new CheckEnhancementsCommandExecutor());
COMMAND_EXECUTOR_MAP.put(Command.INSTALL_EXTERNAL_AGENT.getValue(), new ExternalAgentInstallCommandExecutor());
}

/**
Expand Down Expand Up @@ -81,4 +85,22 @@ public static void process(Map<String, String> agentArgsMap) {
DynamicAgentArgsManager.refreshAgentArgs(agentArgsMap);
commandExecutor.execute(commandArgs);
}

/**
* cache instrumentation for dynamic agent installation
*
* @param inst instrumentation
*/
public static void cacheInstrumentation(Instrumentation inst) {
instrumentation = inst;
}

/**
* get instrumentation for dynamic agent installation
*
* @return instrumentation
*/
public static Instrumentation getInstrumentation() {
return instrumentation;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,13 @@ public static void refreshAgentArgs(Map<String, String> newAgentArgs) {
public static String getAgentArg(String key) {
return AGENT_ARGS.get(key);
}

/**
* get AGENT_ARGS map
*
* @return dynamical args
*/
public static Map<String, String> getAgentArgsMap() {
return AGENT_ARGS;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright (C) 2024-2024 Sermant Authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.sermant.core.command;

import io.sermant.core.common.CommonConstant;
import io.sermant.core.common.LoggerFactory;
import io.sermant.core.ext.ExternalAgentManager;
import io.sermant.core.utils.StringUtils;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
* The command executor of external agent installation
*
* @author lilai
* @since 2024-12-14
*/
public class ExternalAgentInstallCommandExecutor implements CommandExecutor {
private static final Logger LOGGER = LoggerFactory.getLogger();

@Override
public void execute(String args) {
Map<String, String> agentArgsMap = DynamicAgentArgsManager.getAgentArgsMap();
String agentPath = agentArgsMap.get(CommonConstant.AGENT_FILE_KEY);
if (StringUtils.isEmpty(agentPath)) {
LOGGER.severe("Failed to install external agent: AGENT_FILE in command args is empty");
return;
}

try {
ExternalAgentManager.installExternalAgent(true, args, agentPath, agentArgsMap,
CommandProcessor.getInstrumentation());
} catch (IOException | NoSuchMethodException | ClassNotFoundException | InvocationTargetException
| IllegalAccessException e) {
LOGGER.log(Level.SEVERE, "Failed to install external agent: {0}. Error message: {1}",
new String[]{args, e.getMessage()});
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2021 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (C) 2021-2024 Huawei Technologies Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -142,6 +142,11 @@ public class CommonConstant {
*/
public static final String AGENT_PATH_KEY = "agentPath";

/**
* The key of agent file in dynamic installation
*/
public static final String AGENT_FILE_KEY = "AGENT_FILE";

private CommonConstant() {
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2023-2023 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (C) 2023-2024 Huawei Technologies Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -164,4 +164,20 @@ public void collectdHotPluggingEvent(FrameworkEventDefinitions frameworkEventDef
frameworkEventDefinitions.getEventType(),
new EventInfo(frameworkEventDefinitions.getName(), description)));
}

/**
* Collect OpenTelemetry Agent start event
*
* @param startMethod the method name OpenTelemetry Agent starts by
*/
public void collectOtelStartEvent(String startMethod) {
lilai23 marked this conversation as resolved.
Show resolved Hide resolved
if (!eventConfig.isEnable()) {
return;
}
String description = "OpenTelemetry Agent starts by " + startMethod;
offerEvent(new Event(FrameworkEventDefinitions.OTEL_START.getScope(),
FrameworkEventDefinitions.OTEL_START.getEventLevel(),
FrameworkEventDefinitions.OTEL_START.getEventType(),
new EventInfo(FrameworkEventDefinitions.OTEL_START.getName(), description)));
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2023-2023 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (C) 2023-2024 Huawei Technologies Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -74,7 +74,17 @@ public enum FrameworkEventDefinitions {
/**
* Sermant plugin update event definition
*/
SERMANT_PLUGIN_UPDATE("SERMANT_PLUGIN_UPDATE", EventType.OPERATION, EventLevel.NORMAL);
SERMANT_PLUGIN_UPDATE("SERMANT_PLUGIN_UPDATE", EventType.OPERATION, EventLevel.NORMAL),

/**
* External agent install event definition
*/
EXTERNAL_AGENT_INSTALL("EXTERNAL_AGENT_INSTALL", EventType.OPERATION, EventLevel.NORMAL),

/**
* OpenTelemetry agent start event definition
*/
OTEL_START("OTEL_START", EventType.OPERATION, EventLevel.NORMAL);

/**
* event name
Expand Down
Loading
Loading