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

Add Jakarta JSF 3.0+ instrumentation #7786

Merged
merged 11 commits into from
Feb 14, 2023
Merged
Show file tree
Hide file tree
Changes from 5 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
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
plugins {
id("otel.javaagent-instrumentation")
}

dependencies {
compileOnly(project(":instrumentation:servlet:servlet-common:bootstrap"))

compileOnly("jakarta.faces:jakarta.faces-api:3.0.0")
compileOnly("jakarta.el:jakarta.el-api:4.0.0")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.instrumentation.jsf.jakarta;

import io.opentelemetry.instrumentation.api.instrumenter.ErrorCauseExtractor;
import jakarta.faces.FacesException;

public class JsfErrorCauseExtractor implements ErrorCauseExtractor {
@Override
public Throwable extract(Throwable error) {
while (error.getCause() != null && error instanceof FacesException) {
error = error.getCause();
}
return ErrorCauseExtractor.getDefault().extract(error);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.instrumentation.jsf.jakarta;

import jakarta.faces.component.ActionSource2;
import jakarta.faces.event.ActionEvent;
import java.util.Objects;

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;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.instrumentation.jsf.jakarta;

import io.opentelemetry.api.trace.Span;
import io.opentelemetry.context.Context;
import io.opentelemetry.instrumentation.api.instrumenter.LocalRootSpan;
import io.opentelemetry.javaagent.bootstrap.servlet.ServletContextPath;
import jakarta.faces.component.UIViewRoot;
import jakarta.faces.context.FacesContext;

public final class JsfServerSpanNaming {

public static void updateViewName(Context context, FacesContext facesContext) {
// just update the server span name, without touching the http.route
Span serverSpan = LocalRootSpan.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();
String name = ServletContextPath.prepend(context, viewId);
serverSpan.updateName(name);
}

private JsfServerSpanNaming() {}
}
23 changes: 23 additions & 0 deletions instrumentation/jsf/jsf-jakarta-common/testing/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
plugins {
id("otel.java-conventions")
}

dependencies {
api("ch.qos.logback:logback-classic")
api("org.slf4j:log4j-over-slf4j")
api("org.slf4j:jcl-over-slf4j")
api("org.slf4j:jul-to-slf4j")

compileOnly("jakarta.faces:jakarta.faces-api:3.0.0")
compileOnly("jakarta.el:jakarta.el-api:4.0.0")

api("org.eclipse.jetty:jetty-webapp:11.0.0")
api("org.eclipse.jetty:apache-jstl:11.0.0")
api("org.eclipse.jetty:apache-jsp:11.0.0")

implementation(project(":testing-common"))
implementation("org.jsoup:jsoup:1.13.1")

implementation("org.glassfish:jakarta.el:4.0.2")
implementation("jakarta.websocket:jakarta.websocket-api:2.0.0")
}
Loading