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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Release Notes.
* Put `Agent-Version` property reading in the premain stage to avoid deadlock when using `jarsigner`.
* Add a config `agent.enable`(default: true) to support disabling the agent through system property `-Dskywalking.agent.disable=false`
or system environment variable setting `SW_AGENT_ENABLE=false`.
* Enhance redisson plugin to adopt uniform tags.

#### Documentation

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,11 @@ public static final class HTTP {
*/
public static final StringTag CACHE_KEY = new StringTag(18, "cache.key");

/**
* CACHE_INSTANCE records the cache instance
*/
public static final StringTag CACHE_INSTANCE = new StringTag(20, "cache.instance");

public static final String VAL_LOCAL_SPAN_AS_LOGIC_ENDPOINT = "{\"logic-span\":true}";

public static final StringTag SQL_PARAMETERS = new StringTag(19, "db.sql.parameters");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

package org.apache.skywalking.apm.plugin.redisson.v3;

import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import org.apache.skywalking.apm.agent.core.context.ContextManager;
import org.apache.skywalking.apm.agent.core.context.tag.Tags;
Expand All @@ -32,13 +31,15 @@
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
import org.apache.skywalking.apm.plugin.redisson.v3.util.ClassUtil;
import org.apache.skywalking.apm.util.StringUtil;
import org.redisson.client.RedisClient;
import org.redisson.client.RedisConnection;
import org.redisson.client.protocol.CommandData;
import org.redisson.client.protocol.CommandsData;

import java.lang.reflect.Method;
import java.net.InetSocketAddress;
import java.util.Optional;

public class RedisConnectionMethodInterceptor implements InstanceMethodsAroundInterceptor, InstanceConstructorInterceptor {

Expand All @@ -58,43 +59,29 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr
InetSocketAddress remoteAddress = (InetSocketAddress) channel.remoteAddress();
String dbInstance = remoteAddress.getAddress().getHostAddress() + ":" + remoteAddress.getPort();

StringBuilder dbStatement = new StringBuilder();
String operationName = "Redisson/";
String command = "";
Object[] arguments = new Object[0];

if (allArguments[0] instanceof CommandsData) {
operationName = operationName + "BATCH_EXECUTE";
CommandsData commands = (CommandsData) allArguments[0];
for (CommandData commandData : commands.getCommands()) {
addCommandData(dbStatement, commandData);
dbStatement.append(";");
}
command = "BATCH_EXECUTE";
} else if (allArguments[0] instanceof CommandData) {
CommandData commandData = (CommandData) allArguments[0];
String command = commandData.getCommand().getName();
command = commandData.getCommand().getName();
operationName = operationName + command;
addCommandData(dbStatement, commandData);
arguments = commandData.getParams();
}

AbstractSpan span = ContextManager.createExitSpan(operationName, peer);
span.setComponent(ComponentsDefine.REDISSON);
Tags.DB_TYPE.set(span, "Redis");
Tags.DB_INSTANCE.set(span, dbInstance);
Tags.DB_STATEMENT.set(span, dbStatement.toString());
SpanLayer.asCache(span);
}
Tags.CACHE_TYPE.set(span, "Redis");
Tags.CACHE_INSTANCE.set(span, dbInstance);
Tags.CACHE_CMD.set(span, command);

private void addCommandData(StringBuilder dbStatement, CommandData commandData) {
dbStatement.append(commandData.getCommand().getName());
if (RedissonPluginConfig.Plugin.Redisson.TRACE_REDIS_PARAMETERS && commandData.getParams() != null) {
for (Object param : commandData.getParams()) {
dbStatement.append(DELIMITER_SPACE);
String paramStr = param instanceof ByteBuf ? QUESTION_MARK : String.valueOf(param.toString());
if (paramStr.length() > RedissonPluginConfig.Plugin.Redisson.REDIS_PARAMETER_MAX_LENGTH) {
paramStr = paramStr.substring(0, RedissonPluginConfig.Plugin.Redisson.REDIS_PARAMETER_MAX_LENGTH) + ABBR;
}
dbStatement.append(paramStr);
}
}
getKey(arguments).ifPresent(key -> Tags.CACHE_KEY.set(span, key));
parseOperation(command.toLowerCase()).ifPresent(op -> Tags.CACHE_OP.set(span, op));
SpanLayer.asCache(span);
}

@Override
Expand Down Expand Up @@ -131,4 +118,29 @@ public void onConstruct(EnhancedInstance objInst, Object[] allArguments) {
}
objInst.setSkyWalkingDynamicField(peer);
}

private Optional<String> getKey(Object[] allArguments) {
if (!RedissonPluginConfig.Plugin.Redisson.TRACE_REDIS_PARAMETERS) {
return Optional.empty();
}
if (allArguments.length == 0) {
return Optional.empty();
}
Object argument = allArguments[0];
// include null
if (!(argument instanceof String)) {
return Optional.empty();
}
return Optional.of(StringUtil.cut((String) argument, RedissonPluginConfig.Plugin.Redisson.REDIS_PARAMETER_MAX_LENGTH));
}

private Optional<String> parseOperation(String cmd) {
if (RedissonPluginConfig.Plugin.Redisson.OPERATION_MAPPING_READ.contains(cmd)) {
return Optional.of("read");
}
if (RedissonPluginConfig.Plugin.Redisson.OPERATION_MAPPING_WRITE.contains(cmd)) {
return Optional.of("write");
}
return Optional.empty();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@

import org.apache.skywalking.apm.agent.core.boot.PluginConfig;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

public class RedissonPluginConfig {
public static class Plugin {
@PluginConfig(root = RedissonPluginConfig.class)
Expand All @@ -36,6 +40,118 @@ public static class Redisson {
* Set a negative number to save specified length of parameter string to the tag.
*/
public static int REDIS_PARAMETER_MAX_LENGTH = 128;

/**
* Operation represent a cache span is "write" or "read" action , and "op"(operation) is tagged with key "cache.op" usually
* This config term define which command should be converted to write Operation .
*
* @see org.apache.skywalking.apm.agent.core.context.tag.Tags#CACHE_OP
* @see RedisConnectionMethodInterceptor#parseOperation(String)
*/
public static Set<String> OPERATION_MAPPING_WRITE = new HashSet<>(Arrays.asList(
"getset",
"set",
"setbit",
"setex ",
"setnx ",
"setrange",
"strlen ",
"mset",
"msetnx ",
"psetex",
"incr ",
"incrby ",
"incrbyfloat",
"decr ",
"decrby ",
"append ",
"hmset",
"hset",
"hsetnx ",
"hincrby",
"hincrbyfloat",
"hdel",
"rpoplpush",
"rpush",
"rpushx",
"lpush",
"lpushx",
"lrem",
"ltrim",
"lset",
"brpoplpush",
"linsert",
"sadd",
"sdiff",
"sdiffstore",
"sinterstore",
"sismember",
"srem",
"sunion",
"sunionstore",
"sinter",
"zadd",
"zincrby",
"zinterstore",
"zrange",
"zrangebylex",
"zrangebyscore",
"zrank",
"zrem",
"zremrangebylex",
"zremrangebyrank",
"zremrangebyscore",
"zrevrange",
"zrevrangebyscore",
"zrevrank",
"zunionstore",
"xadd",
"xdel",
"del",
"xtrim"
));
/**
* Operation represent a cache span is "write" or "read" action , and "op"(operation) is tagged with key "cache.op" usually
* This config term define which command should be converted to write Operation .
*
* @see org.apache.skywalking.apm.agent.core.context.tag.Tags#CACHE_OP
* @see RedisConnectionMethodInterceptor#parseOperation(String)
*/
public static Set<String> OPERATION_MAPPING_READ = new HashSet<>(Arrays.asList(
"getrange",
"getbit ",
"mget",
"hvals",
"hkeys",
"hlen",
"hexists",
"hget",
"hgetall",
"hmget",
"blpop",
"brpop",
"lindex",
"llen",
"lpop",
"lrange",
"rpop",
"scard",
"srandmember",
"spop",
"sscan",
"smove",
"zlexcount",
"zscore",
"zscan",
"zcard",
"zcount",
"xget",
"get",
"xread",
"xlen",
"xrange",
"xrevrange"
));
}
}
}
4 changes: 4 additions & 0 deletions apm-sniffer/config/agent.config
Original file line number Diff line number Diff line change
Expand Up @@ -305,3 +305,7 @@ plugin.jedis.operation_mapping_read=${SW_PLUGIN_JEDIS_OPERATION_MAPPING_READ:get
plugin.redisson.trace_redis_parameters=${SW_PLUGIN_REDISSON_TRACE_REDIS_PARAMETERS:false}
# If set to positive number and plugin.redisson.trace_redis_parameters is set to true, Redis command parameters would be collected and truncated to this length.
plugin.redisson.redis_parameter_max_length=${SW_PLUGIN_REDISSON_REDIS_PARAMETER_MAX_LENGTH:128}
# Specify which command should be converted to write operation
plugin.redisson.operation_mapping_write=${SW_PLUGIN_REDISSON_OPERATION_MAPPING_WRITE:getset,set,setbit,setex,setnx,setrange,strlen,mset,msetnx,psetex,incr,incrby,incrbyfloat,decr,decrby,append,hmset,hset,hsetnx,hincrby,hincrbyfloat,hdel,rpoplpush,rpush,rpushx,lpush,lpushx,lrem,ltrim,lset,brpoplpush,linsert,sadd,sdiff,sdiffstore,sinterstore,sismember,srem,sunion,sunionstore,sinter,zadd,zincrby,zinterstore,zrange,zrangebylex,zrangebyscore,zrank,zrem,zremrangebylex,zremrangebyrank,zremrangebyscore,zrevrange,zrevrangebyscore,zrevrank,zunionstore,xadd,xdel,del,xtrim}
# Specify which command should be converted to read operation
plugin.redisson.operation_mapping_read=${SW_PLUGIN_REDISSON_OPERATION_MAPPING_READ:getrange,getbit,mget,hvals,hkeys,hlen,hexists,hget,hgetall,hmget,blpop,brpop,lindex,llen,lpop,lrange,rpop,scard,srandmember,spop,sscan,smove,zlexcount,zscore,zscan,zcard,zcount,xget,get,xread,xlen,xrange,xrevrange}
Loading