이 문서는 New Relic Java 에이전트 API 를 사용하여 간단한 클라이언트 및 서버 애플리케이션을 구성하는 방법을 보여줍니다. 계측에는 다음과 같은 목표가 있습니다.
사용 가능한 API 클래스 및 메소드에 대한 전체 설명은 Java 에이전트 API Javadoc 을 참조하십시오.
중요
API를 사용할 때 최상의 결과를 얻으려면 최신 Java 에이전트 릴리스 가 있는지 확인하십시오. 예제에 사용된 여러 API에는 Java 에이전트 3.36.0 이상이 필요합니다.
클라이언트 측 예
다음은 간단한 클라이언트-서버 애플리케이션에 대한 클라이언트 측 코드의 예입니다.
package com.newrelic.example;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.util.Arrays;
import java.util.Collection;
import java.util.stream.Collectors;
// New Relic API imports
import com.newrelic.api.agent.ExternalParameters;
import com.newrelic.api.agent.HeaderType;
import com.newrelic.api.agent.Headers;
import com.newrelic.api.agent.HttpParameters;
import com.newrelic.api.agent.NewRelic;
import com.newrelic.api.agent.Trace;
import com.newrelic.api.agent.TracedMethod;
import com.newrelic.api.agent.Transaction;
import fi.iki.elonen.NanoHTTPD;
import org.apache.http.HttpMessage;
import org.apache.http.NameValuePair;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
public class NewRelicApiExample extends NanoHTTPD {
    public NewRelicApiExample() throws IOException, URISyntaxException {
        super(8080);
        // Set Dispatcher name and version
        NewRelic.setServerInfo("NanoHttp", "2.3.1");
        // Set Appserver port for JVM identification
        NewRelic.setAppServerPort(8080);
        // Set JVM instance name
        NewRelic.setInstanceName("Client");
        start(NanoHTTPD.SOCKET_READ_TIMEOUT, false);
        System.out.println("Running at: http://localhost:8080/");
    }
    public static void main(String[] args) throws URISyntaxException {
        try {
            new NewRelicApiExample();
        } catch (IOException ioe) {
            System.err.println("Unable to start the server:\n" + ioe);
        }
    }
    @Trace(dispatcher = true)
    @Override
    public Response serve(IHTTPSession session) {
        URI uri = null;
        int status = 0;
        try {
            createDB();
            Thread.sleep(1000);
            uri = new URI("http://localhost:8081");
            status = makeExternalCall(uri);
        } catch (URISyntaxException | InterruptedException | IOException e) {
            e.printStackTrace();
        }
        if (status == 200) {
            return newFixedLengthResponse("<html><body><h1>Successful Response</h1>\n</body></html>\n");
        } else {
            return newFixedLengthResponse("<html><body><h1>Error\n" + status + "</h1>\n</body></html>\n");
        }
    }
    @Trace
    public int makeExternalCall(URI uri) throws IOException {
        HttpUriRequest request = RequestBuilder.get().setUri(uri).build();
        // Wrap the outbound Request object
        Headers outboundHeaders = new HeadersWrapper(request);
        // Obtain a reference to the current transaction
        Transaction transaction = NewRelic.getAgent().getTransaction();
        // Add headers for outbound external request
        transaction.insertDistributedTraceHeaders(outboundHeaders);
        CloseableHttpClient connection = HttpClientBuilder.create().build();
        CloseableHttpResponse response = connection.execute(request);
        // Wrap the incoming Response object
        Headers inboundHeaders = new HeadersWrapper(response);
        // Create an input parameter object for a call to an external HTTP service
        ExternalParameters params = HttpParameters
            .library("HttpClient")
            .uri(uri)
            .procedure("execute")
            .inboundHeaders(inboundHeaders)
            .build();
        // Obtain a reference to the method currently being traced
        TracedMethod tracedMethod = NewRelic.getAgent().getTracedMethod();
        // Report a call to an external HTTP service
        tracedMethod.reportAsExternal(params);
        return response.getStatusLine().getStatusCode();
    }
    // Implement Headers interface to create a wrapper for the outgoing Request/incoming Response headers
    static class HeadersWrapper implements Headers {
        private final HttpMessage delegate;
        public HeadersWrapper(HttpMessage request) {
            this.delegate = request;
        }
        @Override
        public void setHeader(String name, String value) {
            delegate.setHeader(name, value);
        }
        @Override
        public HeaderType getHeaderType() {
            return HeaderType.HTTP;
        }
        @Override
        public String getHeader(String name) {
            return delegate.getFirstHeader(name).getValue();
        }
        @Override
        public Collection<String> getHeaders(String name) {
            return Arrays.stream(delegate.getHeaders(name))
                .map(NameValuePair::getValue)
                .collect(Collectors.toList());
        }
        @Override
        public void addHeader(String name, String value) {
            delegate.addHeader(name, value);
        }
        @Override
        public Collection<String> getHeaderNames() {
            return Arrays.stream(delegate.getAllHeaders())
                .map(NameValuePair::getName)
                .collect(Collectors.toSet());
        }
        @Override
        public boolean containsHeader(String name) {
            return Arrays.stream(delegate.getAllHeaders())
                .map(NameValuePair::getName)
                .anyMatch(headerName -> headerName.equals(name));
        }
    }
    @Trace
    public void createDB() {
        Connection c = null;
        Statement stmt = null;
        try {
            Class.forName("org.sqlite.JDBC");
            c = DriverManager.getConnection("jdbc:sqlite:/tmp/test.db");
            System.out.println("Opened database successfully");
            stmt = c.createStatement();
            String dropSql = "DROP TABLE IF EXISTS COMPANY;";
            stmt.executeUpdate(dropSql);
            String sql = "CREATE TABLE COMPANY " +
                    "(ID INT PRIMARY KEY     NOT NULL," +
                    " NAME           TEXT    NOT NULL, " +
                    " AGE            INT     NOT NULL, " +
                    " ADDRESS        CHAR(50), " +
                    " SALARY         REAL)";
            stmt.executeUpdate(sql);
            sql = "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) " +
                   "VALUES (1, 'Paul', 32, 'California', 20000.00 );";
            stmt.executeUpdate(sql);
            sql = "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) " +
                    "VALUES (2, 'Allen', 25, 'Texas', 15000.00 );";
            stmt.executeUpdate(sql);
            sql = "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) " +
            "VALUES (3, 'Teddy', 23, 'Norway', 20000.00 );";
            stmt.executeUpdate(sql);
            sql = "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) " +
                    "VALUES (4, 'Mark', 25, 'Rich-Mond ', 65000.00 );";
            stmt.executeUpdate(sql);
            stmt.close();
            c.close();
        } catch (Exception e) {
            System.err.println(e.getClass().getName() + ": " + e.getMessage());
            System.exit(0);
        }
    }
}다음은 API 사용 방법을 설명하는 섹션으로 나누어진 동일한 클라이언트 앱 코드입니다.
이 섹션에서는 나중에 예제 코드에서 클라이언트 애플리케이션에 분산 추적을 추가하는 데 사용되는 Java 에이전트 API 가져오기를 호출합니다.
import java.io.IOException;import java.net.URI;import java.net.URISyntaxException;import java.sql.Connection;import java.sql.DriverManager;import java.sql.Statement;import java.util.Arrays;import java.util.Collection;import java.util.stream.Collectors;
// New Relic API importsimport com.newrelic.api.agent.ExternalParameters;import com.newrelic.api.agent.HeaderType;import com.newrelic.api.agent.Headers;import com.newrelic.api.agent.HttpParameters;import com.newrelic.api.agent.NewRelic;import com.newrelic.api.agent.Trace;import com.newrelic.api.agent.TracedMethod;import com.newrelic.api.agent.Transaction;
import fi.iki.elonen.NanoHTTPD;import org.apache.http.HttpMessage;import org.apache.http.NameValuePair;import org.apache.http.client.methods.CloseableHttpResponse;import org.apache.http.client.methods.HttpUriRequest;import org.apache.http.client.methods.RequestBuilder;import org.apache.http.impl.client.CloseableHttpClient;import org.apache.http.impl.client.HttpClientBuilder;이 섹션에서는 포트 8080에서 클라이언트 서버를 시작하고 API의 NewRelic 클래스를 사용하여 setServerInfo , setAppServerPort 및 setInstanceName 메서드를 호출합니다. 이러한 API 호출은 New Relic UI에 표시되는 내용에 영향을 줍니다.
public NewRelicApiExample() throws IOException, URISyntaxException {    super(8080);
    // Set Dispatcher name and version    NewRelic.setServerInfo("NanoHttp", "2.3.1");    // Set Appserver port for jvm identification    NewRelic.setAppServerPort(8080);    // Set JVM instance name    NewRelic.setInstanceName("Client");
    start(NanoHTTPD.SOCKET_READ_TIMEOUT, false);    System.out.println("Running at: http://localhost:8080/");}
public static void main(String[] args) throws URISyntaxException {    try {        new NewRelicApiExample();    } catch (IOException ioe) {        System.err.println("Unable to start the server:\n" + ioe);    }}이 메서드는 샘플 데이터베이스를 만들고 스레드를 절전 모드로 전환하며 포트 8081에서 수신 대기하는 서버 앱에 대한 외부 호출을 만듭니다. @Trace(dispatcher = true) 주석은 에이전트에 serve 메서드가 호출될 때 새 트랜잭션을 시작하도록 지시합니다. 기존 트랜잭션의 일부로 호출되지 않습니다(이 경우 호출되지 않음). 기존 트랜잭션의 일부로 호출된 경우 새 트랜잭션을 시작하지 않고 해당 트랜잭션의 일부로 단순히 포함됩니다.
@Trace(dispatcher = true)@Overridepublic Response serve(IHTTPSession session) {    URI uri = null;    int status = 0;
    try {        createDB();        Thread.sleep(1000);        uri = new URI("http://localhost:8081");        status = makeExternalCall(uri);    } catch (URISyntaxException | InterruptedException | IOException e) {        e.printStackTrace();    }
    if (status == 200) {        return newFixedLengthResponse("<html><body><h1>Successful Response</h1>\n</body></html>\n");    } else {        return newFixedLengthResponse("<html><body><h1>Error\n" + status + "</h1>\n</body></html>\n");    }}이 섹션에는 요청하는 응용 프로그램에 대한 분산 추적을 시작하는 코드가 포함되어 있습니다. @Trace 주석은 에이전트가 serve 메소드에 의해 시작된 기존 트랜잭션의 일부로 이 메소드를 추적하도록 지시합니다.
요청 객체는 Java 에이전트 API의 Headers 인터페이스를 구현하는 클래스에 의해 래핑되어 적절한 HeaderType (이 경우 HTTP )이 설정되도록 합니다. insertDistributedTraceHeaders 을 호출하면 헤더가 request 에 추가되고 요청이 서버로 전송됩니다.
response 이 반환되면 Java 에이전트 API의 InboundHeaders 인터페이스를 구현하는 클래스에 의해 래핑됩니다. Headers 는 InboundHeaders 의 하위 인터페이스이며 이 경우 래퍼 클래스를 재사용할 수 있습니다.
inboundHeaders , "library" , URI 및 "procedure" 인수는 HttpParameters 객체를 빌드하는 데 사용됩니다. 그런 다음 params 객체는 TracedMethod 을 외부 HTTP 호출로 보고하는 reportAsExternal 메서드에 인수로 전달됩니다.
@Tracepublic int makeExternalCall(URI uri) throws IOException {    HttpUriRequest request = RequestBuilder.get().setUri(uri).build();
    // Wrap the outbound Request object    Headers outboundHeaders = new HeadersWrapper(request);
    // Obtain a reference to the current transaction    Transaction transaction = NewRelic.getAgent().getTransaction();    // Add headers for outbound external request    transaction.insertDistributedTraceHeaders(outboundHeaders);
    CloseableHttpClient connection = HttpClientBuilder.create().build();    CloseableHttpResponse response = connection.execute(request);
    // Wrap the incoming Response object    Headers inboundHeaders = new HeadersWrapper(response);
    // Create an input parameter object for a call to an external HTTP service    ExternalParameters params = HttpParameters        .library("HttpClient")        .uri(uri)        .procedure("execute")        .inboundHeaders(inboundHeaders)        .build();
    // Obtain a reference to the method currently being traced    TracedMethod tracedMethod = NewRelic.getAgent().getTracedMethod();    // Report a call to an external HTTP service    tracedMethod.reportAsExternal(params);
    return response.getStatusLine().getStatusCode();}Java 에이전트 API의 Headers 인터페이스 구현은 클라이언트 서버의 요청 객체를 래핑하는 데 사용되며, 이 예에서는 HttpUriRequest 유형입니다. 요청은 HeadersWrapper 클래스의 생성자로 전달되고 필요한 메소드의 구현이 제공됩니다.
getHeaderType 메서드는 Java 에이전트 API에서 정의한 대로 HeaderType.HTTP 또는 HeaderType.MESSAGE 일 수 있는 HeaderType 열거형을 반환합니다. 이 예에서 외부 호출 프로토콜은 HTTP이므로 HeaderType.HTTP 가 반환됩니다.
// Implement Headers interface to create a wrapper for the outgoing Request/incoming Response headersstatic class HeadersWrapper implements Headers {    private final HttpMessage delegate;
    public HeadersWrapper(HttpMessage request) {        this.delegate = request;    }
    @Override    public void setHeader(String name, String value) {        delegate.setHeader(name, value);    }
    @Override    public HeaderType getHeaderType() {        return HeaderType.HTTP;    }
    @Override    public String getHeader(String name) {        return delegate.getFirstHeader(name).getValue();    }
    @Override    public Collection<String> getHeaders(String name) {        return Arrays.stream(delegate.getHeaders(name))            .map(NameValuePair::getValue)            .collect(Collectors.toList());    }
    @Override    public void addHeader(String name, String value) {        delegate.addHeader(name, value);    }
    @Override    public Collection<String> getHeaderNames() {        return Arrays.stream(delegate.getAllHeaders())            .map(NameValuePair::getName)            .collect(Collectors.toSet());    }
    @Override    public boolean containsHeader(String name) {        return Arrays.stream(delegate.getAllHeaders())            .map(NameValuePair::getName)            .anyMatch(headerName -> headerName.equals(name));    }}이 방법은 단순히 예제 SQLite 데이터베이스를 생성합니다. @Trace 주석은 에이전트가 serve 메소드에 의해 시작된 기존 트랜잭션의 일부로 이 메소드를 추적하도록 지시합니다.
@Tracepublic void createDB() {    Connection c = null;    Statement stmt = null;
    try {        Class.forName("org.sqlite.JDBC");        c = DriverManager.getConnection("jdbc:sqlite:/tmp/test.db");        System.out.println("Opened database successfully");
        stmt = c.createStatement();
        String dropSql = "DROP TABLE IF EXISTS COMPANY;";        stmt.executeUpdate(dropSql);
        String sql = "CREATE TABLE COMPANY " +                "(ID INT PRIMARY KEY     NOT NULL," +                " NAME           TEXT    NOT NULL, " +                " AGE            INT     NOT NULL, " +                " ADDRESS        CHAR(50), " +                " SALARY         REAL)";        stmt.executeUpdate(sql);
        sql = "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) " +               "VALUES (1, 'Paul', 32, 'California', 20000.00 );";        stmt.executeUpdate(sql);
        sql = "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) " +                "VALUES (2, 'Allen', 25, 'Texas', 15000.00 );";        stmt.executeUpdate(sql);
        sql = "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) " +        "VALUES (3, 'Teddy', 23, 'Norway', 20000.00 );";        stmt.executeUpdate(sql);
        sql = "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) " +                "VALUES (4, 'Mark', 25, 'Rich-Mond ', 65000.00 );";        stmt.executeUpdate(sql);
        stmt.close();        c.close();    } catch (Exception e) {        System.err.println(e.getClass().getName() + ": " + e.getMessage());        System.exit(0);    }}서버 측 예
다음은 이 예제 애플리케이션의 서버 측 코드입니다.
package com.newrelic.example;
import java.io.IOException;
import java.net.URISyntaxException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Collection;
import java.util.Collections;
// New Relic API imports
import com.newrelic.api.agent.DatastoreParameters;
import com.newrelic.api.agent.HeaderType;
import com.newrelic.api.agent.Headers;
import com.newrelic.api.agent.NewRelic;
import com.newrelic.api.agent.Trace;
import com.newrelic.api.agent.TracedMethod;
import com.newrelic.api.agent.Transaction;
import com.newrelic.api.agent.TransportType;
import fi.iki.elonen.NanoHTTPD;
public class NewRelicApiServer extends NanoHTTPD {
    public NewRelicApiServer() throws IOException, URISyntaxException {
        super(8081);
        // Set Dispatcher name and version
        NewRelic.setServerInfo("NanoHttp", "2.3.1");
        // Set Appserver port for jvm identification
        NewRelic.setAppServerPort(8081);
        // Set JVM instance name
        NewRelic.setInstanceName("Server");
        start(NanoHTTPD.SOCKET_READ_TIMEOUT, false);
        System.out.println("\nRunning on http://localhost:8081/ \n");
    }
    public static void main(String[] args) throws URISyntaxException {
        try {
            new NewRelicApiServer();
        } catch (IOException ioe) {
            System.err.println("Unable to start the server:\n" + ioe);
        }
    }
    @Trace(dispatcher = true)
    @Override
    public Response serve(IHTTPSession session) {
        // Obtain a reference to the current Transaction
        Transaction tx = NewRelic.getAgent().getTransaction();
        // Set the name of the current transaction
        NewRelic.setTransactionName("Custom", "ExternalHTTPServer");
        // Wrap the Request object
        Headers req = new HeadersWrapper(session);
        // Set the request for the current transaction and convert it into a web transaction
        tx.acceptDistributedTraceHeaders(TransportType.HTTP, req);
        queryDB();
        return newFixedLengthResponse("<html><body><h1>SuccessfulResponse</h1>\n</body></html>\n");
    }
    // Implement Headers interface to create a wrapper for the outgoing Request/incoming Response headers
    static class HeadersWrapper implements Headers {
        private final IHTTPSession delegate;
        public HeadersWrapper(IHTTPSession request) {
            this.delegate = request;
        }
        @Override
        public HeaderType getHeaderType() {
            return HeaderType.HTTP;
        }
        @Override
        public String getHeader(String name) {
            return delegate.getHeaders().get(name);
        }
        @Override
        public Collection<String> getHeaders(String name) {
            return Collections.singletonList(getHeader(name));
        }
        @Override
        public void setHeader(String name, String value) {
            delegate.getHeaders().put(name, value);
        }
        @Override
        public void addHeader(String name, String value) {
            delegate.getHeaders().put(name, value);
        }
        @Override
        public Collection<String> getHeaderNames() {
            return delegate.getHeaders().keySet();
        }
        @Override
        public boolean containsHeader(String name) {
            return delegate.getHeaders().containsKey(name);
        }
    }
    @Trace
    public void queryDB() {
        Connection c = null;
        Statement stmt = null;
        try {
            Class.forName("org.sqlite.JDBC");
            c = DriverManager.getConnection("jdbc:sqlite:/tmp/test.db");
            c.setAutoCommit(false);
            System.out.println("Opened database successfully");
            stmt = c.createStatement();
            ResultSet rs = stmt.executeQuery("SELECT * FROM COMPANY;");
            while (rs.next()) {
                int id = rs.getInt("id");
                String name = rs.getString("name");
                int age = rs.getInt("age");
                String address = rs.getString("address");
                float salary = rs.getFloat("salary");
                System.out.println("ID = " + id);
                System.out.println("NAME = " + name);
                System.out.println("AGE = " + age);
                System.out.println("ADDRESS = " + address);
                System.out.println("SALARY = " + salary);
                System.out.println();
            }
            rs.close();
            stmt.close();
            c.close();
        } catch (Exception e) {
            System.err.println(e.getClass().getName() + ": " + e.getMessage());
            System.exit(0);
        }
        // Obtain a reference to the method currently being traced
        TracedMethod method = NewRelic.getAgent().getTracedMethod();
        // Create a DatastoreParameters object and report a call to an external datastore service
        method.reportAsExternal(
                DatastoreParameters
                        .product("sqlite")
                        .collection("test.db")
                        .operation("select")
                        .instance("localhost", 8080)
                        .databaseName("test.db")
                        .build());
    }
}다음은 API 사용 방법을 설명하는 섹션으로 나뉜 동일한 예제 서버 코드입니다.
이 섹션에서는 서버 애플리케이션에 대한 외부 데이터 저장소 호출의 분산 추적 및 보고를 추가하는 데 필요한 관련 Java 에이전트 API 가져오기를 보여줍니다.
import java.io.IOException;import java.net.URISyntaxException;import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.Statement;import java.util.Collection;import java.util.Collections;
// New Relic API importsimport com.newrelic.api.agent.DatastoreParameters;import com.newrelic.api.agent.HeaderType;import com.newrelic.api.agent.Headers;import com.newrelic.api.agent.NewRelic;import com.newrelic.api.agent.Trace;import com.newrelic.api.agent.TracedMethod;import com.newrelic.api.agent.Transaction;import com.newrelic.api.agent.TransportType;
import fi.iki.elonen.NanoHTTPD;이 섹션에서는 포트 8081에서 서버를 시작하고 API의 NewRelic 클래스를 사용하여 setServerInfo , setAppServerPort 및 setInstanceName 메서드를 호출합니다. 이러한 API 호출은 APM UI에 표시되는 내용에 영향을 줍니다.
public NewRelicApiServer() throws IOException, URISyntaxException {    super(8081);
    // Set Dispatcher name and version    NewRelic.setServerInfo("NanoHttp", "2.3.1");    // Set Appserver port for jvm identification    NewRelic.setAppServerPort(8081);    // Set JVM instance name    NewRelic.setInstanceName("Server");
    start(NanoHTTPD.SOCKET_READ_TIMEOUT, false);    System.out.println("\nRunning on http://localhost:8081/ \n");}
public static void main(String[] args) throws URISyntaxException {    try {        new NewRelicApiServer();    } catch (IOException ioe) {        System.err.println("Unable to start the server:\n" + ioe);    }}@Trace(dispatcher = true) 주석은 serve 메서드가 기존 트랜잭션의 일부로 호출되지 않은 경우(이 경우 호출되지 않음) 새 트랜잭션을 시작하도록 에이전트에 지시합니다. 기존 트랜잭션의 일부로 호출된 경우 새 트랜잭션을 시작하지 않고 해당 트랜잭션의 일부로 단순히 포함됩니다.
현재 Transaction 에 대한 참조는 getTransaction 호출을 통해 가져오고 트랜잭션 이름은 setTransactionName 메서드 호출을 통해 설정됩니다.
이 예에서 유형이 IHTTPSession 인 요청 객체는 Java 에이전트 API의 Headers 클래스를 확장하는 클래스를 사용하여 래핑됩니다. 그런 다음 현재 Transaction 는 래핑된 ExtendedRequest 를 인수로 사용하는 setWebRequest 호출을 통해 상위 추적에 연결됩니다.
그런 다음 데이터베이스에 대한 호출이 이루어지고 응답 개체가 반환됩니다.
@Trace(dispatcher = true)@Overridepublic Response serve(IHTTPSession session) {    // Obtain a reference to the current Transaction    Transaction tx = NewRelic.getAgent().getTransaction();    // Set the name of the current transaction    NewRelic.setTransactionName("Custom", "ExternalHTTPServer");
    // Wrap the Request object    Headers req = new HeadersWrapper(session);
    // Set the request for the current transaction and convert it into a web transaction    tx.acceptDistributedTraceHeaders(TransportType.HTTP, req);
    queryDB();
    return newFixedLengthResponse("<html><body><h1>SuccessfulResponse</h1>\n</body></html>\n");}Java 에이전트 API의 Headers 클래스의 다른 구현은 서버의 요청 객체를 래핑하는 데 사용되며, 이 예에서는 IHTTPSession 유형입니다. 요청은 getRequestURI , getHeader , getRemoteUser , getParameterNames , getParameterValues , getAttribute , getCookieValue , getHeaderType 의 구현을 제공하는 HeadersWrapper 클래스의 생성자로 전달됩니다. 및 getMethod 메서드.
getHeaderType 메서드는 Java 에이전트 API에서 정의한 대로 HeaderType.HTTP 또는 HeaderType.MESSAGE 일 수 있는 HeaderType 열거형을 반환합니다. 이 예에서 외부 호출 프로토콜은 HTTP이므로 HeaderType.HTTP 가 반환됩니다.
// Implement Headers interface to create a wrapper for the outgoing Request/incoming Response headersstatic class HeadersWrapper implements Headers {    private final IHTTPSession delegate;
    public HeadersWrapper(IHTTPSession request) {        this.delegate = request;    }
    @Override    public HeaderType getHeaderType() {        return HeaderType.HTTP;    }
    @Override    public String getHeader(String name) {        return delegate.getHeaders().get(name);    }
    @Override    public Collection<String> getHeaders(String name) {        return Collections.singletonList(getHeader(name));    }
    @Override    public void setHeader(String name, String value) {        delegate.getHeaders().put(name, value);    }
    @Override    public void addHeader(String name, String value) {        delegate.getHeaders().put(name, value);    }
    @Override    public Collection<String> getHeaderNames() {        return delegate.getHeaders().keySet();    }
    @Override    public boolean containsHeader(String name) {        return delegate.getHeaders().containsKey(name);    }}이 메소드는 클라이언트가 생성한 SQLite 데이터베이스를 외부에서 호출합니다. @Trace 주석은 에이전트가 serve 메소드에 의해 시작된 기존 트랜잭션의 일부로 이 메소드를 추적하도록 지시합니다.
현재 TracedMethod 에 대한 참조는 getTracedMethod 에 대한 호출을 통해 얻습니다. 그러면 빌더 패턴을 사용하여 DatastoreParameters 객체가 생성됩니다. 그러면 ExternalParameters 객체가 reportAsExternal 메서드에 인수로 전달되며, 이는 TracedMethod 를 외부 데이터 저장소 호출로 보고하는 효과가 있습니다.
@Tracepublic void queryDB() {    Connection c = null;    Statement stmt = null;    try {        Class.forName("org.sqlite.JDBC");        c = DriverManager.getConnection("jdbc:sqlite:/tmp/test.db");        c.setAutoCommit(false);        System.out.println("Opened database successfully");
        stmt = c.createStatement();        ResultSet rs = stmt.executeQuery("SELECT * FROM COMPANY;");        while (rs.next()) {            int id = rs.getInt("id");            String name = rs.getString("name");            int age = rs.getInt("age");            String address = rs.getString("address");            float salary = rs.getFloat("salary");            System.out.println("ID = " + id);            System.out.println("NAME = " + name);            System.out.println("AGE = " + age);            System.out.println("ADDRESS = " + address);            System.out.println("SALARY = " + salary);            System.out.println();        }        rs.close();        stmt.close();        c.close();    } catch (Exception e) {        System.err.println(e.getClass().getName() + ": " + e.getMessage());        System.exit(0);    }    // Obtain a reference to the method currently being traced    TracedMethod method = NewRelic.getAgent().getTracedMethod();
    // Create a DatastoreParameters object and report a call to an external datastore service    method.reportAsExternal(            DatastoreParameters                    .product("sqlite")                    .collection("test.db")                    .operation("select")                    .instance("localhost", 8080)                    .databaseName("test.db")                    .build());}