-
Notifications
You must be signed in to change notification settings - Fork 33
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Collect WebLogic specific attributes (#81)
* Collect WebLogic middleware name, version, domain, server and application attributes
- Loading branch information
1 parent
175a0dd
commit 49fc1cc
Showing
6 changed files
with
541 additions
and
14 deletions.
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"))); | ||
} 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.