Skip to content

Commit

Permalink
Add Caffeine plugin as optional (#743)
Browse files Browse the repository at this point in the history
  • Loading branch information
CodePrometheus authored Dec 29, 2024
1 parent b0d5bc1 commit d53f04b
Show file tree
Hide file tree
Showing 31 changed files with 1,158 additions and 15 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:
build:
name: Java ${{ matrix.java-version }} / ${{ matrix.os }}
runs-on: ${{ matrix.os }}-latest
timeout-minutes: 60
timeout-minutes: 90
needs: [ license ]
strategy:
fail-fast: true
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/codeql.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ jobs:
java-version: 17

- name: Initialize CodeQL
uses: github/codeql-action/init@v1
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}

- run: ./mvnw -q -Dmaven.test.skip=true clean install || ./mvnw -q -Dmaven.test.skip=true clean install

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
uses: github/codeql-action/analyze@v3
1 change: 1 addition & 0 deletions .github/workflows/plugins-jdk17-test.1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ jobs:
- c3p0-0.9.0.x-0.9.1.x-scenario
- c3p0-0.9.2.x-0.10.x-scenario
- spring-scheduled-6.x-scenario
- caffeine-3.x-scenario
steps:
- uses: actions/checkout@v2
with:
Expand Down
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Release Notes.
Plugin, Kotlin Coroutine Plugin, and Spring Gateway Plugin
* Change context and parent entry span propagation mechanism from gRPC ThreadLocal context to SkyWalking native dynamic
field as new propagation mechanism, to better support async scenarios.
* Add Caffeine plugin as optional.

All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/222?closed=1)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -259,4 +259,5 @@ public class ComponentsDefine {

public static final OfficialComponent SOLON_MVC = new OfficialComponent(158, "SolonMVC");

public static final OfficialComponent CAFFEINE = new OfficialComponent(160, "Caffeine");
}
4 changes: 4 additions & 0 deletions apm-sniffer/config/agent.config
Original file line number Diff line number Diff line change
Expand Up @@ -332,3 +332,7 @@ plugin.solon.http_params_length_threshold=${SW_PLUGIN_SOLON_HTTP_PARAMS_LENGTH_T
plugin.solon.include_http_headers=${SW_PLUGIN_SOLON_INCLUDE_HTTP_HEADERS:}
# Define the max length of collected HTTP body. The default value(=0) means not collecting.
plugin.solon.http_body_length_threshold=${SW_PLUGIN_SOLON_HTTP_BODY_LENGTH_THRESHOLD:0}
# Specify which command should be converted to write operation
plugin.caffeine.operation_mapping_write=${SW_PLUGIN_CAFFEINE_OPERATION_MAPPING_WRITE:put,putAll,remove,clear}
# Specify which command should be converted to read operation
plugin.caffeine.operation_mapping_read=${SW_PLUGIN_CAFFEINE_OPERATION_MAPPING_READ:getIfPresent,getAllPresent,computeIfAbsent}
46 changes: 46 additions & 0 deletions apm-sniffer/optional-plugins/caffeine-3.x-plugin/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
~
-->

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.skywalking</groupId>
<artifactId>optional-plugins</artifactId>
<version>9.4.0-SNAPSHOT</version>
</parent>

<artifactId>apm-caffeine-3.x-plugin</artifactId>
<packaging>jar</packaging>
<name>caffeine-3.x-plugin</name>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<caffeine.version>3.1.8</caffeine.version>
</properties>

<dependencies>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>${caffeine.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

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

import java.lang.reflect.Method;
import org.apache.skywalking.apm.agent.core.context.ContextManager;
import org.apache.skywalking.apm.agent.core.context.tag.Tags;
import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;

import static org.apache.skywalking.apm.plugin.caffeine.v3.CaffeineOperationTransform.transformOperation;

abstract public class AbstractCaffeineInterceptor implements InstanceMethodsAroundInterceptor {

protected AbstractSpan generateSpanInfo(String methodName) {
AbstractSpan span = ContextManager.createLocalSpan("Caffeine/" + methodName);
span.setComponent(ComponentsDefine.CAFFEINE);
Tags.CACHE_TYPE.set(span, ComponentsDefine.CAFFEINE.getName());
Tags.CACHE_CMD.set(span, methodName);
transformOperation(methodName).ifPresent(op -> Tags.CACHE_OP.set(span, op));
SpanLayer.asCache(span);
return span;
}

@Override
public void beforeMethod(final EnhancedInstance objInst,
final Method method,
final Object[] allArguments,
final Class<?>[] argumentsTypes,
final MethodInterceptResult result) throws Throwable {
}

@Override
public Object afterMethod(final EnhancedInstance objInst,
final Method method,
final Object[] allArguments,
final Class<?>[] argumentsTypes,
final Object ret) throws Throwable {
ContextManager.stopSpan();
return ret;
}

@Override
public void handleMethodException(final EnhancedInstance objInst,
final Method method,
final Object[] allArguments,
final Class<?>[] argumentsTypes,
final Throwable t) {
ContextManager.activeSpan().log(t);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* 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.apm.plugin.caffeine.v3;

import java.lang.reflect.Method;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import org.apache.skywalking.apm.agent.core.context.tag.Tags;
import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;

public class CaffeineIterableInterceptor extends AbstractCaffeineInterceptor {

@Override
public void beforeMethod(final EnhancedInstance objInst,
final Method method,
final Object[] allArguments,
final Class<?>[] argumentsTypes,
final MethodInterceptResult result) throws Throwable {
AbstractSpan span = generateSpanInfo(method.getName());
if (allArguments != null && allArguments.length > 0) {
String keys = StreamSupport
.stream(((Iterable<?>) allArguments[0]).spliterator(), false)
.map(String::valueOf)
.collect(Collectors.joining(","));
Tags.CACHE_KEY.set(span, keys);
}
}
}
Original file line number Diff line number Diff line change
@@ -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.apm.plugin.caffeine.v3;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.skywalking.apm.agent.core.context.tag.Tags;
import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;

public class CaffeineMapInterceptor extends AbstractCaffeineInterceptor {

@Override
public void beforeMethod(final EnhancedInstance objInst,
final Method method,
final Object[] allArguments,
final Class<?>[] argumentsTypes,
final MethodInterceptResult result) throws Throwable {
AbstractSpan span = generateSpanInfo(method.getName());
if (allArguments != null && allArguments.length > 0) {
String keys = ((Map<?, ?>) allArguments[0])
.keySet().stream().map(String::valueOf)
.collect(Collectors.joining(","));
Tags.CACHE_KEY.set(span, keys);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

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

import java.util.Optional;

public class CaffeineOperationTransform {

public static Optional<String> transformOperation(String cmd) {
if (CaffeinePluginConfig.Plugin.Caffeine.OPERATION_MAPPING_READ.contains(cmd)) {
return Optional.of("read");
}
if (CaffeinePluginConfig.Plugin.Caffeine.OPERATION_MAPPING_WRITE.contains(cmd)) {
return Optional.of("write");
}
return Optional.empty();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

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

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import org.apache.skywalking.apm.agent.core.boot.PluginConfig;

/**
* 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 CaffeineOperationTransform#transformOperation(String)
*/
public class CaffeinePluginConfig {
public static class Plugin {
@PluginConfig(root = CaffeinePluginConfig.class)
public static class Caffeine {
public static Set<String> OPERATION_MAPPING_WRITE = new HashSet<>(Arrays.asList(
"put",
"putAll",
"remove",
"clear"
));
public static Set<String> OPERATION_MAPPING_READ = new HashSet<>(Arrays.asList(
"getIfPresent",
"getAllPresent",
"computeIfAbsent"
));
}
}
}
Original file line number Diff line number Diff line change
@@ -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.
*
*/

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

import java.lang.reflect.Method;
import org.apache.skywalking.apm.agent.core.context.tag.Tags;
import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;

public class CaffeineStringInterceptor extends AbstractCaffeineInterceptor {

@Override
public void beforeMethod(final EnhancedInstance objInst,
final Method method,
final Object[] allArguments,
final Class<?>[] argumentsTypes,
final MethodInterceptResult result) throws Throwable {
AbstractSpan span = generateSpanInfo(method.getName());
if (allArguments != null && allArguments.length > 0 && allArguments[0] instanceof String) {
Tags.CACHE_KEY.set(span, allArguments[0].toString());
}
}
}
Loading

0 comments on commit d53f04b

Please sign in to comment.