Skip to content

Commit

Permalink
Collect WebLogic specific attributes (#81)
Browse files Browse the repository at this point in the history
* Collect WebLogic middleware name, version, domain, server and application attributes
  • Loading branch information
agoallikmaa authored Jan 26, 2021
1 parent 175a0dd commit 49fc1cc
Show file tree
Hide file tree
Showing 6 changed files with 541 additions and 14 deletions.
7 changes: 7 additions & 0 deletions instrumentation/weblogic/build.gradle
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')
}
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 "";
}
}
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;
}
}
}
}
Loading

0 comments on commit 49fc1cc

Please sign in to comment.