sigsci-module-apache
This is an implementation of the Signal Sciences module specification for the Apache webserver.
Developer Notes
Please see DEVELOPMENT.md for latest notes to do typical build and test of the module.
NOTE: some of the following sections may be OBSOLETE.
Environment
Static analysis is done via a docker container running the latest gcc
and clang compilers. make docker-analyze will run them for you, and
create all containers for you.
Likewise make docker-format will reformat the c-code using clang.
Makefile Targets
| target | description |
|---|---|
| build | builds the source and tests module with apache |
| clean | left as an exercise for the reader |
These can all be run within any of our fat OS docker using the docker-run.sh script. For
example:
./docker-run sigsci-ubuntu_1404 make new-package
Code Organization
The main file mod_signalsciences.c just does basic configuration and setup.
I'm not sure if mod_signalsciences.h does anything.
- sigsci_global.h -- has global structures
- sigsci_request.h -- handles sockets and transports to the agent
- sigsci_request_start.h is the hook that captures initial headers, AND an input filter to capture POST data, if any
- sigsci_request_end.h is the hook run at the end of the full original HTTP request
- cmp.c contains the basic rpc serialization functionality
- mod_example_hooks.c is used for testing only with our module
Module Data Flow
When a request comes in, our code is called first. This is very early in the apache lifecycle of a request. At first we just setup some variables.
However, if the original request is a POST, then we also need to get a copy of it, using an 'input filter'. Either way at the end of the filter, we
- package up all this data into a JSON blog
- send it via HTTP to the agent which runs on the same machine as the Apache server.
- the response will return "200" (its ok, let the request pass) or a different error code (which is returned back to the original client) and a request id
Then apache runs normally and sends back data to the original client.
At the very end of the request, if we have a RequestID or if the request had an error in it, we make another call to the agent just sending the HTTP response code and HTTP response size.
In English, this might be:
- A request comes in
- It is copied and send to the agent
- Who replies:
- "It'ok, keep going"
- "That's weird, give me more information" or
- "THat's bad, block and give me more information"
- At the end of the original http request, we send back
- the HTTP response code (e.g. 404, 500, 200)
- the HTTP response size (e.g. 200 bytes)
- The server had an error, specifically an response code in [400, 600)
- We were asked to send more information (above)
Performance Notes
Apache has 3 modes of operations:
- one worker process per request (standard for PHP, et)
- threaded module
- evented i/o module
Right now we only work with #1. We use blocking sockets to connect to agent. This maybe need to be improved, but we'll wait for customer requirements first. I don't know anyone using #2 or #3.
C Code Style - OBSOLETE
We follow the LLVM standard http://llvm.org/docs/CodingStandards.html and utilize the clang code formatting tool.
This can be enforced by running make format or make docker-format
Learning more about Apache module development
Contains some info on configuration
- http://threebit.net/tutorials/apache2_modules/tut2/tutorial2.html
- http://www.apachetutor.org/dev/config
- http://docstore.mik.ua/orelly/apache_mod/147.htm#BIN306
- http://docstore.mik.ua/orelly/weblinux2/apache/ch21_03.htm#apache3-CHP-21-EX-16
The later two appears to be an old OReily book perhaps out of print.
Generating DEB and RPM Packages
The new-package target will build the module against the stock version of Apache for a given
fat OS docker container. The resulting package will be targeted for that platform.