Convert jsf to instrumenter api (#3838)
* Convert jsf to instrumenter api * Review comments * Use span name not null
This commit is contained in:
parent
1a9896543a
commit
912ce91b60
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.instrumentation.jsf;
|
||||
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.ErrorCauseExtractor;
|
||||
import javax.faces.FacesException;
|
||||
|
||||
public class JsfErrorCauseExtractor implements ErrorCauseExtractor {
|
||||
|
||||
@Override
|
||||
public Throwable extractCause(Throwable error) {
|
||||
while (error.getCause() != null && error instanceof FacesException) {
|
||||
error = error.getCause();
|
||||
}
|
||||
return ErrorCauseExtractor.jdk().extractCause(error);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.instrumentation.jsf;
|
||||
|
||||
import java.util.Objects;
|
||||
import javax.faces.component.ActionSource2;
|
||||
import javax.faces.event.ActionEvent;
|
||||
|
||||
public class JsfRequest {
|
||||
private final String spanName;
|
||||
|
||||
public JsfRequest(ActionEvent event) {
|
||||
this.spanName = getSpanName(event);
|
||||
}
|
||||
|
||||
public String spanName() {
|
||||
return Objects.requireNonNull(spanName);
|
||||
}
|
||||
|
||||
public boolean shouldStartSpan() {
|
||||
return spanName != null;
|
||||
}
|
||||
|
||||
private static String getSpanName(ActionEvent event) {
|
||||
// https://jakarta.ee/specifications/faces/2.3/apidocs/index.html?javax/faces/component/ActionSource2.html
|
||||
// ActionSource2 was added in JSF 1.2 and is implemented by components that have an action
|
||||
// attribute such as a button or a link
|
||||
if (event.getComponent() instanceof ActionSource2) {
|
||||
ActionSource2 actionSource = (ActionSource2) event.getComponent();
|
||||
if (actionSource.getActionExpression() != null) {
|
||||
// either an el expression in the form #{bean.method()} or navigation case name
|
||||
String expressionString = actionSource.getActionExpression().getExpressionString();
|
||||
// start span only if expression string is really an expression
|
||||
if (expressionString.startsWith("#{") || expressionString.startsWith("${")) {
|
||||
return expressionString;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.instrumentation.jsf;
|
||||
|
||||
import static io.opentelemetry.instrumentation.api.servlet.ServerSpanNaming.Source.CONTROLLER;
|
||||
|
||||
import io.opentelemetry.context.Context;
|
||||
import io.opentelemetry.instrumentation.api.servlet.ServerSpanNaming;
|
||||
import io.opentelemetry.instrumentation.api.servlet.ServletContextPath;
|
||||
import javax.faces.component.UIViewRoot;
|
||||
import javax.faces.context.FacesContext;
|
||||
|
||||
public class JsfServerSpanNaming {
|
||||
|
||||
public static void updateServerSpanName(FacesContext facesContext) {
|
||||
Context parentContext = Context.current();
|
||||
ServerSpanNaming.updateServerSpanName(
|
||||
parentContext, CONTROLLER, () -> getServerSpanName(parentContext, facesContext));
|
||||
}
|
||||
|
||||
private static String getServerSpanName(Context context, FacesContext facesContext) {
|
||||
UIViewRoot uiViewRoot = facesContext.getViewRoot();
|
||||
if (uiViewRoot == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// JSF spec 7.6.2
|
||||
// view id is a context relative path to the web application resource that produces the view,
|
||||
// such as a JSP page or a Facelets page.
|
||||
String viewId = uiViewRoot.getViewId();
|
||||
return ServletContextPath.prepend(context, viewId);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.instrumentation.jsf;
|
||||
|
||||
import io.opentelemetry.api.trace.Span;
|
||||
import io.opentelemetry.context.Context;
|
||||
import io.opentelemetry.instrumentation.api.servlet.ServletContextPath;
|
||||
import io.opentelemetry.instrumentation.api.tracer.BaseTracer;
|
||||
import io.opentelemetry.instrumentation.api.tracer.ServerSpan;
|
||||
import javax.faces.FacesException;
|
||||
import javax.faces.component.ActionSource2;
|
||||
import javax.faces.component.UIViewRoot;
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.faces.event.ActionEvent;
|
||||
|
||||
public abstract class JsfTracer extends BaseTracer {
|
||||
|
||||
public Context startSpan(ActionEvent event) {
|
||||
// https://jakarta.ee/specifications/faces/2.3/apidocs/index.html?javax/faces/component/ActionSource2.html
|
||||
// ActionSource2 was added in JSF 1.2 and is implemented by components that have an action
|
||||
// attribute such as a button or a link
|
||||
if (event.getComponent() instanceof ActionSource2) {
|
||||
ActionSource2 actionSource = (ActionSource2) event.getComponent();
|
||||
if (actionSource.getActionExpression() != null) {
|
||||
// either an el expression in the form #{bean.method()} or navigation case name
|
||||
String expressionString = actionSource.getActionExpression().getExpressionString();
|
||||
// start span only if expression string is really an expression
|
||||
if (expressionString.startsWith("#{") || expressionString.startsWith("${")) {
|
||||
return startSpan(expressionString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void updateServerSpanName(Context context, FacesContext facesContext) {
|
||||
Span serverSpan = ServerSpan.fromContextOrNull(context);
|
||||
if (serverSpan == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
UIViewRoot uiViewRoot = facesContext.getViewRoot();
|
||||
if (uiViewRoot == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// JSF spec 7.6.2
|
||||
// view id is a context relative path to the web application resource that produces the view,
|
||||
// such as a JSP page or a Facelets page.
|
||||
String viewId = uiViewRoot.getViewId();
|
||||
serverSpan.updateName(ServletContextPath.prepend(context, viewId));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Throwable unwrapThrowable(Throwable throwable) {
|
||||
while (throwable.getCause() != null && throwable instanceof FacesException) {
|
||||
throwable = throwable.getCause();
|
||||
}
|
||||
return super.unwrapThrowable(throwable);
|
||||
}
|
||||
}
|
||||
|
|
@ -5,13 +5,15 @@
|
|||
|
||||
package io.opentelemetry.javaagent.instrumentation.mojarra;
|
||||
|
||||
import static io.opentelemetry.javaagent.instrumentation.mojarra.MojarraTracer.tracer;
|
||||
import static io.opentelemetry.javaagent.instrumentation.mojarra.MojarraSingletons.instrumenter;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
|
||||
import io.opentelemetry.context.Context;
|
||||
import io.opentelemetry.context.Scope;
|
||||
import io.opentelemetry.instrumentation.jsf.JsfRequest;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
|
||||
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
|
||||
import javax.faces.event.ActionEvent;
|
||||
import net.bytebuddy.asm.Advice;
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
|
|
@ -37,28 +39,31 @@ public class ActionListenerImplInstrumentation implements TypeInstrumentation {
|
|||
@Advice.OnMethodEnter(suppress = Throwable.class)
|
||||
public static void onEnter(
|
||||
@Advice.Argument(0) ActionEvent event,
|
||||
@Advice.Local("otelRequest") JsfRequest request,
|
||||
@Advice.Local("otelContext") Context context,
|
||||
@Advice.Local("otelScope") Scope scope) {
|
||||
context = tracer().startSpan(event);
|
||||
if (context != null) {
|
||||
scope = context.makeCurrent();
|
||||
Context parentContext = Java8BytecodeBridge.currentContext();
|
||||
|
||||
request = new JsfRequest(event);
|
||||
if (!request.shouldStartSpan() || !instrumenter().shouldStart(parentContext, request)) {
|
||||
return;
|
||||
}
|
||||
|
||||
context = instrumenter().start(parentContext, request);
|
||||
scope = context.makeCurrent();
|
||||
}
|
||||
|
||||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
||||
public static void stopSpan(
|
||||
@Advice.Thrown Throwable throwable,
|
||||
@Advice.Local("otelRequest") JsfRequest request,
|
||||
@Advice.Local("otelContext") Context context,
|
||||
@Advice.Local("otelScope") Scope scope) {
|
||||
if (scope == null) {
|
||||
return;
|
||||
}
|
||||
scope.close();
|
||||
if (throwable != null) {
|
||||
tracer().endExceptionally(context, throwable);
|
||||
} else {
|
||||
tracer().end(context);
|
||||
}
|
||||
instrumenter().end(context, request, null, throwable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.mojarra;
|
||||
|
||||
import io.opentelemetry.api.GlobalOpenTelemetry;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
|
||||
import io.opentelemetry.instrumentation.jsf.JsfErrorCauseExtractor;
|
||||
import io.opentelemetry.instrumentation.jsf.JsfRequest;
|
||||
|
||||
public class MojarraSingletons {
|
||||
private static final String INSTRUMENTATION_NAME = "io.opentelemetry.mojarra-1.2";
|
||||
|
||||
private static final Instrumenter<JsfRequest, Void> INSTRUMENTER;
|
||||
|
||||
static {
|
||||
INSTRUMENTER =
|
||||
Instrumenter.<JsfRequest, Void>newBuilder(
|
||||
GlobalOpenTelemetry.get(), INSTRUMENTATION_NAME, JsfRequest::spanName)
|
||||
.setErrorCauseExtractor(new JsfErrorCauseExtractor())
|
||||
.newInstrumenter();
|
||||
}
|
||||
|
||||
public static Instrumenter<JsfRequest, Void> instrumenter() {
|
||||
return INSTRUMENTER;
|
||||
}
|
||||
|
||||
private MojarraSingletons() {}
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.mojarra;
|
||||
|
||||
import io.opentelemetry.instrumentation.jsf.JsfTracer;
|
||||
|
||||
public class MojarraTracer extends JsfTracer {
|
||||
private static final MojarraTracer TRACER = new MojarraTracer();
|
||||
|
||||
public static MojarraTracer tracer() {
|
||||
return TRACER;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getInstrumentationName() {
|
||||
return "io.opentelemetry.mojarra-1.2";
|
||||
}
|
||||
}
|
||||
|
|
@ -5,13 +5,12 @@
|
|||
|
||||
package io.opentelemetry.javaagent.instrumentation.mojarra;
|
||||
|
||||
import static io.opentelemetry.javaagent.instrumentation.mojarra.MojarraTracer.tracer;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
|
||||
|
||||
import io.opentelemetry.instrumentation.jsf.JsfServerSpanNaming;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
|
||||
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
|
||||
import javax.faces.context.FacesContext;
|
||||
import net.bytebuddy.asm.Advice;
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
|
|
@ -36,7 +35,7 @@ public class RestoreViewPhaseInstrumentation implements TypeInstrumentation {
|
|||
|
||||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
||||
public static void onExit(@Advice.Argument(0) FacesContext facesContext) {
|
||||
tracer().updateServerSpanName(Java8BytecodeBridge.currentContext(), facesContext);
|
||||
JsfServerSpanNaming.updateServerSpanName(facesContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,13 +5,15 @@
|
|||
|
||||
package io.opentelemetry.javaagent.instrumentation.myfaces;
|
||||
|
||||
import static io.opentelemetry.javaagent.instrumentation.myfaces.MyFacesTracer.tracer;
|
||||
import static io.opentelemetry.javaagent.instrumentation.myfaces.MyFacesSingletons.instrumenter;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
|
||||
import io.opentelemetry.context.Context;
|
||||
import io.opentelemetry.context.Scope;
|
||||
import io.opentelemetry.instrumentation.jsf.JsfRequest;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
|
||||
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
|
||||
import javax.faces.event.ActionEvent;
|
||||
import net.bytebuddy.asm.Advice;
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
|
|
@ -37,28 +39,31 @@ public class ActionListenerImplInstrumentation implements TypeInstrumentation {
|
|||
@Advice.OnMethodEnter(suppress = Throwable.class)
|
||||
public static void onEnter(
|
||||
@Advice.Argument(0) ActionEvent event,
|
||||
@Advice.Local("otelRequest") JsfRequest request,
|
||||
@Advice.Local("otelContext") Context context,
|
||||
@Advice.Local("otelScope") Scope scope) {
|
||||
context = tracer().startSpan(event);
|
||||
if (context != null) {
|
||||
scope = context.makeCurrent();
|
||||
Context parentContext = Java8BytecodeBridge.currentContext();
|
||||
|
||||
request = new JsfRequest(event);
|
||||
if (!request.shouldStartSpan() || !instrumenter().shouldStart(parentContext, request)) {
|
||||
return;
|
||||
}
|
||||
|
||||
context = instrumenter().start(parentContext, request);
|
||||
scope = context.makeCurrent();
|
||||
}
|
||||
|
||||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
||||
public static void stopSpan(
|
||||
@Advice.Thrown Throwable throwable,
|
||||
@Advice.Local("otelRequest") JsfRequest request,
|
||||
@Advice.Local("otelContext") Context context,
|
||||
@Advice.Local("otelScope") Scope scope) {
|
||||
if (scope == null) {
|
||||
return;
|
||||
}
|
||||
scope.close();
|
||||
if (throwable != null) {
|
||||
tracer().endExceptionally(context, throwable);
|
||||
} else {
|
||||
tracer().end(context);
|
||||
}
|
||||
instrumenter().end(context, request, null, throwable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.myfaces;
|
||||
|
||||
import io.opentelemetry.instrumentation.jsf.JsfErrorCauseExtractor;
|
||||
import javax.el.ELException;
|
||||
|
||||
public class MyFacesErrorCauseExtractor extends JsfErrorCauseExtractor {
|
||||
|
||||
@Override
|
||||
public Throwable extractCause(Throwable error) {
|
||||
error = super.extractCause(error);
|
||||
while (error.getCause() != null && error instanceof ELException) {
|
||||
error = error.getCause();
|
||||
}
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.myfaces;
|
||||
|
||||
import io.opentelemetry.api.GlobalOpenTelemetry;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
|
||||
import io.opentelemetry.instrumentation.jsf.JsfRequest;
|
||||
|
||||
public class MyFacesSingletons {
|
||||
private static final String INSTRUMENTATION_NAME = "io.opentelemetry.myfaces-1.2";
|
||||
|
||||
private static final Instrumenter<JsfRequest, Void> INSTRUMENTER;
|
||||
|
||||
static {
|
||||
INSTRUMENTER =
|
||||
Instrumenter.<JsfRequest, Void>newBuilder(
|
||||
GlobalOpenTelemetry.get(), INSTRUMENTATION_NAME, JsfRequest::spanName)
|
||||
.setErrorCauseExtractor(new MyFacesErrorCauseExtractor())
|
||||
.newInstrumenter();
|
||||
}
|
||||
|
||||
public static Instrumenter<JsfRequest, Void> instrumenter() {
|
||||
return INSTRUMENTER;
|
||||
}
|
||||
|
||||
private MyFacesSingletons() {}
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.myfaces;
|
||||
|
||||
import io.opentelemetry.instrumentation.jsf.JsfTracer;
|
||||
import javax.el.ELException;
|
||||
|
||||
public class MyFacesTracer extends JsfTracer {
|
||||
private static final MyFacesTracer TRACER = new MyFacesTracer();
|
||||
|
||||
public static MyFacesTracer tracer() {
|
||||
return TRACER;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Throwable unwrapThrowable(Throwable throwable) {
|
||||
throwable = super.unwrapThrowable(throwable);
|
||||
while (throwable.getCause() != null && throwable instanceof ELException) {
|
||||
throwable = throwable.getCause();
|
||||
}
|
||||
return throwable;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getInstrumentationName() {
|
||||
return "io.opentelemetry.myfaces-1.2";
|
||||
}
|
||||
}
|
||||
|
|
@ -5,13 +5,12 @@
|
|||
|
||||
package io.opentelemetry.javaagent.instrumentation.myfaces;
|
||||
|
||||
import static io.opentelemetry.javaagent.instrumentation.myfaces.MyFacesTracer.tracer;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
|
||||
|
||||
import io.opentelemetry.instrumentation.jsf.JsfServerSpanNaming;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
|
||||
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
|
||||
import javax.faces.context.FacesContext;
|
||||
import net.bytebuddy.asm.Advice;
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
|
|
@ -36,7 +35,7 @@ public class RestoreViewExecutorInstrumentation implements TypeInstrumentation {
|
|||
|
||||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
||||
public static void onExit(@Advice.Argument(0) FacesContext facesContext) {
|
||||
tracer().updateServerSpanName(Java8BytecodeBridge.currentContext(), facesContext);
|
||||
JsfServerSpanNaming.updateServerSpanName(facesContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue