Skip to content

Commit 703b5ca

Browse files
committed
Metric Writer Framework
This change adds a framework for writing Spring Boot metrics into a Metric Forwarder service. [resolves cloudfoundry#440]
1 parent 28c1833 commit 703b5ca

10 files changed

Lines changed: 206 additions & 4 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ To learn how to configure various properties of the buildpack, follow the "Confi
8585
* [JMX](docs/framework-jmx.md) ([Configuration](docs/framework-jmx.md#configuration))
8686
* [Luna Security Provider](docs/framework-luna_security_provider.md) ([Configuration](docs/framework-luna_security_provider.md#configuration))
8787
* [MariaDB JDBC](docs/framework-maria_db_jdbc.md) ([Configuration](docs/framework-maria_db_jdbc.md#configuration))
88+
* [Metric Writer](docs/framework-metric_writer.md) ([Configuration](docs/framework-metric_writer.md#configuration))
8889
* [New Relic Agent](docs/framework-new_relic_agent.md) ([Configuration](docs/framework-new_relic_agent.md#configuration))
8990
* [Play Framework Auto Reconfiguration](docs/framework-play_framework_auto_reconfiguration.md) ([Configuration](docs/framework-play_framework_auto_reconfiguration.md#configuration))
9091
* [Play Framework JPA Plugin](docs/framework-play_framework_jpa_plugin.md) ([Configuration](docs/framework-play_framework_jpa_plugin.md#configuration))

config/components.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,16 @@ frameworks:
4141
- "JavaBuildpack::Framework::ContainerCustomizer"
4242
- "JavaBuildpack::Framework::ContainerSecurityProvider"
4343
- "JavaBuildpack::Framework::Debug"
44+
- "JavaBuildpack::Framework::DyadicEkmSecurityProvider"
4445
- "JavaBuildpack::Framework::DynatraceAppmonAgent"
4546
- "JavaBuildpack::Framework::DynatraceOneAgent"
4647
- "JavaBuildpack::Framework::GoogleStackdriverDebugger"
4748
# - "JavaBuildpack::Framework::IntroscopeAgent"
4849
- "JavaBuildpack::Framework::Jmx"
4950
- "JavaBuildpack::Framework::JrebelAgent"
5051
- "JavaBuildpack::Framework::LunaSecurityProvider"
51-
- "JavaBuildpack::Framework::DyadicEkmSecurityProvider"
5252
- "JavaBuildpack::Framework::MariaDbJDBC"
53+
- "JavaBuildpack::Framework::MetricWriter"
5354
- "JavaBuildpack::Framework::NewRelicAgent"
5455
- "JavaBuildpack::Framework::PlayFrameworkAutoReconfiguration"
5556
- "JavaBuildpack::Framework::PlayFrameworkJPAPlugin"

config/metric_writer.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 2013-2017 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+
# Metric Writer configuration
17+
---
18+
version: 1.+
19+
repository_root: "{default.repository.root}/metric-writer"

docs/framework-metric_writer.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Metric Writer Framework
2+
The Metric Writer Framework causes an application to be automatically configured to work with a bound Metrics Forwarder Service.
3+
4+
<table>
5+
<tr>
6+
<td><strong>Detection Criterion</strong></td><td>Existence of a single bound Metrics Forwarder service.
7+
<ul>
8+
<li>Existence of a Metrics Forwarder 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>metrics-forwarder</code> as a substring.</li>
9+
</ul>
10+
</td>
11+
</tr>
12+
<tr>
13+
<td><strong>Tags</strong></td>
14+
<td><tt>metric_writer=&lt;version&gt;</tt></td>
15+
</tr>
16+
</table>
17+
Tags are printed to standard output by the buildpack detect script
18+
19+
The credential payload of the service may contain the following entries:
20+
21+
| Name | Description
22+
| ---- | -----------
23+
| `access_key` | The access key used to authenticate agains the endpoint
24+
| `hostname` | The hostname of the endpoint
25+
26+
## Configuration
27+
For general information on configuring the buildpack, including how to specify configuration values through environment variables, refer to [Configuration and Extension][].
28+
29+
The framework can be configured by modifying the [`config/metric_writer.yml`][] file in the buildpack fork. The framework uses the [`Repository` utility support][repositories] and so it supports the [version syntax][] defined there.
30+
31+
| Name | Description
32+
| ---- | -----------
33+
| `repository_root` | The URL of the Metric Writer repository index ([details][repositories]).
34+
| `version` | The version of Metric Writer to use. Candidate versions can be found in [this listing][].
35+
36+
[Configuration and Extension]: ../README.md#configuration-and-extension
37+
[`config/metric_writer.yml`]: ../config/metric_writer.yml
38+
[repositories]: extending-repositories.md
39+
[this listing]: https://java-buildpack.cloudfoundry.org/metric-writer/index.yml
40+
[version syntax]: extending-repositories.md#version-syntax-and-ordering

lib/java_buildpack/framework/container_security_provider.rb

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,12 @@
1515

1616
require 'java_buildpack/component/versioned_dependency_component'
1717
require 'java_buildpack/framework'
18-
require 'java_buildpack/util/qualify_path'
1918

2019
module JavaBuildpack
2120
module Framework
2221

2322
# Encapsulates the functionality for contributing a container-based security provider to an application.
2423
class ContainerSecurityProvider < JavaBuildpack::Component::VersionedDependencyComponent
25-
include JavaBuildpack::Util
2624

2725
# (see JavaBuildpack::Component::BaseComponent#compile)
2826
def compile
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Cloud Foundry Java Buildpack
2+
# Copyright 2013-2017 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+
require 'java_buildpack/component/versioned_dependency_component'
17+
require 'java_buildpack/framework'
18+
19+
module JavaBuildpack
20+
module Framework
21+
22+
# Encapsulates the functionality for contributing a container-based security provider to an application.
23+
class MetricWriter < JavaBuildpack::Component::VersionedDependencyComponent
24+
25+
# (see JavaBuildpack::Component::BaseComponent#compile)
26+
def compile
27+
download_jar
28+
@droplet.additional_libraries << (@droplet.sandbox + jar_name)
29+
end
30+
31+
# (see JavaBuildpack::Component::BaseComponent#release)
32+
def release
33+
credentials = @application.services.find_service(FILTER)['credentials']
34+
35+
@droplet.additional_libraries << (@droplet.sandbox + jar_name)
36+
@droplet.java_opts
37+
.add_system_property('cloudfoundry.metrics.accessToken', credentials[ACCESS_KEY])
38+
.add_system_property('cloudfoundry.metrics.applicationId', @application.details['application_id'])
39+
.add_system_property('cloudfoundry.metrics.endpoint', "https://#{credentials[HOSTNAME]}")
40+
.add_system_property('cloudfoundry.metrics.instanceId', '$CF_INSTANCE_GUID')
41+
.add_system_property('cloudfoundry.metrics.instanceIndex', '$CF_INSTANCE_INDEX')
42+
end
43+
44+
protected
45+
46+
# (see JavaBuildpack::Component::VersionedDependencyComponent#supports?)
47+
def supports?
48+
@application.services.one_service? FILTER, ACCESS_KEY, HOSTNAME
49+
end
50+
51+
ACCESS_KEY = 'access_key'.freeze
52+
53+
FILTER = /metrics-forwarder/
54+
55+
HOSTNAME = 'hostname'.freeze
56+
57+
private_constant :ACCESS_KEY, :FILTER, :HOSTNAME
58+
59+
end
60+
61+
end
62+
end

rakelib/versions_task.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ def initialize
6464
'luna_security_provider' => 'Gemalto Luna Security Provider',
6565
'maria_db_jdbc' => 'MariaDB JDBC Driver',
6666
'memory_calculator' => 'Memory Calculator',
67+
'metric_writer' => 'Metric Writer',
6768
'new_relic_agent' => 'New Relic Agent',
6869
'play_framework_auto_reconfiguration' => 'Play Framework Auto-reconfiguration',
6970
'play_framework_jpa_plugin' => 'Play Framework JPA Plugin',

spec/application_helper.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@
4646
let(:services) { application.services }
4747

4848
let(:vcap_application) do
49-
{ 'application_name' => 'test-application-name',
49+
{ 'application_id' => 'test-application-id',
50+
'application_name' => 'test-application-name',
5051
'application_version' => 'test-application-version' }
5152
end
5253

spec/fixtures/stub-metric-writer.jar

Whitespace-only changes.
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# Cloud Foundry Java Buildpack
2+
# Copyright 2013-2017 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+
require 'spec_helper'
17+
require 'component_helper'
18+
require 'java_buildpack/framework/metric_writer'
19+
20+
describe JavaBuildpack::Framework::MetricWriter do
21+
include_context 'component_helper'
22+
23+
it 'does not detect without metric-forwarder service' do
24+
expect(component.detect).to be_nil
25+
end
26+
27+
context do
28+
29+
before do
30+
allow(services).to receive(:one_service?).with(/metrics-forwarder/, 'access_key', 'hostname').and_return(true)
31+
end
32+
33+
it 'detects with metric-forwarder service' do
34+
expect(component.detect).to eq("metric-writer=#{version}")
35+
end
36+
37+
it 'downloads Metric Writer JAR',
38+
cache_fixture: 'stub-metric-writer.jar' do
39+
40+
component.compile
41+
42+
expect(sandbox + "metric_writer-#{version}.jar").to exist
43+
end
44+
45+
it 'adds the metric writer to the additional libraries in compile when needed',
46+
cache_fixture: 'stub-metric-writer.jar' do
47+
48+
component.compile
49+
50+
expect(additional_libraries).to include(sandbox + "metric_writer-#{version}.jar")
51+
end
52+
53+
it 'adds the metric writer to the additional libraries in release when needed',
54+
cache_fixture: 'stub-metric-writer.jar' do
55+
56+
allow(services).to receive(:find_service).and_return('credentials' => { 'access_key' => 'test-access-key',
57+
'hostname' => 'test-hostname' })
58+
59+
component.release
60+
61+
expect(additional_libraries).to include(sandbox + "metric_writer-#{version}.jar")
62+
end
63+
64+
it 'updates JAVA_OPTS' do
65+
allow(services).to receive(:find_service).and_return('credentials' => { 'access_key' => 'test-access-key',
66+
'hostname' => 'test-hostname' })
67+
68+
component.release
69+
70+
expect(java_opts).to include('-Dcloudfoundry.metrics.accessToken=test-access-key')
71+
expect(java_opts).to include('-Dcloudfoundry.metrics.applicationId=test-application-id')
72+
expect(java_opts).to include('-Dcloudfoundry.metrics.endpoint=https://test-hostname')
73+
expect(java_opts).to include('-Dcloudfoundry.metrics.instanceId=$CF_INSTANCE_GUID')
74+
expect(java_opts).to include('-Dcloudfoundry.metrics.instanceIndex=$CF_INSTANCE_INDEX')
75+
end
76+
77+
end
78+
79+
end

0 commit comments

Comments
 (0)