]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - include/SugarLogger/SugarLogger.php
Release $ver
[Github/sugarcrm.git] / include / SugarLogger / SugarLogger.php
1 <?php
2 if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
3 /*********************************************************************************
4  * SugarCRM Community Edition is a customer relationship management program developed by
5  * SugarCRM, Inc. Copyright (C) 2004-2012 SugarCRM Inc.
6  * 
7  * This program is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU Affero General Public License version 3 as published by the
9  * Free Software Foundation with the addition of the following permission added
10  * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
11  * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
12  * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
13  * 
14  * This program is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
17  * details.
18  * 
19  * You should have received a copy of the GNU Affero General Public License along with
20  * this program; if not, see http://www.gnu.org/licenses or write to the Free
21  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22  * 02110-1301 USA.
23  * 
24  * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
25  * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
26  * 
27  * The interactive user interfaces in modified source and object code versions
28  * of this program must display Appropriate Legal Notices, as required under
29  * Section 5 of the GNU Affero General Public License version 3.
30  * 
31  * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
32  * these Appropriate Legal Notices must retain the display of the "Powered by
33  * SugarCRM" logo. If the display of the logo is not reasonably feasible for
34  * technical reasons, the Appropriate Legal Notices must display the words
35  * "Powered by SugarCRM".
36  ********************************************************************************/
37
38 /*********************************************************************************
39
40  * Description:  Defines the English language pack for the base application.
41  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
42  * All Rights Reserved.
43  * Contributor(s): ______________________________________..
44  ********************************************************************************/
45 require_once('include/SugarLogger/LoggerManager.php');
46 require_once('include/SugarLogger/LoggerTemplate.php');
47
48 /**
49  * Default SugarCRM Logger
50  * @api
51  */
52 class SugarLogger implements LoggerTemplate
53 {
54     /**
55      * properties for the SugarLogger
56      */
57         protected $logfile = 'sugarcrm';
58         protected $ext = '.log';
59         protected $dateFormat = '%c';
60         protected $logSize = '10MB';
61         protected $maxLogs = 10;
62         protected $filesuffix = "";
63     protected $date_suffix = "";
64         protected $log_dir = '.';
65
66
67         /**
68          * used for config screen
69          */
70         public static $filename_suffix = array(
71         //bug#50265: Added none option for previous version users
72         "" => "None",
73             "%m_%Y"    => "Month_Year",
74         "%d_%m"    => "Day_Month",
75             "%m_%d_%y" => "Month_Day_Year",
76             );
77
78         /**
79          * Let's us know if we've initialized the logger file
80          */
81     protected $initialized = false;
82
83     /**
84      * Logger file handle
85      */
86     protected $fp = false;
87
88     public function __get(
89         $key
90         )
91     {
92         return $this->$key;
93     }
94
95     /**
96      * Used by the diagnostic tools to get SugarLogger log file information
97      */
98     public function getLogFileNameWithPath()
99     {
100         return $this->full_log_file;
101     }
102
103     /**
104      * Used by the diagnostic tools to get SugarLogger log file information
105      */
106     public function getLogFileName()
107     {
108         return ltrim($this->full_log_file, "./");
109     }
110
111     /**
112      * Constructor
113      *
114      * Reads the config file for logger settings
115      */
116     public function __construct()
117     {
118         $config = SugarConfig::getInstance();
119         $this->ext = $config->get('logger.file.ext', $this->ext);
120         $this->logfile = $config->get('logger.file.name', $this->logfile);
121         $this->dateFormat = $config->get('logger.file.dateFormat', $this->dateFormat);
122         $this->logSize = $config->get('logger.file.maxSize', $this->logSize);
123         $this->maxLogs = $config->get('logger.file.maxLogs', $this->maxLogs);
124         $this->filesuffix = $config->get('logger.file.suffix', $this->filesuffix);
125         $log_dir = $config->get('log_dir' , $this->log_dir);
126         $this->log_dir = $log_dir . (empty($log_dir)?'':'/');
127         unset($config);
128         $this->_doInitialization();
129         LoggerManager::setLogger('default','SugarLogger');
130         }
131
132         /**
133          * Handles the SugarLogger initialization
134          */
135     protected function _doInitialization()
136     {
137
138         if( $this->filesuffix && array_key_exists($this->filesuffix, self::$filename_suffix) )
139         { //if the global config contains date-format suffix, it will create suffix by parsing datetime
140             $this->date_suffix = "_" . date(str_replace("%", "", $this->filesuffix));
141         }
142         $this->full_log_file = $this->log_dir . $this->logfile . $this->date_suffix . $this->ext;
143         $this->initialized = $this->_fileCanBeCreatedAndWrittenTo();
144         $this->rollLog();
145     }
146
147     /**
148          * Checks to see if the SugarLogger file can be created and written to
149          */
150     protected function _fileCanBeCreatedAndWrittenTo()
151     {
152         $this->_attemptToCreateIfNecessary();
153         return file_exists($this->full_log_file) && is_writable($this->full_log_file);
154     }
155
156     /**
157          * Creates the SugarLogger file if it doesn't exist
158          */
159     protected function _attemptToCreateIfNecessary()
160     {
161         if (file_exists($this->full_log_file)) {
162             return;
163         }
164         @touch($this->full_log_file);
165     }
166
167     /**
168      * see LoggerTemplate::log()
169      */
170         public function log(
171             $level,
172             $message
173             )
174         {
175         if (!$this->initialized) {
176             return;
177         }
178                 //lets get the current user id or default to -none- if it is not set yet
179                 $userID = (!empty($GLOBALS['current_user']->id))?$GLOBALS['current_user']->id:'-none-';
180
181                 //if we haven't opened a file pointer yet let's do that
182                 if (! $this->fp)$this->fp = fopen ($this->full_log_file , 'a' );
183
184
185                 // change to a string if there is just one entry
186             if ( is_array($message) && count($message) == 1 )
187                 $message = array_shift($message);
188             // change to a human-readable array output if it's any other array
189             if ( is_array($message) )
190                     $message = print_r($message,true);
191
192                 //write out to the file including the time in the dateFormat the process id , the user id , and the log level as well as the message
193                 fwrite($this->fp,
194                     strftime($this->dateFormat) . ' [' . getmypid () . '][' . $userID . '][' . strtoupper($level) . '] ' . $message . "\n"
195                     );
196         }
197
198         /**
199          * rolls the logger file to start using a new file
200          */
201         protected function rollLog(
202             $force = false
203             )
204         {
205         if (!$this->initialized || empty($this->logSize)) {
206             return;
207         }
208                 // bug#50265: Parse the its unit string and get the size properly
209         $units = array(
210             'b' => 1,                   //Bytes
211             'k' => 1024,                //KBytes
212             'm' => 1024 * 1024,         //MBytes
213             'g' => 1024 * 1024 * 1024,  //GBytes
214         );
215         if( preg_match('/^\s*([0-9]+\.[0-9]+|\.?[0-9]+)\s*(k|m|g|b)(b?ytes)?/i', $this->logSize, $match) ) {
216             $rollAt = ( int ) $match[1] * $units[strtolower($match[2])];
217         }
218                 //check if our log file is greater than that or if we are forcing the log to roll if and only if roll size assigned the value correctly
219                 if ( $force || ($rollAt && filesize ( $this->full_log_file ) >= $rollAt) ) {
220                         //now lets move the logs starting at the oldest and going to the newest
221                         for($i = $this->maxLogs - 2; $i > 0; $i --) {
222                 if (file_exists ( $this->log_dir . $this->logfile . $this->date_suffix . '_'. $i . $this->ext )) {
223                                         $to = $i + 1;
224                     $old_name = $this->log_dir . $this->logfile . $this->date_suffix . '_'. $i . $this->ext;
225                     $new_name = $this->log_dir . $this->logfile . $this->date_suffix . '_'. $to . $this->ext;
226                                         //nsingh- Bug 22548  Win systems fail if new file name already exists. The fix below checks for that.
227                                         //if/else branch is necessary as suggested by someone on php-doc ( see rename function ).
228                                         sugar_rename($old_name, $new_name);
229
230                                         //rename ( $this->logfile . $i . $this->ext, $this->logfile . $to . $this->ext );
231                                 }
232                         }
233                         //now lets move the current .log file
234             sugar_rename ($this->full_log_file, $this->log_dir . $this->logfile . $this->date_suffix . '_1' . $this->ext);
235
236                 }
237         }
238
239     /**
240          * This is needed to prevent unserialize vulnerability
241      */
242     public function __wakeup()
243     {
244         // clean all properties
245         foreach(get_object_vars($this) as $k => $v) {
246             $this->$k = null;
247         }
248         throw new Exception("Not a serializable object");
249     }
250
251         /**
252          * Destructor
253          *
254          * Closes the SugarLogger file handle
255      */
256         public function __destruct()
257         {
258                 if ($this->fp)
259         {
260                         fclose($this->fp);
261             $this->fp = FALSE;
262         }
263         }
264 }