Download PDF
Download page Injection Using Apache.
Injection Using Apache
This page describes how to instrument a browser application using Apache to automatically inject the JavaScript Agent. If you are using Apache as your web container, or you are currently using, or willing to use, Apache as a reverse proxy, you can use a container substitution module to automatically inject the JavaScript Agent into your pages. The module intercepts the response object as it is being returned and makes a string substitution.
This method uses the two Apache modules mod_substitute
and mod_filter.
Download the Agent
You must first download the JavaScript Agent from the Browser Monitoring configuration pane.
Open the browser application in which you are interested.
From the left navigation menu, select Configuration.
Click the Configure and download JavaScript Agent.
For the JavaScript hosting option, select I will host all the JavaScript agent files.
Click Download to download the JavaScript Agent.
Place the file somewhere accessible to the Apache instance. The name of the saved file should be
adrum.js
.
Configure Apache
The basic configuration procedure includes:
- Make Sure the Modules are Loaded
- Create an Adrum Configuration File
- Add the Location of the Adrum Configuration File to httpd.conf
- Restart the Web Server
Make Sure the Modules are Loaded
Check your global Apache httpd.conf
file and make sure that the following two LoadModule
commands are in the file:
LoadModule substitute_module modules/mod_substitute.so LoadModule filter_module modules/mod_filter.so
Create an Adrum Configuration File
Create a file named adrum.conf
with contents similar to the example below, based on your Apache version. (See this Stack Overflow post for details.) In this case, the substitution rule covers the location of the entire site (Location /
) but you can also recursively select a specific directory and its subdirectories by using /somedirectory.
Sample adrum.conf Apache 2.2
Replace the sample code below with your own JavaScript Agent script.
<Location "/">
SetOutputFilter INFLATE;SUBSTITUTE;DEFLATE
AddOutputFilterByType SUBSTITUTE text/html
Substitute "s#<head>#<head><script>window['adrum-start-time'] = new Date().getTime();</script><script>(function(config){config.appKey='<EUM_APP_KEY>';})(window['adrum-config'] || (window['adrum-config'] = {}));</script><script src='./adrum.js'></script>#inq"
</Location>
If you use <meta>
tags, you should place them right after your <head>
tag, and then place the JavaScript Agent directly after the last <meta>
tag and before other <script>
tags. This can avoid issues with some versions of IE and improve the accuracy of the resource timing.
Sample adrum.conf Apache 2.4
Replace the sample code below with your own JavaScript Agent script.
<Location "/">
AddOutputFilterByType SUBSTITUTE text/html
Substitute "s#<head>#<head><script>window['adrum-start-time'] = new Date().getTime();</script><script>(function(config){config.appKey='<EUM_APP_KEY>';})(window['adrum-config'] || (window['adrum-config'] = {}));</script><script src='./adrum.js'></script>#inq"
</Location>
Where ./adrum.js
is the path to a copy of the adrum file that is accessible to the server. The flags after the #
are:
i -
matching is case-insensitiven -
pattern is treated as a fixed string (removing then
means the pattern is treated as a regular expression)q -
module does not flatten the buckets after each substitution - this can speed performance.
For more information, see the Apache module docs here.
If your <head>
tag has an attribute like <head lang="en">
, you can use a regex in the substitution string and omit the n
flag. Replace the sample code below with your own JavaScript Agent script.
Substitute "s#(<head[^>]*>)#$1<script>window['adrum-start-time'] = new Date().getTime();</script><script>(function(config){config.appKey='<EUM_APP_KEY>';})(window['adrum-config'] || (window['adrum-config'] = {}));</script><script src='./adrum.js'></script>#iq"
Note the timer initialization: <script>window['adrum-start-time'] = new Date().getTime();</script>.
Injecting these scripts as close as possible to the top of the document, preferably right after the <head>
tag, ensures the best possible timings.
Also, if you use <meta>
tags, you should place them right after your <head>
tag, and then place the JavaScript Agent directly after the last <meta>
tag and before other <script>
tags. This can avoid issues with some versions of IE and again improve the accuracy of the resource timing.
(Optional) Adjust for gzipped resources
If your page is compressed, the substitution won't work unless the content is INFLATEd, the substitution is made, and then the content is DEFLATEd. There are multiple ways to do this. For example, in the FilterProvider
line:
FilterProvider AdrumFilter INFLATE;SUBSTITUTE;DEFLATE resp=Content-Type $text/html
See this Stack Overflow post for more information. If you are using Apache as a proxy, you can also instruct it not to accept gzip-encoded content.
Add the Location of the Adrum Configuration File to httpd.conf
Add the following line to your global Apache httpd.conf
file:
Include [absolutePathTo]/adrum.conf
Alternatively, you can add the directives to the httpd.conf
file directly instead of creating a separate adrum file.
Restart the Web Server
To pick up the new configuration, restart:
sudo apchectl -k restart
If you get a warning "Useless use of AllowOverride in line 2 of [absolutePathTo]/adrum.conf", it can be ignored. It simply means AllowOverride
is redundant. You can remove it if you wish.
Possible variations on the script string can be found in Configure the JavaScript Agent.
Other Alternatives
If you are setting up your automatic injection using an Apache instance that is configured as a reverse proxy, you must use the Location
directive method described above, with the ProxyPass
and ProxyPassReverse
directives also in the Location
directive. If you are using an Apache instance that is your primary web container you have two additional options for describing the actual substitution step:
Use the Directory Directive
You can use the Directory
directive instead of the Location
directive.
Use .htaccess
Add lines similar to this to an .htaccess
file in the base document directory for your site, replacing your filter name for <MyFilter>
. If you don't have an .htaccess
file, create one:
Apache 2.2
Replace the sample code below with your own JavaScript Agent script.
Substitute "s#<head>#<head><script>window['adrum-start-time'] = new Date().getTime();</script><script>(function(config){config.appKey='<EUM_APP_KEY>';})(window['adrum-config'] || (window['adrum-config'] = {}));</script><script src='./adrum.js'></script>#inq"
AllowOverride Options
FilterDeclare <MyFilter>
FilterProvider <MyFilter> SUBSTITUTE resp=Content-Type $text/html
FilterChain <MyFilter>
Substitute "s#<head>#<head><script>window['adrum-start-time'] = new Date().getTime();</script><script>(function(config){config.appKey='<EUM_APP_KEY>';})(window['adrum-config'] || (window['adrum-config'] = {}));</script><script src='./adrum.js'></script>#inq"
Apache 2.4
Replace the sample code below with your own JavaScript Agent script.
Substitute "s#<head>#<head><script>window['adrum-start-time'] = new Date().getTime();</script><script>(function(config){config.appKey='<EUM_APP_KEY>';})(window['adrum-config'] || (window['adrum-config'] = {}));</script><script src='./adrum.js'></script>#inq"
AddOutputFilterByType SUBSTITUTE text/html
Substitute "s#<head>#<head><script>window['adrum-start-time'] = new Date().getTime();</script><script>(function(config){config.appKey='<EUM_APP_KEY>';})(window['adrum-config'] || (window['adrum-config'] = {}));</script><script src='./adrum.js'></script>#inq"
Where ./adrum.js
is the path to a copy of the adrum file that is accessible to the server. Make sure .htaccess
is world-readable.