Getting Started

This page contains documentation of how to configure and attach the Codekvast agent to your application.

The architecture diagram is a helicopter view on how Codekvast works.

Installing the Codekvast agent

Download a ZIP file containing the codekvast-agent plus a sample configuration file from https://downloads.codekvast.io/codekvast-agent-1.0.0.zip.

Unzip the file to a suitable location and add -javaagent:path/to/codekvast-agent-1.0.0.jar to the command that launches your JVM (substituting 1.0.0 with the exact version of the agent that you are using).

codekvast-agent-1.0.0.jar including sources and JavaDocs is also available on JCenter:

pom.xml
<!--
Assumes that JCenter is added as a remote repository.
Go to https://bintray.com/bintray/jcenter and click SET ME UP! in the right margin to get instructions.
-->

<dependency>
    <groupId>io.codekvast</groupId>
    <artifactId>codekvast-agent</artifactId>
    <version>1.0.0</version>
</dependency>
build.gradle
repositories { jcenter() }
dependencies {
    runtime "io.codekvast:codekvast-agent:1.0.0"
}

Configuring the Codekvast agent

The Codekvast agent is configured by means of the file codekvast.conf.

The configuration file can be located in any of a well-defined list of locations. See About locating codekvast.conf for the exact search algorithm.

The format of codekvast.conf is a standard Java Properties file, that is, key: value or key = value. Long lines can be continued by ending the line with a backslash ('\') and indenting the continuation line with at least one space.

The right-hand side may contain references to environment variables and Java system properties. Example:

codekvast.conf
codeBase = ${app.home}/lib (1)
codeBase = $APP_HOME/lib (2)
1 A Java system property specified by -Dapp.home=xxx
2 The environment variable APP_HOME

Parameter overrides

Parameters in codekvast.conf can be overridden in a number of ways. This can come in handy if you have more than one application deployed in the same server, since they can use a shared codekvast.conf.

Override mechanisms
Environment variables CODEKVAST_XXX_YYY

An environment variable named CODEKVAST_XXX_YYY will override a single parameter named xxxYyy in codekvast.conf (if such a parameter exists).

Example: export CODEKVAST_SERVER_URL="http://someserver:8080" will override serverUrl=xxx inside codekvast.conf.

javaagent arguments

One can supply arguments to a Java Agent by appending "=args" to the -javaagent:codekvast-agent-1.0.0.jar string.

The args string should contain a semicolon separated list of key=value pairs.

Example: -javaagent:lib/codekvast-agent-1.0.0.jar=appName=App1;environment=staging.

This will set the appName to App1 and the environment to staging.

CODEKVAST_OPTS

This one is similar to javaagent arguments, but the values are defined in the environment variable CODEKVAST_OPTS.

The string should contain a semicolon separated list of key=value pairs.

Example: CODEKVAST_OPTS="httpProxyHost=10.20.30.40; httpProxyPort=4711"

Description of parameters

The following is an annotated codekvast.conf that describes all parameters and their default values.

codekvast.conf
#===========================================================================
# Mandatory parameters
#
# All of these parameters must be specified, or else codekvast-agent will refuse to start.
#===========================================================================

#---------------------------------------------------------------------------
# What is the license key for authenticating to the Codekvast Server?
# A string obtained when signing up for Codekvast.
#
# Example:
# licenseKey = 1958370a-346f-11e9-83ce-08626630cd01
#
# licenseKey =

#---------------------------------------------------------------------------
# What is my application's name?
# Identifies the application's data in the Codekvast server.
#
# Example:
# appName = MyAppName
#
# appName =

#---------------------------------------------------------------------------
# Where are my application binaries?
# A comma-separated list of file system paths.
#
# Example:
# codeBase = build/install/myapp/libs (1)
#
# codeBase =

#---------------------------------------------------------------------------
# What packages shall be tracked?
# A comma-separated list of package prefixes.
#
# Example:
# packages = com.acme, foo.bar
#
# packages =

#===========================================================================
# Connectivity parameters
#
# These parameters control how codekvast-agents connects to the server.
# Most of them are optional, with default values that suits for a development environment.
#===========================================================================

#---------------------------------------------------------------------------
# Where is the Codekvast Server?
# A URL obtained when signing up for Codekvast.
#
# Example:
# serverUrl = https://api.codekvast.io
#
# Default value:
# serverUrl = http://localhost:8080

#---------------------------------------------------------------------------
# How long shall codekvast-agent wait for establishing a connection to the server?
# A positive integer denoting a number of seconds.
#
# Default value:
# httpConnectTimeoutSeconds = 10

#---------------------------------------------------------------------------
# How long shall codekvast-agent wait when reading a response from the server?
# A positive integer denoting a number of seconds.
#
# Default value:
# httpReadTimeoutSeconds = 10

#---------------------------------------------------------------------------
# How long may a request to codekvastServer take at most?
# A positive integer denoting a number of seconds.
#
# Default value:
# httpWriteTimeoutSeconds = 30

#---------------------------------------------------------------------------
# Do we need to call the Codekvast Server via an HTTP proxy such as Squid?
# The value is a hostname or an IP address
#
# Example:
# httpProxyHost = 10.57.0.10
#
# Default value:
# httpProxyHost =

#---------------------------------------------------------------------------
# Which port at the httpProxyHost should we connect to?
# A socket port number. Is only used if httpProxyHost is non-empty
#
# Default value:
# httpProxyPort = 3128

#---------------------------------------------------------------------------
# Does the proxy need basic authentication?
# A username. Is only used if httpProxyHost is non-empty
#
# Since: 1.0.0
#
# Default value:
# httpProxyUsername =

#---------------------------------------------------------------------------
# Does the proxy need basic authentication?
# A password. Is only used if httpProxyHost and httpProxyUsername is non-empty
#
# Since: 1.0.0
#
# Default value:
# httpProxyPassword =

#===========================================================================
# Analysis parameters
#
# These parameters are optional, but you may want to set them to simplify analysis.
#===========================================================================

#---------------------------------------------------------------------------
# What is my app's version?
# The value of this parameter is a strategy for obtaining the actual version from the running application.
#
# Strategies: filename, manifest, property, literal (2)
#
# Example:
# appVersion = filename myApp-(.*).jar
#
# Default value:
# appVersion = literal unspecified

#---------------------------------------------------------------------------
# In which environment is the application deployed?
# An arbitrary string, useful when analysing the collected data.
#
# Example:
# environment = prod
#
# Default value:
# environment = <default>

#---------------------------------------------------------------------------
# In which host is the application deployed?
# An arbitrary string, useful when analysing the collected data.
#
# Example:
# host = prod-1
#
# Since: 1.0.0
#
# Default value: The value returned from java.net.InetAddress.getLocalHost().getHostName().
#
# hostname =

#===========================================================================
# Tuning parameters
#
# These parameters are optional, but you may want to specify them to tune codekvast-agent's behaviour.
#===========================================================================

#---------------------------------------------------------------------------
# What packages shall be *not* be tracked?
# A comma-separated list of strings.
#
# Example:
# excludePackages = com.acme.timecritical, foo.bar.even.more.time.critical (3)
#
# Default value: An empty list.
# excludePackages =

#---------------------------------------------------------------------------
# Which methods should be tracked?
# Can be used for tuning how much of your code base that should be instrumented.
#
# One of the keywords public, protected, package-private or private. (4)
#
# Default value:
# methodVisibility = protected

#===========================================================================
# Trouble shooting parameters
#
# These parameters are optional, but you may want to use them for trouble shooting.
#===========================================================================

#---------------------------------------------------------------------------
# Should codekvast-agent be enabled?
# If codekvast-agent is disabled, the AspectJ Weaver is not engaged and no attempt to contact the Codekvast server is made.
#
# Example:
# enabled = true
#
# Since: 1.0.0
#
# Default value:
# enabled = true

#---------------------------------------------------------------------------
# aspectjOptions
# Should Codekvast Agent configure logging for AspectJ Weaver?
# A string.
#
# Example:
# aspectjOptions = -verbose -showWeaveInfo (5)
#
# Default value:
# aspectjOptions =

#---------------------------------------------------------------------------
# bridgeAspectjMessagesToJUL
# Should AspectJ Weaver be configured to send AspectJ messages to `java.util.logging` (JUL)? (5) (6) (7)
# true or false.
#
# Default value:
# bridgeAspectjMessagesToJUL = false

About specifying appVersion

Codekvast has some strategies for automatically finding the deployed application’s version.

This means that you can deploy new versions of your application without updating the appVersion field in codekvast.conf. Instead, Codekvast will use the configured strategy for extracting the application’s version.

manifest

Locates a certain jar file within the code base with a well-known name and extracts the version from the jar file’s META-INF/MANIFEST.MF

Examples:

  1. appVersion = manifest myapp.jar

  2. appVersion = manifest myapp.jar Implementation-Version

  3. appVersion = manifest myapp.jar My-Custom-Version-Attribute

Example 1 and 2 yields the same result, since the default is to look for the standard manifest attribute Implementation-Version.

filename

Locates a jar file within the code base with a name that matches a regular expression and extracts the version from the part within parenthesis in the found file name.

Example:

appVersion = filename myapp-(.*).jar

yields 1.2-4711 provided that there is a file named myapp-1.2-4711.jar in the code base.

If more than one file matches the regular expression, the first found wins.
property

Locates a text file within the code base with a specific name and extracts the version from within the file. If more than one parameter is specified, then the values are separated with a dash ('-').

Example:

appVersion = property version.txt version buildNumber

yields 1.2-4711 given the following version.txt:

version = 1.2
buildNumber = 4711
The file is loaded into a java.util.Properties object.
literal

The value in the configuration file is used as-is.

Example:

appVersion = literal 3.14

yields 3.14

All other values are treated as literal. This means that literal 3.14 and 3.14 yields the same result.

About specifying codeBase

The parameter codeBase should be set to a comma-separated list of directories that contains the application’s jar files.

If the app is packaged as an executable jar, codeBase should be set to either a directory containing only the executable jar file or to the executable jar file itself.

If running from within a Gradle workspace, specify codeBase as build/libs/.

If running from within a Maven workspace, specify codeBase as target/.

If the app is packaged as a web archive (war), specify codeBase as path/to/WEB-INF

About excluding packages

Codekvast Agent is extremely efficient, and each tracked method only incurs a runtime cost of approximately 15 nanoseconds. If you have code that execute in tight loops even this low overhead could be too much.

In such situations you can exclude code from Codekvast. You do that by specifying excludePackages as a comma-separated list of package name prefixes.

About specifying methodVisibility

There is a certain overhead associated with tracking method calls, both in terms of CPU cycles and memory consumption. By specifying which methods shall be tracked, you can control the overhead.

Modern IDEs like IntelliJ are capable of suggesting deletion of dead methods as long as the method visibility is package private or private. They cannot suggest deletion of public or protected method is dead, since they cannot know what other clients to the method that exist.

methodVisibility values
public

Track public methods only. This one has the lowest overhead, since the fewest methods are tracked.

protected

Tracks public and protected methods. This is the default.

package-private

Tracks public, protected and package-private (default) methods. Synonym: !private

private

Tracks all methods. This one has the highest overhead. Synonym: all.

About AspectJ options

codekvast-agent can optionally set options for the AspectJ Weaver, to facilitate debugging and reweaving.

The value of aspectjOptions is a space-separated list of AspectJ Weaver options.

See AspectJ Load-Time Weaver configuration for valid values. Search for "Weaver Options".

The -XmessageHandlerClass option is handled separately, and should not be specified in aspectjOptions.

About Bridging AspectJ messages

codekvast-agent can optionally install an AspectJ IMessageHandler that acts as a bridge between AspectJ Weaver and java.util.logging (JUL).

This bridge is by default disabled, which means that AspectJ will log on standard output (if logging at all, depending on aspectjOptions).

See also AspectJ Load-Time Weaver configuration. Search for "-XmessageHandlerClass".

How codekvast-agent logs

codekvast-agent uses standard java.util.logging (JUL) for logging it’s activities.

It uses the logger name io.codekvast.

AspectJ Weaver logs by default on stdout and stderr if configured to be verbose, and no logging bridge is installed.

About locating codekvast.conf

This is how codekvast-agent locates codekvast.conf:

  1. If the Java system property codekvast.configuration is defined and points to a file, use it.

  2. If the environment variable CODEKVAST_CONF is defined and points to a file, use it.

  3. If the file ./codekvast.conf exists, use it.

  4. If the file ./conf/codekvast.conf exists, use it.

  5. If the system property catalina.home is defined and the file ${catalina.home}/conf/codekvast.conf exists, use it.

  6. If the environment variable CATALINA_HOME exists and ${CATALINA_HOME}/conf/codekvast.conf exists, use it.

  7. If the system property catalina.base is defined and the file ${catalina.base}/conf/codekvast.conf exists, use it.

  8. If the environment variable CATALINA_BASE exists and ${CATALINA_BASE}/conf/codekvast.conf exists, use it

  9. If the environment variable HOME exists and ${HOME}/.config/codekvast.conf exists, use it.

  10. If /etc/codekvast/codekvast.conf exists, use it,

  11. If /etc/codekvast.conf exists, use it.

If no codekvast.conf can be found, codekvast-agent will not start.

Running Codekvast as a Heroku add-on

You attach Codekvast to you Heroku app by doing heroku addons:create codekvast.

This will prepare the Codekvast server for your application and set a couple of Heroku environment parameters that should be used in codekvast.conf:

codekvast.conf
serverUrl = $CODEKVAST_URL
licenseKey = $CODEKVAST_LICENSE_KEY

heroku addons:create codekvast does not download the codekvast-agent-1.0.0.jar, that must be done manually.

See also a copy of the he Heroku document Running as a Heroku add-on.


Updated 21 May 2018