1 /******************************************************************************* 2 3 Periodic console tracer 4 5 Periodic console tracer - writes messages to the console limited to a 6 specified update interval. This can be used to safely limit the number of 7 writes to the console. The write is done using either Stderr or 8 ocean.util.log.StaticTrace, depending on the value of the struct's 9 static_display member. 10 11 12 Two global instances of this struct exist for convenience: PeriodicTrace and 13 StaticPeriodicTrace. The latter has the static_display flag set to true. 14 15 Usage example with the global instance: 16 17 --- 18 19 import ocean.util.log.PeriodicTrace; 20 21 const ulong trace_interval = 500_000; // only update display after at least half a second has passed 22 23 for ( uint i; i < uint.max; i++ ) 24 { 25 StaticPeriodicTrace.format(trace_interval, "{}", i); 26 } 27 28 --- 29 30 A local instance of the PeriodicTracer struct may be useful in situations 31 where two or more separate periodic outputs are required each with a 32 different update interval. 33 34 Usage example with a local instance: 35 36 --- 37 38 import ocean.util.log.PeriodicTrace; 39 40 PeriodicTracer trace1; 41 trace1.interval = 500_000; // only update display after at least half a second has passed 42 43 PeriodicTracer trace2; 44 trace2.interval = 5_000_000; // only update display after at least 5 seconds have passed 45 46 for ( uint i; i < uint.max; i++ ) 47 { 48 trace1.format("{}", i); 49 trace2.format("{}", i); 50 } 51 52 --- 53 54 Note: 55 this struct automatically calls Trace.flush / StaticTrace.flush after 56 updating. 57 58 Copyright: 59 Copyright (c) 2009-2016 dunnhumby Germany GmbH. 60 All rights reserved. 61 62 License: 63 Boost Software License Version 1.0. See LICENSE_BOOST.txt for details. 64 Alternatively, this file may be distributed under the terms of the Tango 65 3-Clause BSD License (see LICENSE_BSD.txt for details). 66 67 *******************************************************************************/ 68 69 module ocean.util.log.PeriodicTrace; 70 71 import ocean.core.TypeConvert; 72 import ocean.io.Stdout; 73 import ocean.text.convert.Formatter; 74 import ocean.time.StopWatch; 75 import ocean.meta.types.Qualifiers; 76 import ocean.util.log.StaticTrace; 77 78 79 /******************************************************************************* 80 81 Two shared instances of the PeriodicTracer struct, one with a normal 82 "streaming" display via Trace, and one with a static updating display via 83 StaticTrace. 84 85 *******************************************************************************/ 86 87 public PeriodicTracer PeriodicTrace; 88 89 public PeriodicTracer StaticPeriodicTrace; 90 91 static this ( ) 92 { 93 StaticPeriodicTrace.static_display = true; 94 } 95 96 97 98 /******************************************************************************* 99 100 PeriodicTracer struct. 101 102 *******************************************************************************/ 103 104 struct PeriodicTracer 105 { 106 /*************************************************************************** 107 108 Minimum time between updates (microsec) 109 110 ***************************************************************************/ 111 112 public ulong interval = 100_000; // defaults to 1/10 of a second 113 114 115 /*************************************************************************** 116 117 Toggles between static display (true) and line-by-line display (false) 118 119 ***************************************************************************/ 120 121 public bool static_display; 122 123 124 /*************************************************************************** 125 126 Timer, shared by all instances of this struct (there's only one time!) 127 128 ***************************************************************************/ 129 130 static public StopWatch timer; 131 132 133 /*************************************************************************** 134 135 Time of last update 136 137 ***************************************************************************/ 138 139 private ulong last_update_time; 140 141 142 /*************************************************************************** 143 144 Time retrieved by the most recent call to timeToUpdate() 145 146 ***************************************************************************/ 147 148 private ulong now; 149 150 151 /*************************************************************************** 152 153 Buffer for string formatting. 154 155 ***************************************************************************/ 156 157 private mstring formatted; 158 159 160 /*************************************************************************** 161 162 Outputs a formatted string to the console if the update interval has 163 passed. The display is either static or adds a newline depending on the 164 this.static_display member. 165 166 Params: 167 Args = Tuple of arguments to format 168 fmt = format string (same format as tanog.util.log.Trace) 169 args = variadic list of values referenced in format string 170 171 Returns: 172 this instance for method chaining 173 174 ***************************************************************************/ 175 176 public typeof(&this) format (Args...) ( cstring fmt, Args args ) 177 { 178 if (this.timeToUpdate()) 179 { 180 this.last_update_time = this.now; 181 182 this.formatted.length = 0; 183 assumeSafeAppend(this.formatted); 184 sformat(this.formatted, fmt, args); 185 186 if (this.static_display) 187 StaticTrace.format("{}", this.formatted).flush; 188 else 189 Stderr.formatln("{}", this.formatted).flush; 190 } 191 return &this; 192 } 193 194 195 /*************************************************************************** 196 197 Outputs a formatted string to the console if the specified update 198 interval has passed. The display is either static or adds a newline 199 depending on the this.static_display member. 200 201 Params: 202 Args = Tuple of arguments to format 203 interval = minimum interval between display updates 204 fmt = format string (same format as tanog.util.log.Trace) 205 args = variadic list of values referenced in format string 206 207 Returns: 208 this instance for method chaining 209 210 ***************************************************************************/ 211 212 public typeof(&this) format (Args...) ( ulong interval, cstring fmt, Args args ) 213 { 214 this.interval = interval; 215 return this.format(fmt, args); 216 } 217 218 219 // TODO: flush() method 220 221 222 /*************************************************************************** 223 224 Checks if it's time to update the display. 225 226 Note: this method is public so that using classes can determine whether 227 they need to perform any internal update before calling display(). 228 229 TODO: this would be better done with a lazy char[] version of format(), 230 which only calls the lazy delegate if it *is* time to update. 231 232 Returns: 233 true if the display update interval has passed 234 235 ***************************************************************************/ 236 237 public bool timeToUpdate ( ) 238 { 239 this.now = timer.microsec(); 240 return this.now > this.last_update_time + this.interval; 241 } 242 243 244 /*************************************************************************** 245 246 Static constructor, starts the shared timer. 247 248 ***************************************************************************/ 249 250 static this ( ) 251 { 252 timer.start(); 253 } 254 }