All you need to know about jQuery Source Maps

What are exactly Source Maps?

In case of jQuery, Source Map is nothing but mapping of minified version of jQuery against the un-minified version. At the moment just Google Chrome is supporting this feature, but Mozilla Firefox is planning support as well. To know more about Source Map, visit this tutorial.

At the time of writing this article, Chrome version is : 24.0.1312.52 m

UPDATED ON SEPTEMBER 5, 2013: Source Map feature is now also supported by Firefox version : 23.0.1 Read “How to enable source maps in Firefox

Why Source Maps are useful?

Well, imagine that you are using compressed versions of your files on your production site, including a compressed version of jQuery. You get a report that an important customer is running into a problem. Then how do you debug it? You could debug it a lot easier if you had the uncompressed source, but using that on your high-traffic production site isn’t an option.

Consider, you are using minified version of jQuery and you are trying to debug particular line of code. (See Image)

Now when you start debugging and you are on the particular line.

And you press (F11 or Click Step into Next Function Call), the debugger tool will take you to jquery.min.js.

And looking at jquery minified version, it is impossible to find out the error.

But with source maps, you can let the browser’s debugger “map” the lines in the compressed file into the uncompressed source. For Source map to work successfully, two things are required.
1. Value of sourceMappingURL exists on your server or locally.
2. Browser Support

If you are using jQuery from any of the CDN (jQuery, Google, Microsoft) then you don’t have to worry about sourceMappingURL variable value because it is already set. Below screenshot is of jQuery 1.9.0.min.js and notice that the value is already set to jquery.min.map file.

jQuery team has also confirmed that jQuery final releases will also get matching source maps from now on.

Enable Source Map in Chrome

To enable source maps in chrome, Go to Tools -> Developer Tools. Or right click on the browser area and select “Inspect Element”. Once it is open, click on Setting. (See Image)

Now, in Settings -> General Tab, you will find option to “Enable Source Map”. So check this option to enable it. If you don’t find this option, then please update your Chrome to latest version.

Now when you execute the same line of code again and press (F11 or Click Step into Next Function Call), the debugger tool will take you to jquery.js

Important notes

When hosting your own copy of jQuery, copy the map to your server and use it from there. For simplicity we assume that the compressed and uncompressed copy of jQuery is in the same folder as the map file; this is the case for CDN versions and you should follow the same rule if you make local copies.

The map file name is the same as the compressed version, with .map replacing .js. Do not rename the files when you copy them. So, if you were to use a local copy of jquery-1.9.0.min.js the corresponding map file would be jquery-1.9.0.min.map and the uncompressed file would be jquery-1.9.0.js in the same folder.

And you must be wondering how to I create .map file or what are the content of .map file? Well, you can get all the details 

rget="_blank" rel="nofollow">here. If you want to take a look at jquery.min.map file then open thisURL.

Conclusion

This is indeed a very useful feature as it allows to debug minified version against a un-minified version. And it will become more effective when other browsers also start supporting it.

via: http://www.jquerybyexample.net/2013/01/all-you-need-to-know-about-jquery-source-maps.html

Creating Log4Net appenders programatically in C#

In most cases using log4net’s xml configuration is best to set up how your application will log. However I found it more practical to create the configuration programatically in a shared c# file, to easily add common options between my applications. First create a static class to hold the following methods and add using:

using log4net;
using log4net.Core;
using log4net.Repository.Hierarchy;
using log4net.Appender;
using log4net.Layout;
using log4net.Filter;

A file appender

        public static IAppender CreateFileAppender(string appCode)
        {
            var appender = new RollingFileAppender
            {
                Name = "RollingFileAppender",
                File = String.Format(@"C:\logs\{0}.log", appCode),
                AppendToFile = false,
                RollingStyle = RollingFileAppender.RollingMode.Size,
                MaxSizeRollBackups = 10,
                MaximumFileSize = "100MB"
            };

            var layout = new PatternLayout
            {
                ConversionPattern = "%newline%date %-5level %logger – %message – %property%newline"
            };

            layout.ActivateOptions();

            appender.Layout = layout;
            appender.ActivateOptions();

            return appender;
        }

A console appender

        public static IAppender CreateConsoleAppender()
        {
            var appender = new ConsoleAppender {Name = "ConsoleAppender"};
            var layout = new PatternLayout
            {
                ConversionPattern = "%newline%date %-5level %logger – %message – %property%newline"
            };

            layout.ActivateOptions();
            appender.Layout = layout;
            appender.ActivateOptions();

            return appender;
        }

An ADO.NET appender

        public static IAppender CreateAdoNetAppender(string cs)
        {
            var appender = new AdoNetAppender
            {
                Name = "AdoNetAppender",
                BufferSize = 1,
                ConnectionType = "System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
                ConnectionString = cs,
                CommandText = @"INSERT INTO Log ([Date], [Thread], [Level], [Logger], [Message], [Exception], [User], [Ip]) VALUES (@log_date, @thread, @log_level, @logger, @message, @exception, @user, @ip)"
            };

            AddDateTimeParameterToAppender(appender, "log_date");
            AddStringParameterToAppender(appender, "thread", 255, "%thread");
            AddStringParameterToAppender(appender, "log_level", 50, "%level");
            AddStringParameterToAppender(appender, "logger", 255, "%logger");
            AddStringParameterToAppender(appender, "message", 4000, "%message");
            AddStringParameterToAppender(appender, "user", 50, "%aspnet-request{AUTH_USER}");
            AddStringParameterToAppender(appender, "ip", 15, "%aspnet-request{REMOTE_ADDR}");
            AddErrorParameterToAppender(appender, "exception", 2000);
            appender.ActivateOptions();
            
            return appender;
        }

The above requires 3 helper functions:

        public static void AddStringParameterToAppender(this AdoNetAppender appender, string paramName, int size, string conversionPattern)
        {
            var param = new AdoNetAppenderParameter
            {
                ParameterName = paramName,
                DbType = System.Data.DbType.String,
                Size = size,
                Layout = new Layout2RawLayoutAdapter(new PatternLayout(conversionPattern))
            };
            appender.AddParameter(param);
        }
        public static void AddDateTimeParameterToAppender(this AdoNetAppender appender, string paramName)
        {
            var param = new AdoNetAppenderParameter
            {
                ParameterName = paramName,
                DbType = System.Data.DbType.DateTime,
                Layout = new RawUtcTimeStampLayout()
            };
            appender.AddParameter(param);
        }
        public static void AddErrorParameterToAppender(this AdoNetAppender appender, string paramName, int size)
        {
            var param = new AdoNetAppenderParameter
            {
                ParameterName = paramName,
                DbType = System.Data.DbType.String,
                Size = size,
                Layout = new Layout2RawLayoutAdapter(new ExceptionLayout())
            };
            appender.AddParameter(param);
        }

Initializing log4net

Now you can easily initialize log4not in the startup of your application. Here are some extra helper functions:

        public static void ConfigureWithFile(string appCode)
        {
            var h = (Hierarchy)LogManager.GetRepository();
            h.Root.Level = Level.All;
            h.Root.AddAppender(CreateFileAppender(appCode));
            h.Configured = true;
        }
        public static void ConfigureWithDb(string cs, bool onlyErrors)
        {
            var h = (Hierarchy)LogManager.GetRepository();
            h.Root.Level = Level.All;

            var ado = CreateAdoNetAppender(cs);
            h.Root.AddAppender(ado);

            if (onlyErrors)
            {
                var filter = new LevelRangeFilter {LevelMin = Level.Error};
                ((AppenderSkeleton)ado).AddFilter(filter);
            }

            h.Configured = true;
        }

So now, if example you have a web application:

protected void Application_Start(object sender, EventArgs e)
{
LogHelpers.ConfigureWithDb(@"Data Source=.\SQL2008;Initial Catalog=Today;Integrated Security=True",false);
LogHelpers.ConfigureWithFile("MyWebApp");
}

The above would log to the database (only the errors) plus a file (all log levels). The rest is all the same, e.g. to get the logger instance:

public static readonly ILog Log = LogManager.GetLogger(typeof(MyClass));

via: http://codesofair.wordpress.com/2012/02/01/creating-log4net-appenders-programatically-in-c/