|
| 1 | +# [Javaagent] Singletons Patterns |
| 2 | + |
| 3 | +## Quick Reference |
| 4 | + |
| 5 | +- Use when: reviewing `*Singletons` holder classes and their callers |
| 6 | +- Review focus: private fields, accessor naming, eager initialization, static-import call sites |
| 7 | + |
| 8 | +Javaagent modules keep shared `Instrumenter` instances and related collaborators in a dedicated |
| 9 | +`Singletons` holder class such as `MyLibrarySingletons`. |
| 10 | + |
| 11 | +## Rules |
| 12 | + |
| 13 | +- Keep exported singleton-holder fields `private`. Do not expose package-private or public |
| 14 | + `static` fields from `*Singletons` classes. |
| 15 | +- Initialize shared collaborators at class-load time, either with `static final` field |
| 16 | + initializers or in a `static {}` block. |
| 17 | +- Use `GlobalOpenTelemetry.get()` to obtain the `OpenTelemetry` instance. |
| 18 | +- The instrumentation name string should match the Gradle module path: |
| 19 | + `"io.opentelemetry.<module-name>"`. |
| 20 | +- For exported collaborators, use lower camel case field names and give the accessor method the |
| 21 | + exact same name as the field. Do not prefix these accessors with `get`. |
| 22 | + - `instrumenter` -> `instrumenter()` |
| 23 | + - `helper` -> `helper()` |
| 24 | + - `setter` -> `setter()` |
| 25 | +- Callers should static import singleton accessor methods and invoke them unqualified. |
| 26 | +- Keep verb-named helper methods as verbs when they perform work instead of returning a stored |
| 27 | + field. This naming rule applies to field accessors. |
| 28 | + |
| 29 | +## Preferred Pattern |
| 30 | + |
| 31 | +```java |
| 32 | +public final class MyLibrarySingletons { |
| 33 | + |
| 34 | + private static final Instrumenter<Request, Response> instrumenter = |
| 35 | + JavaagentHttpServerInstrumenters.create(...); |
| 36 | + |
| 37 | + private static final Helper helper = new Helper(); |
| 38 | + |
| 39 | + public static Instrumenter<Request, Response> instrumenter() { |
| 40 | + return instrumenter; |
| 41 | + } |
| 42 | + |
| 43 | + public static Helper helper() { |
| 44 | + return helper; |
| 45 | + } |
| 46 | + |
| 47 | + private MyLibrarySingletons() {} |
| 48 | +} |
| 49 | +``` |
| 50 | + |
| 51 | +Caller: |
| 52 | + |
| 53 | +```java |
| 54 | +import static io.opentelemetry.javaagent.instrumentation.example.MyLibrarySingletons.helper; |
| 55 | +import static io.opentelemetry.javaagent.instrumentation.example.MyLibrarySingletons.instrumenter; |
| 56 | + |
| 57 | +class MyInstrumentation implements TypeInstrumentation { |
| 58 | + void doSomething(Request request) { |
| 59 | + if (instrumenter().shouldStart(parentContext, request)) { |
| 60 | + helper().beforeStart(request); |
| 61 | + } |
| 62 | + } |
| 63 | +} |
| 64 | +``` |
| 65 | + |
| 66 | +## What to Flag in Review |
| 67 | + |
| 68 | +- Exposed singleton-holder fields such as `public static final Instrumenter ...`. |
| 69 | +- Accessor methods named `getInstrumenter()`, `getHelper()`, `getSetter()`, and similar when they |
| 70 | + simply return a backing field. |
| 71 | +- Call sites that qualify singleton field-accessor calls with the holder class instead of static |
| 72 | + importing the accessor method. |
| 73 | +- Mismatches between a field name and its accessor, such as `private static final Helper helper;` |
| 74 | + with `public static Helper getHelper()`. |
0 commit comments