Logging errors via error_page + post_action?

Hi

In our nginx setup we use proxy_pass to pass most requests to backend
servers.

We like to monitor our logs regularly for any errors to see that
everything is working as expected. We can grep the nginx logs, but:

a) That’s not real time
b) We can’t get extended information about the request, like if it’s a
POST, what the POST body actually was

So what we wanted to do was use an error_page handler in nginx so if any
backend returned an error, we resent the request details to an error
handler script, something like:

location / {
  proxy_pass http://backend/;
}

error_page 500 /internal_error_page_500;
location /internal_error_page_500 {
  internal;
  proxy_set_header X-URL      "$host$request_uri";
  proxy_set_header X-Post     $request_body;
  proxy_set_header X-Method   $request_method;
  proxy_set_header X-Real-IP  $remote_addr;
  proxy_pass http://local/cgi-bin/error.pl;
}

The problem is that this replaces any result content from the main /
proxy_pass with the content that error.pl generates. We don’t want that,
we want to keep the original result, but just use the error_page handler
to effectively “log” the error for later.

I thought maybe we could replace:

  proxy_pass http://local/cgi-bin/error.pl;

With:

  post_action http://local/cgi-bin/error.pl;

But that just causes nginx to return a “404 Not Found” error instead.

Is there any way to do this? Return the original result content of a
proxy_pass directive, but if that proxy_pass returns an error code (eg
500, etc), do a request to another URL with “logging” information (eg
URL, method, POST body content, etc)


Rob M.
[email protected]

I posted this about a month ago and didn’t hear anything, so I’m
reposting again to hopefully catch some new eyes and see if anyone has
any ideas.


Hi

In our nginx setup we use proxy_pass to pass most requests to backend
servers.

We like to monitor our logs regularly for any errors to see that
everything is working as expected. We can grep the nginx logs, but:

a) That’s not real time
b) We can’t get extended information about the request, like if it’s a
POST, what the POST body actually was

So what we wanted to do was use an error_page handler in nginx so if any
backend returned an error, we resent the request details to an error
handler script, something like:

location / {
  proxy_pass http://backend/;
}

error_page 500 /internal_error_page_500;
location /internal_error_page_500 {
  internal;
  proxy_set_header X-URL      "$host$request_uri";
  proxy_set_header X-Post     $request_body;
  proxy_set_header X-Method   $request_method;
  proxy_set_header X-Real-IP  $remote_addr;
  proxy_pass http://local/cgi-bin/error.pl;
}

The problem is that this replaces any result content from the main /
proxy_pass with the content that error.pl generates. We don’t want that,
we want to keep the original result, but just use the error_page handler
to effectively “log” the error for later.

I thought maybe we could replace:

  proxy_pass http://local/cgi-bin/error.pl;

With:

  post_action http://local/cgi-bin/error.pl;

But that just causes nginx to return a “404 Not Found” error instead.

Is there any way to do this? Return the original result content of a
proxy_pass directive, but if that proxy_pass returns an error code (eg
500, etc), do a request to another URL with “logging” information (eg
URL, method, POST body content, etc)


Rob M.
[email protected]

Hello!

On Thu, Jan 17, 2013 at 03:41:59PM +1100, Robert Mueller wrote:

We like to monitor our logs regularly for any errors to see that
everything is working as expected. We can grep the nginx logs, but:

a) That’s not real time
b) We can’t get extended information about the request, like if it’s a
POST, what the POST body actually was

The “tail -F /path/to/log” is actually recommended solution. It
is realtime and doesn’t introduce additional point of failure in
client request processing.

  internal;

to effectively “log” the error for later.

Is there any way to do this? Return the original result content of a
proxy_pass directive, but if that proxy_pass returns an error code (eg
500, etc), do a request to another URL with “logging” information (eg
URL, method, POST body content, etc)

The error_page is executed to replace content returned to client.
It can’t be used to do something in addition to normal request
processing.

If you are brave enough to do post_action and understand
consequences, you may do something like

location / {
    proxy_pass http://backend/;
    post_action /post;
}

location = /post {
    if ($status != 500) {
        return 204;
    }

    # do something
}

Though I wouldn’t recommend using post_action unless you understand what
it implies. It’s left undocumented on purpose.


Maxim D.