Log4js - It’s a little different now.

Thanks, Tutorial, Tools No Comments »

One of the good parts about including things with scope is that you don’t have to worry about changing them into a more extension-friendly namespace format, which is nice.

So I didn’t have to adapt log4js to get it to play nicely in chrome at all. However, I did have to change it to make it a little more Andy friendly.

Basically, I wanted the log output to hit the console (using dump()) and to look like…

startTime logLevel [fileName:lineNum] message\n
eg.


23/03/07 22:10:11:342 DEBUG [overlay.js:14] A debug message
23/03/07 22:10:12:589 DEBUG [overlay.js:21] Another message

Log4js can’t log to a command prompt using dump(). That was an easy change, we just needed to add another appender, as below.


/**
 * Appender writes the logs to the Shell of Firefox when it is launched with
 * firefox -console (and has the necessary properties enabled)
 * PLEASE NOTE - Only works in Firefox
 * @constructor
 * @extends Appender
 * @param logger log4js instance this appender is attached to
 * @author Andrew Mutton
 */
function FirefoxConsoleAppender(logger) {
...
	this.layout = new MozStackLayout(true);
}

FirefoxConsoleAppender.superclass = Appender.prototype;
FirefoxConsoleAppender.prototype = {
	/**
	 * @see Appender#doAppend
	 */
	doAppend: function(loggingEvent) {
		dump(this.layout.format(loggingEvent));
	},
...

So now we can dump to the console. Notice that there’s a new Layout there too? You probably didn’t, since not many people use log4js I imagine.

The new layout is there to take advantage of the information we can get from Components.stack - notably, line numbers and source files.


/**
 * MozStackLayout is a layout that takes advantage of stack data from Mozilla.
 *
 * startTime logLevel [fileName:lineNum] messagen
 *
 *
 * @constructor
 * @extends Layout
 * @author Andrew Mutton
 */
function MozStackLayout(showDate) {
	this.LINE_SEP  = "n";
	this.showDate = showDate;
}
MozStackLayout.prototype = {
	format: function(loggingEvent) {
	    if (this.showDate && Log4js.simpledate) {
    	    var d = new Log4js.simpledate.SimpleDate(loggingEvent.startTime.getTime());
          	return d.toFormattedString("~d/~k/~y ~H:~m:~s:~S") + " " + loggingEvent.level.toString() + " [" +  loggingEvent.getStackFileName() + ":" + loggingEvent.getStackLineNum() + "] " + loggingEvent.message + this.LINE_SEP;
	    } else {
	        return loggingEvent.level.toString() + " [" +  loggingEvent.getStackFileName() + ":" + loggingEvent.getStackLineNum() + "] " + loggingEvent.message + this.LINE_SEP;
	    }
	},
...

this is the bit that uses simpledate: to format the date in a less ugly way than you usually get for free from Javascript. I honestly have no idea why there isn’t a nice date formatter built into the language. It is ridiculous.

There’s a few more changes here as well. I had to change the log() method so that it attempts to get stack data (if it’s available).


log: function(message, logLevel) {
    if (Components && Components.stack) {
        var stack = Components.stack.caller;
        if (stack.toString().indexOf("log4js.js") != -1) {
            stack = stack.caller;
        }
        var loggingEvent = new Log4js.LoggingEvent(this.category, logLevel, message, this, stack.toString());
    } else {
        var loggingEvent = new Log4js.LoggingEvent(this.category, logLevel, message, this);
    }
...

and also LoggingEvent, so that it can give the stack information


getStackFileName : function() {
    if (this.stackInfo != null) {
        var split = this.stackInfo.split(" :: ");
        var fileName = split[1];
        if (fileName.lastIndexOf("/") != -1) {
            var pathSplit = fileName.split("/");
            fileName = pathSplit[pathSplit.length - 1];
        }
        return fileName
    }
    return null;
},

getStackLineNum : function() {
    if (this.stackInfo != null) {
        var split = this.stackInfo.split(" :: ");
        var lineNum = split[3].split(" ")[1];
        return lineNum;
    }
    return null;
}

So there you have it. Not very interesting today, but this should be the last infrastructure post. I think we can begin doing things properly now.

I’m very interested in getting log4js to be configurable via a properties files (ala log.properties in log4j). This doesn’t seem too hard, so I may have to check it out. An alternative to log.properties would be to write the configuration in JS. Something like…


logger("booksmarts.log").atLevel("DEBUG")
    .withAppender("FirefoxConsoleAppender")
    .andLayout("MozStackLayout");

this would be too simple though. Maybe something more elaborate. Who can really say eh?

Venkman is your friend.

Tools No Comments »

I was going to start doing some actual work on the extension tonight, and investigate the new database support in Firefox (I think this is something that will be very useful)…

Instead, I started dealing with one of my pet Javascript peeves. I hate having to put multiple <script> tags in my code to include lots of JS files. If one piece of Javascript depends on another piece of Javascript then I WANT IT TO SAY SO!

I’d hoped that someone else would’ve figured out a neat way of doing this by now, but they haven’t (dojo comes close, but it’s not good enough).

Here’s what I want…

  1. import(”org.getbooksmarts.SomeClass”) should load the JS at org/getbooksmarts/SomeClass.js from the root.
  2. the root should be definable by a parameter
  3. my importer should be able to start my other js. It should act as a bootstrap loader using something like <script src="import.js?main=org.getbooksmarts.Booksmarts">
  4. ideally it will work in chrome and html, but I can live with just chrome for now

It’s conceptually not too hard. The addition of new JS files is done by adding new <script> tags into the DOM. That works fine in HTML, I’m just having trouble in chrome for some reason.

This is why Venkman. Everyone thinking about developing extensions NEEDS the Mozilla Javascript debugger. This is not an optional step.

About the Ant build script

Tools No Comments »

It’s not too bad (build.xml).

It has targets to do the two main things you need:

  • create (and delete) the pointer file in your Firefox profile/extension directory
  • create xpi files for releases

and it gets some of the information it needs from the project’s install.rdf.

You have to edit the build.xml project name and the path to your Firefox profile. Everything else comes from install.rdf. I used to get annoyed about manually updating version numbers and stuff in multiple places, and having different ant scripts for my projects so now it just works.

An environmentalist.

Tutorial, Tools No Comments »

Today is a lazy Saturday and I’ve decided it’s a perfect day to start writing this extension. Luckily I don’t actually have to do that much to start. It’s all getting the file structure right and configuring the dev environment. Admin stuff really (the exciting stuff was getting the server to work for this website - you missed it).

Dev environment
I’m a Java developer by day (now working at an investment bank in London), so I have ways I like to do things that come from my Java life. You’ll find this in everything I do. It’s just how I am. I’d like to get into other languages (Ruby) but scripting languages don’t have the amazing refactoring tools that I love from Java. When they do, I’m there!

  1. I use Eclipse. It’s a choice and it’s probably overkill for extension development, but it’s what I use.
  2. I use the JSEclipse plugin to get semi-decent JavaScript development going from within Eclipse.
  3. I use Subversion to hold all of my stuff in source-control (normally on my local machine, but for this I’ll put it up on the website).
  4. I build my extensions using Ant. I have a script that works and I use it.

The SVN connection url is http://getbooksmarts.org/svn/booksmarts/. Anonymouse access is enabled. If anyone wants to contribute get in touch and we’ll see what we can do. You’d have to write about how you’re doing stuff on here too.

If you ever checkout the SVN repository, you’ll have my source, project and Ant scripts. It’ll all work without Eclipse, but it’s all integrated in there so I like it.

JSEclipse was recently bought by Adobe, so I don’t know what they’re going to do with it. Hopefully it means money will be there and they can make it REALLY good. Refactoring support for JavaScript would be really hard and REALLY awesome.

Firefox (post 1.5) lets you work on extensions in place, and tell it where to find the source using a pointer file in your profile. This is probably the most useful thing they added for extension developers. The only thing it requires is a special testing format chrome.manifest file. I use the testing chrome.manifest and then produce the package format (using Ant substitutions) when building a deployable. You shouldn’t have to think about it if you use my script.

There’s always a better way to do stuff. I just do what seems best and stick with it. Tell me if I’m being dumb.

© 2007 Andy Mutton | WordPress Theme & Icons by N.Design Studio
Entries RSS Comments RSS Login