Hopeless Geek

Tagline

Power corrupts. Absolute power is kind of neat.

Home » Blogs » Adam Knight's blog

Better Logging


  • Cocoa
November 18, 2005 - 10:22pm

NSLog is nice, but we can do better (no, not that NSLog, though it’s good, too). I came across A Better NSLog a few weeks ago and loved the result so much I came up with a variant in use, and I’m sure you can come up with others.

The deal is, would you rather have:

2005-11-15 01:30:20.566 MyApp[123] we shouldn't hit this!

Or:

2005-11-15 01:30:20.566 MyApp[123] MyDocument:43 in -[MyDocument buggyMethod]: we shouldn't hit this!

The answer is obvious.

To do this, I made a new Cocoa class for my apps called DLog, for, obviously, Debug Log. The code is below and the classes are attached to this post.

==

#import <Cocoa/Cocoa.h>




#define DLog(s,...) [DLog logFile:FILE lineNumber:LINE format:(s),##__VA_ARGS__]


#define DFLog(s,...) [DLog logFile:FILE lineNumber:LINE function:(char*)__FUNCTION__ format:(s),##__VA_ARGS__]




interface</span> DLog : NSObject {</p> <p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Monaco">}</p> <p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Monaco; min-height: 14.0px"><br /></p> <p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Monaco">+ (<span style="color: #760f50">void</span>) logFile: (<span style="color: #760f50">char</span> *) sourceFile lineNumber: (<span style="color: #760f50">int</span>) lineNumber format: (NSString *) format, ...;</p> <p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Monaco">+ (<span style="color: #760f50">void</span>) logFile: (<span style="color: #760f50">char</span> *) sourceFile lineNumber: (<span style="color: #760f50">int</span>) lineNumber function: (<span style="color: #760f50">char</span> *) functionName format: (NSString *) format, ...;</p> <p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Monaco">+ (<span style="color: #760f50">void</span>) setLogOn: (<span style="color: #760f50">BOOL</span>) logOn;</p> <p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Monaco; min-height: 14.0px"><br /></p> <p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Monaco; color: #760f50">end

==

When you import this header into your code, two macros are defined for you. The C preprocessor replaces such macros with the macro content before compiling the code, so the __LINE__ item becomes the line of the item you’re dealing with. Thus, every time I use DFLog I’m invoking the class method logFile:lineNumber:function:format: instead.

Speaking of methods:

==



#import “DLog.h”




static BOOL __DEBUG=NO;




implementation<span style="color: #000000"> DLog</span></p> <p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Monaco; min-height: 14.0px"><br /></p> <p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Monaco">+ (<span style="color: #760f50">void</span>) initialize</p> <p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Monaco">{</p> <p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Monaco"><span class="Apple-tab-span" style="white-space:pre"> </span><span style="color: #760f50">char</span> *env = getenv(<span style="color: #891315">"DEBUG"</span>);</p> <p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Monaco"><span class="Apple-tab-span" style="white-space:pre"> </span>env = (env NULL ? "" : env);

if(strcmp(env, "YES") <span style="color: #0000ff">0</span>)</p> <p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Monaco"><span class="Apple-tab-span" style="white-space:pre"> </span><span class="Apple-tab-span" style="white-space:pre"> </span>__DEBUG = <span style="color: #760f50">YES</span>;</p> <p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Monaco">}</p> <p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Monaco; min-height: 14.0px"><br /></p> <p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Monaco">+ (<span style="color: #760f50">void</span>) logFile: (<span style="color: #760f50">char</span> *) sourceFile</p> <p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Monaco"><span class="Apple-tab-span" style="white-space:pre"> </span><span class="Apple-converted-space">  </span>lineNumber: (<span style="color: #760f50">int</span>) lineNumber</p> <p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Monaco"><span class="Apple-tab-span" style="white-space:pre"> </span><span class="Apple-tab-span" style="white-space:pre"> </span><span class="Apple-converted-space">  </span>format: (NSString *) format, ...;</p> <p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Monaco">{</p> <p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Monaco"><span class="Apple-tab-span" style="white-space:pre"> </span>va_list ap;</p> <p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Monaco"><span class="Apple-tab-span" style="white-space:pre"> </span>NSString *print, *file;</p> <p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Monaco"><span class="Apple-tab-span" style="white-space:pre"> </span><span style="color: #760f50">if</span>(__DEBUG NO)

return;

va_start(ap, format);

file = [NSString stringWithCString:sourceFile];

print = [[NSString alloc] initWithFormat:format arguments:ap];

va_end(ap);

NSLog(@"%s:%d %@", [[file lastPathComponent] UTF8String], lineNumber, print);

[print release];

}


+ (void) logFile: (char *) sourceFile

  lineNumber: (int) lineNumber

function: (char *) functionName

  format: (NSString *) format, ...;

{

va_list ap;

NSString *print, *file, *function;

if(__DEBUG <span style="color: #760f50">NO</span>)</p> <p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Monaco; color: #760f50"><span style="color: #000000"><span class="Apple-tab-span" style="white-space:pre"> </span><span class="Apple-tab-span" style="white-space:pre"> </span></span>return<span style="color: #000000">;</span></p> <p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Monaco"><span class="Apple-tab-span" style="white-space:pre"> </span>va_start(ap,format);</p> <p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Monaco"><span class="Apple-tab-span" style="white-space:pre"> </span>file = [NSString stringWithCString:sourceFile];</p> <p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Monaco"><span class="Apple-tab-span" style="white-space:pre"> </span>function = [NSString stringWithCString:functionName];</p> <p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Monaco"><span class="Apple-tab-span" style="white-space:pre"> </span>print = [[NSString alloc] initWithFormat:format arguments:ap];</p> <p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Monaco"><span class="Apple-tab-span" style="white-space:pre"> </span>va_end(ap);</p> <p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Monaco; min-height: 14.0px"><span class="Apple-tab-span" style="white-space:pre"> </span></p> <p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Monaco"><span class="Apple-tab-span" style="white-space:pre"> </span>NSLog(<span style="color: #891315">”%s:%d in %@ %@”, [[file lastPathComponent] UTF8String], lineNumber, function, print);



[print release];


}




+ (void) setLogOn: (BOOL) logOn


{


__DEBUG=logOn;


}




@end

==

Now the really great thing about this solution is that it’s a drop-in replacement for NSLog. Replace all instances of NSLog in other files with DLog to get the file and line, or DFLog to get the function as well.

Now this won’t work by default. You’ll need to add the environment variable DEBUG=YES to your executable in Xcode. What this means, also, is that you can tell your users to run with that flag and then get a level of debugging output. Perhaps you could setup a DFLog1 to DFLog9 and get logging levels. You get the idea.

  • Adam Knight's blog
  • Printer-friendly version

Post new comment

The content of this field is kept private and will not be shown publicly.
 
Input format
  • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>. Beside the tag style "<foo>" it is also possible to use "[foo]".
  • Link to Amazon products with: [amazon product_id inline|full|thumbnail]. Example: [amazon 1590597559 thumbnail]
  • You can use Textile markup to format text.
  • Textual smileys will be replaced with graphical ones.
  • You may insert videos with [video:URL]
  • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>. Beside the tag style "<foo>" it is also possible to use "[foo]".
  • Link to Amazon products with: [amazon product_id inline|full|thumbnail]. Example: [amazon 1590597559 thumbnail]
  • You can use Markdown syntax to format and style the text. Also see Markdown Extra for tables, footnotes, and more.
  • Textual smileys will be replaced with graphical ones.
  • You may insert videos with [video:URL]
  • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>. Beside the tag style "<foo>" it is also possible to use "[foo]".
  • Link to Amazon products with: [amazon product_id inline|full|thumbnail]. Example: [amazon 1590597559 thumbnail]
  • Lines and paragraphs break automatically.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Textual smileys will be replaced with graphical ones.
  • You may insert videos with [video:URL]

More information about formatting options

Syndicate content Syndicate content

Site Navigation

  • Home
  • Recent
  • Popular
    • Today
  • Top rated
    • Recent votes
  • Elsewhere
    • FriendFeed
    • Friends
    • Software
    • Unsane
View Adam Knight's profile on LinkedIn

Navigation

  • My votes

Recent comments

  • Do you have any idea as to
    2 weeks 2 days ago
  • Absolutely amazing when you
    2 weeks 3 days ago
  • I am pro-choice, but not for
    3 weeks 6 days ago
  • My apologies. It is your
    4 weeks 12 hours ago
  • Well, first, get your own
    4 weeks 16 hours ago
  • There is nothing mythical
    4 weeks 17 hours ago
  • Well, the number of square
    4 weeks 4 days ago
  • I think you’re wrong by a
    4 weeks 4 days ago
  • I couldn’t agree more! I am
    4 weeks 4 days ago
  • I think those numbers are
    4 weeks 5 days ago

Today's popular content

  • Careful, America... (533)
  • Comment Spam Attack (32)
  • Do-It-Yourself Smart Radio Station (30)
  • Krispy Kreme bacon cheddar cheeseburgers (20)
  • Panther's Major Text Services Upgrade (16)
more

Hopeless Geek Feeds

  • Hopeless Geek
  • Hopeless Geek - Comments

Quotes

“By experts in poverty I do not mean sociologists, but poor men.” — ILN, 3/25/11 – G. K. Chesterton

Footer Links

  • Badges
  • Contact
Powered by Drupal, an open source content management system
© Adam Knight, All Rights Reserved except where otherwise noted.