Skip to content

Commit

Permalink
updates to make JCO instrumentation work in version 3.1
Browse files Browse the repository at this point in the history
  • Loading branch information
dhilpipre committed Oct 18, 2024
1 parent d184701 commit b4fd99d
Show file tree
Hide file tree
Showing 16 changed files with 525 additions and 4 deletions.
34 changes: 34 additions & 0 deletions sap-jco-3.1/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@

// Build.gradle generated for instrumentation module sap-jco-3.1

apply plugin: 'java'

dependencies {
// Declare a dependency on each JAR you want to instrument
// Example:
// implementation 'javax.servlet:servlet-api:2.5'

// New Relic Labs Java Agent dependencies
implementation 'com.newrelic.agent.java:newrelic-agent:7.4.0'
implementation 'com.newrelic.agent.java:newrelic-api:7.4.0'
implementation fileTree(include: ['*.jar'], dir: 'lib')
implementation fileTree(include: ['*.jar'], dir: '../libs')
implementation fileTree(include: ['*.jar'], dir: '../test-lib')
}

jar {
manifest {
attributes 'Implementation-Title': 'com.newrelic.instrumentation.labs.sap-jco-3.1'
attributes 'Implementation-Vendor': 'New Relic Labs'
attributes 'Implementation-Vendor-Id': 'com.newrelic.labs'
attributes 'Implementation-Version': 1.0
}
}

verifyInstrumentation {
// Verifier plugin documentation:
// https://github.com/newrelic/newrelic-gradle-verify-instrumentation
// Example:
// passes 'javax.servlet:servlet-api:[2.2,2.5]'
// exclude 'javax.servlet:servlet-api:2.4.public_draft'
}
5 changes: 5 additions & 0 deletions sap-jco-3.1/lib/holder.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
sap_epa.jar
sapj2eeclient.jar
sapjco3.jar
sapni.jar
sapxmltoolkit.jar
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package com.newrelic.instrumentation.labs.sap.jco;

import java.util.List;
import java.util.Map;
import java.util.Set;

import com.sap.conn.jco.JCoAttributes;
import com.sap.conn.jco.JCoDestination;
import com.sap.conn.jco.JCoFunction;
import com.sap.conn.jco.JCoFunctionUnit;
import com.sap.conn.jco.JCoRepository;
import com.sap.conn.jco.server.JCoServer;
import com.sap.conn.jco.server.JCoServerContext;

public class NRJcoUtils {

public static void addAttribute(Map<String, Object> attributes, String key, Object value) {
if(attributes != null && key != null && !key.isEmpty() && value != null) {
attributes.put(key, value);
}
}

public static void addJcoServerContext(Map<String, Object> attributes, JCoServerContext ctx) {
addAttribute(attributes, "SAP Call Type", ctx.getCallType());
addJcoAttributes(attributes,ctx.getConnectionAttributes());
addAttribute(attributes, "Connection ID", ctx.getConnectionID());
addJcoServer(attributes, ctx.getServer());
addJcoRepository(attributes, ctx.getRepository());
String[] queueNames = ctx.getQueueNames();
if(queueNames != null && queueNames.length > 0) {
addAttribute(attributes, "QueueNames", getQueueNames(queueNames));
}
addAttribute(attributes, "QueueName", ctx.getQueueName());
addAttribute(attributes, "JCoServerCallType", ctx.getCallType());


}

private static String getQueueNames(String[] names) {
int len = names.length;
StringBuffer sb = new StringBuffer();
for(int i=0;i<len;i++) {
String queueName = names[i];
sb.append(queueName);
if(i < len -1) sb.append(',');
}
return sb.toString();
}

public static void addJcoAttributes(Map<String, Object> attributes, JCoAttributes jco_attributes) {
if (jco_attributes != null) {
addAttribute(attributes, "JcoAttributes - Client", jco_attributes.getClient());
addAttribute(attributes, "JcoAttributes - Destination", jco_attributes.getDestination());
addAttribute(attributes, "JcoAttributes - Host", jco_attributes.getHost());
}
}

public static void addJcoServer(Map<String, Object> attributes, JCoServer server) {
if (server != null) {
addAttribute(attributes, "JCoServer - GatewayHost", server.getGatewayHost());
addAttribute(attributes, "JCoServer - GatewayService", server.getGatewayService());
}
}

public static void addJcoRepository(Map<String, Object> attributes, JCoRepository repo) {
if(repo != null) {
addAttribute(attributes, "JCoRepository - Name", repo.getName());
}
}

public static void addJcoDestination(Map<String, Object> attributes, JCoDestination dest) {
if(dest != null) {
addAttribute(attributes, "JCoDestination - DestinationName", dest.getDestinationName());
addAttribute(attributes, "JCoDestination - GatewayHost", dest.getGatewayHost());
addAttribute(attributes, "JCoDestination - GatewayService", dest.getGatewayService());
}
}

public static void addJCoFunctionUnit(Map<String,Object> attributes, JCoFunctionUnit unit) {
if(unit != null) {
List<JCoFunction> functions = unit.getFunctions();
StringBuffer functionNames = new StringBuffer();
int size = functions.size();
int i = 1;
for(JCoFunction function : functions) {
functionNames.append(function.getName());
if(i < size) {
functionNames.append(',');
}
i++;
}
addAttribute(attributes, "Functions", functionNames.toString());

Set<String> queueNames = unit.getQueueNames();
size = queueNames.size();
i = 1;
StringBuffer sb = new StringBuffer();
for(String queueName : queueNames) {
sb.append(queueName);
if(i < size) {
sb.append(',');
}
i++;
}
addAttribute(attributes, "QueueNames", sb.toString());

}
}
}
60 changes: 60 additions & 0 deletions sap-jco-3.1/src/main/java/com/sap/conn/jco/JCoRequest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.sap.conn.jco;

import com.newrelic.api.agent.NewRelic;
import com.newrelic.api.agent.Trace;
import com.newrelic.api.agent.TracedMethod;
import com.newrelic.api.agent.weaver.MatchType;
import com.newrelic.api.agent.weaver.Weave;
import com.newrelic.api.agent.weaver.Weaver;

@Weave(type = MatchType.Interface)
public abstract class JCoRequest {

public abstract String getName();

@Trace(dispatcher = true)
public JCoResponse execute(JCoDestination destination) throws JCoException {
NewRelic.getAgent().getTracedMethod().setMetricName(new String[] { "Custom", "JCoRequest", getClass().getSimpleName(), "execute", getName() });
NewRelic.getAgent().getTracedMethod().addCustomAttribute("Name", getName());
NewRelic.getAgent().getTracedMethod().addCustomAttribute("Destination", destination != null ? destination.getDestinationName() : "Unkown");
JCoResponse response = null;
try {
response = Weaver.callOriginal();
} catch (Exception e) {
NewRelic.noticeError(e);
throw e;
}
return response;

}

public void execute(JCoDestination destination, String tid) throws JCoException {
TracedMethod traced = NewRelic.getAgent().getTracedMethod();
traced.addCustomAttribute("Name", getName());
traced.addCustomAttribute("Destination", destination != null ? destination.getDestinationName() : "Unkown");
traced.setMetricName(new String[] { "Custom", "JCoRequest", getClass().getSimpleName(), "execute", getName() });
traced.addCustomAttribute("TID", tid);
try {
Weaver.callOriginal();
} catch (Exception e) {
NewRelic.noticeError(e);
throw e;
}
}

public void execute(JCoDestination destination, String tid, String queueName) throws JCoException {
TracedMethod traced = NewRelic.getAgent().getTracedMethod();
traced.setMetricName(new String[] { "Custom", "JCoRequest", getClass().getSimpleName(), "execute", getName() });
traced.addCustomAttribute("TID", tid);
traced.addCustomAttribute("QueueName", queueName);
traced.addCustomAttribute("Name", getName());
traced.addCustomAttribute("Destination", destination != null ? destination.getDestinationName() : "Unkown");
try {
Weaver.callOriginal();
} catch (Exception e) {
NewRelic.noticeError(e);
throw e;
}
}

}
81 changes: 81 additions & 0 deletions sap-jco-3.1/src/main/java/com/sap/conn/jco/rt/AbapFunction.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package com.sap.conn.jco.rt;

import java.util.HashMap;

import com.newrelic.api.agent.NewRelic;
import com.newrelic.api.agent.weaver.Weave;
import com.newrelic.api.agent.weaver.Weaver;
import com.newrelic.instrumentation.labs.sap.jco.NRJcoUtils;
import com.sap.conn.jco.JCoDestination;
import com.sap.conn.jco.JCoException;
import com.newrelic.api.agent.Trace;

@Weave
public abstract class AbapFunction {


public abstract String getName();

@Trace(dispatcher=true)
public void execute(JCoDestination destination) throws JCoException {
String destName = destination != null ? destination.getDestinationName() : "UnknownDestination";
String abapName = getName() != null ? getName() : "UnknownABAP";
NewRelic.getAgent().getTracedMethod().setMetricName("Custom","AbapFunction","execute",abapName,destName);
HashMap<String, Object> attributes = new HashMap<String, Object>();
NRJcoUtils.addJcoDestination(attributes, destination);
NewRelic.getAgent().getTracedMethod().addCustomAttributes(attributes);
try {
Weaver.callOriginal();
} catch(Exception e) {
if(e instanceof JCoException) {
JCoException jce = (JCoException)e;
NewRelic.noticeError(jce);
throw jce;
}

}
}

@Trace(dispatcher=true)
public void execute(JCoDestination destination, String tid) throws JCoException {
String destName = destination != null ? destination.getDestinationName() : "UnknownDestination";
String abapName = getName() != null ? getName() : "UnknownABAP";
NewRelic.getAgent().getTracedMethod().setMetricName("Custom","AbapFunction","execute",abapName,destName);
HashMap<String, Object> attributes = new HashMap<String, Object>();
NRJcoUtils.addJcoDestination(attributes, destination);
NRJcoUtils.addAttribute(attributes, "TID", tid);
NewRelic.getAgent().getTracedMethod().addCustomAttributes(attributes);
try {
Weaver.callOriginal();
} catch(Exception e) {
if(e instanceof JCoException) {
JCoException jce = (JCoException)e;
NewRelic.noticeError(jce);
throw jce;
}

}
}

@Trace(dispatcher=true)
public void execute(JCoDestination destination, String tid, String queueName) throws JCoException {
String destName = destination != null ? destination.getDestinationName() : "UnknownDestination";
String abapName = getName() != null ? getName() : "UnknownABAP";
NewRelic.getAgent().getTracedMethod().setMetricName("Custom","AbapFunction","execute",abapName,destName);
HashMap<String, Object> attributes = new HashMap<String, Object>();
NRJcoUtils.addJcoDestination(attributes, destination);
NRJcoUtils.addAttribute(attributes, "TID", tid);
NRJcoUtils.addAttribute(attributes, "QueueName", queueName);
NewRelic.getAgent().getTracedMethod().addCustomAttributes(attributes);
try {
Weaver.callOriginal();
} catch(Exception e) {
if(e instanceof JCoException) {
JCoException jce = (JCoException)e;
NewRelic.noticeError(jce);
throw jce;
}

}
}
}
24 changes: 24 additions & 0 deletions sap-jco-3.1/src/main/java/com/sap/conn/jco/rt/CallbackHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.sap.conn.jco.rt;

import com.newrelic.api.agent.NewRelic;
import com.newrelic.api.agent.Trace;
import com.newrelic.api.agent.weaver.MatchType;
import com.newrelic.api.agent.weaver.Weave;
import com.newrelic.api.agent.weaver.Weaver;
import com.sap.conn.jco.JCoFunction;

@Weave(type = MatchType.Interface)
public abstract class CallbackHandler {

@Trace
public void execute(JCoFunction function) {
String classname = getClass().getSimpleName();
if (classname != null && !classname.isEmpty()) {
NewRelic.getAgent().getTracedMethod().setMetricName(new String[] { "Custom", "CallbackHander", classname, "execute", "JCoFunction", function.getName() });
} else {
NewRelic.getAgent().getTracedMethod().setMetricName(new String[] { "Custom", "CallbackHander", "execute", "JCoFunction", function.getName() });
}
Weaver.callOriginal();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.sap.conn.jco.rt;

import java.util.HashMap;

import com.newrelic.api.agent.NewRelic;
import com.newrelic.api.agent.Trace;
import com.newrelic.api.agent.weaver.Weave;
import com.newrelic.api.agent.weaver.Weaver;
import com.newrelic.instrumentation.labs.sap.jco.NRJcoUtils;
import com.sap.conn.jco.AbapClassException;

@Weave
public abstract class ClientConnection {

public abstract ConnectionAttributes getAttributes();

@Trace
private void execute(String functionName, DefaultParameterList input,DefaultParameterList inputTables, DefaultParameterList changing,DefaultParameterList output, boolean supportsASXML,
AbapClassException.Mode classExceptionMode) {
NewRelic.getAgent().getTracedMethod().setMetricName("Custom","ClientConnection","execute",functionName);
HashMap<String, Object> attributes = new HashMap<String, Object>();
NRJcoUtils.addJcoAttributes(attributes, getAttributes());
NewRelic.getAgent().getTracedMethod().addCustomAttributes(attributes);
Weaver.callOriginal();
}

}
Loading

0 comments on commit b4fd99d

Please sign in to comment.