Skip to content
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

Jetty12 core server transactions #1950

Merged
merged 5 commits into from
Jun 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 3 additions & 17 deletions instrumentation/jetty-12/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,12 @@ With the introduction of [Jetty 12](https://webtide.com/introducing-jetty-12/),
As a result **Jetty** can be used as a core server without any involvement with servlets.
In addition, it now supports every **Servlet API** spec starting from Jakarta EE 8 above.

One of the challenges that resulted from this is that while in theory transactions can
be started in a core server, there is no straightforward way to manage transactions
in async servlets. Jetty 12 offers implementation for each Jakarta EE spec so transactions can instead be
managed through the servlet implementations. As a result the Jetty 12 instrumentation was split into 5 new modules.
This means this instrumentation module does not have means to manage servlet based tasks such as handling async servlet operations.

## Instrumentation Modules

### jetty-12
The current instrumentation module. This module instruments the core Jetty server that handles tasks that does not require the Servlet AP. Such tasks include:
As a result this instrumentation module handles the following tasks:

- Reporting threadpool metrics
- Reporting the dispatcher name and version as well as the port number for the server.
- Adding outbound CAT headers for outgoing requests. CAT however is deprecated during the time this module is made (i.e. December 2023).
- Reporting errors

### jetty-ee*-servlet-12
This refers to any module named based on the pattern `jetty-ee*-servlet-12`.
These modules instrument the Servlet API implementations for Jetty.
As a result, the instrumentation works with tasks that require us to work with the Servlet API such as:

- Start and ending web transactions
- Linking transactions to async activity
- Reporting errors
- Starting and ending web transactions
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package com.nr.agent.instrumentation.jetty12;

import com.newrelic.api.agent.ExtendedRequest;
import com.newrelic.api.agent.HeaderType;
import org.eclipse.jetty.http.HttpCookie;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.util.Fields;

import java.security.Principal;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;

public class JettyRequest extends ExtendedRequest {

private final Request request;

public JettyRequest(Request request) {
this.request = request;
}

@Override
public String getMethod() {
return request.getMethod();
}

@Override
public HeaderType getHeaderType() {
return HeaderType.HTTP;
}

@Override
public String getHeader(String name) {
return request.getHeaders().get(name);
}

@Override
public String getRequestURI() {
return request.getHttpURI().getPath();
}

@Override
public String getRemoteUser() {
Request.AuthenticationState state = Request.getAuthenticationState(request);
if (state != null) {
Principal principle = state.getUserPrincipal();
if (principle != null) {
return principle.getName();
}
}
return null;
}

@Override
public Enumeration getParameterNames() {
Fields fields = Request.extractQueryParameters(request);
if (fields == null) {
return null;
}
return Collections.enumeration(fields.getNames());
}

@Override
public String[] getParameterValues(String name) {
Fields fields = Request.extractQueryParameters(request);
if (fields == null) {
return new String[0];
}

List<String> valueList = fields.getValues(name);

return valueList.toArray(new String[0]);
}

@Override
public Object getAttribute(String name) {
return request.getAttribute(name);
}

@Override
public String getCookieValue(String name) {
List<HttpCookie> cookies = Request.getCookies(request);

for (HttpCookie cookie: cookies) {
if (cookie.getName() != null && cookie.getName().equals(cookie.getName())) {
return cookie.getValue();
}
}
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.nr.agent.instrumentation.jetty12;

import com.newrelic.api.agent.HeaderType;
import org.eclipse.jetty.server.Response;

public class JettyResponse implements com.newrelic.api.agent.Response {

private final Response response;

public JettyResponse(Response response) {
this.response = response;
}


@Override
public HeaderType getHeaderType() {
return HeaderType.HTTP;
}

@Override
public void setHeader(String name, String value) {
response.getHeaders().add(name, value);
}

@Override
public int getStatus() throws Exception {
return response.getStatus();
}

@Override
public String getStatusMessage() throws Exception {
return null;
}

@Override
public String getContentType() {
return response.getHeaders().get("content-type");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import com.newrelic.api.agent.weaver.MatchType;
import com.newrelic.api.agent.weaver.Weave;
import com.newrelic.api.agent.weaver.Weaver;
import com.nr.agent.instrumentation.jetty12.JettyRequest;
import com.nr.agent.instrumentation.jetty12.JettyResponse;
import com.nr.agent.instrumentation.jetty12.JettySampler;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.thread.ThreadPool;
Expand All @@ -25,9 +27,27 @@ protected void doStart() {
Weaver.callOriginal();
}

// Required so that earlier jetty versions do not apply.
// Transactions are managed in the jetty-12-ee* modules.
public abstract boolean handle(Request request, Response response, Callback callback);
public boolean handle(Request request, Response response, Callback callback) {
boolean isStarted = AgentBridge.getAgent().getTransaction().isStarted();
// if there is a #ContextHolder, then this is not embedded Jetty, so the transaction should start there
boolean startTransaction = request != null && !isStarted;

if (startTransaction) {
AgentBridge.getAgent().getTransaction(true)
.requestInitialized(new JettyRequest(request), new JettyResponse(response));
}

boolean result = false;
try {
result = Weaver.callOriginal();
} finally {
if (startTransaction) {
AgentBridge.getAgent().getTransaction().requestDestroyed();
}
}

return result;
}

public static String getVersion() {
return Weaver.callOriginal();
Expand Down
27 changes: 4 additions & 23 deletions instrumentation/jetty-ee10-servlet-12.0.1/README.md
Original file line number Diff line number Diff line change
@@ -1,30 +1,11 @@
# Jetty 12 EE 10 Servlet Instrumentation
# Jetty 12 Servlet Instrumentation

With the introduction of [Jetty 12](https://webtide.com/introducing-jetty-12/), Jetty is now designed with the philosophy of being *Servlet API independent*.
As a result **Jetty** can be used as a core server without any involvement with servlets.
In addition, it now supports every **Servlet API** spec starting from Jakarta EE 8 above.

One of the challenges that resulted from this is that while in theory transactions can
be started in a core server, there is no straightforward way to manage transactions
in async servlets. Jetty 12 offers implementation for each Jakarta EE spec so transactions can instead be
managed through the servlet implementations. As a result the Jetty 12 instrumentation was split into 5 new modules.
Much of the instrumentation work is handled in the core Jetty module. This module handles servlet specific work such as:

## Instrumentation Modules

### jetty-12
This module instruments the core Jetty server that handles tasks that does not require the Servlet API.
The tasks of this module includes but is not limited to:

- Reporting threadpool metrics
- Reporting the dispatcher name and version as well as the port number for the server.
- Adding outbound CAT headers for outgoing requests. CAT however is deprecated during the time this module is made (i.e. December 2023).
- Reporting errors

### jetty-ee*-servlet-12
This refers to our current module and any module named based on the same pattern, `jetty-ee*-servlet-12`.
These modules instrument the Servlet API implementations for Jetty.
As a result, the instrumentation works with tasks that require us to work with the Servlet API such as:

- Start and ending web transactions
- Linking transactions to async activity
- Marking the transaction as a servlet based call with a `requestDispatcher` segment
- Suspending, resuming, and ending transactions associated with async servlet operations
- Reporting errors
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*
*/

package com.nr.agent.instrumentation.jetty.ee10.servlet;
package com.nr.agent.instrumentation.jetty12.ee10.servlet;

import com.newrelic.agent.bridge.AgentBridge;
import jakarta.servlet.AsyncEvent;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*
*/

package com.nr.agent.instrumentation.jetty.ee10.servlet;
package com.nr.agent.instrumentation.jetty12.ee10.servlet;

import com.newrelic.api.agent.ExtendedRequest;
import com.newrelic.api.agent.HeaderType;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*
*/

package com.nr.agent.instrumentation.jetty.ee10.servlet;
package com.nr.agent.instrumentation.jetty12.ee10.servlet;

import com.newrelic.agent.bridge.AgentBridge;
import com.newrelic.api.agent.NewRelic;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*
*/

package com.nr.agent.instrumentation.jetty.ee9.servlet;
package com.nr.agent.instrumentation.jetty12.ee10.servlet;

import com.newrelic.api.agent.HeaderType;
import com.newrelic.api.agent.Response;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*
*/

package com.nr.agent.instrumentation.jetty.ee10.servlet;
package com.nr.agent.instrumentation.jetty12.ee10.servlet;

import jakarta.servlet.ServletRequest;
import org.eclipse.jetty.server.Request;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@
package org.eclipse.jetty.ee10.servlet;

import com.newrelic.api.agent.NewRelic;
import com.newrelic.api.agent.Token;
import com.newrelic.api.agent.weaver.MatchType;
import com.newrelic.api.agent.weaver.Weave;
import com.newrelic.api.agent.weaver.Weaver;
import com.nr.agent.instrumentation.jetty.ee10.servlet.ServerHelper;
import com.nr.agent.instrumentation.jetty12.ee10.servlet.ServerHelper;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Response;
import org.eclipse.jetty.util.Callback;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import com.newrelic.api.agent.weaver.MatchType;
import com.newrelic.api.agent.weaver.Weave;
import com.newrelic.api.agent.weaver.Weaver;
import com.nr.agent.instrumentation.jetty.ee10.servlet.AsyncListenerFactory;
import com.nr.agent.instrumentation.jetty12.ee10.servlet.AsyncListenerFactory;
import jakarta.servlet.AsyncContext;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
import com.newrelic.api.agent.weaver.MatchType;
import com.newrelic.api.agent.weaver.Weave;
import com.newrelic.api.agent.weaver.Weaver;
import com.nr.agent.instrumentation.jetty.ee10.servlet.JettyRequestListener;
import com.nr.agent.instrumentation.jetty.ee10.servlet.ServerHelper;
import com.nr.agent.instrumentation.jetty12.ee10.servlet.JettyRequestListener;
import com.nr.agent.instrumentation.jetty12.ee10.servlet.ServerHelper;
import jakarta.servlet.http.HttpServletRequest;
import org.eclipse.jetty.server.Request;

Expand Down
27 changes: 4 additions & 23 deletions instrumentation/jetty-ee10-servlet-12/README.md
Original file line number Diff line number Diff line change
@@ -1,30 +1,11 @@
# Jetty 12 EE 10 Servlet Instrumentation
# Jetty 12 Servlet Instrumentation

With the introduction of [Jetty 12](https://webtide.com/introducing-jetty-12/), Jetty is now designed with the philosophy of being *Servlet API independent*.
As a result **Jetty** can be used as a core server without any involvement with servlets.
In addition, it now supports every **Servlet API** spec starting from Jakarta EE 8 above.

One of the challenges that resulted from this is that while in theory transactions can
be started in a core server, there is no straightforward way to manage transactions
in async servlets. Jetty 12 offers implementation for each Jakarta EE spec so transactions can instead be
managed through the servlet implementations. As a result the Jetty 12 instrumentation was split into 5 new modules.
Much of the instrumentation work is handled in the core Jetty module. This module handles servlet specific work such as:

## Instrumentation Modules

### jetty-12
This module instruments the core Jetty server that handles tasks that does not require the Servlet API.
The tasks of this module includes but is not limited to:

- Reporting threadpool metrics
- Reporting the dispatcher name and version as well as the port number for the server.
- Adding outbound CAT headers for outgoing requests. CAT however is deprecated during the time this module is made (i.e. December 2023).
- Reporting errors

### jetty-ee*-servlet-12
This refers to our current module and any module named based on the same pattern, `jetty-ee*-servlet-12`.
These modules instrument the Servlet API implementations for Jetty.
As a result, the instrumentation works with tasks that require us to work with the Servlet API such as:

- Start and ending web transactions
- Linking transactions to async activity
- Marking the transaction as a servlet based call with a `requestDispatcher` segment
- Suspending, resuming, and ending transactions associated with async servlet operations
- Reporting errors
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*
*/

package com.nr.agent.instrumentation.jetty.ee9.servlet;
package com.nr.agent.instrumentation.jetty12.ee10.servlet;

import com.newrelic.agent.bridge.AgentBridge;
import jakarta.servlet.AsyncEvent;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*
*/

package com.nr.agent.instrumentation.jetty.ee9.servlet;
package com.nr.agent.instrumentation.jetty12.ee10.servlet;

import com.newrelic.api.agent.ExtendedRequest;
import com.newrelic.api.agent.HeaderType;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*
*/

package com.nr.agent.instrumentation.jetty.ee10.servlet;
package com.nr.agent.instrumentation.jetty12.ee10.servlet;

import com.newrelic.agent.bridge.AgentBridge;
import com.newrelic.api.agent.NewRelic;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*
*/

package com.nr.agent.instrumentation.jetty.ee10.servlet;
package com.nr.agent.instrumentation.jetty12.ee10.servlet;

import com.newrelic.api.agent.HeaderType;
import com.newrelic.api.agent.Response;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*
*/

package com.nr.agent.instrumentation.jetty.ee10.servlet;
package com.nr.agent.instrumentation.jetty12.ee10.servlet;

import jakarta.servlet.ServletRequest;
import org.eclipse.jetty.server.Request;
Expand Down
Loading
Loading