Java Observability Toolkit (JOT) es una plataforma para hacer observable cualquier aplicación Java sin escribir ningún código o incluso recompilar. La plataforma consta de...
Puede crear JOT de forma rápida y sencilla sin necesidad de codificación. Los JOT pueden hacer observable casi cualquier cosa en una aplicación Java en ejecución. Aquí hay algunos ejemplos de para qué podrías usarlo... pero el único límite es tu creatividad.
Estás atascado solucionando un problema de producción y no tienes suficientes registros ni la capacidad de depurar. Con una sencilla regla JOT podrás obtener los datos que necesitas de forma rápida y sencilla.
Quiere monitorear algo a lo que solo se puede acceder desde lo profundo de una aplicación y no tiene forma de exponerlo a sus herramientas.
Quiere evitar que los atacantes abusen de métodos potentes, pero están en bibliotecas que no controla.
El objetivo de JOT es proporcionar la máxima potencia de instrumentación sin comprometer la simplicidad.
¡Cuéntanos las cosas interesantes que haces con JOT! Y considera contribuir con ellos al proyecto para que otros puedan compartir tu genialidad. La forma más sencilla de contribuir es crear una solicitud de extracción. Si está compartiendo un JOT, agréguelo al directorio "contrib" de los proyectos... e incluya un comentario que detalle para qué se utilizará.
Defina sus sensores e informes en yaml y guárdelos en un archivo .jot. Los sensores definen qué datos capturar y los "informes" le indican a JOT cómo rastrear los datos a lo largo del tiempo.
sensors:
- name: "get-ciphers"
description: "Identifies encryption ciphers"
methods:
- "javax.crypto.Cipher.getInstance"
captures:
- "#P0"
reports:
- name: "Encryption Usage"
type: "list"
cols: "get-ciphers"
Básicamente todo lo que tienes que hacer es agregar JOT a la JVM
Luego, simplemente use su aplicación normalmente y deje que JOT recopile datos por usted. JOT creará una buena tabla que capturará exactamente dónde se utiliza el cifrado y qué algoritmo se especifica.
Encryption Algorithms get-ciphers
------------------------------------------------------------ ----------------------
com.acme.ticketbook.Ticket.encrypt(Ticket.java:125) DES
org.apache.jsp.accessA_jsp._jspService(accessA_jsp.java:212) AES
org.apache.jsp.accessA_jsp._jspService(accessA_jsp.java:213) PBEWithMD5AndTripleDES
org.apache.jsp.accessB_jsp._jspService(accessB_jsp.java:212) DES
org.apache.jsp.accessC_jsp._jspService(accessC_jsp.java:212) DES/CBC/PKCS5Padding
Puede que le resulte útil utilizar la variable de entorno JAVA_TOOL_OPTIONS. Como "exportar JAVA_TOOL_OPTIONS="-javaagent:jot.jar=ciphers.jot". Entonces, no importa cómo se lance Java, utilizará JOT.
Si desea utilizar varios JOT al mismo tiempo, puede colocarlos todos en un archivo .jot grande o puede colocar varios archivos .jot en un directorio y utilizar "-javaagent:jot.jar=directorio".
Por último, cada JOT puede tener múltiples "capturas". Una captura es una forma de especificar qué datos desea recopilar de los métodos que especificó en el JOT. Las capturas simples son cosas como: #P0 - el primer parámetro #P1 - el segundo parámetro #ARGS - todos los parámetros concatenados en una cadena #OBJ - el objeto en el que se llama al método #RET - el retorno del método
Las capturas son en realidad expresiones de Spring Expression Language (SpEL), por lo que puedes llamar a métodos en esos objetos básicos, comparar cosas y realizar operaciones. Esto le ayuda a observar exactamente lo que desea. Consulte a continuación todos los detalles sobre cómo escribir sus propios sensores.
JOT usa FluentLogger que toma la configuración de java.util.logging
y puede ser configurado por la JVM con -Djava.util.logging.config.file
Esta configuración de muestra registrará JOT en la salida estándar y en /tmp/jot.log
handlers = java.util.logging.ConsoleHandler, java.util.logging.FileHandler
java.util.logging.ConsoleHandler.level = ALL
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
java.util.logging.SimpleFormatter.format = %1$tF %1$tT %4$-7s [%2$s] - %5$s %n
java.util.logging.FileHandler.level=ALL
java.util.logging.FileHandler.pattern=/tmp/jot.log
java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter
java.util.logging.FileHandler.append=true
usando:
java -javaagent:jot.jar=ciphers.jot -Djava.util.logging.config.file=/root/jul.properties
Los sensores son la forma de definir los datos que desea recopilar. También puede utilizar sensores para realizar acciones limitadas dentro de una aplicación.
# The name of this sensor, which can be referenced by reports
- name: "get-ciphers"
# Use this to describe what this sensor does. Try to provide enough
# detail so that anyone would understand what it's about.
description: "What does sensor do?"
# A list of methods to gather data from. To avoid potential performance issues,
# avoid putting sensors in methods that are extremely frequently used,
# like StringBuffer.append() or File.<init>.
methods:
- "a.b.c.Class.method"
- "d.e.f.Class.method"
# Scopes allow you to limit when a sensor will fire.
# A sensor will fire if it is invoked while "inside" one of the scopes. That is,
# when any of these methods is on the stack.
# You can define negative scopes using !scope, so that this sensor will only fire outside the scope
# For static methods you need to prefix the method with "static"
scopes:
- "a.b.c.Class.method" # matches only if inside method
- "!a.b.c.Class.method" # matches only if NOT inside method
- "static a.b.c.Class.method" # matches if inside static method
# Excludes allow you to prevent data from being gathered from any
# classes that starts with any of these patterns or are "isAssignableFrom" these classes
# FIXME: currently you must put .all after each classname
excludes:
- "javax.el.MapELResolver.all"
- "org.foo.package.all"
# Captures are the workhorse of JOT and are written in Spring Expression Language (SpEL)
# You may reference data from the method currently running.
# Options are OBJ, P1..P10, ARGS, RET, STACK. These objects are whatever type they happen
# to be, and you can invoke any existing methods on those objects. Note that STACK is a StackFrame[]
# See https://blog.abelotech.com/posts/useful-things-spring-expression-language-spel/
captures:
- "#RET?.toUpperCase()" # call toUpperCase if #RET is not null (note ?. operator)
- """+#P0+":"+#RET" # for methods that take a name and return a value
- "#OBJ.getCanonicalPath() + " " + #OBJ.exists() ? [EXISTS] : [DOES NOT EXIST]" # use ternary operator
- """+#P0+":"+(#RET ? "Y" : "N")" # for methods that return boolean
# Matchers allow you to filter the data that was captured with a set of regular expressions.
# If there are no matchers then all captures will report data.
# Positive matchers only fire if the data matches the pattern. You'll get a result if any positive matchers match.
# Negative matchers (starting with !) only fire if the data does not match the pattern. You'll get a result if no negative matchers match.
# If you mix positive and negative, you'll get a result if any positive captures match and no negative matchers match.
matchers:
- "^\w*$" # matches anything with word characters start to finish
- "!^\[foo" # matches anything that doesn't start with foo
- "!null" # hide empty results from output
# Exceptions are a way to change the behavior of an application.
# If the sensor fires (capture occurs and matchers fire) then JOT will
# throw a SensorException.
# The message should be appropriate for end user, JOT will log all the relevant details.
# Note that generally you don't want to use #RET in your capture if you're throwing an exception,
# because it will throw at the end of the method, which is probably too late.
exception: "Message"
# Debug mode will generate extra logging for this rule only
debug: "false"
Los informes le permiten definir cómo JOT recopilará datos a lo largo del tiempo y cómo los formateará.
# Title of this report that will be displayed above the results
- name: "example"
# Type of reports include
# 1. list
# ROWS: caller method
# COLS: one column named after the sensor defined in "cols"
# DATA: values from the sensor named in "cols"
# 2. compare
# ROWS:
# COLS: uses the "cols" sensor values as column headers
# DATA: values from the sensor named in "cols"
# 3. table
# ROWS:
# COLS: uses rule names for cols[0-n] as column headers - parses data values
# DATA: values from the sensor named in "cols"
# 4. series - table but each row starts with a timestamp (currently includes callers col too)
# ROWS:
# COLS: uses rule names for cols[0-n] as column headers - parses data values
# DATA: values from the sensor named in "cols"
type: "table"
# Rows indicates a sensor to be used to populate row headers
rows: "get-routes"
# Cols indicates a sensor (or list of sensors) to be used to populate column headers
cols: "get-users"
# Data indicates how the content of data cells should be populated. Can be a fixed string or a rule name.
data: "X"
Debería ser tan simple como clonar este repositorio y compilarlo con maven
$ git clone https://github.com/planetlevel/jot.git
$ cd jot
$ mvn install
Luego puede usar jot-xxjar en el directorio de destino.
Las contribuciones son bienvenidas. Consulte el rastreador de errores para encontrar problemas en los que trabajar si desea mejorar JOT.
- Solve problem of sensors inside JOT scope
1) don't instrument JOT classes -- anything using shading
2) use global scope to check anywhere you're inside a sensor call
- Create separate JOT log file instead of using java.util.logging
- New rules
1) which routes are non-idempotent?
- Sensors
# future features - maybe think about reporting?
# enabled: "false"
# sample: "1000" # report every 1000 times? time frequency?
# counter: "?" # report 10 mins?
# scope: include a capture and regex to say whether to start scope (if service.P0.getParameter=foobar)
# exec: run this code. before? after? during?
- Reports
# possible additions to cols -- caller, stack[n], trace#
- Query Language
# investigate using query language instead of yaml jots.
# Perhaps two types of "queries" -- one to create sensors, another to pull reports.
# SELECT #P0.toUpperCase()
FROM java.lang.Runtime.getRuntime.exec
WITHIN javax.servlet.Servlet.service
WHERE pattern
# SELECT [capture, capture]
FROM [method, method]
EXCLUDE [class, class]
WITHIN [scope, scope]
WHERE [pattern, pattern]
THROWS [msg]
# SELECT #P0 FROM javax.crypto.Cipher.getInstance
# SELECT #P0 FROM javax.crypto.Cipher.getInstance
WHERE "DES|DESEDE"
THROWS "Weak encryption algorithm detected"