Skip to content

Commit 54dfe8d

Browse files
author
Christopher Frost
committed
Support configurable Tomcat Access Logging
Currently, in order to enable access logging the buildpack must be forked and a custom access valve added to the Tomcat configuration in the resources folder. A customised Access Valve is required as the one provided with Tomcat does not support logging to stdout which is required for Loggregator. This change allows Access logging to be enabled with a simple configuration change to the Tomcat container configuration in the 'config' folder. The default pattern for the logging output is specified in the server.xml file located in the 'resources/tomcat' folder. The default pattern begins with '[ACCESS]' and includes the 'X-Vcap-Request_Id' request header but otherwise follows the default for Apache access logs. [#72881930]
1 parent 664da99 commit 54dfe8d

File tree

10 files changed

+167
-50
lines changed

10 files changed

+167
-50
lines changed

config/tomcat.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ lifecycle_support:
2424
logging_support:
2525
version: 2.+
2626
repository_root: "{default.repository.root}/tomcat-logging-support"
27+
access_logging_support:
28+
version: 2.+
29+
repository_root: "{default.repository.root}/tomcat-access-logging-support"
30+
access_logging: disabled
2731
redis_store:
2832
version: 1.+
2933
repository_root: "{default.repository.root}/redis-store"

docs/container-tomcat.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ The container can be configured by modifying the [`config/tomcat.yml`][] file in
2525
| `lifecycle_support.version` | The version of Tomcat Lifecycle Support to use. Candidate versions can be found in [this listing](http://download.pivotal.io.s3.amazonaws.com/tomcat-lifecycle-support/index.yml).
2626
| `logging_support.repository_root` | The URL of the Tomcat Logging Support repository index ([details][repositories]).
2727
| `logging_support.version` | The version of Tomcat Logging Support to use. Candidate versions can be found in [this listing](http://download.pivotal.io.s3.amazonaws.com/tomcat-logging-support/index.yml).
28+
| `access_logging_support.repository_root` | The URL of the Tomcat Access Logging Support repository index ([details][repositories]).
29+
| `access_logging_support.version` | The version of Tomcat Access Logging Support to use. Candidate versions can be found in [this listing](http://download.pivotal.io.s3.amazonaws.com/tomcat-access-logging-support/index.yml).
30+
| `access_logging` | Set to 'enabled' to turn on the access logging support. Default is 'disabled'.
2831
| `redis_store.connection_pool_size` | The Redis connection pool size. Note that this is per-instance, not per-application.
2932
| `redis_store.database` | The Redis database to connect to.
3033
| `redis_store.repository_root` | The URL of the Redis Store repository index ([details][repositories]).

java-buildpack.iml

Lines changed: 36 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<module type="RUBY_MODULE" version="4">
3+
<component name="CompassSettings">
4+
<option name="compassSupportEnabled" value="true" />
5+
</component>
36
<component name="ModuleRunConfigurationManager">
47
<configuration default="false" name="All Tests" type="RSpecRunConfigurationType" factoryName="RSpec" singleton="true">
58
<predefined_log_file id="RUBY_RSPEC" enabled="true" />
@@ -266,40 +269,40 @@
266269
<excludeFolder url="file://$MODULE_DIR$/coverage" />
267270
<excludeFolder url="file://$MODULE_DIR$/doc" />
268271
</content>
269-
<orderEntry type="jdk" jdkName="rbenv: 1.9.3-p545" jdkType="RUBY_SDK" />
272+
<orderEntry type="jdk" jdkName="rbenv: 1.9.3-p547" jdkType="RUBY_SDK" />
270273
<orderEntry type="sourceFolder" forTests="false" />
271-
<orderEntry type="library" scope="PROVIDED" name="addressable (v2.3.6, rbenv: 1.9.3-p545) [gem]" level="application" />
272-
<orderEntry type="library" scope="PROVIDED" name="ast (v2.0.0, rbenv: 1.9.3-p545) [gem]" level="application" />
273-
<orderEntry type="library" scope="PROVIDED" name="bundler (v1.6.1, rbenv: 1.9.3-p545) [gem]" level="application" />
274-
<orderEntry type="library" scope="PROVIDED" name="codeclimate-test-reporter (v0.3.0, rbenv: 1.9.3-p545) [gem]" level="application" />
275-
<orderEntry type="library" scope="PROVIDED" name="crack (v0.4.2, rbenv: 1.9.3-p545) [gem]" level="application" />
276-
<orderEntry type="library" scope="PROVIDED" name="debugger-ruby_core_source (v1.3.5, rbenv: 1.9.3-p545) [gem]" level="application" />
277-
<orderEntry type="library" scope="PROVIDED" name="diff-lcs (v1.2.5, rbenv: 1.9.3-p545) [gem]" level="application" />
278-
<orderEntry type="library" scope="PROVIDED" name="docile (v1.1.4, rbenv: 1.9.3-p545) [gem]" level="application" />
279-
<orderEntry type="library" scope="PROVIDED" name="json (v1.8.1, rbenv: 1.9.3-p545) [gem]" level="application" />
280-
<orderEntry type="library" scope="PROVIDED" name="multi_json (v1.10.1, rbenv: 1.9.3-p545) [gem]" level="application" />
281-
<orderEntry type="library" scope="PROVIDED" name="parser (v2.1.9, rbenv: 1.9.3-p545) [gem]" level="application" />
282-
<orderEntry type="library" scope="PROVIDED" name="powerpack (v0.0.9, rbenv: 1.9.3-p545) [gem]" level="application" />
283-
<orderEntry type="library" scope="PROVIDED" name="rainbow (v2.0.0, rbenv: 1.9.3-p545) [gem]" level="application" />
284-
<orderEntry type="library" scope="PROVIDED" name="rake (v10.3.2, rbenv: 1.9.3-p545) [gem]" level="application" />
285-
<orderEntry type="library" scope="PROVIDED" name="redcarpet (v3.1.2, rbenv: 1.9.3-p545) [gem]" level="application" />
286-
<orderEntry type="library" scope="PROVIDED" name="rspec (v3.0.0, rbenv: 1.9.3-p545) [gem]" level="application" />
287-
<orderEntry type="library" scope="PROVIDED" name="rspec-core (v3.0.1, rbenv: 1.9.3-p545) [gem]" level="application" />
288-
<orderEntry type="library" scope="PROVIDED" name="rspec-expectations (v3.0.1, rbenv: 1.9.3-p545) [gem]" level="application" />
289-
<orderEntry type="library" scope="PROVIDED" name="rspec-mocks (v3.0.1, rbenv: 1.9.3-p545) [gem]" level="application" />
290-
<orderEntry type="library" scope="PROVIDED" name="rspec-support (v3.0.0, rbenv: 1.9.3-p545) [gem]" level="application" />
291-
<orderEntry type="library" scope="PROVIDED" name="rubocop (v0.23.0, rbenv: 1.9.3-p545) [gem]" level="application" />
292-
<orderEntry type="library" scope="PROVIDED" name="ruby-debug-base19x (v0.11.30.pre15, rbenv: 1.9.3-p545) [gem]" level="application" />
293-
<orderEntry type="library" scope="PROVIDED" name="ruby-debug-ide (v0.4.22, rbenv: 1.9.3-p545) [gem]" level="application" />
294-
<orderEntry type="library" scope="PROVIDED" name="ruby-progressbar (v1.5.1, rbenv: 1.9.3-p545) [gem]" level="application" />
295-
<orderEntry type="library" scope="PROVIDED" name="rubyzip (v1.1.4, rbenv: 1.9.3-p545) [gem]" level="application" />
296-
<orderEntry type="library" scope="PROVIDED" name="safe_yaml (v1.0.3, rbenv: 1.9.3-p545) [gem]" level="application" />
297-
<orderEntry type="library" scope="PROVIDED" name="simplecov (v0.8.2, rbenv: 1.9.3-p545) [gem]" level="application" />
298-
<orderEntry type="library" scope="PROVIDED" name="simplecov-html (v0.8.0, rbenv: 1.9.3-p545) [gem]" level="application" />
299-
<orderEntry type="library" scope="PROVIDED" name="slop (v3.5.0, rbenv: 1.9.3-p545) [gem]" level="application" />
300-
<orderEntry type="library" scope="PROVIDED" name="tee (v1.0.0, rbenv: 1.9.3-p545) [gem]" level="application" />
301-
<orderEntry type="library" scope="PROVIDED" name="webmock (v1.18.0, rbenv: 1.9.3-p545) [gem]" level="application" />
302-
<orderEntry type="library" scope="PROVIDED" name="yard (v0.8.7.4, rbenv: 1.9.3-p545) [gem]" level="application" />
274+
<orderEntry type="library" scope="PROVIDED" name="addressable (v2.3.6, rbenv: 1.9.3-p547) [gem]" level="application" />
275+
<orderEntry type="library" scope="PROVIDED" name="ast (v2.0.0, rbenv: 1.9.3-p547) [gem]" level="application" />
276+
<orderEntry type="library" scope="PROVIDED" name="bundler (v1.6.3, rbenv: 1.9.3-p547) [gem]" level="application" />
277+
<orderEntry type="library" scope="PROVIDED" name="codeclimate-test-reporter (v0.3.0, rbenv: 1.9.3-p547) [gem]" level="application" />
278+
<orderEntry type="library" scope="PROVIDED" name="crack (v0.4.2, rbenv: 1.9.3-p547) [gem]" level="application" />
279+
<orderEntry type="library" scope="PROVIDED" name="debugger-ruby_core_source (v1.3.5, rbenv: 1.9.3-p547) [gem]" level="application" />
280+
<orderEntry type="library" scope="PROVIDED" name="diff-lcs (v1.2.5, rbenv: 1.9.3-p547) [gem]" level="application" />
281+
<orderEntry type="library" scope="PROVIDED" name="docile (v1.1.5, rbenv: 1.9.3-p547) [gem]" level="application" />
282+
<orderEntry type="library" scope="PROVIDED" name="json (v1.8.1, rbenv: 1.9.3-p547) [gem]" level="application" />
283+
<orderEntry type="library" scope="PROVIDED" name="multi_json (v1.10.1, rbenv: 1.9.3-p547) [gem]" level="application" />
284+
<orderEntry type="library" scope="PROVIDED" name="parser (v2.2.0.pre.3, rbenv: 1.9.3-p547) [gem]" level="application" />
285+
<orderEntry type="library" scope="PROVIDED" name="powerpack (v0.0.9, rbenv: 1.9.3-p547) [gem]" level="application" />
286+
<orderEntry type="library" scope="PROVIDED" name="rainbow (v2.0.0, rbenv: 1.9.3-p547) [gem]" level="application" />
287+
<orderEntry type="library" scope="PROVIDED" name="rake (v10.3.2, rbenv: 1.9.3-p547) [gem]" level="application" />
288+
<orderEntry type="library" scope="PROVIDED" name="redcarpet (v3.1.2, rbenv: 1.9.3-p547) [gem]" level="application" />
289+
<orderEntry type="library" scope="PROVIDED" name="rspec (v3.0.0, rbenv: 1.9.3-p547) [gem]" level="application" />
290+
<orderEntry type="library" scope="PROVIDED" name="rspec-core (v3.0.2, rbenv: 1.9.3-p547) [gem]" level="application" />
291+
<orderEntry type="library" scope="PROVIDED" name="rspec-expectations (v3.0.2, rbenv: 1.9.3-p547) [gem]" level="application" />
292+
<orderEntry type="library" scope="PROVIDED" name="rspec-mocks (v3.0.2, rbenv: 1.9.3-p547) [gem]" level="application" />
293+
<orderEntry type="library" scope="PROVIDED" name="rspec-support (v3.0.2, rbenv: 1.9.3-p547) [gem]" level="application" />
294+
<orderEntry type="library" scope="PROVIDED" name="rubocop (v0.24.1, rbenv: 1.9.3-p547) [gem]" level="application" />
295+
<orderEntry type="library" scope="PROVIDED" name="ruby-debug-base19x (v0.11.30.pre15, rbenv: 1.9.3-p547) [gem]" level="application" />
296+
<orderEntry type="library" scope="PROVIDED" name="ruby-debug-ide (v0.4.22, rbenv: 1.9.3-p547) [gem]" level="application" />
297+
<orderEntry type="library" scope="PROVIDED" name="ruby-progressbar (v1.5.1, rbenv: 1.9.3-p547) [gem]" level="application" />
298+
<orderEntry type="library" scope="PROVIDED" name="rubyzip (v1.1.6, rbenv: 1.9.3-p547) [gem]" level="application" />
299+
<orderEntry type="library" scope="PROVIDED" name="safe_yaml (v1.0.3, rbenv: 1.9.3-p547) [gem]" level="application" />
300+
<orderEntry type="library" scope="PROVIDED" name="simplecov (v0.8.2, rbenv: 1.9.3-p547) [gem]" level="application" />
301+
<orderEntry type="library" scope="PROVIDED" name="simplecov-html (v0.8.0, rbenv: 1.9.3-p547) [gem]" level="application" />
302+
<orderEntry type="library" scope="PROVIDED" name="slop (v3.5.0, rbenv: 1.9.3-p547) [gem]" level="application" />
303+
<orderEntry type="library" scope="PROVIDED" name="tee (v1.0.0, rbenv: 1.9.3-p547) [gem]" level="application" />
304+
<orderEntry type="library" scope="PROVIDED" name="webmock (v1.18.0, rbenv: 1.9.3-p547) [gem]" level="application" />
305+
<orderEntry type="library" scope="PROVIDED" name="yard (v0.8.7.4, rbenv: 1.9.3-p547) [gem]" level="application" />
303306
</component>
304307
<component name="RModuleSettingsStorage">
305308
<LOAD_PATH number="4" string0="$MODULE_DIR$/lib" string1="$MODULE_DIR$/spec" string2="$MODULE_DIR$/bin" string3="$MODULE_DIR$/spec/bin" />

lib/java_buildpack/container/tomcat.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
require 'java_buildpack/container/tomcat/tomcat_instance'
2121
require 'java_buildpack/container/tomcat/tomcat_lifecycle_support'
2222
require 'java_buildpack/container/tomcat/tomcat_logging_support'
23+
require 'java_buildpack/container/tomcat/tomcat_access_logging_support'
2324
require 'java_buildpack/container/tomcat/tomcat_redis_store'
2425

2526
module JavaBuildpack
@@ -48,6 +49,7 @@ def sub_components(context)
4849
TomcatInstance.new(sub_configuration_context(context, 'tomcat')),
4950
TomcatLifecycleSupport.new(sub_configuration_context(context, 'lifecycle_support')),
5051
TomcatLoggingSupport.new(sub_configuration_context(context, 'logging_support')),
52+
TomcatAccessLoggingSupport.new(sub_configuration_context(context, 'access_logging_support')),
5153
TomcatRedisStore.new(sub_configuration_context(context, 'redis_store')),
5254
TomcatInsightSupport.new(context)
5355
]
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# Encoding: utf-8
2+
# Cloud Foundry Java Buildpack
3+
# Copyright 2013 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 'java_buildpack/component/versioned_dependency_component'
18+
require 'java_buildpack/container/tomcat/tomcat_utils'
19+
require 'java_buildpack/container'
20+
21+
module JavaBuildpack
22+
module Container
23+
24+
# Encapsulates the detect, compile, and release functionality for Tomcat logging support.
25+
class TomcatAccessLoggingSupport < JavaBuildpack::Component::VersionedDependencyComponent
26+
include JavaBuildpack::Container
27+
28+
# (see JavaBuildpack::Component::BaseComponent#compile)
29+
def compile
30+
download_jar(jar_name, tomcat_lib)
31+
end
32+
33+
# (see JavaBuildpack::Component::BaseComponent#release)
34+
def release
35+
@droplet.java_opts.add_system_property 'access.logging.enabled', @configuration[KEY_ENABLED] == 'enabled'
36+
end
37+
38+
protected
39+
40+
# (see JavaBuildpack::Component::VersionedDependencyComponent#supports?)
41+
def supports?
42+
true
43+
end
44+
45+
private
46+
47+
KEY_ENABLED = 'access_logging'.freeze
48+
49+
def jar_name
50+
"tomcat_access_logging_support-#{@version}.jar"
51+
end
52+
53+
end
54+
55+
end
56+
end

lib/java_buildpack/container/tomcat/tomcat_logging_support.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
# limitations under the License.
1616

1717
require 'java_buildpack/component/versioned_dependency_component'
18-
require 'java_buildpack/container'
1918

2019
module JavaBuildpack
2120
module Container

resources/tomcat/conf/server.xml

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,19 @@
1818

1919
<Server port='-1'>
2020

21-
<Listener className='org.apache.catalina.core.JasperListener'/>
22-
23-
<Service name='Catalina'>
24-
<Connector port='${http.port}' bindOnInit="false"/>
25-
26-
<Engine defaultHost='localhost' name='Catalina'>
27-
<Valve className="org.apache.catalina.valves.RemoteIpValve" protocolHeader="x-forwarded-proto"/>
28-
<Host name='localhost'>
29-
<Listener className="com.gopivotal.cloudfoundry.tomcat.lifecycle.ApplicationStartupFailureDetectingLifecycleListener"/>
30-
</Host>
31-
</Engine>
32-
</Service>
21+
<Listener className='org.apache.catalina.core.JasperListener'/>
22+
23+
<Service name='Catalina'>
24+
<Connector port='${http.port}' bindOnInit="false"/>
25+
26+
<Engine defaultHost='localhost' name='Catalina'>
27+
<Valve className="org.apache.catalina.valves.RemoteIpValve" protocolHeader="x-forwarded-proto"/>
28+
<Valve className="com.gopivotal.cloudfoundry.tomcat.logging.access.CloudFoundryAccessLoggingValve"
29+
pattern='[ACCESS] %h %l %u %t "%r" %s %b %{X-Vcap-Request-Id}i' enabled="${access.logging.enabled}"/>
30+
<Host name='localhost'>
31+
<Listener className="com.gopivotal.cloudfoundry.tomcat.lifecycle.ApplicationStartupFailureDetectingLifecycleListener"/>
32+
</Host>
33+
</Engine>
34+
</Service>
3335

3436
</Server>
2.6 KB
Binary file not shown.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Encoding: utf-8
2+
# Cloud Foundry Java Buildpack
3+
# Copyright 2013 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/container/tomcat/tomcat_access_logging_support'
20+
21+
describe JavaBuildpack::Container::TomcatAccessLoggingSupport do
22+
include_context 'component_helper'
23+
24+
let(:component_id) { 'tomcat' }
25+
26+
it 'should always detect' do
27+
expect(component.detect).to eq("tomcat-access-logging-support=#{version}")
28+
end
29+
30+
it 'should copy resources',
31+
cache_fixture: 'stub-access-logging-support.jar' do
32+
33+
component.compile
34+
35+
expect(sandbox + "lib/tomcat_access_logging_support-#{version}.jar").to exist
36+
end
37+
38+
it 'should do nothing during release' do
39+
component.release
40+
end
41+
42+
end

spec/java_buildpack/container/tomcat_spec.rb

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
require 'java_buildpack/container/tomcat/tomcat_instance'
2323
require 'java_buildpack/container/tomcat/tomcat_lifecycle_support'
2424
require 'java_buildpack/container/tomcat/tomcat_logging_support'
25+
require 'java_buildpack/container/tomcat/tomcat_access_logging_support'
2526
require 'java_buildpack/container/tomcat/tomcat_redis_store'
2627

2728
describe JavaBuildpack::Container::Tomcat do
@@ -30,10 +31,11 @@
3031
let(:component) { StubTomcat.new context }
3132

3233
let(:configuration) do
33-
{ 'tomcat' => tomcat_configuration,
34-
'lifecycle_support' => lifecycle_support_configuration,
35-
'logging_support' => logging_support_configuration,
36-
'redis_store' => redis_store_configuration }
34+
{ 'tomcat' => tomcat_configuration,
35+
'lifecycle_support' => lifecycle_support_configuration,
36+
'logging_support' => logging_support_configuration,
37+
'access_logging_support' => access_logging_support_configuration,
38+
'redis_store' => redis_store_configuration }
3739
end
3840

3941
let(:tomcat_configuration) { double('tomcat-configuration') }
@@ -42,6 +44,8 @@
4244

4345
let(:logging_support_configuration) { double('logging-support-configuration') }
4446

47+
let(:access_logging_support_configuration) { double('logging-support-configuration') }
48+
4549
let(:redis_store_configuration) { double('redis-store-configuration') }
4650

4751
it 'should detect WEB-INF',
@@ -69,6 +73,8 @@
6973
.to receive(:new).with(sub_configuration_context(lifecycle_support_configuration))
7074
expect(JavaBuildpack::Container::TomcatLoggingSupport)
7175
.to receive(:new).with(sub_configuration_context(logging_support_configuration))
76+
expect(JavaBuildpack::Container::TomcatAccessLoggingSupport)
77+
.to receive(:new).with(sub_configuration_context(access_logging_support_configuration))
7278
expect(JavaBuildpack::Container::TomcatRedisStore)
7379
.to receive(:new).with(sub_configuration_context(redis_store_configuration))
7480
expect(JavaBuildpack::Container::TomcatInsightSupport).to receive(:new).with(context)

0 commit comments

Comments
 (0)