Java Observability Toolkit (JOT) adalah platform untuk membuat aplikasi Java apa pun dapat diamati tanpa menulis kode apa pun atau bahkan mengkompilasi ulang. Platformnya terdiri dari...
Anda dapat membuat JOT dengan cepat dan mudah tanpa coding apa pun. JOT dapat membuat apa saja dalam aplikasi Java yang sedang berjalan dapat diamati. Berikut adalah beberapa contoh kegunaannya... tetapi satu-satunya batasan adalah kreativitas Anda.
Anda terjebak dalam memecahkan masalah produksi dan Anda tidak memiliki cukup log atau kemampuan untuk melakukan debug. Dengan aturan JOT sederhana Anda bisa mendapatkan data yang Anda butuhkan dengan cepat dan mudah.
Anda ingin memantau sesuatu yang hanya dapat diakses jauh di dalam aplikasi dan Anda tidak memiliki cara untuk mengeksposnya ke alat Anda.
Anda ingin mencegah penyalahgunaan metode canggih oleh penyerang, namun metode tersebut berada di perpustakaan yang tidak Anda kendalikan.
Tujuan JOT adalah memberikan kekuatan instrumentasi maksimum tanpa mengorbankan kesederhanaan.
Beri tahu kami hal-hal keren yang Anda lakukan dengan JOT! Dan pertimbangkan untuk menyumbangkannya kembali ke proyek sehingga orang lain dapat berbagi kehebatan Anda. Cara termudah untuk berkontribusi adalah dengan membuat pull request. Jika Anda berbagi JOT, tambahkan ke direktori "kontribusi" proyek... dan harap sertakan komentar yang merinci tujuan penggunaannya.
Tentukan sensor dan laporan Anda di yaml dan simpan dalam file .jot. Sensor menentukan data apa yang akan diambil dan "laporan" memberi tahu JOT cara melacak data dari waktu ke waktu.
sensors:
- name: "get-ciphers"
description: "Identifies encryption ciphers"
methods:
- "javax.crypto.Cipher.getInstance"
captures:
- "#P0"
reports:
- name: "Encryption Usage"
type: "list"
cols: "get-ciphers"
Pada dasarnya yang harus Anda lakukan adalah menambahkan JOT ke JVM
Kemudian Anda cukup menggunakan aplikasi Anda seperti biasa dan biarkan JOT mengumpulkan data untuk Anda. JOT akan membuat tabel bagus yang menangkap dengan tepat di mana enkripsi digunakan dan algoritma apa yang ditentukan.
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
Anda mungkin menemukan penggunaan variabel lingkungan JAVA_TOOL_OPTIONS berguna. Seperti "export JAVA_TOOL_OPTIONS="-javaagent:jot.jar=ciphers.jot". Maka tidak peduli bagaimana Java akhirnya diluncurkan, Java akan menggunakan JOT.
Jika Anda ingin menggunakan beberapa JOT secara bersamaan, Anda dapat memasukkan semuanya ke dalam satu file .jot yang besar, atau Anda dapat meletakkan beberapa file .jot dalam satu direktori dan menggunakan "-javaagent:jot.jar=directory"
Terakhir, setiap JOT dapat memiliki banyak "pengambilan". Pengambilan adalah cara untuk menentukan data apa yang ingin Anda kumpulkan dari metode yang Anda tentukan di JOT. Tangkapan sederhananya adalah: #P0 - parameter pertama #P1 - parameter kedua #ARGS - semua parameter digabungkan dalam sebuah String #OBJ - objek tempat metode dipanggil #RET - hasil dari metode
Tangkapan sebenarnya adalah ekspresi Spring Expression Language (SpEL), sehingga Anda dapat memanggil metode pada objek dasar tersebut, membandingkan sesuatu, dan melakukan operasi. Ini membantu Anda mengamati dengan tepat apa yang Anda inginkan. Lihat di bawah untuk semua detail penulisan sensor Anda sendiri.
JOT menggunakan FluentLogger yang mengambil konfigurasi dari java.util.logging
dan dapat dikonfigurasi oleh JVM dengan -Djava.util.logging.config.file
Contoh konfigurasi ini akan mencatat JOT ke stdout dan juga ke /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
menggunakan:
java -javaagent:jot.jar=ciphers.jot -Djava.util.logging.config.file=/root/jul.properties
Sensor adalah cara Anda menentukan data yang ingin Anda kumpulkan. Anda juga dapat menggunakan sensor untuk melakukan tindakan terbatas dalam suatu aplikasi.
# 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"
Laporan memungkinkan Anda menentukan bagaimana JOT mengumpulkan data dari waktu ke waktu dan bagaimana JOT memformatnya untuk Anda.
# 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"
Sesederhana mengkloning repo ini dan membangunnya dengan pakar
$ git clone https://github.com/planetlevel/jot.git
$ cd jot
$ mvn install
Kemudian Anda bisa menggunakan jot-xxjar di direktori target.
Kontribusi dipersilakan. Lihat pelacak bug untuk menemukan masalah yang perlu diatasi jika Anda ingin menjadikan JOT lebih baik.
- 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"