-
Notifications
You must be signed in to change notification settings - Fork 33
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
Collect WebLogic specific attributes #81
Merged
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
plugins { | ||
id "java" | ||
} | ||
|
||
dependencies { | ||
compileOnly('javax.servlet:servlet-api:2.2') | ||
} |
88 changes: 88 additions & 0 deletions
88
...rc/main/java/com/splunk/opentelemetry/middleware/weblogic/WebLogicAttributeCollector.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
/* | ||
* Copyright Splunk Inc. | ||
* | ||
* 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 com.splunk.opentelemetry.middleware.weblogic; | ||
|
||
import com.splunk.opentelemetry.javaagent.bootstrap.MiddlewareHolder; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
import javax.servlet.http.HttpServletRequest; | ||
|
||
public class WebLogicAttributeCollector { | ||
private static final String CONTEXT_ATTRIBUTE_NAME = "otel.weblogic.attributes"; | ||
public static final String REQUEST_ATTRIBUTE_NAME = "otel.middleware"; | ||
|
||
public static void attachMiddlewareAttributes(HttpServletRequest servletRequest) { | ||
WebLogicEntity.Request request = WebLogicEntity.Request.wrap(servletRequest); | ||
|
||
Map<?, ?> attributes = fetchMiddlewareAttributes(request.getContext()); | ||
request.instance.setAttribute(REQUEST_ATTRIBUTE_NAME, attributes); | ||
} | ||
|
||
private static Map<?, ?> fetchMiddlewareAttributes(WebLogicEntity.Context context) { | ||
if (context.instance == null) { | ||
return null; | ||
} | ||
|
||
Object value = context.instance.getAttribute(CONTEXT_ATTRIBUTE_NAME); | ||
|
||
if (value instanceof Map<?, ?>) { | ||
return (Map<?, ?>) value; | ||
} | ||
|
||
// Do this here to avoid duplicate work | ||
storeMiddlewareIdentity(context); | ||
|
||
Map<String, String> middleware = collectMiddlewareAttributes(context); | ||
context.instance.setAttribute(CONTEXT_ATTRIBUTE_NAME, middleware); | ||
return middleware; | ||
} | ||
|
||
private static void storeMiddlewareIdentity(WebLogicEntity.Context context) { | ||
MiddlewareHolder.trySetName("WebLogic Server"); | ||
MiddlewareHolder.trySetVersion(detectVersion(context)); | ||
} | ||
|
||
private static Map<String, String> collectMiddlewareAttributes(WebLogicEntity.Context context) { | ||
WebLogicEntity.Bean applicationBean = context.getBean(); | ||
WebLogicEntity.Bean webServerBean = context.getServer().getBean(); | ||
WebLogicEntity.Bean serverBean = webServerBean.getParent(); | ||
WebLogicEntity.Bean clusterBean = WebLogicEntity.Bean.wrap(serverBean.getAttribute("Cluster")); | ||
WebLogicEntity.Bean domainBean = serverBean.getParent(); | ||
|
||
Map<String, String> attributes = new HashMap<>(); | ||
attributes.put("middleware.weblogic.domain", domainBean.getName()); | ||
attributes.put("middleware.weblogic.cluster", clusterBean.getName()); | ||
attributes.put("middleware.weblogic.server", webServerBean.getName()); | ||
attributes.put("middleware.weblogic.application", applicationBean.getName()); | ||
|
||
return attributes; | ||
} | ||
|
||
private static String detectVersion(WebLogicEntity.Context context) { | ||
String serverInfo = context.instance.getServerInfo(); | ||
|
||
if (serverInfo != null) { | ||
for (String token : serverInfo.split(" ")) { | ||
if (token.length() > 0 && Character.isDigit(token.charAt(0))) { | ||
return token; | ||
} | ||
} | ||
} | ||
|
||
return ""; | ||
} | ||
} |
266 changes: 266 additions & 0 deletions
266
...n/weblogic/src/main/java/com/splunk/opentelemetry/middleware/weblogic/WebLogicEntity.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,266 @@ | ||
/* | ||
* Copyright Splunk Inc. | ||
* | ||
* 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 com.splunk.opentelemetry.middleware.weblogic; | ||
|
||
import java.lang.invoke.MethodHandle; | ||
import java.lang.invoke.MethodHandles; | ||
import java.lang.invoke.MethodType; | ||
import javax.servlet.ServletContext; | ||
import javax.servlet.ServletRequest; | ||
|
||
/** Provides wrappers around WebLogic internal class instances. */ | ||
public class WebLogicEntity { | ||
private static final MethodHandle REQUEST_GET_CONTEXT; | ||
private static final MethodHandle CONTEXT_GET_MBEAN; | ||
private static final MethodHandle CONTEXT_GET_SERVER; | ||
private static final MethodHandle SERVER_GET_MBEAN; | ||
private static final MethodHandle MBEAN_GET_PARENT; | ||
private static final MethodHandle MBEAN_GET_KEY; | ||
private static final Class<?> MBEAN_CLASS; | ||
private static final MethodHandle MBEAN_GET_ATTRIBUTE; | ||
|
||
static { | ||
MethodHandle requestGetContext; | ||
MethodHandle contextGetMBean; | ||
MethodHandle contextGetServer; | ||
MethodHandle serverGetMBean; | ||
MethodHandle mbeanGetParent; | ||
MethodHandle mbeanGetKey; | ||
MethodHandle mbeanGetAttribute; | ||
Class<?> mbeanClass; | ||
|
||
try { | ||
requestGetContext = | ||
MethodHandles.publicLookup() | ||
.findVirtual( | ||
Class.forName("weblogic.servlet.internal.ServletRequestImpl"), | ||
"getContext", | ||
MethodType.methodType( | ||
Class.forName("weblogic.servlet.internal.WebAppServletContext"))); | ||
vovencij marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} catch (Exception e) { | ||
requestGetContext = null; | ||
} | ||
|
||
REQUEST_GET_CONTEXT = requestGetContext; | ||
|
||
try { | ||
contextGetMBean = | ||
MethodHandles.publicLookup() | ||
.findVirtual( | ||
Class.forName("weblogic.servlet.internal.WebAppServletContext"), | ||
"getMBean", | ||
MethodType.methodType( | ||
Class.forName("weblogic.management.configuration.WebAppComponentMBean"))); | ||
} catch (Exception e) { | ||
contextGetMBean = null; | ||
} | ||
|
||
CONTEXT_GET_MBEAN = contextGetMBean; | ||
|
||
try { | ||
contextGetServer = | ||
MethodHandles.publicLookup() | ||
.findVirtual( | ||
Class.forName("weblogic.servlet.internal.WebAppServletContext"), | ||
"getServer", | ||
MethodType.methodType(Class.forName("weblogic.servlet.internal.HttpServer"))); | ||
} catch (Exception e) { | ||
contextGetServer = null; | ||
} | ||
|
||
CONTEXT_GET_SERVER = contextGetServer; | ||
|
||
try { | ||
serverGetMBean = | ||
MethodHandles.publicLookup() | ||
.findVirtual( | ||
Class.forName("weblogic.servlet.internal.HttpServer"), | ||
"getMBean", | ||
MethodType.methodType( | ||
Class.forName("weblogic.management.configuration.WebServerMBean"))); | ||
} catch (Exception e) { | ||
serverGetMBean = null; | ||
} | ||
|
||
SERVER_GET_MBEAN = serverGetMBean; | ||
|
||
try { | ||
mbeanGetParent = | ||
MethodHandles.publicLookup() | ||
.findVirtual( | ||
Class.forName("weblogic.descriptor.DescriptorBean"), | ||
"getParentBean", | ||
MethodType.methodType(Class.forName("weblogic.descriptor.DescriptorBean"))); | ||
} catch (Exception e) { | ||
mbeanGetParent = null; | ||
} | ||
|
||
MBEAN_GET_PARENT = mbeanGetParent; | ||
|
||
try { | ||
mbeanGetKey = | ||
MethodHandles.publicLookup() | ||
.findVirtual( | ||
Class.forName("weblogic.descriptor.internal.AbstractDescriptorBean"), | ||
"_getKey", | ||
MethodType.methodType(Object.class)); | ||
} catch (Exception e) { | ||
mbeanGetKey = null; | ||
} | ||
|
||
MBEAN_GET_KEY = mbeanGetKey; | ||
|
||
try { | ||
mbeanGetAttribute = | ||
MethodHandles.publicLookup() | ||
.findVirtual( | ||
Class.forName("javax.management.DynamicMBean"), | ||
"getAttribute", | ||
MethodType.methodType(Object.class, String.class)); | ||
} catch (Exception e) { | ||
mbeanGetAttribute = null; | ||
} | ||
|
||
MBEAN_GET_ATTRIBUTE = mbeanGetAttribute; | ||
|
||
try { | ||
mbeanClass = Class.forName("weblogic.management.WebLogicMBean"); | ||
} catch (Exception e) { | ||
mbeanClass = null; | ||
} | ||
|
||
MBEAN_CLASS = mbeanClass; | ||
} | ||
|
||
public static class Request { | ||
private static final Request NULL = new Request(null); | ||
|
||
public final ServletRequest instance; | ||
|
||
private Request(ServletRequest instance) { | ||
this.instance = instance; | ||
} | ||
|
||
public static Request wrap(ServletRequest instance) { | ||
return instance != null ? new Request(instance) : NULL; | ||
} | ||
|
||
public Context getContext() { | ||
try { | ||
return Context.wrap( | ||
REQUEST_GET_CONTEXT != null ? REQUEST_GET_CONTEXT.invoke(instance) : null); | ||
} catch (Throwable throwable) { | ||
return Context.NULL; | ||
} | ||
} | ||
} | ||
|
||
public static class Context { | ||
private static final Context NULL = new Context(null); | ||
|
||
public final ServletContext instance; | ||
|
||
private Context(ServletContext instance) { | ||
this.instance = instance; | ||
} | ||
|
||
public static Context wrap(Object instance) { | ||
return instance instanceof ServletContext ? new Context((ServletContext) instance) : NULL; | ||
} | ||
|
||
public Bean getBean() { | ||
try { | ||
return Bean.wrap(CONTEXT_GET_MBEAN != null ? CONTEXT_GET_MBEAN.invoke(instance) : null); | ||
} catch (Throwable throwable) { | ||
return Bean.NULL; | ||
} | ||
} | ||
|
||
public Server getServer() { | ||
try { | ||
return Server.wrap(CONTEXT_GET_SERVER != null ? CONTEXT_GET_SERVER.invoke(instance) : null); | ||
} catch (Throwable throwable) { | ||
return Server.NULL; | ||
} | ||
} | ||
} | ||
|
||
public static class Server { | ||
private static final Server NULL = new Server(null); | ||
|
||
public final Object instance; | ||
|
||
private Server(Object instance) { | ||
this.instance = instance; | ||
} | ||
|
||
public static Server wrap(Object instance) { | ||
return instance != null ? new Server(instance) : NULL; | ||
} | ||
|
||
public Bean getBean() { | ||
try { | ||
return Bean.wrap(SERVER_GET_MBEAN != null ? SERVER_GET_MBEAN.invoke(instance) : null); | ||
} catch (Throwable throwable) { | ||
return Bean.NULL; | ||
} | ||
} | ||
} | ||
|
||
public static class Bean { | ||
private static final Bean NULL = new Bean(null); | ||
|
||
public final Object instance; | ||
|
||
private Bean(Object instance) { | ||
this.instance = instance; | ||
} | ||
|
||
public static Bean wrap(Object instance) { | ||
return instance != null | ||
&& MBEAN_CLASS != null | ||
&& MBEAN_CLASS.isAssignableFrom(instance.getClass()) | ||
? new Bean(instance) | ||
: NULL; | ||
} | ||
|
||
public String getName() { | ||
try { | ||
Object key = MBEAN_GET_KEY != null ? MBEAN_GET_KEY.invoke(instance) : null; | ||
return key != null ? key.toString() : null; | ||
} catch (Throwable throwable) { | ||
return null; | ||
} | ||
} | ||
|
||
public Bean getParent() { | ||
try { | ||
return Bean.wrap(MBEAN_GET_PARENT != null ? MBEAN_GET_PARENT.invoke(instance) : null); | ||
} catch (Throwable throwable) { | ||
return Bean.NULL; | ||
} | ||
} | ||
|
||
public Object getAttribute(String name) { | ||
try { | ||
return MBEAN_GET_ATTRIBUTE != null ? MBEAN_GET_ATTRIBUTE.invoke(instance, name) : null; | ||
} catch (Throwable throwable) { | ||
return null; | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just wondering: have you considered adding a field to
MiddlewareHolder
and storing those attributes there instead of the request?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The server and application fields may have different values in a single JVM, so the current static field approach
MiddlewareHolder
would not work there.