APItoolkit full color logo
Sign Up

Springboot SDK Guide

In this guide, you’ll learn how to integrate OpenTelemetry into your Java application and install the APItoolkit Springboot SDK to enhance its functionalities. By combining OpenTelemetry’s robust tracing and metrics capabilities with the APItoolkit SDK, you’ll be able to monitor incoming and outgoing requests, report errors, and gain deeper insights into your application’s performance. This setup provides comprehensive observability, helping you track requests and troubleshoot issues effectively.


Prerequisites

Ensure you have already completed the first three steps of the onboarding guide{target="\_blank"}.

Installation

To install the SDK, kindly add the following dependency to your pom.xml file within the <dependencies> section, like so:

<dependency>
  <groupId>io.apitoolkit.springboot</groupId>
  <artifactId>apitoolkit-springboot</artifactId>
  <version>2.0.9</version>
</dependency>

Open Telemetry Setup

Setting up open telemetry allows you to send traces, metrics and logs to the APIToolkit platform. To setup open telemetry, you need to install the opentelemetry-javaagent.jar file.

curl -L -O https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar

Setup Open Telemetry Variables

The environment variables include your API key and the endpoint to send the data to, this allows you to send data to the APIToolkit platform.

export OTEL_EXPORTER_OTLP_ENDPOINT="http://otelcol.apitoolkit.io:4317"
export OTEL_SERVICE_NAME="my-service" # Specifies the name of the service.
export OTEL_RESOURCE_ATTRIBUTES=at-project-key="{ENTER_YOUR_API_KEY_HERE}" # Adds your API KEY to the resource.
export OTEL_EXPORTER_OTLP_PROTOCOL="grpc" #Specifies the protocol to use for the OpenTelemetry exporter.

<div class="callout"> <p><i class="fa-regular fa-lightbulb"></i> <b>Tip</b></p> <p>The {ENTER_YOUR_API_KEY_HERE} demo string should be replaced with the API key generated from the APItoolkit dashboard.</p> </div>

You can then run the application with opentelemetry instrumented using the following command:

java -javaagent:/opentelemetry-javaagent.jar -jar target/your_app.jar

or using maven

mvn spring-boot:run -Dspring-boot.run.jvmArguments="-javaagent:/opentelemetry-javaagent.jar"

APItoolkit SDK Configuration

The apitoolkit sdk can be configured using the following optional properties in your resource/application.properties file:

apitoolkit.captureRequestBody=true # Capture request body.
apitoolkit.captureResponseBody=true # Capture response body.
apitoolkit.serviceName=my-service # Service name.
apitoolkit.serviceVersion="2.0" # Service version.
apitoolkit.tags = "value1,value2" # Comma-separated list of tags.
apitoolkit.redactHeaders = "Authorizations, X-Api-Key" # Comma-separated list of headers to redact.
apitoolkit.redactRequestBody= "$.password,$.creditCardNumber" # Comma-separated list of JSON paths to redact.
apitoolkit.redactResponseBody= "$.password,$.creditCardNumber" # Comma-separated list of JSON paths to redact.
apitoolkit.debug=false # Enable debug mode.
# ...

Then, initialize the SDK, like so:

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
// Import APItoolkit annotation
import io.apitoolkit.springboot.annotations.EnableAPIToolkit;
// END Import APItoolkit annotation
import org.springframework.web.bind.annotation.*;

@SpringBootApplication
// Add APIToolkit custom annotation
@EnableAPIToolkit
// END Add APIToolkit custom annotation
@RestController
public class DemoApplication {

  public static void main(String[] args) {
    SpringApplication.run(DemoApplication.class, args);
  }

  @GetMapping("/greet/{name}")
  public String getUser(@PathVariable String name) {
    return "Hello, " + name;
  }
}

Redacting Sensitive Data

If you have fields that are sensitive and should not be sent to APItoolkit servers, you can mark those fields to be redacted (the fields will never leave your servers).

To mark a field for redacting via this SDK, you need to provide additional configuration options to the application.properties file with paths to the fields that should be redacted. There are three arguments you can provide to configure what gets redacted, namely:

  1. redactHeaders: A list of HTTP header keys.
  2. redactRequestBody: A list of JSONPaths from the request body.
  3. redactResponseBody: A list of JSONPaths from the response body.

<hr /> JSONPath is a query language used to select and extract data from JSON files. For example, given the following sample user data JSON object:

{
  "user": {
    "name": "John Martha",
    "email": "[email protected]",
    "addresses": [
      {
        "street": "123 Main St",
        "city": "Anytown",
        "state": "CA",
        "zip": "12345"
      },
      {
        "street": "123 Main St",
        "city": "Anytown",
        "state": "CA",
        "zip": "12345"
      }
    ],
    "credit_card": {
      "number": "4111111111111111",
      "expiration": "12/28",
      "cvv": "123"
    }
  }
}

Examples of valid JSONPath expressions would be:

JSONPathDescription
$.user.addresses[*].zipIn this case, APItoolkit will replace the zip field in all the objects of the addresses list inside the user object with the string [CLIENT_REDACTED].
$.user.credit_cardIn this case, APItoolkit will replace the entire credit_card object inside the user object with the string [CLIENT_REDACTED].

<div class="callout"> <p><i class="fa-regular fa-lightbulb"></i> <b>Tip</b></p> <p>To learn more about JSONPaths, please take a look at the official docs or use this JSONPath Evaluator to validate your JSONPath expressions. </p> <p>You can also use our JSON Redaction Tool <i class="fa-regular fa-screwdriver-wrench"></i> to preview what the final data sent from your API to APItoolkit will look like, after redacting any given JSON object.</p> </div> <hr />

Here's an example of what the configuration would look like with redacted fields:

apitoolkit.redactHeaders=content-type,Authorization,HOST
apitoolkit.redactRequestBody=$.user.email,$.user.addresses
apitoolkit.redactResponseBody=$.users[*].email,$.users[*].credit_card

<div class="callout"> <p><i class="fa-regular fa-circle-info"></i> <b>Note</b></p> <ul> <li>The apitoolkit.redactHeaders config field expects a list of <b>case-insensitive headers as strings</b>.</li> <li>The apitoolkit.redactRequestBody and apitoolkit.redactResponseBody config fields expect a list of <b>JSONPaths as strings</b>.</li> <li>The list of items to be redacted will be applied to all endpoint requests and responses on your server.</li> </ul> </div>

Error Reporting

With APItoolkit, you can track and report different unhandled or uncaught errors, API issues, and anomalies at different parts of your application. This will help you associate more detail and context from your backend with any failing customer request.

To manually report specific errors at different parts of your application, use the reportError() method, passing in the request and exception parameters, like so:

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.*;
import jakarta.servlet.http.HttpServletRequest;

import io.apitoolkit.springboot.APErrors;
import io.apitoolkit.springboot.annotations.EnableAPIToolkit;

@EnableAPIToolkit
@SpringBootApplication
public class DemoApplication {

  public static void main(String[] args) {
    SpringApplication.run(DemoApplication.class, args);
  }

  @GetMapping("/hello")
  public String hello(@RequestParam(value = "name", defaultValue = "World") String name, HttpServletRequest request) {
    try {
      System.out.print(1 / 0); // This will throw an ArithmeticException
    } catch (Exception e) {
      // Report the error to APItoolkit
      APErrors.reportError(request, e);
    }
    return String.format("Hello %s!", name);
  }
}

Monitoring Outgoing Requests

Outgoing requests are external API calls you make from your API. By default, APItoolkit monitors all requests users make from your application and they will all appear in the API Log Explorer{target="\blank"} page. However, you can separate outgoing requests from others and explore them in the Outgoing Integrations{target="\blank"} page, alongside the incoming request that triggered them.

The Springboot SDK provides the ObserveRequest class for monitoring outgoing requests using the Apache HTTP client. First, you will create an instance of the class, then use the instance to create a new HTTP client, passing in the current request context and an optional url_path string (for URLs with path parameters), like so:

package com.example.demo;

import java.util.List;

import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import io.apitoolkit.springboot.annotations.EnableAPIToolkit;
import io.apitoolkit.springboot.integrations.ObserveRequest;
import jakarta.servlet.http.HttpServletRequest;

import org.springframework.web.bind.annotation.*;

@SpringBootApplication
@EnableAPIToolkit
@RestController
public class DemoApplication {

  public static void main(String[] args) {
    SpringApplication.run(DemoApplication.class, args);
  }

  // Create an instance of the ObserveRequest class
  private ObserveRequest observingClient = new ObserveRequest(
    // Optional parameters to redact headers and request/response body
    List.of("content-type", "Authorization", "HOST"),
    List.of("$.user.email", "$.user.addresses"),
    List.of("$.users[*].email", "$.users[*].credit_card")
  );

  @GetMapping("/hello")
  public String hello(HttpServletRequest request) {
    // Use the observingClient instance to create an HTTP Client
    CloseableHttpClient httpClient = observingClient.createHttpClient(request, "/posts/{post_id}");
    try {
      HttpGet httpGet = new HttpGet("https://jsonplaceholder.typicode.com/posts/1");
      CloseableHttpResponse response = httpClient.execute(httpGet);
      String responseStr = EntityUtils.toString(response.getEntity());
      return responseStr;
    } catch (Exception e) {
      e.printStackTrace();
      return "Error occurred while processing the request...";
    }
  }
}

Explore the Springboot SDK