108

I want to create a logfile for my system to register/log every action they do inside the system. But I have no idea how to do it.

For example, I have this php code that does the login function.

public function hasAccess($username,$password){
    $form = array();
    $form['username'] = $username;
    $form['password'] = $password;
    

    $securityDAO = $this->getDAO('SecurityDAO');
    $result = $securityDAO->hasAccess($form);
    //var_dump($form);
    //var_dump($result);
    if($result[0]['success']=='1'){
        $this->Session->add('user_id', $result[0]['id']);
        //$this->Session->add('username', $result[0]['username']);
        //$this->Session->add('roleid', $result[0]['roleid']);
        return $this->status(0,true,'auth.success',$result);
    }else{
        return $this->status(0,false,'auth.failed',$result);
    }
}

now I want to create a logfile entitled 'the date today', then when that functions is used for loging in, it will write that user has logged in, the same with other functions. But I only want a single file for every day.

Could anyone be kind enough to guide and teach me how I should do my code?

starball
  • 20,030
  • 7
  • 43
  • 238
maecy m
  • 1,287
  • 3
  • 15
  • 20

11 Answers11

190

To write to a log file and make a new one each day, you could use date("j.n.Y") as part of the filename.

//Something to write to txt log
$log  = "User: ".$_SERVER['REMOTE_ADDR'].' - '.date("F j, Y, g:i a").PHP_EOL.
        "Attempt: ".($result[0]['success']=='1'?'Success':'Failed').PHP_EOL.
        "User: ".$username.PHP_EOL.
        "-------------------------".PHP_EOL;
//Save string to log, use FILE_APPEND to append.
file_put_contents('./log_'.date("j.n.Y").'.log', $log, FILE_APPEND);

So you would place that within your hasAccess() method.

public function hasAccess($username,$password){
    $form = array();
    $form['username'] = $username;
    $form['password'] = $password;

    $securityDAO = $this->getDAO('SecurityDAO');
    $result = $securityDAO->hasAccess($form);

    //Write action to txt log
    $log  = "User: ".$_SERVER['REMOTE_ADDR'].' - '.date("F j, Y, g:i a").PHP_EOL.
            "Attempt: ".($result[0]['success']=='1'?'Success':'Failed').PHP_EOL.
            "User: ".$username.PHP_EOL.
            "-------------------------".PHP_EOL;
    //-
    file_put_contents('./log_'.date("j.n.Y").'.txt', $log, FILE_APPEND);

    if($result[0]['success']=='1'){
        $this->Session->add('user_id', $result[0]['id']);
        //$this->Session->add('username', $result[0]['username']);
        //$this->Session->add('roleid', $result[0]['roleid']);
        return $this->status(0,true,'auth.success',$result);
    }else{
        return $this->status(0,false,'auth.failed',$result);
    }
}
Lawrence Cherone
  • 46,049
  • 7
  • 62
  • 106
  • I tried to put my system on a linux based computer and now there's a problem with the log file regarding permissions. How can I fix it? – maecy m Nov 22 '13 at 03:24
  • 4
    Definitely wouldn't store plain-text passwords, period, including log files. – smoothware May 19 '18 at 13:07
  • 1
    Adding on to this: "PHP_EOL is like doing "\n" or "\r\n" dependent on which os platform. I hate lots of \n\n\n\n's ;p – Lawrence Cherone Nov 11 '13 at 4:55 " EOL simply stands for End of Line. Available since PHP 5.0.2. Read more here : https://www.php.net/manual/en/reserved.constants.php – kPieczonka Sep 23 '19 at 14:38
  • *Especially* log files. There are plenty of applications that ask for a password to be stored in a plaintext config file, that's a pretty well accepted norm. The folders that contain these files need to be locked down permissions wise though and those should only ever be service-specific passwords, never, ever real blood-n-bone user passwords. – Robert Talada Jun 16 '20 at 20:59
  • 4
    the code isn't safe against concurrent writes, if there's 2 scripts trying to write to the log at the same time, and script 1 has so much data that not all of the data is written in a single write() (whereupon file_put_contents will automatically do a 2nd write() to try to write the remaining data), and script #2 write its log after the 1'st scripts 1st write, but before script1's 2nd write(), the logs will be mangled - you can avoid that potential issue by using LOCK_EX in combination to FILE_APPEND (or'ed together, bitflags), then script2 will wait for script1 to finish completely – hanshenrik Jul 08 '20 at 16:04
  • `file_put_contents` is a bad function that causes code that follows it to occasionally fail. – Pyromonk Feb 03 '21 at 12:20
41

create a logfile in php, to do it you need to pass data on function and it will create log file for you.

function wh_log($log_msg)
{
    $log_filename = "log";
    if (!file_exists($log_filename)) 
    {
        // create directory/folder uploads.
        mkdir($log_filename, 0777, true);
    }
    $log_file_data = $log_filename.'/log_' . date('d-M-Y') . '.log';
    // if you don't add `FILE_APPEND`, the file will be erased each time you add a log
    file_put_contents($log_file_data, $log_msg . "\n", FILE_APPEND);
} 
// call to function
wh_log("this is my log message");
JON
  • 965
  • 2
  • 10
  • 28
16

Agree with the @jon answer. Just added modified the path to create the log directory inside the root

 function wh_log($log_msg) {
    $log_filename = $_SERVER['DOCUMENT_ROOT']."/log";
    if (!file_exists($log_filename))
    {
        // create directory/folder uploads.
        mkdir($log_filename, 0777, true);
    }
    $log_file_data = $log_filename.'/log_' . date('d-M-Y') . '.log';
    file_put_contents($log_file_data, $log_msg . "\n", FILE_APPEND);
}

wh_log('log to file');

just added $_SERVER['DOCUMENT_ROOT']

James Valeii
  • 472
  • 1
  • 4
  • 14
Manish
  • 639
  • 6
  • 17
12

Please check with this documentation.

http://php.net/manual/en/function.error-log.php

Example:

<?php
// Send notification through the server log if we can not
// connect to the database.
if (!Ora_Logon($username, $password)) {
    error_log("Oracle database not available!", 0);
}

// Notify administrator by email if we run out of FOO
if (!($foo = allocate_new_foo())) {
    error_log("Big trouble, we're all out of FOOs!", 1,
               "operator@example.com");
}

// another way to call error_log():
error_log("You messed up!", 3, "/var/tmp/my-errors.log");
?>
Surabhil Sergy
  • 1,946
  • 1
  • 23
  • 40
6

Please check this code, it works fine for me.

$data = array('shopid'=>3,'version'=> 1,'value=>1');  //here $data is dummy varaible

error_log(print_r($data,true), 3, $_SERVER['DOCUMENT_ROOT']."/your-file-name.log");

//In $data we can mention the error messege and create the log
Pasupathi Thangavel
  • 942
  • 1
  • 10
  • 17
  • In above code error_log line is enough to create a new log file in your root folder, print_r($data,true) data mention what you are really want to print in that log file. – Pasupathi Thangavel Jan 04 '17 at 07:06
3

You could use built-in function trigger_error() to trigger user errors/warnings/notices and set_error_handler() to handle them. Inside your error handler you might want to use error_log() or file_put_contents() to store all records on files. To have a single file for every day just use something like sprintf('%s.log', date('Y-m-d')) as filename. And now you should know where to start... :)

Paulo Freitas
  • 13,194
  • 14
  • 74
  • 96
  • 1
    How do I write it? Do you mind if you could give me a sample code? If it's not too much to ask. Thank you. – maecy m Nov 11 '13 at 04:45
1

This is my working code. Thanks to Paulo for the links. You create a custom error handler and call the trigger_error function with the correct $errno exception, even if it's not an error. Make sure you can write to the log file directory without administrator access.

<?php
    $logfile_dir = "C:\workspace\logs\\";   // or "/var/log/" for Linux
    $logfile = $logfile_dir . "php_" . date("y-m-d") . ".log";
    $logfile_delete_days = 30;

    function error_handler($errno, $errstr, $errfile, $errline)
    {
        global $logfile_dir, $logfile, $logfile_delete_days;

        if (!(error_reporting() & $errno)) {
            // This error code is not included in error_reporting, so let it fall
            // through to the standard PHP error handler
            return false;
        }

        $filename = basename($errfile);

        switch ($errno) {
            case E_USER_ERROR:
                file_put_contents($logfile, date("y-m-d H:i:s.").gettimeofday()["usec"] . " $filename ($errline): " . "ERROR >> message = [$errno] $errstr\n", FILE_APPEND | LOCK_EX);
                exit(1);
                break;

            case E_USER_WARNING:
                file_put_contents($logfile, date("y-m-d H:i:s.").gettimeofday()["usec"] . " $filename ($errline): " . "WARNING >> message = $errstr\n", FILE_APPEND | LOCK_EX);
                break;

            case E_USER_NOTICE:
                file_put_contents($logfile, date("y-m-d H:i:s.").gettimeofday()["usec"] . " $filename ($errline): " . "NOTICE >> message = $errstr\n", FILE_APPEND | LOCK_EX);
                break;

            default:
                file_put_contents($logfile, date("y-m-d H:i:s.").gettimeofday()["usec"] . " $filename ($errline): " . "UNKNOWN >> message = $errstr\n", FILE_APPEND | LOCK_EX);
                break;
        }

        // delete any files older than 30 days
        $files = glob($logfile_dir . "*");
        $now   = time();

        foreach ($files as $file)
            if (is_file($file))
                if ($now - filemtime($file) >= 60 * 60 * 24 * $logfile_delete_days)
                    unlink($file);

        return true;    // Don't execute PHP internal error handler
    }

    set_error_handler("error_handler");

    trigger_error("testing 1,2,3", E_USER_NOTICE);
?>
xinthose
  • 3,213
  • 3
  • 40
  • 59
0

Use below function

// Enable error reporting
ini_set('display_errors', 1);
//Report runtime errors
error_reporting(E_ERROR | E_WARNING | E_PARSE);
//error_reporting(E_ALL & ~E_NOTICE);
// Tell php where your custom php error log is
ini_set('error_log', 'php_error.log');

$dateTime=date("Y-m-d H:i:s");
$ip= $_SERVER['REMOTE_ADDR'];
$errorString="Error occured on time $dateTime by ip $ip";
$php_error_msg.=$errorString;
// Append the error message to the php-error log
//error_log($php_error_msg);
error_log("A custom error has been triggered",1,"email_address","From: email_address");

Above function will create a log in file php_error with proper description and email will be sent.

vritika
  • 21
  • 3
0

For printing log use this function, this will create log file in log folder. Create log folder if its not exists .

logger("Your msg in log ", "Filename you want ", "Data to be log string or array or object");


function logger($logMsg="logger", $filename="logger", $logData=""){     
            $log  = date("j.n.Y h:i:s")." || $logMsg : ".print_r($logData,1).PHP_EOL .                  
            "-------------------------".PHP_EOL;
            file_put_contents('./log/'.$filename.date("j.n.Y").'.log', $log, FILE_APPEND);                      
    }
Ashwani Panwar
  • 3,819
  • 3
  • 46
  • 66
0

A custom log function (for php server):

Features:

logs will be hidden (invisible) to public (without doing setting on server)

easy to read logs data

function log_it($info)
{
$filename = $_SERVER['DOCUMENT_ROOT'] . '/' . '1LOGS.php';
$dieCode = "<?php die();?>";
$fileStart = @file_get_contents($filename, false, null, 0, 14);
if ($fileStart) {
    if ($fileStart !== $dieCode)
        file_put_contents($filename, $dieCode . file_get_contents($filename));
} else file_put_contents($filename, $dieCode);

if (is_string($info) || is_int($info) || is_float($info)) $txt = '    ' . $info;
elseif (is_array($info) || is_object($info)) $txt = PHP_EOL . '    ' . print_r($info, true);
else $txt = '    ' . 'Data Type: ' . gettype($info);
file_put_contents(
    $filename,
    PHP_EOL . '>>> ( Date:' . date("Y:m:d H:i:s") . ' )' . $txt,
    FILE_APPEND
);
}

inform if it has room for improvement

proseosoc
  • 1,168
  • 14
  • 23
-1

Here's my PHP log function:

If you want to edit the log rows $maxLogs=5, or the order to write your logs $logOrder='top'

<?php
##### Start Script
lg('Script start','start');

#Code......
lg('Script end','end');

function lg($str,$mod='Your Log Category'){
    
    $ts = microtime(true);
    if(!defined('logTimer')){
        define('logTimer',microtime(true));
    }
    $diff=abs(round(($ts-logTimer)*1000,2));
    $maxLogs=5;
    $logOrder='top';#new Logs at top
    
    
    $filename = './log.txt';
    $log=[];
    if(!file_exists($filename)){
        if(!file_put_contents($filename,json_encode($log,128))){
            echo "Can’t open to write '$filename' Check Permissions";
            return;
        }
    }else{
        $c=file_get_contents($filename);
        if(trim($c)==''){$c='[]';}
        
        $log =@json_decode($c,true);
        if(!is_Array($log)){$log=[];}
    }
    $new=['mod'=>$mod,'date'=> date('Y-m-d H:i:s')." Scripttime: ".$diff."ms",'log'=>$str];
    if($logOrder=='top'){
        array_unshift($log , $new);
        $log=array_slice($log,0,$maxLogs);
        }else{
        $log[]=$new;
        $log=array_slice($log,0-$maxLogs,$maxLogs);
    }
    
    
    $logs=json_encode($log,128);
    if(!file_put_contents($filename,$logs) ){echo ("Can’t open to write '$filename' Check Permissions") ;return;}
    return $str;
}
?>

The Output looks like:

[
    {
        "mod": "delete",
        "date": "2022-08-04 13:48:02 0.33ms",
        "log": "test 2"
    },
    {
        "mod": "start",
        "date": "2022-08-04 13:48:29 0ms",
        "log": "test"
    },
    {
        "mod": "delete",
        "date": "2022-08-04 13:48:29 0.27ms",
        "log": "test 2"
    }      
   
]
dazzafact
  • 2,570
  • 3
  • 30
  • 49
  • 1
    Now we have a bad one. The limited capacity, the performance issues, the whole log file gets truncated due to race condition, the overall bad code quality. – Your Common Sense Aug 04 '22 at 14:15
  • lol, this code is not for Amzon Servers etc. Its just default programming Code. Do you expect a PHP Class with includes, methods and other libraries, etc?? – dazzafact Aug 04 '22 at 17:33