Apache Logging Via ZeroMQ (Part 2)
July 20 2012 10:00 CET
Since my previous blog post about Apache Logging Via ZeroMQ I’ve noticed that the Ruby script seems to use a lot of CPU on our servers.
I rewrote the logger in C which uses way less memory and a lot less CPU. Feel free to grab it and do whatever :)
Note that the server IP is hardcoded in the program. You might want to pass the IP and port using ARGV instead.
Also note that it will only read 2048 characters from STDIN at a time. This should, however, be more than sufficient for Apache access log lines.
To compile this script you will ofcourse need libzmq and gcc. Then just compile as gcc -Wall -lzmq zeromqlogger.c -o zeromqlogger.
/*
zeromqlogger.c
This program takes Apache log lines from STDIN and sends them via zeromq.
Written by Morten Møller Riis
*/
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <zmq.h>
#include <signal.h>
// These are global so we can close them in the signal handler
void* ctx = NULL;
void* socket = NULL;
void term(int signum)
{
printf("Received %i, closing context and socket...\n", signum);
zmq_close(socket);
zmq_term(ctx);
printf("Exiting.");
exit(0);
}
int main(int argc, char **argv) {
signal(SIGTERM, term);
signal(SIGINT, term);
int nbytes = 2049; // The max message size +1
char message[nbytes];
char c;
int i;
int rc;
void *ctx, *socket;
zmq_msg_t query;
ctx = zmq_init(1);
assert(ctx);
socket = zmq_socket(ctx, ZMQ_PUSH);
assert(socket);
// The server ip is compiled in for the moment
rc = zmq_connect(socket, "tcp://1.2.3.4:4010");
assert(rc == 0);
while(1) {
// Clear the char array
memset(message, '\0', nbytes);
// Read the input from stdin
for(i=0;i<nbytes-1;i++) {
c = fgetc(stdin);
if(c == EOF) break;
if(c == '\n') break;
message[i] = c;
}
// Send the message
rc = zmq_msg_init_size(&query, strlen(message));
assert(rc == 0);
memcpy(zmq_msg_data(&query), message, strlen(message));
rc = zmq_send(socket, &query, 0);
assert(rc == 0);
zmq_msg_close(&query);
}
// Should never reach this point
zmq_close(socket);
zmq_term(ctx);
return 0;
}