Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Add filter possibility to only log perf data when some specific condi…

…tions are triggered

Tag for 0.5 release
  • Loading branch information...
commit e7de046f7b4e2884d5f9aec2e678dc3cbee38e97 1 parent e3a315f
Gaetano Giunta authored
111 classes/ezperflogger.php
@@ -12,6 +12,7 @@
12 12 class eZPerfLogger implements eZPerfLoggerProvider, eZPerfLoggerLogger
13 13 {
14 14 static protected $custom_variables = array();
  15 + static protected $outputSize = null;
15 16
16 17 /**
17 18 * Record a value associated with a given variable name.
@@ -27,7 +28,7 @@ static public function recordValue( $varName, $value )
27 28 */
28 29 static public function recordValues( array $vars )
29 30 {
30   - foreach( $vars as $varname => $value )
  31 + foreach( $vars as $varName => $value )
31 32 {
32 33 self::$custom_variables[$varName] = $value;
33 34 }
@@ -45,48 +46,79 @@ static public function filter( $output )
45 46 {
46 47 // look up any perf data provider, and ask each one to record its values
47 48 $ini = eZINI::instance( 'ezperformancelogger.ini' );
48   - foreach( $ini->variable( 'GeneralSettings', 'VariableProviders' ) as $measuringClass )
  49 +
  50 + $skip = false;
  51 +
  52 + $filters = $ini->variable( 'GeneralSettings', 'LogFilters' );
  53 + // cater to 'array reset' situations
  54 + foreach( $filters as $i => $v )
49 55 {
50   - /// @todo !important check that $class exposes the correct interface
51   - $measured = call_user_func( array( $measuringClass, 'measure' ) );
52   - if ( is_array( $measured ) )
53   - {
54   - self::recordValues( $measured );
55   - }
56   - else
  56 + if ( $v == '' )
57 57 {
58   - eZDebug::writeError( "Perf measuring class $class did not return an array of data", __METHOD__ );
  58 + unset( $filters[$i] );
59 59 }
60 60 }
61   - // build the array with the values we want to record in the logs -
62   - // only the ones corresponding to variables defined in the ini file,
63   - // not all the values measured so far
64   - /// @todo !important replace with a faster array_intersect?
65   - $values = array();
66   - foreach( $ini->variable( 'GeneralSettings', 'TrackVariables' ) as $i => $var )
  61 + if ( count( $filters ) )
67 62 {
68   - $values[$var] = isset( self::$custom_variables[$var] ) ? self::$custom_variables[$var] : null;
  63 + $skip = true;
  64 + foreach( $filters as $filterClass )
  65 + {
  66 + if ( call_user_func_array( array( $filterClass, 'shouldLog' ), array( $output ) ) )
  67 + {
  68 + $skip = false;
  69 + break;
  70 + }
  71 + }
69 72 }
70 73
71   - // for each logging type configured, log values to it
72   - foreach( $ini->variable( 'GeneralSettings', 'LogMethods' ) as $logMethod )
  74 + if ( ! $skip )
73 75 {
74   - $logged = false;
75   - foreach( $ini->variable( 'GeneralSettings', 'LogProviders' ) as $loggerClass )
  76 + // get perf data from all registered providers
  77 + foreach( $ini->variable( 'GeneralSettings', 'VariableProviders' ) as $measuringClass )
76 78 {
77 79 /// @todo !important check that $class exposes the correct interface
78   - if ( in_array( $logMethod, call_user_func( array( $loggerClass, 'supportedLogMethods' ) ) ) )
  80 + $measured = call_user_func_array( array( $measuringClass, 'measure' ), array( $output ) );
  81 + if ( is_array( $measured ) )
79 82 {
80   -
81   - call_user_func_array( array( $loggerClass, 'doLog' ), array( $logMethod, $values ) );
82   - $logged = true;
83   - break;
  83 + self::recordValues( $measured );
  84 + }
  85 + else
  86 + {
  87 + eZDebug::writeError( "Perf measuring class $class did not return an array of data", __METHOD__ );
84 88 }
85 89 }
86   - if ( !$logged )
  90 +
  91 + // build the array with the values we want to record in the logs -
  92 + // only the ones corresponding to variables defined in the ini file,
  93 + // not all the values measured so far
  94 + /// @todo !important replace with a faster array_intersect?
  95 + $values = array();
  96 + foreach( $ini->variable( 'GeneralSettings', 'TrackVariables' ) as $i => $var )
87 97 {
88   - eZDebug::writeError( "Could not log perf data to log '$logMethod', no logger class supports it", __METHOD__ );
  98 + $values[$var] = isset( self::$custom_variables[$var] ) ? self::$custom_variables[$var] : null;
89 99 }
  100 +
  101 + // for each logging type configured, log values to it
  102 + foreach( $ini->variable( 'GeneralSettings', 'LogMethods' ) as $logMethod )
  103 + {
  104 + $logged = false;
  105 + foreach( $ini->variable( 'GeneralSettings', 'LogProviders' ) as $loggerClass )
  106 + {
  107 + /// @todo !important check that $class exposes the correct interface
  108 + if ( in_array( $logMethod, call_user_func( array( $loggerClass, 'supportedLogMethods' ) ) ) )
  109 + {
  110 +
  111 + call_user_func_array( array( $loggerClass, 'doLog' ), array( $logMethod, $values ) );
  112 + $logged = true;
  113 + break;
  114 + }
  115 + }
  116 + if ( !$logged )
  117 + {
  118 + eZDebug::writeError( "Could not log perf data to log '$logMethod', no logger class supports it", __METHOD__ );
  119 + }
  120 + }
  121 +
90 122 }
91 123
92 124 if ( eZXHProfLogger::isRunning() )
@@ -106,19 +138,33 @@ static public function filter( $output )
106 138 return $output;
107 139 }
108 140
  141 + static public function supportedVariables()
  142 + {
  143 + return array( 'execution_time', 'mem_usage', 'db_queries', 'output_size', 'xhkprof_runs' );
  144 + }
  145 +
109 146 /**
110 147 * This method is called to allow this class to provide values for the measurements
111 148 * variables it caters to.
112 149 * In this case, it actually gets called by self::filter().
113 150 */
114   - static public function measure()
  151 + static public function measure( $output )
115 152 {
116 153 global $scriptStartTime;
117 154
118   - $ini = eZINI::instance( 'ezperformancelogger.ini' );
  155 + // This var we want to save as it is used for logs even when not in TrackVariables
  156 + /// @todo this way of passing data around is not really beautiful...
  157 + self::$outputSize = strlen( $output );
  158 +
119 159 $out = array();
  160 + $ini = eZINI::instance( 'ezperformancelogger.ini' );
120 161 $vars = $ini->variable( 'GeneralSettings', 'TrackVariables' );
121 162
  163 + if ( in_array( 'ouput_size', $vars ) )
  164 + {
  165 + $out['execution_time'] = self::$outputSize;
  166 + }
  167 +
122 168 if ( in_array( 'execution_time', $vars ) )
123 169 {
124 170 $out['execution_time'] = round( microtime( true ) - $scriptStartTime, 3 );
@@ -207,7 +253,7 @@ public static function doLog( $method, $values )
207 253 case 'syslog':
208 254 /// same format as Apache "combined" by default
209 255 /// @todo it's not always a 200 ok response...
210   - $size = strlen( $output );
  256 + $size = self::$outputSize;
211 257 if ( $size == 0 )
212 258 $size = '-';
213 259 $text = self::apacheLogLine( 'combined', $size, 200 ) . ' ';
@@ -262,7 +308,7 @@ public static function doLog( $method, $values )
262 308 'time' => time(),
263 309 /// @todo
264 310 'response_status' => "200",
265   - 'response_size' => strlen( $output ),
  311 + 'response_size' => self::$outputSize,
266 312 'counters' => $values
267 313 ) ) );
268 314 break;
@@ -529,6 +575,7 @@ static function apacheLogLine( $format = 'common', $size='-', $httpReturn = '200
529 575 return $_SERVER["REMOTE_ADDR"] . ' - - [' . date( 'd/M/Y:H:i:s O' ) . '] "' . $_SERVER["REQUEST_METHOD"] . ' ' . $_SERVER["REQUEST_URI"]. ' ' . $_SERVER["SERVER_PROTOCOL"] . '" 200 ' . $size;
530 576 }
531 577 }
  578 +
532 579 }
533 580
534 581 ?>
4 doc/changelogs/changelog-0.4-to-0.5
... ... @@ -1,7 +1,9 @@
1   -changelog from version 0.4 to 0.5 - released 2012.x.y
  1 +changelog from version 0.4 to 0.5 - released 2012.5.19
2 2
3 3 * New features
4 4 . performance metrics can be logged to syslog
  5 +. filters can be added to only log performance data when specific conditions apply.
  6 + This allows to e.g. replicate the equivalent of the mysql slow query log
5 7
6 8 * Bugfixes
7 9 . make the record_value template operator actually do something
5 doc/todo.txt
@@ -11,7 +11,10 @@ perf logging:
11 11 . add to app some sample spreadsheets where to copy data into that come with pre-made formulas to show eg. view-cache relevancy
12 12 . allow using a Pinba server as target for measurements
13 13 . allow user to set a callback function to make perf logging optional (triggerable)
14   -. allow using snmp traps for logs
  14 +. allow using snmp traps for as target for measurements
  15 +. add some sample filters (eg. log if total time too long or db queries too many or db time too long)
  16 +
  17 +. do some basic testing: pps with no tracing, with tracing on, with debug on
15 18
16 19 xhprof:
17 20 . fix typeahead find in "view" view
25 interfaces/ezperfloggerfilter.php
... ... @@ -0,0 +1,25 @@
  1 +<?php
  2 +/**
  3 + * @author G. Giunta
  4 + * @copyright (C) G. Giunta 2012
  5 + * @license Licensed under GNU General Public License v2.0. See file license.txt
  6 + */
  7 +
  8 +/**
  9 + * Interface implemented by classes which can be used to decide whether to log
  10 + * perf. data at all.
  11 + */
  12 +interface eZPerfLoggerFilter
  13 +{
  14 + /**
  15 + * This method gets called by the framework for all classes regsitered in
  16 + * LogFilters in ezperformancelogger.ini.
  17 + * As soon as one class returns true, logging is activated
  18 + *
  19 + * @string $output current page output
  20 + * @return bool
  21 + */
  22 + public static function shouldLog( $output );
  23 +}
  24 +
  25 +?>
3  interfaces/ezperfloggerlogger.php
@@ -22,6 +22,9 @@ public static function supportedLogMethods();
22 22 * This method gets called to actually log data
23 23 * @param string $logmethod
24 24 * @param array $data $varname => $value
  25 + * @param string $output passed here in case logger wants to examine it more
  26 + *
  27 + * @todo could add a bool return val in case logging fails
25 28 */
26 29 public static function doLog( $logmethod, $data );
27 30 }
9 interfaces/ezperfloggerprovider.php
@@ -14,9 +14,16 @@
14 14 /**
15 15 * This method is called (by the framework) to allow this class to provide
16 16 * values for the variables it caters to.
  17 + * @param string $output current page output
17 18 * @return array variable name => value
18 19 */
19   - public static function measure();
  20 + public static function measure( $output );
  21 +
  22 + /**
  23 + * Returns the list of variables this Provider can measure
  24 + * @return array
  25 + */
  26 + public static function supportedVariables();
20 27 }
21 28
22 29 ?>
2  pake/options-ezperformancelogger.yaml
@@ -3,7 +3,7 @@ extension:
3 3
4 4 version:
5 5 major: 0
6   - minor: 4
  6 + minor: 5
7 7 release: 0
8 8
9 9 ezp:
6 settings/ezperformancelogger.ini
@@ -57,6 +57,12 @@ LogMethods[]=logfile
57 57 LogProviders[]
58 58 LogProviders[]=eZPerfLogger
59 59
  60 +# Optional: logging filters
  61 +# Every php class registered here needs to implement the eZPerfLoggerFilter interface.
  62 +# If no logging filter is defined, performance data is logged on every poge.
  63 +# If filters are defined, perf. data is logged only when at least one filter class returns true
  64 +LogFilters[]
  65 +
60 66 # The name of the log file, for example mytest.log
61 67 # NB: this is used only by logging method "logfile" above.
62 68 # When logging method "apache" is used you should properly configure logfile.ini

0 comments on commit e7de046

Please sign in to comment.
Something went wrong with that request. Please try again.