JEP draft: Optional Usage Metadata Logging facility

AuthorLaurence Cable
OwnerLarry Cable
TypeFeature
ScopeJDK
StatusDraft
Componenthotspot / svc
Discussionserviceability dash dev at openjdk dot java dot net
EffortS
DurationS
Created2020/03/03 20:17
Updated2020/03/04 18:54
Issue8240497

Summary

Add capability to JVM in order to provide optional logging of Java usage metadata.

Goals

To enable consumers of JDK/JRE distributions to enable optional usage logging of their deployments; capturing usage metadata in a standard fashion.

Success Metrics

All JDK consumers are able to optionally log usage metadata from their JRE/JDK deployments.

Motivation

For many large enterprise customers that deploy a number of instances of (potentially multiple) JDK distributions across their computing environments, and subsequently utilize those installations in order to execute their application and services, the ability to capture a standard (metadata) description of each individual invocation (usage) of such deployments, for a variety of purposes (a.g compliance auditing, version tracking, security vulnerabilities, debugging and telemetry etc), is highly desirable.

The Oracle JDK distribution already provides a similar mechanism to facilitate the (optional) capture and retention of such information for later consumption and analysis (this proposal is not compatible with that existing implementation).

With the increasing adoption of multiple distributions by enterprise consumers; providing a common implementation of usage logging in the JDK would allow such consumers to (optionally) capture and retain such usage metadata from invocations of all their (various) JDK distribution installations in a consistent, standard manner and format, independent of their distribution source and version.

Description

Usage logging would (optionally, when enabled through property configuration) occur shortly after the Java runtime initialization completes; and either prior to, or in parallel with any application code being executed.

Default usage logger implementations shall capture and emit a log "entry" containing (at least) the following usage metadata extracted from the runtime environment:

NameValueRequired/Optional
current.timeDate & Time of invocationR
hostnamehostnameR
ip.addresshost IP or 0.0.0.0R
cmd.linejava cmd line argsR
java.versionjava version #R
java.vendorjava vendor nameR
java.vm.versionjvm version #R
java.vm.vendorJVM vendor nameR
os.namename of O.S platformR
os.versionO.S version #R
os.archinstruction set architecture nameR
jvm.argsJVM argumentsR
classpathclasspathR
modulepathmodulepathR
user.nameO.S usernameO
user.dircurrent working directoryO
os.pidO.S pid of JVMO
jvm.uuidUUID of JVMO
additional propertiesO

Configuration, and thus enabling, of usage logging occurs via the presence of standard Usage Logger properties, either described in a properties file in a prescribed location, or via the command line options of an individual java command invocation.

To enable usage logging “per JDK installation” a usagelogger.properties file shall be present in that installation’s ${JAVA_HOME}/conf/management directory.

This usagelogger.properties file shall contain (at least) the following properties:

jdk.usagelogger.url

This will specify the URL to be used in order to log usage metadata to, e.g file:///tmp/usagelogger.txt would specify a file location into which to append usage logger entries, or http://my.usagelogger/usagelog would direct an http POST (of application/json) payload to the target of the URL.

By default, the proposed implementation will support (host local) file:, http: and https: usage logging URL scheme protocol implementations but other protocols may be supported in addition to those defaults, either by individual JDK distributions implementation's or by specifying a Usage Logger Provider class (override) property in order to take precedence over the default implementation provider(s).

In order to take precedence over the default usage logger implementation provider the following property may be also be specified within the usagelogger.properties file (or via override on the the cmd line):

jdk.usagelogger.usagelogger.provider

This property, if specified will name a fully qualified classname that implements the jdk.usagelogger.UsageLoggerProvider interface which is a factory method for providing jdk.usagelogger.UsageLogger instances for a particular URL scheme (e.g file: or https:)

public UsageLogger provideUsageLoggerFor(URI usageURI) throws MalformedURLException;

If this property is specified; the provider configured will be invoked in order to provide an appropriate usage logger instance for the specified URL (scheme) prior to querying the default providers for an implementation.

The jdk.usagelogger.UsageLoggerProvider, returns an object of type jdk.usagelogger.UsageLogger (or null in the case where the provider either does not support, or does not wish to service the specified URL) which defines a single method signature:

public void logUsage(Set<Map.Entry<String, String[]>> usageInfo) throws IOException

Each provider queried returning a non-null value for a jdk.usagelogger.UsageLogger instance shall have that instance invoked and passed a Set object comprising Map.Entry instances, each of which will contain a (String) “key” describing the name of the usage metadata property, and a (String[]) array (of at least length == 1) containing the values associated with that particular metadata property.

The default Usage Logger provider implementations shall behave as follows:

The file: provider shall accept any valid (localhost relative) file: URIs such as: file:///<path>, file://localhost/<path>, or file:/<path>.

The provider will transcribe each log Set as plain text; each key, value tuple, quoted and CSV demarcated, terminated with a \n character.

The http:, https: provider: will accept either an http: or https: URL and will POST an application/json entry to the target specified.

If any provider fails, for any reason, to successfully emit a usage log entry, it may throw a checked or unchecked exception, as appropriate, and the runtime caller may choose to report the failure, or continue silently.

Alternatives

Without modifying the Java runtime itself, the only other mechanism available is to “wrapper” the java cmd invocation in some form of script that captures the cmd line arguments etc and emits a similar description, however this approach is costly, error prone, and not guaranteed to capture all invocations that could occur, but only those that are known to the developer and deployer of the wrapping scripts, and these scripts can of course potentially may be subverted (un)intentionally.

Testing

Basic unit tests to demonstrate the functionality, of the mechanism would be developed, including:

Risks and Assumptions

N.A

Dependencies

There are no inbound or outbound dependencies for this JEP at this time, however a JVM “UUID” JEP (under development) may be a dependency (if approved) in order to enable this JEP implementation to, in addition to the current state output, to also emit such a JVM UUID if available.