TypeScript logging with log4javascript in an ASP.Net MVC application

I needed to add logging functionality to an existing TypeScript application hosted on ASP.Net MVC.

Since I usually use log4net in C#, log4javascript was an obvious choice, as it provides a similar API.

First, I needed to declare the parts of the log4javascript API I use in TypeScript:

declare module log4javascript {
    class Logger {
        info(msg: string);
        info(msg: string, value: any);
        addAppender(app: AjaxAppender);
    function getLogger(name: string): Logger;
    function getNullLogger(): Logger;
    class AjaxAppender {
        constructor(url: string);
        setSessionId(id: string);
        setLayout(layout: JsonLayout);
        addHeader(key: string, value: string);
    class JsonLayout {
        constructor(readable: boolean, combine: boolean);

In the logging class, I added logger and AjaxAppender. Depending on the data to log, I also configure a JsonLayout.

logger: log4javascript.Logger;

A non-logging logger instance is created using getNullLogger():

this.logger = log4javascript.getNullLogger();

Plain-text AjaxAppender

Use these statements to create an Ajax-based logger in TypeScript:

this.logger = log4javascript.getLogger("MyLoggerName");
var app = new log4javascript.AjaxAppender("http://myhost/myapp/mylogger");

On the MVC side, the controller receives the parameters: logger, timestamp, level, url, message, sessionid, and layout. (Note that these parameter names can be changed using the setKeys() method)

The value for sessionid is set using


To log a string message, simply write

this.logger.info("my info log message");

The C# controller method stub therefore looks something like this:

public ActionResult Log(long? timestamp, string level, string sessionid, string message)
    var ipaddr = Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
    if (string.IsNullOrEmpty(ipaddr))
        ipaddr = Request.ServerVariables["REMOTE_ADDR"];
    if (string.IsNullOrEmpty(ipaddr))
        ipaddr = Request.UserHostAddress;

    if (level == "INFO")
        logger.Info(ipaddr + " " + sessionid + " " + message);
        logger.Debug("[" + level + "] " + ipaddr + " " + sessionid + " " + message);
    return Json(null);

where logger is an instance of log4net.Ilog.

JSON-formatted AjaxAppender

To change the appender’s data format to JSON, we set its layout to JsonLayout:

this.logger = log4javascript.getLogger("MyJsonLogger");
var app = new log4javascript.AjaxAppender("http://myhost/myapp/myjsonlogger");
app.setLayout(new log4javascript.JsonLayout(false, false));
app.addHeader("Content-Type", "application/json");

The C# controller method receives a JSON array of log entries

            [    "message1",
                "message2", ...

where message1, message2, etc are the parameters of the logger’s debug/info/warn etc. calls.

We create a C# class containing the required properties

public class Data
    public string logger;
    public long? timestamp;
    public string level;
    public string url;
    public string[] message;

and deserialize the HTTP request’s InputStream using JSON.Net:

public ActionResult Execute()
    string inputContent;
    using (var sr = new StreamReader(HttpContext.Request.InputStream))
        inputContent = sr.ReadToEnd();
    var data = JsonConvert.DeserializeObject<Data[]>(inputContent);

    if (data != null)
        foreach (var d in data)
            if (d.level == "INFO")
                logger.Info(d.message[0] + " " + d.message[1]);
                logger.Debug("[" + d.level + "] " + d.message[0] + " " + d.message[1]);
    return Json(null);

Again, logger is an instance of log4net.Ilog.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: