Skip to content

Common.Logging Packaging and Versions

sbohlen edited this page Oct 27, 2014 · 5 revisions

Background

Common.Logging has been around for a long time -- its design, packaging, versioning, and naming choices all pre-date the arrival of NuGet as a .NET package manager by a considerable margin. Its important to note that this means that the choices for these aspects of how Common.Logging was initially structured were all made in a world where NuGet did not exist.

Common.Logging has always supported multiple logging frameworks -- after all, that's the primary point of Common.Logging: the developer codes to a single abstraction and then is able to plug their logging framework of choice into Common.Logging to do the actual logging work itself. In addition to supporting multiple logging frameworks, Common.Logging also supports multiple versions of each of the logging frameworks for which it provides adapters.

Understanding by Example

The simplest way to understand the history of the versioning and packaging choices is to use a single logging framework as an example. We'll use NLog for our discussions, although the patterns and versioning discussed here apply identically to all other logging frameworks supported by Common.Logging.

When Common.Logging 1.0 was released, it supported only a single version of each logging framework -- the latest version of each available at the time (e.g., NLog 1.0, Log4Net 1.2.9). The binary that specifically supported NLog was named simply Common.Logging.NLog. This worked fine so long as there was only a single version of NLog (Nlog 1.0), but what do you do when NLog 2.0 is released and we want to support that in Common.Logging as well?

The decision at the time was to handle this as follows:

  1. update the Common.Loggin.NLog binary to support the new NLog 2.0
  2. introduce a new binary to support the "older" NLog 1.0 and append a version suffix to it to distinguish that it supported only the "older" version (e.g., Common.Logging.NLog10)

Unfortunately, this approach to supporting multiple concurrent versions of the same logging framework had two adverse side-effects that routinely created friction for adopters of Common.Logging:

  1. Users had no way to tell from the name of an assembly (e.g., Common.Logging.NLog) which version of NLog it targeted
  2. Updating to the "latest" e.g., Common.Logging.NLog because you wanted to benefit from a bug-fix often meant that users would be surprised to discover that updating Common.Logging.NLog not only updated Common.Logging.NLog but also might very well mean a "secret forced upgrade" from e.g., NLog 1.0 to NLog 2.0

Both of these are issues that are somewhat tenable in a pre-NuGet world where "updating" usually meant travelling to the proejct's website, searching for the binaries you wanted, reading the release notes, downloading, unzipping, and manually updating the references in your projects. That process was sufficiently manual that developers both didn't do it very frequently and paid close attention to what they were doing during an update.

However, both of these issues are radically exacerbated in a NuGet-centric world where a single-click can invoke a whole host of "silent udpates" to any number of binary dependencies in multiple projects. This can be even more pronounced (and often requires NO CLICK AT ALL) thanks to Visual Studio and/or CI servers that blindly try to acquire "the latest" of a package during the NuGet Package-Restore process on each compilation cycle.

To mitigate these issues, the decision was made some time ago to change the strategy for supporting multiple concurrent versions of a single logging framework as follows:

  1. all logger-specific packages (including those that support "the latest" version of each logger) would contain the version-specific suffix always (e.g., Common.Logging.NLog10, Common.Logging.NLog20, Common.Logging.NLog30, etc.)
  2. the existing suffix-free packages (e.g., Common.Logging.NLog) would be abandoned and no longer maintained

This change permits the following benefits:

  1. The package name itself is able to identify the target version of the logging framework that it supports (e.g., Common.Logging.NLog20 targets NLog 2.0)
  2. Users are able to update their existing packages (e.g., Common.Logging.NLog20 v2.1.2 to Common.Logging.NLog20 v2.2.0) to benefit from bug-fixes, new features, etc. in either Common.Logging itself or in the Common.Logging support of NLog 2.0 without concern that these updates might force them to update the version of the logging framework which they presently use in their projects.

To Summarize (again, using NLog as the example):

  1. Use of Common.Logging.NLog is no longer supported. This binary, the accompanying NuGet package, etc. will never be updated/maintained ever again. Consider such packages DEAD.
  2. You should take a dependency on the Common.Logging.NLog#### package the corresponds to the specific version of NLog which you are using in your software (e.g., Common.Logging.NLog20 for NLog 2.0, Common.Logging.NLog31 for NLog 3.1, and so on)
Clone this wiki locally