Integration library that acts as a smart link between your application and the n1netails platform quiet, powerful, and built to vanish into your stack like a spirit fox.
Kuda can act as a simple logger but its main purpose is to send tail data over to n1netails-api. More details on setting
up and using Kuda will be reveled later.
Kuda should be setup alongside the N1netails core system but it can work without it as simple logging service for your application. Learn how to set up the core system here: N1netails
/ninetails/alert and a matching TailRequest POJO in your service.
Example Tail Request POJO:
public class KudaTailRequest {
// tail title
private String title;
// add description about the tail alert
private String description;
// place the exception stack trace in the `details` or any extra information that will help with identifying the issue or alert
private String details;
// tail timestamp
private Instant timestamp;
// tail level (ex. INFO, SUCCESS, WARN, ERROR, CRITICAL)
private String level;
// tail type (ex. SYSTEM_ALERT)
private String type;
// tail metadata (add information about the application in here)
private Map<String, String> metadata;
}TailConfig. Read more in Configure.
Install the Kuda by adding the following dependency:
<dependency>
<groupId>com.n1netails</groupId>
<artifactId>n1netails-kuda</artifactId>
<version>0.2.0</version>
</dependency>Set up and have the n1netails-api running on your server.
- N1netails-Api README
In order to get started with Kuda all you need to do is add the following three lines of code.
// your n1netails-api location
TailConfig.setApiUrl("http://your-n1netails-api-location.com");
// your n1ne token (created by the n1netails user interface or api)
TailConfig.setN1neToken("n1ne-token-uuid");
// send your first tail
Tail.error("Testing kuda error").withTag("env", "prod").send();TailConfig then Kuda will log a single warning about missing configurations and default to simple logging.
Example of using TailConfig to set the N1ne-token, API url and path.
import com.n1netails.n1netails.kuda.internal.TailConfig;
public class ExampleService {
public ExampleService() {
// You can configure this anywhere must be set once.
TailConfig.setApiUrl("http://localhost:9901");
// (Optional) set a custom path to send the alerts. If not set it will default to `/ninetails/alert`
TailConfig.setApiPath("/ninetails/alert");
// Set the n1ne-token value generated by n1netails api. If you are using n1netails-kuda for your own alerting api this value is optional.
TailConfig.setN1neToken("79dd8985-2d85-4a22-bfa0-0d70e963d713");
}
}Use the kuda tail methods to send alerts.
import com.n1netails.n1netails.kuda.api.Tail;
import com.n1netails.n1netails.kuda.internal.TailConfig;
public class ExampleService {
public ExampleService() {
// You can configure this anywhere must be set once.
TailConfig.setApiUrl("http://localhost:9901");
TailConfig.setN1neToken("79dd8985-2d85-4a22-bfa0-0d70e963d713");
}
public void myRandomMethod() {
try {
this.doSomeLogic();
Tail.success("Testing kuda success").send();
} catch (Exception ex) {
Tail.error("Testing kuda error").withTag("env", "prod").send();
}
}
public void otherN1neTailNotes() {
// Here are the other methods that can be used to provide more kuda details.
/////////////////
// INFO
////////////////
Tail.info("Testing kuda info").send();
Tail.info("Testing kuda info1").withTag("env", "prod").send();
Tail.info("Testing kuda info2").description("Extra description on the tail if needed").send();
Tail.info("Testing kuda info3").details("extra log stack details").send();
Tail.info("Testing kuda info4").type("SYSTEM_ALERT").send();
// utilizing all methods
Map<String, String> tags = new HashMap<>();
tags.put("env", "prod");
tags.put("test", "info");
tags.put("n1ne", "tails-info");
Tail.info("Testing kuda info5")
.description("Extra description on the tail if needed")
.details("extra log stack details")
.type("SYSTEM_ALERT")
.withTags(tags).send();
/////////////////
// SUCCESS
/////////////////
Tail.success("Testing kuda success").send();
Tail.success("Testing kuda success1").withTag("env", "prod").send();
Tail.success("Testing kuda success2").description("Extra description on the tail if needed").send();
Tail.success("Testing kuda success3").details("extra log stack details").send();
Tail.success("Testing kuda success4").type("SYSTEM_ALERT").send();
// utilizing all methods
Map<String, String> tags = new HashMap<>();
tags.put("env", "prod");
tags.put("test", "success");
tags.put("n1ne", "tails-success");
Tail.success("Testing kuda success5")
.description("Extra description on the tail if needed")
.details("extra log stack details")
.type("SYSTEM_ALERT")
.withTags(tags).send();
/////////////////
// WARN
/////////////////
Tail.warn("Testing kuda warn").send();
Tail.warn("Testing kuda warn1").withTag("env", "prod").send();
Tail.warn("Testing kuda warn2").description("Extra description on the tail if needed").send();
Tail.warn("Testing kuda warn3").details("extra log stack details").send();
Tail.warn("Testing kuda warn4").type("SYSTEM_ALERT").send();
// utilizing all methods
Map<String, String> tags = new HashMap<>();
tags.put("env", "prod");
tags.put("test", "warn");
tags.put("n1ne", "tails-warn");
Tail.warn("Testing kuda warn5")
.description("Extra description on the tail if needed")
.details("extra log stack details")
.type("SYSTEM_ALERT")
.withTags(tags).send();
/////////////////
// ERROR
/////////////////
Tail.error("Testing kuda error").send();
Tail.error("Testing kuda error1").withTag("env", "prod").send();
Tail.error("Testing kuda error2").description("Extra description on the tail if needed").send();
Tail.error("Testing kuda error3").details("extra log stack details").send();
Tail.error("Testing kuda error4").type("SYSTEM_ALERT").send();
Map<String, String> tags = new HashMap<>();
tags.put("env", "prod");
tags.put("test", "error");
tags.put("n1ne", "tails-error");
Tail.error("Testing kuda error5")
.description("Extra description on the tail if needed")
.details("extra log stack details")
.type("SYSTEM_ALERT")
.withTags(tags).send();
/////////////////
// CRITICAL
/////////////////
Tail.critical("Testing kuda critical").send();
Tail.critical("Testing kuda critical1").withTag("env", "prod").send();
Tail.critical("Testing kuda critical2").description("Extra description on the tail if needed").send();
Tail.critical("Testing kuda critical3").details("extra log stack details").send();
Tail.critical("Testing kuda critical4").type("SYSTEM_ALERT").send();
Map<String, String> tags = new HashMap<>();
tags.put("env", "prod");
tags.put("test", "critical");
tags.put("n1ne", "tails-critical");
Tail.critical("Testing kuda critical5")
.description("Extra description on the tail if needed")
.details("extra log stack details")
.type("SYSTEM_ALERT")
.withTags(tags).send();
/////////////////
// KUDA
// Send message with your own custom level (replace "MY_KUDA_LEVEL" with the level you want to create)
/////////////////
Tail.kuda("MY_KUDA_LEVEL", "Testing kuda").send();
Tail.kuda("MY_KUDA_LEVEL", "Testing kuda1").withTag("env", "prod").send();
Tail.kuda("MY_KUDA_LEVEL", "Testing kuda2").description("Extra description on the tail if needed").send();
Tail.kuda("MY_KUDA_LEVEL", "Testing kuda3").details("extra log stack details").send();
Tail.kuda("MY_KUDA_LEVEL", "Testing kuda4").type("SYSTEM_ALERT").send();
Map<String, String> tags = new HashMap<>();
tags.put("env", "prod");
tags.put("test", "kuda");
tags.put("n1ne", "tails-kuda");
Tail.kuda("MY_KUDA_LEVEL", "Testing kuda5")
.description("Extra description on the tail if needed")
.details("extra log stack details")
.type("SYSTEM_ALERT")
.withTags(tags).send();
}
}Kuda can also be used to set up a default exception handler with Tail.report you can pass throwable exceptions to kuda and it
will generate a detailed report on the exception.
You can also use TailConfig.enableExceptionHandler() to enable kuda as the default uncaught exception handler. This will allow you to capture any uncaught exceptions that you have not identified.
import com.n1netails.n1netails.kuda.api.Tail;
import com.n1netails.n1netails.kuda.internal.TailConfig;
public class ExampleService {
public ExampleService() {
// You can configure this anywhere must be set once.
TailConfig.setApiUrl("http://localhost:9901");
TailConfig.setN1neToken("79dd8985-2d85-4a22-bfa0-0d70e963d713");
// enable kuda to handle Default Uncaught Exception Handler (optional)
TailConfig.enableExceptionHandler();
}
public void defaultExceptionHandler() {
// exception handler
try {
throw new IllegalArgumentException("User ID was null");
} catch (Exception e) {
Tail.report(e); // manually report caught exception
}
}
public void defaultExceptionHandlerWithCustomLevel() {
// exception handler with custom tail level
try {
throw new IllegalArgumentException("CRITICAL - User ID was null");
} catch (Exception e) {
Tail.report("CRITICAL", e); // manually report caught exception with custom tail level
}
}
public void uncaughtException() {
// handle uncaught exceptions
new Thread(() -> {
throw new RuntimeException("This will trigger the kuda handler");
}).start();
}
}Build the project using the following command
mvn clean installUse the following doc to get setup with publishing to the maven central repository https://central.sonatype.org/register/central-portal/#publishing
Maven install using release profile.
mvn clean install -P releaseMaven deploy to the maven central repository
mvn deploy -P releaseFor community users, open an issue on GitHub or Join our Discord
Please use the following guidelines for contributions CONTRIBUTING