3 * Application logger. Puts daily logs in the server's temporary directory. Log level is set in
4 * globals as $GLOBALS["log_level"] (this is customizable in the globals file).
6 * A *nix user can run the following command to see the logs:
8 * > tail -f /var/www/openemr/logs/2016_11_24_application.log
9 * 2016-11-24 20:15:07 [TRACE] \common\database\Connector - Connecting with pooled mode
10 * 2016-11-24 20:15:07 [TRACE] \common\database\Connector - Wiring up Doctrine entities
11 * 2016-11-24 20:15:07 [TRACE] \common\database\Connector - Creating connection
12 * 2016-11-24 20:15:07 [INFO] \some\other\Class - Some info message
13 * 2016-11-24 20:18:01 [WARN] \some\other\Class - Some field is missing
16 * @note Error level logs will also be sent to Apache error log.
18 * @note Application logging is sparse at the moment (will be introduced w/ the modernization project).
20 * Copyright (C) 2016 Matthew Vita <matthewvita48@gmail.com>
22 * LICENSE: This program is free software; you can redistribute it and/or
23 * modify it under the terms of the GNU General Public License
24 * as published by the Free Software Foundation; either version 2
25 * of the License, or (at your option) any later version.
26 * This program is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 * GNU General Public License for more details.
30 * You should have received a copy of the GNU General Public License
31 * along with this program. If not, see <http://opensource.org/licenses/gpl-license.php>.
34 * @author Matthew Vita <matthewvita48@gmail.com>
35 * @link http://www.open-emr.org
38 namespace common\logging
;
42 * The class that is associated with a log entry.
44 private $classContext;
47 * The fully qualified log file path.
52 * Default constructor. Only continues with instance creation
53 * if logging is enabled.
55 * @param $classContext - provided when a class uses the logger.
57 public function __construct($classContext="UnknownClassContext") {
58 if (isset($GLOBALS["log_level"]) && $GLOBALS["log_level"] !== "OFF") {
59 $this->classContext
= $classContext;
60 $this->determineLogFilePath();
65 * Sets the log file on the operating system's temporary directory. Format is:
66 * [log area] + FILE_SEP + YYYY_MM_DD_application.log
68 * On *nix, the file will be stored in /home/current_user/openemr/ (if writable). On Windows, it will
69 * be stored in C:\Users\current_user\openemr\ (if writable).
71 private function determineLogFilePath() {
72 $fileName = date("Y_m_d") . "_application.log";
74 global $webserver_root;
75 $currentDir = $webserver_root;
77 $combinedLogDir = $currentDir . DIRECTORY_SEPARATOR
. $logDirName;
79 if (!is_dir($combinedLogDir)) {
80 mkdir($combinedLogDir);
83 if (is_writable($combinedLogDir)) {
84 $this->logFile
= $combinedLogDir . DIRECTORY_SEPARATOR
. $fileName;
86 error_log('Can\'t write application log file to ' . $combinedLogDir);
91 * Determines if the log level is allowed by the log level in the global
94 * Hierarchy/conditions:
95 * - TRACE (allows TRACE, DEBUG, INFO, WARN, ERROR)
96 * - DEBUG (allows DEBUG, INFO, WARN, ERROR)
97 * - INFO (allows INFO, WARN, ERROR)
98 * - WARN (allows WARN, ERROR)
99 * - ERROR (allows ERROR)
102 * @param $level the incoming log level
103 * @return boolean that represents if log entry should be made
105 private function isLogLevelInDesiredHierarchy($level) {
106 if (empty($GLOBALS["log_level"]) ||
$GLOBALS["log_level"] === "OFF") {
110 if ($GLOBALS["log_level"] === "TRACE") {
112 } else if ($GLOBALS["log_level"] === "DEBUG" && in_array($level, array("DEBUG", "INFO", "WARN", "ERROR"))) {
114 } else if ($GLOBALS["log_level"] === "INFO" && in_array($level, array("INFO", "WARN", "ERROR"))) {
116 } else if ($GLOBALS["log_level"] === "WARN" && in_array($level, array("WARN", "ERROR"))) {
118 } else if ($GLOBALS["log_level"] === "ERROR" && $level === "ERROR") {
126 * Used for informational messages of the application.
128 * @param $message - the log message
130 public function info($message) {
131 $this->log($message, "INFO");
135 * Used by developers that wish to expose information that is
136 * notable for developers.
138 * @param $message - the log message
140 public function debug($message) {
141 $this->log($message, "DEBUG");
145 * Used by developers that wish to expose information that is
146 * notable for developers. Note this is more "noisy" than debug.
148 * @param $message - the log message
150 public function trace($message) {
151 $this->log($message, "TRACE");
155 * Used for in case of harmful conditions.
157 * @param $message - the log message
159 public function warn($message) {
160 $this->log($message, "WARN");
164 * Used for in case an error occurs and the application might continue running.
166 * @param $message - the log message
168 public function error($message) {
169 $this->log($message, "ERROR");
173 * Writes the entry to the log file. If the level is type "error", the message
174 * will additionally go to the Apache error log.
176 * @param $message - the log message
177 * @param $type - the log type
179 private function log($message, $type) {
180 if ($this->isLogLevelInDesiredHierarchy($type) && !empty($this->logFile
)) {
181 $logEntry = date("Y-m-d H:i:s") . " [" . $type . "] " . $this->classContext
. " - " . $message;
183 file_put_contents($this->logFile
, $logEntry.PHP_EOL
, FILE_APPEND | LOCK_EX
);
185 if ($type === "ERROR") {