Skip to content

Fix Rest and DB Interceptors #3

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

Merged
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
19 changes: 18 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.12</version>
<version>2.7.18</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>dev.inspector</groupId>
Expand Down Expand Up @@ -40,6 +40,23 @@
<artifactId>agent</artifactId>
<version>0.0.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.github.gavlyukovskiy/p6spy-spring-boot-starter -->
<dependency>
<groupId>com.github.gavlyukovskiy</groupId>
<artifactId>p6spy-spring-boot-starter</artifactId>
<scope>compile</scope>
<version>1.9.2</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20240303</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.16</version>
</dependency>
</dependencies>

<licenses>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,4 @@ public Config inspectorConfig() {
return config;
}

@Bean
public Inspector inspector(Config config) {
return new Inspector(config);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package dev.inspector.spring.interceptors.context;


import dev.inspector.agent.executor.Inspector;
import dev.inspector.agent.model.Config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class MonitoringContextHolder {

private Config inspectorConfig;

private ThreadLocal<Inspector> inspectorServiceThreadSafeWrapper;

public MonitoringContextHolder(@Autowired Config inspectorConfig) {
this.inspectorConfig = inspectorConfig;
inspectorServiceThreadSafeWrapper = new ThreadLocal<>();
}

public Inspector getInspectorService() {
Inspector inspectorService = inspectorServiceThreadSafeWrapper.get();
if (inspectorService == null) {
inspectorService = new Inspector(inspectorConfig);
inspectorServiceThreadSafeWrapper.set(inspectorService);
}

return inspectorService;
}

public void removeInspectorService() {
inspectorServiceThreadSafeWrapper.remove();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package dev.inspector.spring.interceptors.db;

import com.p6spy.engine.common.ConnectionInformation;
import com.p6spy.engine.common.StatementInformation;
import org.springframework.util.StringUtils;

public class DatabaseInfo {

private String databaseProductName;

public DatabaseInfo(String databaseProductName) {
this.databaseProductName = databaseProductName;
}

public String getDatabaseProductName() {
return databaseProductName;
}

public void setDatabaseProductName(String databaseProductName) {
this.databaseProductName = databaseProductName;
}

public static DatabaseInfo buildFrom(StatementInformation statementInformation) {
if (statementInformation == null) {
return null;
}

ConnectionInformation connectionInfo = statementInformation.getConnectionInformation();

if (connectionInfo == null) {
return null;
}

String rawDbUrl = connectionInfo.getUrl();

if (!StringUtils.hasText(rawDbUrl)) {
return null;
}

String dbUrl = dev.inspector.spring.utils.StringUtils.removePrefix(dev.inspector.spring.utils.StringUtils.removePrefix(rawDbUrl, "jdbc:"), "p6spy:");
String[] dbUrlParts = dbUrl.split(":");

String dbSystem = dbUrlParts[0];

return new DatabaseInfo(dbSystem);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package dev.inspector.spring.interceptors.db;

import com.p6spy.engine.common.StatementInformation;
import com.p6spy.engine.event.SimpleJdbcEventListener;
import dev.inspector.agent.executor.Inspector;
import dev.inspector.agent.model.Segment;
import dev.inspector.spring.interceptors.context.MonitoringContextHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.sql.SQLException;
import java.util.concurrent.TimeUnit;

@Service
public class JdbcInterceptor extends SimpleJdbcEventListener {

private static final Logger LOGGER = LoggerFactory.getLogger(JdbcInterceptor.class);


private MonitoringContextHolder monitoringContextHolder;

private final ThreadLocal<Segment> currentSegment = new ThreadLocal<>();
public JdbcInterceptor(@Autowired MonitoringContextHolder monitoringContextHolder) {
this.monitoringContextHolder = monitoringContextHolder;
}

@Override
public void onBeforeAnyExecute(StatementInformation statementInformation) {
DatabaseInfo databaseInfo = DatabaseInfo.buildFrom(statementInformation);
Inspector inspector = monitoringContextHolder.getInspectorService();

if (databaseInfo == null || !inspector.hasTransaction()) {
return;
}

LOGGER.debug(
"Thread {}: JDBC Interceptor. Starting monitoring segment for query {}",
Thread.currentThread().getName(),
statementInformation.getSql()
);
Segment currentMonitoringSegment = inspector.startSegment(databaseInfo.getDatabaseProductName());
currentSegment.set(currentMonitoringSegment);
}

@Override
public void onAfterAnyExecute(StatementInformation statementInformation, long timeElapsedNanos, SQLException e) {
Segment currentMonitoringSegment = currentSegment.get();

if (currentMonitoringSegment != null) {
LOGGER.debug(
"Thread {}: JDBC Interceptor. Ending monitoring segment for query {}",
Thread.currentThread().getName(),
statementInformation.getSql()
);
currentMonitoringSegment.setLabel(statementInformation.getSql());
currentMonitoringSegment.end(BigDecimal.valueOf(TimeUnit.NANOSECONDS.toMillis(timeElapsedNanos)));
}

currentSegment.remove();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import dev.inspector.agent.executor.Inspector;
import dev.inspector.agent.model.Transaction;
import dev.inspector.spring.interceptors.context.MonitoringContextHolder;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
Expand All @@ -15,7 +16,7 @@
public class GlobalExceptionHandler {

@Autowired
private Inspector inspector;
private MonitoringContextHolder monitoringContextHolder;

@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleException(Exception ex, HttpServletRequest request) {
Expand All @@ -30,6 +31,7 @@ public ResponseEntity<String> handleException(Exception ex, HttpServletRequest r
//
// // Aggiungere il contesto dell'errore alla transazione
// transaction.addContext("Error", errorContext);
Inspector inspector = monitoringContextHolder.getInspectorService();
inspector.reportException(ex);
inspector.getTransaction().setResult("error");

Expand All @@ -43,6 +45,7 @@ public ResponseEntity<String> handleException(Exception ex, HttpServletRequest r
public ResponseEntity<String> handleNotFoundException(NoHandlerFoundException ex, HttpServletRequest request) {
// Log the error
String methodName = request.getMethod() + " " + request.getRequestURI();
Inspector inspector = monitoringContextHolder.getInspectorService();
Transaction transaction = inspector.startTransaction("Error Transaction for " + methodName);

// Creare un oggetto JSON per il messaggio di errore
Expand All @@ -53,6 +56,7 @@ public ResponseEntity<String> handleNotFoundException(NoHandlerFoundException ex
// Aggiungere il contesto dell'errore alla transazione
transaction.addContext("Error", errorContext);
inspector.flush();
monitoringContextHolder.removeInspectorService();

// Creare una risposta not found
return new ResponseEntity<>("Resource not found", HttpStatus.NOT_FOUND);
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

import dev.inspector.agent.executor.Inspector;
import dev.inspector.agent.model.Segment;
import dev.inspector.spring.interceptors.context.MonitoringContextHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
Expand All @@ -14,12 +17,18 @@
@Component
public class OutgoingRestInterceptor implements ClientHttpRequestInterceptor {

private static final Logger LOGGER = LoggerFactory.getLogger(OutgoingRestInterceptor.class);

@Autowired
Inspector inspector;
private MonitoringContextHolder monitoringContextHolder;

@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
System.out.println("Outgoing REST request intercepted.");
LOGGER.debug(
"Thread {}: Outgoing HTTP call intercepted. Starting monitoring segment",
Thread.currentThread().getName()
);
Inspector inspector = monitoringContextHolder.getInspectorService();
Segment segment = inspector.startSegment("http", request.getURI().toString());
try {
return execution.execute(request, body);
Expand Down
Loading