Skip to content

Commit 1b70c22

Browse files
committed
Merge pull request #187 from svrc-pivotal/dynatrace_support_may14
Dynatrace 6.x+ framework support for Java buildpack This merge adds support for the Dyna Trace application performance monitoring framework. See http://www.dynatrace.com/ . Tests and documentation are included and should be read for full details on how to use this support. Thanks to Stu Charlton (svrc-pivotal) for contributing it.
2 parents b64a5e9 + d7ca8cf commit 1b70c22

9 files changed

Lines changed: 305 additions & 0 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ To learn how to configure various properties of the buildpack, follow the "Confi
5454
* Standard Frameworks
5555
* [AppDynamics Agent](docs/framework-app_dynamics_agent.md) ([Configuration](docs/framework-app_dynamics_agent.md#configuration))
5656
* [Introscope Agent](docs/framework-introscope_agent.md) ([Configuration](docs/framework-introscope_agent.md#configuration))
57+
* [DynaTrace Agent](docs/framework-dyna_trace_agent.md) ([Configuration](docs/framework-dyna_trace_agent.md#configuration))
5758
* [Java Options](docs/framework-java_opts.md) ([Configuration](docs/framework-java_opts.md#configuration))
5859
* [JRebel Agent](docs/framework-jrebel_agent.md) ([Configuration](docs/framework-jrebel_agent.md#configuration))
5960
* [MariaDB JDBC](docs/framework-maria_db_jdbc.md) ([Configuration](docs/framework-maria_db_jdbc.md#configuration))

config/components.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ jres:
3434
frameworks:
3535
- "JavaBuildpack::Framework::AppDynamicsAgent"
3636
# - "JavaBuildpack::Framework::IntroscopeAgent"
37+
# - "JavaBuildpack::Framework::DynaTraceAgent"
3738
- "JavaBuildpack::Framework::JavaOpts"
3839
- "JavaBuildpack::Framework::JrebelAgent"
3940
- "JavaBuildpack::Framework::MariaDbJDBC"

config/dyna_trace_agent.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Cloud Foundry Java Buildpack
2+
# Copyright (c) 2015 the original author or authors.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
# Configuration for the Dynatrace framework
17+
---
18+
version: 6.1.0_+
19+
repository_root: ""

docs/framework-dyna_trace_agent.md

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# DynaTrace Agent Framework
2+
The DynaTrace Agent Framework causes an application to be automatically configured to work with a bound [DynaTrace Service][] instance (Free trials available).
3+
4+
The Cloud Foundry pushed application name is used as the `agent group` in DynaTrace, and must be pre-configured on the DynaTrace server.
5+
A system profile may be provided as an optional argument (defaults to `Monitoring`).
6+
7+
**Current Issues:**
8+
* The DynaTrace agent slows down app execution significantly at first, but gets faster over time. You may want to update your CF deployment manifest to set `maximum_health_check_timeout` to 180 or more and/or execute `cf push -t 180` or more when pushing a DynaTrace-monitored application.
9+
10+
* As you `cf push` multiple times, many dead penguins will litter the DynaTrace agent dashboard, as CF launches/disposes application containers. These can be hidden but will collect in the dynatrace database.
11+
12+
<table>
13+
<tr>
14+
<td><strong>Detection Criterion</strong></td><td>Existence of a single bound DynaTrace service.
15+
<ul>
16+
<li>Existence of a DynaTrace service is defined as the <a href="http://docs.cloudfoundry.org/devguide/deploy-apps/environment-variable.html#VCAP-SERVICES"><code>VCAP_SERVICES</code></a> payload containing a service who's name, label or tag has <code>dynatrace</code> as a substring.</li>
17+
</ul>
18+
</td>
19+
</tr>
20+
<tr>
21+
<td><strong>Tags</strong></td>
22+
<td><tt>dyna-trace-agent=&lt;version&gt;</tt></td>
23+
</tr>
24+
</table>
25+
Tags are printed to standard output by the buildpack detect script
26+
27+
## User-Provided Service
28+
Users must provide their own DynaTrace service. A user-provided DynaTrace service must have a name or tag with `dynatrace` in it so that the DynaTrace Agent Framework will automatically configure the application to work with the service.
29+
30+
The credential payload of the service may contain the following entries:
31+
32+
| Name | Description
33+
| ---- | -----------
34+
| `server` | The DynaTrace collector hostname to connect to. Use `host:port` format for a specific port number.
35+
| `profile` | (optional) The DynaTrace server profile this is associated with. Uses `Monitoring` by default.
36+
37+
**NOTE** Be sure to open an Application Security Group to your DynaTrace collector prior to starting your application:
38+
```
39+
$ cat security.json
40+
[
41+
{
42+
"protocol": "tcp",
43+
"destination": "dynatrace_host",
44+
"ports": "9998"
45+
}
46+
]
47+
48+
$ cf create-security-group dynatrace_group ./security.json
49+
Creating security group dynatrace_group as admin
50+
OK
51+
52+
$ cf bind-running-security-group dynatrace_group
53+
Binding security group dynatrace_group to defaults for running as admin
54+
OK
55+
56+
TIP: Changes will not apply to existing running applications until they are restarted.
57+
```
58+
59+
## Configuration
60+
For general information on configuring the buildpack, refer to [Configuration and Extension][].
61+
62+
The framework can be configured by modifying the [`dyna_trace_agent.yml`][] file in the buildpack fork. The framework uses the [`Repository` utility support][repositories] and so it supports the [version syntax][] defined there.
63+
64+
| Name | Description
65+
| ---- | -----------
66+
| `repository_root` | The URL of the DynaTrace repository index ([details][repositories]).
67+
| `version` | The version of DynaTrace to use. This buildpack framework has been tested on 6.1.0.
68+
69+
70+
**NOTE:** This framework does not connect to a pre-populated repository. Instead you will need to create your own repository by:
71+
72+
1. Downloading the DynaTrace agent unix binary (in JAR format) to an HTTP-accesible location
73+
1. Uploading an `index.yml` file with a mapping from the version of the agent to its location to the same HTTP-accessible location
74+
1. Configuring the [`dyna_trace_agent.yml`][] file to point to the root of the repository holding both the index and agent binary
75+
76+
Sample **`repository_root`** for [`dyna_trace_agent.yml`][] (under java-buildpack/config) assuming a bosh-lite setup and a local webserver (e.g. `brew install tomcat7`) on port 8080
77+
78+
```
79+
repository_root: "http://files.192.168.50.1.xip.io:8080/fileserver/dynatrace"
80+
```
81+
82+
The buildpack would look for an **`index.yml`** file at the specified **repository_root** for obtaining the DynaTrace agent.
83+
84+
The index.yml at the repository_root location should have a entry matching the DynaTrace version and the corresponding DynaTrace agent download JAR
85+
86+
```
87+
---
88+
6.1.0.7880: http://files.192.168.50.1.xip.io:8080/fileserver/dynatrace/dynatrace-agent-6.1.0.7880-unix.jar
89+
```
90+
91+
Ensure the DynaTrace binary is available at the location indicated by the index.yml referred by the DynaTrace repository_root.
92+
93+
[Configuration and Extension]: ../README.md#configuration-and-extension
94+
[`dyna_trace_agent.yml`]: ../config/dyna_trace_agent.yml
95+
[DynaTrace Service]: https://dynatrace.com
96+
[repositories]: extending-repositories.md
97+
[version syntax]: extending-repositories.md#version-syntax-and-ordering

lib/java_buildpack/component/java_opts.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,16 @@ def add_javaagent(path)
4242
add_preformatted_options "-javaagent:#{qualify_path path}"
4343
end
4444

45+
# Adds a +agentpath+ entry to the +JAVA_OPTS+. Prepends +$PWD+ to the path (relative to the droplet root) to
46+
# ensure that the path is always accurate.
47+
#
48+
# @param [Pathname] path the path to the +agentpath+ shared library
49+
# @param [Properties] properties to append to the agentpath entry
50+
# @return [JavaOpts] +self+ for chaining
51+
def add_agentpath_with_props(path, props)
52+
add_preformatted_options "-agentpath:#{qualify_path path}=" + props.map { |k, v| "#{k}=#{v}" }.join(',')
53+
end
54+
4555
# Adds an +agentpath+ entry to the +JAVA_OPTS+. Prepends +$PWD+ to the path (relative to the droplet root) to
4656
# ensure that the path is always accurate.
4757
#
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# Encoding: utf-8
2+
# Cloud Foundry Java Buildpack
3+
# Copyright 2015 the original author or authors.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
require 'fileutils'
18+
require 'java_buildpack/component/versioned_dependency_component'
19+
require 'java_buildpack/framework'
20+
require 'java_buildpack/util/qualify_path'
21+
22+
module JavaBuildpack
23+
module Framework
24+
25+
# Encapsulates the functionality for enabling zero-touch Dynatrace support.
26+
class DynaTraceAgent < JavaBuildpack::Component::VersionedDependencyComponent
27+
include JavaBuildpack::Util
28+
29+
# (see JavaBuildpack::Component::BaseComponent#compile)
30+
def compile
31+
download_zip false
32+
@droplet.copy_resources
33+
FileUtils.mkdir(home_dir)
34+
FileUtils.mv(@droplet.sandbox + 'agent/linux-x86-64/agent', home_dir)
35+
delete_extra_files
36+
end
37+
38+
# (see JavaBuildpack::Component::BaseComponent#release)
39+
def release
40+
@droplet.java_opts
41+
.add_agentpath_with_props(agent_dir + 'libdtagent.so',
42+
name: application_name + '_' + profile_name,
43+
server: server)
44+
end
45+
46+
protected
47+
48+
# (see JavaBuildpack::Component::VersionedDependencyComponent#supports?)
49+
def supports?
50+
@application.services.one_service? FILTER, 'server'
51+
end
52+
53+
private
54+
55+
FILTER = /dynatrace/.freeze
56+
57+
private_constant :FILTER
58+
59+
def application_name
60+
@application.details['application_name']
61+
end
62+
63+
def profile_name
64+
@application.services.find_service(FILTER)['credentials']['profile'] || 'Monitoring'
65+
end
66+
67+
def agent_dir
68+
@droplet.sandbox + 'home/agent/lib64'
69+
end
70+
71+
def delete_extra_files
72+
FileUtils.rm_rf(@droplet.sandbox + 'agent')
73+
FileUtils.rm_rf(@droplet.sandbox + 'init.d')
74+
FileUtils.rm_rf(@droplet.sandbox + 'com')
75+
FileUtils.rm_rf(@droplet.sandbox + 'org')
76+
FileUtils.rm_rf(@droplet.sandbox + 'META_INF')
77+
FileUtils.rm_f(@droplet.sandbox + 'YouShouldNotHaveUnzippedMe.txt')
78+
end
79+
80+
def logs_dir
81+
@droplet.sandbox + 'home/log'
82+
end
83+
84+
def home_dir
85+
@droplet.sandbox + 'home'
86+
end
87+
88+
def server
89+
@application.services.find_service(FILTER)['credentials']['server']
90+
end
91+
92+
end
93+
94+
end
95+
end
1.26 KB
Binary file not shown.

spec/java_buildpack/component/java_opts_spec.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,18 @@
2929
expect(opts).to include('-javaagent:$PWD/.java-buildpack/java_opts/test-java-agent')
3030
end
3131

32+
it 'adds a qualified agentpath to the collection' do
33+
opts.add_agentpath droplet.sandbox + 'test-agentpath'
34+
35+
expect(opts).to include('-agentpath:$PWD/.java-buildpack/java_opts/test-agentpath')
36+
end
37+
38+
it 'adds a qualified agentpath with properties to the collection' do
39+
opts.add_agentpath_with_props(droplet.sandbox + 'test-agentpath', 'key1' => 'value1', 'key2' => 'value2')
40+
41+
expect(opts).to include('-agentpath:$PWD/.java-buildpack/java_opts/test-agentpath=key1=value1,key2=value2')
42+
end
43+
3244
it 'adds a qualified system property to the collection' do
3345
opts.add_system_property 'test-key', droplet.sandbox
3446

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Encoding: utf-8
2+
# Cloud Foundry Java Buildpack
3+
# Copyright 2015 the original author or authors.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
require 'spec_helper'
18+
require 'component_helper'
19+
require 'java_buildpack/framework/dyna_trace_agent'
20+
21+
describe JavaBuildpack::Framework::DynaTraceAgent do
22+
include_context 'component_helper'
23+
24+
it 'does not detect without dynatrace-n/a service' do
25+
expect(component.detect).to be_nil
26+
end
27+
28+
context do
29+
30+
before do
31+
allow(services).to receive(:one_service?).with(/dynatrace/, 'server').and_return(true)
32+
allow(services).to receive(:find_service).and_return('credentials' => { 'server' => 'test-host-name' })
33+
end
34+
35+
it 'detects with dynatrace-n/a service' do
36+
expect(component.detect).to eq("dyna-trace-agent=#{version}")
37+
end
38+
39+
it 'expands DynaTrace agent zip',
40+
cache_fixture: 'stub-dyna-trace-agent.jar' do
41+
42+
component.compile
43+
expect(sandbox + 'home/agent/lib64/libdtagent.so').to exist
44+
expect(sandbox + 'YouShouldNotHaveUnzippedMe.txt').not_to exist
45+
end
46+
47+
it 'updates JAVA_OPTS' do
48+
component.release
49+
expect(java_opts).to include(
50+
'-agentpath:$PWD/.java-buildpack/dyna_trace_agent/home/agent/lib64/'\
51+
'libdtagent.so=name=test-application-name_Monitoring,server=test-host-name')
52+
end
53+
end
54+
55+
context do
56+
before do
57+
allow(services).to receive(:one_service?).with(/dynatrace/, 'server').and_return(true)
58+
allow(services).to receive(:find_service).and_return('credentials' => { 'server' => 'test-host-name',
59+
'profile' => 'test-profile' })
60+
end
61+
62+
it 'updates JAVA_OPTS with custom profile' do
63+
component.release
64+
expect(java_opts).to include(
65+
'-agentpath:$PWD/.java-buildpack/dyna_trace_agent/home/agent/lib64/'\
66+
'libdtagent.so=name=test-application-name_test-profile,server=test-host-name')
67+
end
68+
69+
end
70+
end

0 commit comments

Comments
 (0)