Location: PHPKode > scripts > Logger_ciacob > logger_ciacob/assets/Logger.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Logger</title>
</head>
<body>
<h1>Logger</h1>
<h2>Description</h2>
<p>Dumps input data to a file on disk.</p>
<p>The file location is logically related to the class or class group (from here onward named <em>calling context</em>) that invokes the module's logging functionality.</p>
<p>Note: the module is built on top of the ParamsProxy module, and therefore inherits its security model, base functionality and limitations.</p>
<h2>Features list</h2>
<ul>
  <li>
    <p>built-in serialization 	of complex input data (objects, arrays);</p>
  </li>
  <li>
    <p>built-in <em>split</em> functionality: 	there can be several volumes of a 	given log file, based on a file size constraint;</p>
  </li>
  <li>
    <p>built-in <em>trim</em> functionality: or, there can be a single log file that automatically 	trims itself from top to bottom – as new content is logged to the 	file – based on a file size constraint;</p>
  </li>
  <li>
    <p>built-in optional wrapping of 	logged content;</p>
  </li>
  <li>
    <p>built-in optional stamping of 	entries with current date and time;*</p>
  </li>
  <li>
    <p>configurable output using 	templates – for log file header and entries.</p>
  </li>
</ul>
<p>* via including the appropriate placeholders in the <em>entries</em> template.</p>
<h2>How it works</h2>
<p>The module is a singleton – therefor any configuration is shared system wide. </p>
<p>The module's API provides a single public method,</p>
<pre>
 /**
 * Writes given data on disk.
 * If data is anything but a string, it is first serialized.
 */
 log ($data);</pre>
<p>one would invoke like this:</p>
<pre>Logger::getInstance()-&gt;log (&quot;FAIL: could not send email '$emailSubject' to $recipient; server responded: $error.&quot;);</pre>
<p>Upon making this call, the module will use PHP's <em>trace debug </em>feature to figure out the name of the calling class and will try to match it against a <em>context</em> definition, as stated by the module's configuration file.</p>
<p><em>Note: more on configuration file, their use, structure and location in the ParamsProxy.html document.</em></p>
<p>If the calling class isn't part of any defined context, the default <em>Main</em> context will be assumed. The string passed as argument to log will then be written into the</p>
<pre>&lt;<strong>logs directory</strong>&gt;/&lt;<strong>context name</strong>&gt;/log.txt</pre>
<p>file (the file will be created if it doesn't yet exist). See also the insides about the <em>split</em> operation mode of the module.</p>
<p>The location of the <code>&lt;<strong>logs directory</strong>&gt;</code> is the parent directory of the <code>&lt;<strong>configuration directory</strong>&gt;</code> and cannot be changed. Therefore, the above could have been written as such:</p>
<pre>&lt;<strong>configuration directory</strong>&gt;/../&lt;<strong>context name</strong>&gt;/log.txt</pre>
<p><em>Note: for more on the configuration folder, please consult the ParamsProxy.html document.</em></p>
<h2>XML</h2>
<p>The module is configured via its dedicated XML configuration file. The module introduces no syntax extensions to the standard defined by the ParamsProxy module.</p>
<p><em>Note: for more on the configuration files syntax, please consult the ParamsProxy.html document..</em></p>
<p>However, some values – shown in bold in the example below – are to be parsed by the module, and therefor must be entered literally.</p>
<pre>
    &lt;config for=&quot;Logger&quot;&gt;
        &lt;param&gt;
            &lt;type&gt;number&lt;/type&gt;
            &lt;name&gt;<strong>maxFileSize</strong>&lt;/name&gt;
            &lt;value&gt;125&lt;/value&gt;
        &lt;/param&gt;
        &lt;param&gt;
            &lt;type&gt;string&lt;/type&gt;
            &lt;name&gt;<strong>operatingMode</strong>&lt;/name&gt;
            &lt;value&gt;<strong>split</strong>&lt;/value&gt;
        &lt;/param&gt;
        &lt;param&gt;
            &lt;type&gt;number&lt;/type&gt;
            &lt;name&gt;<strong>wrapLimit</strong>&lt;/name&gt;
            &lt;value&gt;80&lt;/value&gt;
        &lt;/param&gt;
        &lt;param&gt;
            &lt;type&gt;string&lt;/type&gt;
            &lt;name&gt;<strong>bannerTemplate</strong>&lt;/name&gt;
    		&lt;value&gt;
&lt;![CDATA[
FILE:			<strong>%FILE NAME%</strong> &lt;<strong>%FILE SIZE%</strong>&gt;
PATH:			<strong>%FILE PATH%</strong>
DESCRIPTION: 	Log file for the <strong>%RELATED CONTEXT NAME%</strong>
STATUS: 		<strong>%FILE STATUS%</strong> as of <strong>%LAST MODIFIED DATE%</strong>
----------------------------------------------------------------------
]]&gt;
        	&lt;/value&gt;
        &lt;/param&gt;
        &lt;param&gt;
            &lt;type&gt;string&lt;/type&gt;
            &lt;name&gt;<strong>entryTemplate</strong>&lt;/name&gt;
            &lt;value&gt;
&lt;![CDATA[[
<strong>%CALLING CLASS NAME%</strong> @ <strong>%Y%</strong>/<strong>%M%</strong>/<strong>%D%</strong>-<strong>%H%</strong>:<strong>%S%</strong>
<strong>%CONTENT% </strong>
]]&gt;
        	&lt;/value&gt;
        &lt;/param&gt;
        &lt;param&gt;
            &lt;type&gt;<strong>array</strong>&lt;/type&gt;
            &lt;!-- This is a context name! There may be countless of them,
             		as long as each name appears only once (or else will
             		cause a fatal error). --&gt; 
            &lt;name&gt;LoginOperations&lt;/name&gt;
            &lt;value&gt;
                &lt;!-- This is a class name! A class that appeared in one
                 		context cannot appear in another (or else will
                 		cause a fatal error). --&gt;
                &lt;item&gt;Authenticator&lt;/item&gt;
                &lt;item&gt;CookieManager&lt;/item&gt;
                &lt;item&gt;MailHandler&lt;/item&gt;
            &lt;/value&gt;
        &lt;/param&gt;
    &lt;/config&gt;
</pre>
<p>This example uses all parameters but not all possible values. Parameters, their usage and possible values are described in the next section.</p>
<h2>Configuration</h2>
<table width="100%" border="1" cellpadding="4" cellspacing="0">
  <col width="52*" />
  <col width="63*" />
  <col width="141*" />
  <thead>
    <tr valign="top">
      <td><p >PARAMETER NAME</p></td>
      <th> <p>POSSIBLE VALUES</p></th>
      <th> <p>COMMENTS</p></th>
    </tr>
  </thead>
  <tbody>
    <tr valign="top">
      <td><p>maxFileSize</p></td>
      <td><p>125 to 1250</p></td>
      <td><p>Ranges from a hundred to a thousand 				bytes – with plenty of room for additional noise introduced by 				templates – for the log file <em>upper size</em> limit.</p>
        <p>If the log file is about to exceed 				its upper size limit, <em>trimming</em> or <em>splitting</em> occurs, based on the <strong>operatingMode </strong>parameter 				setting.</p>
        <p>If omitted, 				defaults to 125.</p></td>
    </tr>
    <tr valign="top">
      <td><p>operatingMode</p></td>
      <td><p>one of the &quot;trim&quot; or &quot;split&quot; words, 				literally </p></td>
      <td><p>Sets up the action to trigger when 				the log file is about to grow oversize due to incoming data.</p>
        <p><em>Trim</em> will keep the file size the same but will alter content, by 				progressively deleting oldest entries until there is room for new 				ones.</p>
        <p><em>Split</em> will keep both the file size <em>and</em> content the same, but will archive the file and will start 				writing to a new file instead. </p>
        <p>In 				this documentation, archived files are currently referred to as <em>volumes</em>. Making a 				log file into a volume is handled behind the scene, and simply 				means renaming it, i.e., from &quot;log.txt&quot; 				to &quot;log.txt.2&quot;.</p>
        <p>The &quot;log.txt.2&quot; 				above means there are at least three 				volumes, – count starts from 1. The last (improperly named) 				volume is the log file currently being written, therefore its 				name is not altered: &quot;log.txt&quot;.</p>
        <p>If omitted, this parameter defaults 				to <em>trim</em>.</p></td>
    </tr>
    <tr valign="top">
      <td><p>wrapLimit</p></td>
      <td><p>80 to 240 or -1</p></td>
      <td><p>The number of chars to allow per each 				written line of the log file. &quot;-1&quot; will disable the 				feature.</p>
        <p>Wrapping line is aggressive, i.e., 				&quot;middle word&quot; splits can occur if there's no other 				available split point on a line (this is especially prone to 				happen with url-encoded links).</p>
        <p>By exception, the <em>banner</em> will 				never be split, rather trim horizontally to the <strong>wrapLimit</strong> number of chars (see next). Wrapping is off by default.</p></td>
    </tr>
    <tr valign="top">
      <td><p>bannerTemplate</p></td>
      <td><p>any string, optionally including one or more of the following 				placeholders, literally, in the form of %PLACEHOLDER%:</p>
        <p>&quot;FILE PATH&quot;</p>
        <p>&quot;FILE SIZE&quot;</p>
        <p>&quot;FILE STATUS&quot;</p>
        <p>&quot;LAST MODIFIED DATE&quot;</p>
        <p>&quot;RELATED CONTEXT NAME&quot;</p></td>
      <td><p>The <em>banner </em>of 				a log file represents a reserved, rectangular area found at the 				top of the file.</p>
        <p>This <em>banner</em> will always 				be <strong>wrapLimit</strong> columns by <em>5</em> rows (hardcoded) wide, <em>regardless 				of the actual size needed by the banner template or the data that 				will populate the template</em>.</p>
        <p>If 				a template taller than 5 rows has been defined, it will be 				populated, then trimmed to 5 lines starting at the top, then 				applied. An ellipsis (…) 				char will be added at the end of the last line to indicate 				trimming.</p>
        <p> If a template shorter than 5 rows has been defined, empty lines 				will be added to the bottom – which implies that, if no 				template is defined, 5 blank lines will be at the top of every 				log file.</p>
        <p>Template 				content does not wrap horizontally. If the applied, i.e., <em>populated</em>, 				template is greater than <strong>wrapLimit</strong> chars, each line will be trimmed at <strong>wrapLimit</strong> chars and ellipsis chars will be added to indicate trimming.</p>
        <p>If wrapping is 				disabled, the banner will be horizontally trimmed at 240 chars 				(the maximum wrapping value).</p>
        <p>Shorter lines in 				the banner will be right padded with spaces to the wrapping width 				(or the maximum wrapping value if disabled).</p>
        <p> Placeholder names are quite self-explanatory, except: </p>
        <ul>
          <li>
            <p>&quot;FILE STATUS&quot;: will 					return one of the &quot;full&quot;, &quot;trimmed&quot; or &quot;vol. 					no. #&quot;,<br />
              where <em>full</em>, means that no split or trim 					operation have occurred yet, <em>trimmed</em> means the log file 					has been trimmed, and <em>vol</em>... means a split has been made, 					and the current<br />
              file is the <em>n</em>th in the collection;</p>
          </li>
          <li>
            <p>&quot;RELATED CONTEXT NAME&quot;: is the name of the 					calling context, as described by the module's configuration XML 					file. Taking the XML snippet in the previous section as an example, 					it would be &quot;LoginOperations&quot;.</p>
          </li>
        </ul></td>
    </tr>
    <tr valign="top">
      <td><p>entryTemplate</p></td>
      <td><p>any string, optionally including one or more of the following 				placeholders, literally, in the form of %PLACEHOLDER%:<br />
          &quot;Y&quot; 				(for year)</p>
        <p>&quot;M&quot; (for month)</p>
        <p>&quot;D&quot; (for day)</p>
        <p>&quot;H&quot; (for hour)</p>
        <p>&quot;MIN&quot; (for minute)</p>
        <p>&quot;S&quot; (for seconds)</p>
        <p>&quot;CALLING CLASS NAME&quot;</p>
        <p>&quot;CONTENT&quot;</p></td>
      <td><p>Each log file is comprised by a 				header and several <em>entries</em>.</p>
        <p>An <em>entry</em> represents the result of <em>one</em> call to the log() 				method (see the API section). Although entries will frequently 				only span one line, entries and lines mustn't be mistaken.</p>
        <p>The 				module internally adds a non printing <strong>start-of-heading 				char</strong> right before any entry;  				the module uses this delimiter for operations that involve entry 				manipulation, such as the <em>trim</em> functionality. Entries are 				stripped from null chars before printing, should they have any.</p>
        <p>A <strong>bell</strong> char is inserted after the first <strong>start-of-heading 				char</strong>  in file, if the file has been trimmed.</p>
        <p>The <strong>entryTemplate</strong> parameter controls the printed look of an entry. Unlike the 				banner, entries <em>do</em> wrap, and have no limitations in lines number. New lines within 				entries content are preserved.</p>
        <p> The placeholders names are quite self-explanatory, except:</p>
        <ul>
          <li>
            <p>&quot;CALLING 					CLASS NAME&quot;: represents the class name that actually made 					the call to Logger::getInstance()-&gt;log 					(…). Taking 					the XML snippet in the previous section as example, it could be 					either of the &quot;Authenticator&quot;, &quot;CookieManager&quot; 					or &quot;MailHandler&quot;.</p>
          </li>
          <li>
            <p>If omitted, defaults to &quot;%CONTENT%&lt;NL&gt;&quot;; 					If given, it must contain the CONTENT placeholder, or a fatal 					error will be produced.</p>
          </li>
        </ul></td>
    </tr>
    <tr valign="top">
      <td><p>&lt;context&gt; nodes</p></td>
      <td><p>an array holding class names, in the form of &quot;ClassName&quot;</p></td>
      <td><p>Any param 				node with a name 				different from all of the above is considered to be a <em>context</em> definition.</p>
        <p>A 				context definition must be comprised of one or several unique 				class names and have an unique name. In other words, there cannot 				be several <em>contexts</em> named the same, nor can a class name appear in more than exactly 				one <em>context</em> definition. Failing to comply with any of the above will produce 				a fatal error.</p>
        <p> The rationale is to group calling classes into contexts, since it 				is likely to be impractical to have each calling class logging 				into its own log file – this can be achieved, though, by 				specifying a context with a single class.</p>
        <p>If 				none given, a context named &quot;Main&quot; is assumed, which 				will include all calling classes that will ever log 				(…). 				 By exception, the &quot;Main&quot; context can be </p>
        <p>overridden by explicitly 				defining a context with this name.</p></td>
    </tr>
  </tbody>
</table>
<h2>Known Limitations &amp; Gotchas</h2>
<ul>
  <li>
    <p>The module can only be called from within a class execution 	context.</p>
  </li>
  <li>
    <p>The line ending in log files will be <em>UNIX style</em>, 	irrespective to the host operating system or the line ending used by 	the <em>entries template</em> or the original line ending of the 	content to be logged.</p>
  </li>
</ul>
</body>
</html>
Return current item: Logger_ciacob