1

We use REST for logging - we need more info than a simple textlog can provide. So we implemented a REST service, that accepts some basic information about the event and then asynchronously fetches more detail from the event's source web. So it's practically a ping with very little additional info. The logger machine than verifies API key, connects to DB and writes the basic info along with pointers to more detailed information.

We have a problem though, that logging may slow down the app a lot, because the connection and waiting for answer takes quite some time (it's fast but when you log 10+ events in one request it's a problem).

The question is:

Is there a way in plain PHP (5.3) to do a request to an URL and NOT wait for any answer, or just wait for HTTP 200 header to be sure?

I think I can make the logging server send HTTP 200 header as soon as it gets the request. But it needs to do some more work then ;)

Tomáš Fejfar
  • 11,129
  • 8
  • 54
  • 82

2 Answers2

2

What you want is called a asynchrnous request.

A solution could look like this (quoted):

function curl_post_async($url, $params)
{
    foreach ($params as $key => &$val) {
      if (is_array($val)) $val = implode(',', $val);
        $post_params[] = $key.'='.urlencode($val);
    }
    $post_string = implode('&', $post_params);

    $parts=parse_url($url);

    $fp = fsockopen($parts['host'],
        isset($parts['port'])?$parts['port']:80,
        $errno, $errstr, 30);

    $out = "POST ".$parts['path']." HTTP/1.1\r\n";
    $out.= "Host: ".$parts['host']."\r\n";
    $out.= "Content-Type: application/x-www-form-urlencoded\r\n";
    $out.= "Content-Length: ".strlen($post_string)."\r\n";
    $out.= "Connection: Close\r\n\r\n";
    if (isset($post_string)) $out.= $post_string;

    fwrite($fp, $out);
    fclose($fp);
}

If you need more informations take a look at:

http://petewarden.typepad.com/searchbrowser/2008/06/how-to-post-an.html

TheNiceGuy
  • 3,462
  • 8
  • 34
  • 64
1

Here are two tricks maybe helpful.

I. Continue execute after http connection closed. Which means you can close the connection immediately when the main function finished, then continue with your log process.

<?php
ignore_user_abort(true);//avoid apache to kill the php running
ob_start();//start buffer output
echo "show something to user";//do something you need -- your main function
session_write_close();//close session file on server side if needed
header("Content-Encoding: none");//send header to avoid the browser side to take content as gzip format
header("Content-Length: ".ob_get_length());//send length header
header("Connection: close");//or redirect to some url 
ob_end_flush();flush();//really send content, can't change the order:1.ob buffer to normal buffer, 2.normal buffer to output
//continue do something on server side
ob_start();
sleep(5);//the user won't wait for the 5 seconds
echo 'for log';//user can't see this
file_put_contents('/tmp/process.log', ob_get_contents());
// or call remote server like http://your.log.server/log.php?xxx=yyy&aaa=bbb
ob_end_clean();
?>

II. Use function apache_note to write logs is pretty lightweight choice than insert into DB. Because Apache will open the log file and keep the handle during Apache running. It's stable and really fast.

Apache configuration:

<VirtualHost *:80>
DocumentRoot /path/to/your/web
ServerName your.domain.com
ErrorLog /path/to/your/log/error_log
    <Directory /path/to/your/web>
        AllowOverride All
        Order allow,deny
        Allow from all
    </Directory>
    SetEnvIf Request_URI "/log\.php" mylog
    LogFormat "%{mylog}n" log1
    CustomLog "|/usr/sbin/cronolog /path/to/logs/mylog/%Y%m%d/mysite.%Y%m%d%H.log" log1 env=mylog
</VirtualHost>

PHP code:

<?php
apache_note('mylog', session_id()); //you can log any data you need, see http://www.php.net/manual/en/function.apache-note.php

Then you can use my tricks both I and II, call URL http://your.log.server/log.php?xxx=yyy&aaa=bbb to log your detail data after connection of main page closed. No extra time cost needed at all.

Alix
  • 256
  • 3
  • 17