diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 50709f679a4c80a0c4af614eecdae531b7905e2b..b339a45c43a1dcb4b80ab99e6224bc7232abd723 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,123 +1,55 @@
 stages:
-  - build
   - test
-  - docs
-  - update-assembly-info
-  - build-release
-  - semantic-release
   - release
-  - pre_release
+  - releasetrigger
 
-build:
-  stage: build
-  script:
-    - PowerShell .\build.ps1 -Target Build -Configuration Debug
-  variables:
-    GIT_STRATEGY: clone
-  except:
-    variables:
-      - $GITLAB_USER_ID == $GIT_BOT_USER_ID
-
-test:
+cake:Test:
   stage: test
   script:
-    - PowerShell .\build.ps1 -Target LinterAndTest -Configuration Debug
+    - PowerShell .\build.ps1 -Target Test -Configuration Debug
   variables:
-    GIT_STRATEGY: none
-  dependencies:
-    - build
+    GIT_STRATEGY: clone
   artifacts:
     reports:
       junit: "./Artifacts/TestResults.xml"
     paths:
       - "./Artifacts/*"
   except:
-    variables:
-      - $GITLAB_USER_ID == $GIT_BOT_USER_ID
-
-update-assembly-info:
-  stage: update-assembly-info
-  script:
-    - PowerShell .\build.ps1 -Target UpdateAssemblyInfo
-  variables:
-    GIT_STRATEGY: none
-  dependencies:
-    - test
-  only:
-    - master
-  except:
-    variables:
-      - $GITLAB_USER_ID == $GIT_BOT_USER_ID
-
-build-release:
-  stage: build-release
-  script:
-    - PowerShell .\build.ps1 -Target Build -Configuration Release
-    - PowerShell .\build.ps1 -Configuration Release -Target NugetPack
-  variables:
-    GIT_STRATEGY: none
-  dependencies:
-    - update-assembly-info
-  only:
     - master
-  except:
-    variables:
-      - $GITLAB_USER_ID == $GIT_BOT_USER_ID
-
-docs:
-  stage: docs
-  script:
-    - .\publishDocs.ps1 $GITLAB_TOKEN
-  variables:
-    GIT_STRATEGY: none
-  dependencies:
-    - test
-  only:
-    - master
-  except:
-    variables:
-      - $GITLAB_USER_ID == $GIT_BOT_USER_ID
-
-semantic-release:
-  stage: semantic-release
-  script:
-    - PowerShell .\build.ps1 -Target SemanticRelease
-  variables:
-    GIT_STRATEGY: none
-  dependencies:
-    - test
-  only:
-    - master
-  except:
-    variables:
-      - $GITLAB_USER_ID == $GIT_BOT_USER_ID
+    - tags
 
-release:
-  before_script:
+cake:Release:
   stage: release
   script:
-    - PowerShell .\build.ps1 -Target Build -Configuration Release
-    - PowerShell .\build.ps1 -Configuration Release -Target NugetPack
-    - PowerShell .\build.ps1 -Configuration Release -Target NugetPush --nugetApiKey="$NUGET_API_KEY"
+    - PowerShell .\build.ps1 -Target Release -Configuration Release --nugetApiKey="${NUGET_API_KEY}"
   variables:
     GIT_STRATEGY: clone
+  dependencies:
+    - cake:Test
   artifacts:
     paths:
       - "./Artifacts/*"
   only:
     - tags
 
-pre_release:
-  stage: pre_release
+cake:Prerelease:
+  stage: release
   script:
-    - PowerShell .\build.ps1 -Target Build -Configuration Release
+    - PowerShell .\build.ps1 -Target Prerelease -Configuration Release
   variables:
     GIT_STRATEGY: clone
+  dependencies:
+    - cake:Test
   artifacts:
     paths:
       - "./Artifacts/*"
-  when: manual
   except:
     - tags
     - master
-    
\ No newline at end of file
+
+cake:GitlabRelease:
+    stage: releasetrigger
+    script:
+      - PowerShell .\build.ps1 -Target GitlabRelease --GitlabProjectPath="${CI_PROJECT_PATH}" --gitlabProjectId="${CI_PROJECT_ID}" --gitlabToken="${GITLAB_TOKEN}"
+    only:
+      - master
\ No newline at end of file
diff --git a/GitVersion.yml b/GitVersion.yml
new file mode 100644
index 0000000000000000000000000000000000000000..1bdc0fe219f5f35d8a024a66d9fd715f44539640
--- /dev/null
+++ b/GitVersion.yml
@@ -0,0 +1,7 @@
+mode: ContinuousDeployment
+next-version: 1.0.0
+major-version-bump-message: 'Breaking:'
+minor-version-bump-message: '(Update|New):'
+patch-version-bump-message: 'Fix:'
+no-bump-message: '.*'
+commit-message-incrementing: Enabled
\ No newline at end of file
diff --git a/build.cake b/build.cake
index 4827ab9efc72cf3b541ac20b05fa38295795369a..81648ff61bbee492e1bc7b4390eb8e0cc33d3056 100644
--- a/build.cake
+++ b/build.cake
@@ -1,65 +1,53 @@
-#tool nuget:?package=NUnit.ConsoleRunner&version=3.9.0
-#tool nuget:?package=JetBrains.ReSharper.CommandLineTools&version=2018.3.4
-#tool nuget:?package=vswhere&version=2.6.7
-	
-#addin nuget:https://api.nuget.org/v3/index.json?package=Cake.Npx&version=1.6.0
-#addin nuget:https://api.nuget.org/v3/index.json?package=Cake.Issues&version=0.7.1
-#addin nuget:https://api.nuget.org/v3/index.json?package=Cake.Issues.InspectCode&version=0.7.1
+#tool nuget:?package=NUnit.ConsoleRunner&version=3.10.0
+#tool nuget:?package=vswhere&version=2.8.4
+#tool nuget:?package=GitVersion.CommandLine&version=5.1.3
+
+#addin nuget:https://api.nuget.org/v3/index.json?package=Cake.Json&version=4.0.0
+#addin nuget:https://api.nuget.org/v3/index.json?package=Newtonsoft.Json&version=11.0.2
 #addin nuget:https://api.nuget.org/v3/index.json?package=Cake.FileHelpers&version=3.2.1
-//////////////////////////////////////////////////////////////////////
-// ARGUMENTS
-//////////////////////////////////////////////////////////////////////
+
+using System.Net;
+using System.Net.Http;
+
+// Commandline arguments
 var target = Argument("target", "Default");
 var configuration = Argument("configuration", "Release");
 var nugetApiKey = Argument<string>("nugetApiKey", null);
+var version = Argument("nugetVersion", "");
+var gitlabProjectPath = Argument("gitlabProjectPath", "");
+var gitlabProjectId = Argument("gitlabProjectId", "");
+var gitlabToken = Argument("gitlabToken", "");
 
-//////////////////////////////////////////////////////////////////////
-// PREPARATION
-//////////////////////////////////////////////////////////////////////
-// Define directories.
+// Define directories
 var projects = GetFiles("./**/*.csproj");
 var artifactsDir = Directory("./Artifacts");
 string nupkgDir;
 var solutionFile = GetFiles("./**/*.sln").First();
 var projectName = solutionFile.GetFilenameWithoutExtension().ToString();
-var assemblyInfoSubPath = "Properties/AssemblyInfo.cs";
 var nugetSource = "https://api.nuget.org/v3/index.json";
+var assemblyInfoSubPath = "Properties/AssemblyInfo.cs";
+var semanticVersion = "";
+string localNugetFeed;
 
 // get latest MSBuild version
 var vsLatest  = VSWhereLatest();	
 var msBuildPathX64 = (vsLatest == null) ? null : vsLatest.CombineWithFilePath("./MSBuild/Current/Bin/MSBuild.exe");
 
-// Error rules for resharper
-// Example: {"InconsistentNaming", "RedundantUsingDirective"};
-string[] resharperErrorRules = {};
-// Paths to exclude from dupFinder
-List<string> dupFinderExcludePatterns = projects.Select( x => $"{x.GetDirectory().ToString()}/{assemblyInfoSubPath}").ToList();
-string[] dupFinderExcludeCodeRegionsByNameSubstring = { "DupFinder Exclusion" };
-
-Action <NpxSettings> requiredSemanticVersionPackages = settings =>
-	settings.AddPackage("semantic-release")
-	.AddPackage("@semantic-release/commit-analyzer")
-	.AddPackage("@semantic-release/release-notes-generator")
-	.AddPackage("@semantic-release/gitlab")
-	.AddPackage("@semantic-release/git")
-	.AddPackage("@semantic-release/exec")
-	.AddPackage("conventional-changelog-eslint");
-
-///////////////////////////////////////////////////////////////////////////////
-// SETUP / TEARDOWN
-///////////////////////////////////////////////////////////////////////////////
 Setup(context =>{
 	nupkgDir = $"{artifactsDir.ToString()}/nupkg";
-	Information("Running tasks...");
+	var branch = GitVersion(new GitVersionSettings {
+			UpdateAssemblyInfo = false
+		}).BranchName.Replace("/", "-");
+
+	localNugetFeed = $"C:\\coscine\\LocalNugetFeeds\\{branch}";
+	Information("{0}", branch);
+	Information("Started at {0}", DateTime.Now);
 });
 
 Teardown(context =>{
-	Information("Finished running tasks.");
+	Information("Finished at {0}", DateTime.Now);
 });
 
-//////////////////////////////////////////////////////////////////////
-// TASKS
-//////////////////////////////////////////////////////////////////////
 Task("Clean")
 .Description("Cleans all build and artifacts directories")
 .Does(() =>{
@@ -68,70 +56,36 @@ Task("Clean")
 		Force = true
 	};
 	
-	var directoriesToDelete = new List<DirectoryPath>();
+	var directoriesToClean = new List<DirectoryPath>();
 	
 	foreach(var project in projects) {
-		directoriesToDelete.Add(Directory($"{project.GetDirectory()}/obj"));
-		directoriesToDelete.Add(Directory($"{project.GetDirectory()}/bin"));
+		directoriesToClean.Add(Directory($"{project.GetDirectory()}/obj"));
+		directoriesToClean.Add(Directory($"{project.GetDirectory()}/bin"));
 	}
 	
-	directoriesToDelete.Add(artifactsDir);
+	directoriesToClean.Add(artifactsDir);
 
-	foreach(var dir in directoriesToDelete) {
+	foreach(var dir in directoriesToClean) {
+		Information("Cleaning {0}", dir.ToString());
 		if (DirectoryExists(dir)) {
-			Information($"Cleaning path {dir} ...");
 			DeleteDirectory(dir, settings);
+			CreateDirectory(dir);
+		} else {
+			CreateDirectory(dir);
 		}
 	}
 });
 
 Task("Restore")
 .Does(() =>{
-	// Restore all NuGet packages.
-	Information($"Restoring {solutionFile}...");
 	NuGetRestore(solutionFile, new NuGetRestoreSettings {
-		NoCache = true
+		NoCache = true,
+		FallbackSource = new List<string>{ localNugetFeed },
 	});
 });
 
-Task("DupFinder")
-.Description("Find duplicates in the code")
-.Does(() =>{
-	var settings = new DupFinderSettings() {
-		ShowStats = true,
-		ShowText = true,
-		OutputFile = $"{artifactsDir}/dupfinder.xml",
-		ExcludeCodeRegionsByNameSubstring = dupFinderExcludeCodeRegionsByNameSubstring,
-		ExcludePattern = dupFinderExcludePatterns.ToArray(),
-		ThrowExceptionOnFindingDuplicates = true
-	};
-	DupFinder(solutionFile, settings);
-});
-
-Task("InspectCode")
-.Description("Inspect the code using Resharper's rule set")
-.Does(() =>{
-	var settings = new InspectCodeSettings() {
-		SolutionWideAnalysis = true,
-		OutputFile = $"{artifactsDir}/inspectcode.xml",
-		ThrowExceptionOnFindingViolations = false
-	};
-	InspectCode(solutionFile, settings);
-
-	var issues = ReadIssues(
-	InspectCodeIssuesFromFilePath($"{artifactsDir}/inspectcode.xml"), Context.Environment.WorkingDirectory);
-
-	Information("{0} issues are found.", issues.Count());
-
-	var errorIssues = issues.Where(issue =>resharperErrorRules.Any(issue.Rule.Contains)).ToList();
-
-	if (errorIssues.Any()) {
-		var errorMessage = errorIssues.Aggregate(new StringBuilder(), (stringBuilder, issue) =>stringBuilder.AppendFormat("FileName: {0} Line: {1} Message: {2}{3}", issue.AffectedFileRelativePath, issue.Line, issue.Message, Environment.NewLine));
-		throw new CakeException($"{errorIssues.Count} errors detected: {Environment.NewLine}{errorMessage}.");
-	}
-});
-
 Task("Test")
+.IsDependentOn("Build")
 .Does(() =>{
 	NUnit3($"./src/**/bin/{configuration}/*.Tests.dll", new NUnit3Settings {
 		// generate the xml file
@@ -139,92 +93,167 @@ Task("Test")
 		Results = new NUnit3Result[] {
 			new NUnit3Result() {
 				FileName = $"{artifactsDir}/TestResults.xml",
-				Transform = Context.Environment.WorkingDirectory + "/nunit3-junit.xslt"
+				Transform = $"{Context.Environment.WorkingDirectory}/nunit3-junit.xslt"
 			}
 		}
 	});
 });
 
-Task("NugetPush")
-.Does(() =>{
-	var nupkgs = GetFiles($"{nupkgDir}/*.nupkg");
-
-	Information("Need to push {0} packages", nupkgs.Count);
-	foreach(var nupkg in nupkgs) {
-		Information("Pushing {0}", nupkg);
-		NuGetPush(nupkg, new NuGetPushSettings {
-			Source = nugetSource,
-			ApiKey = nugetApiKey
- 		});
+Task("GitVersion")
+.Does(() => {
+	if(string.IsNullOrWhiteSpace(version)) {
+		version = GitVersion(new GitVersionSettings {
+			UpdateAssemblyInfo = false
+		}).NuGetVersionV2;
 	}
+	var index = version.IndexOf("-");
+	semanticVersion = index > 0 ? version.Substring(0, index) : version;
+	Information("Version: {0}, SemanticVersion: {1}", version, semanticVersion);
 });
 
-Task("NugetPack")
+Task("UpdateAssemblyInfo")
 .Does(() =>{
+	var index = version.IndexOf("-");
+	var semanticVersion = index > 0 ? version.Substring(0, index) : version;
+
 	foreach(var project in projects) {
-			var nuspec = $"{project.GetDirectory()}/{project.GetFilenameWithoutExtension()}.nuspec";
-			if(!project.ToString().EndsWith(".Tests") 
-			&& FileExists(nuspec))
-			{
-				Information("Packing {0}...", nuspec);
-				
-				
-
-				if(!DirectoryExists(nupkgDir)) {
-					CreateDirectory(nupkgDir);
-				}
-				 
-				 NuGetPack(project.ToString() ,new NuGetPackSettings 
-				 {
-					OutputDirectory = nupkgDir,
-					Properties = new Dictionary<string, string> { {"Configuration", "Release"}}
-				 });
-			}
-		}
+		CreateAssemblyInfo($"{project.GetDirectory()}/{assemblyInfoSubPath}", new AssemblyInfoSettings {
+			Product = project.GetFilenameWithoutExtension().ToString(),
+			Title = project.GetFilenameWithoutExtension().ToString(),
+			Company = "IT Center, RWTH Aachen University",
+			Version = semanticVersion,
+			FileVersion = semanticVersion,
+			InformationalVersion = version,
+			Copyright = $"{DateTime.Now.Year} IT Center, RWTH Aachen University",
+			Description = $"{project.GetFilenameWithoutExtension().ToString()} is a part of the CoScInE group."
+		});
+	}
 });
 
+Task("GitlabRelease")
+.IsDependentOn("GitVersion")
+.Does(() => {
+	var client = new HttpClient();
+	client.DefaultRequestHeaders.Add("PRIVATE-TOKEN", gitlabToken);
+	
+	// get the latest tag
+	var result = client.GetAsync($"https://git.rwth-aachen.de/api/v4/projects/{gitlabProjectId}/repository/tags").Result;
+	if(!result.IsSuccessStatusCode) {
+		throw new Exception("Tag query failed.");
+	}
 
-Task("UpdateAssemblyInfo")
-.Does(() =>{
-	Information("Running semantic-release in dry run mode to extract next semantic version number");
-
-	string[] semanticReleaseOutput;
-	Npx("semantic-release", "--dry-run", requiredSemanticVersionPackages, out semanticReleaseOutput);
+	var tagList = result.Content.ReadAsStringAsync().Result;
+	var jArray = JArray.Parse(tagList);
+	// null if not tags exists yet
+	var lastTag = jArray.Select(x => x["name"]).FirstOrDefault();
 
-	Information(string.Join(Environment.NewLine, semanticReleaseOutput));
+	var url = $"https://git.rwth-aachen.de/{gitlabProjectPath}";
+	
+	if(url.EndsWith(".git")) {
+		url = url.Substring(0, url.Length - ".git".Length);
+	}
 
-	var nextSemanticVersionNumber = ExtractNextSemanticVersionNumber(semanticReleaseOutput);
+	if(url.EndsWith("/")) {
+		url = url.Substring(0, url.Length - 1);
+	}
 
-	if (nextSemanticVersionNumber == null) {
-		Warning("There are no relevant changes. AssemblyInfo won't be updated!");
+	var description = "";
+	// First line of description
+	// Gitlab compare url, if something can be compared
+	if(lastTag == null) {
+		description = $"# {semanticVersion} ({DateTime.Now.Year}-{DateTime.Now.Month}-{DateTime.Now.Day})\n\n\n";
 	} else {
-		Information("Next semantic version number is {0}", nextSemanticVersionNumber);
-
-		var assemblyVersion = $"{nextSemanticVersionNumber}.0";
-
-		foreach(var project in projects) {
-			CreateAssemblyInfo($"{project.GetDirectory()}/{assemblyInfoSubPath}", new AssemblyInfoSettings {
-				Product = project.GetFilenameWithoutExtension().ToString(),
-				Title = project.GetFilenameWithoutExtension().ToString(),
-				Company = "IT Center, RWTH Aachen University",
-				Version = assemblyVersion,
-				FileVersion = assemblyVersion,
-				InformationalVersion = assemblyVersion,
-				Copyright = $"{DateTime.Now.Year} IT Center, RWTH Aachen University",
-				Description = $"{project.GetFilenameWithoutExtension().ToString()} is a part of the CoScInE group."
-			});
+		description = $"# [{semanticVersion}]({url}/compare/{lastTag}...v{semanticVersion}) ({DateTime.Now.Year}-{DateTime.Now.Month}-{DateTime.Now.Day})\n\n\n";
+	}
+
+	// From when will messages be parsed, null results in all messages
+	var logParam = "";
+	if(lastTag != null) {
+		logParam = $"{lastTag}..Head";
+	}
+
+	Information(lastTag);
+
+	IEnumerable<string> redirectedStandardOutput;
+	var exitCodeWithArgument =
+		StartProcess(
+			"git",
+			new ProcessSettings {
+				Arguments = $"log {logParam} --pretty=format:HASH%h:%B",
+				RedirectStandardOutput = true
+			},
+			out redirectedStandardOutput
+		);
+
+	var prefixList = new Dictionary<string, List<string>>{
+		{"Fix", new List<string>()},
+		{"Update", new List<string>()},
+		{"New", new List<string>()},
+		{"Breaking", new List<string>()},
+		{"Docs", new List<string>()},
+		{"Build", new List<string>()},
+		{"Upgrade", new List<string>()},
+		{"Chore", new List<string>()},
+	};
+
+	var currentHash = "";
+	// Output last line of process output.
+	foreach(var line in redirectedStandardOutput) {
+		var commitMessage = "";
+		if(line.StartsWith("HASH")) {
+			currentHash = line.Substring("HASH".Length);
+			currentHash = currentHash.Substring(0, currentHash.IndexOf(":"));
+			commitMessage = line.Substring(currentHash.Length + line.IndexOf(currentHash) + 1);
+		} else {
+			commitMessage = line;
 		}
+
+		foreach(var kv in prefixList) {
+			if(commitMessage.StartsWith($"{kv.Key}:")) {
+				kv.Value.Add($"* {commitMessage.Substring(kv.Key.Length + 1).Trim()} {currentHash}");
+				break;
+			}
+		};
+	}
+	
+	foreach(var kv in prefixList) {
+		if(kv.Value.Any()) {
+			description += $" ### {kv.Key}\n\n";
+			foreach(var line in kv.Value) {
+				description += $"{line}\n";
+			}
+			description += "\n";
+		}
+	}
+	// correctly escape the json newlines
+	description = description.Replace("\n", "\\n");
+	Information("Description: {0}", description);
+
+	// create tag
+	result = client.PostAsync($"https://git.rwth-aachen.de/api/v4/projects/{gitlabProjectId}/repository/tags?tag_name=v{semanticVersion}&ref=master", null).Result;
+	Information("Create tag: {0}", result.Content.ReadAsStringAsync().Result);
+	if(!result.IsSuccessStatusCode) {
+		throw new Exception("Tag creation failed.");
+	}
+
+	// create release
+	var json = $"{{\"name\": \"v{semanticVersion}\", \"tag_name\": \"v{semanticVersion}\", \"description\": \"{description}\"}}";
+	var content = new StringContent(json, Encoding.UTF8, "application/json");
+	result = client.PostAsync($"https://git.rwth-aachen.de/api/v4/projects/{gitlabProjectId}/releases", content).Result;
+	Information("Create release: {0}", result.Content.ReadAsStringAsync().Result);
+	if(!result.IsSuccessStatusCode) {
+		throw new Exception("Release creation failed.");
 	}
 });
 
 Task("Build")
 .IsDependentOn("Clean")
+.IsDependentOn("GitVersion")
+.IsDependentOn("UpdateAssemblyInfo")
 .IsDependentOn("Restore")
 .Does(() =>{
-	if (IsRunningOnWindows()) {
 		var frameworkSettingsWindows = new MSBuildSettings {
-			Configuration = configuration,
-			Restore = true
+			Configuration = configuration
 		};
 		
 		frameworkSettingsWindows.ToolPath = msBuildPathX64;
@@ -234,74 +263,89 @@ Task("Build")
 			frameworkSettingsWindows.WithProperty("DebugSymbols", "false");
 			frameworkSettingsWindows.WithProperty("DebugType", "None");
 		}
+
 		// Use MSBuild
-		Information($"Building {solutionFile}");
+		Information("Building {0}", solutionFile);
 		MSBuild(solutionFile, frameworkSettingsWindows);
-	}
-	else {
-		var frameworkSettingsUnix = new XBuildSettings {
-			Configuration = configuration
-		};
+});
 
-		if (configuration.Equals("Release")) {
-			frameworkSettingsUnix.WithProperty("DebugSymbols", "false");
-			frameworkSettingsUnix.WithProperty("DebugType", "None");
-		}
-		// Use XBuild
-		Information($"Building {solutionFile}");
-		XBuild(solutionFile, frameworkSettingsUnix);
-	}
-	
-	if (configuration.Equals("Release")) {
-		if(!DirectoryExists(artifactsDir)) {
-			CreateDirectory(artifactsDir);
-		}
-		
-		foreach(var project in projects) {
-			if(!project.GetDirectory().ToString().EndsWith(".Tests")
-			&& !FileExists($"{project.GetDirectory()}/{project.GetFilenameWithoutExtension()}.nuspec"))
+Task("NugetPack")
+.IsDependentOn("Build")
+.Does(() =>{
+	foreach(var project in projects) {
+			var nuspec = $"{project.GetDirectory()}/{project.GetFilenameWithoutExtension()}.nuspec";
+			if(!project.ToString().EndsWith(".Tests") && FileExists(nuspec))
 			{
-				Information($"Copying {project.GetDirectory()}/bin/{configuration}/* to {artifactsDir}");
-				CopyDirectory($"{project.GetDirectory()}/bin/{configuration}/", artifactsDir);
+				var settings = new NuGetPackSettings 
+				{
+					OutputDirectory = nupkgDir,
+					Version = version,
+					Properties = new Dictionary<string, string>
+					{
+						{ "Configuration", configuration}
+					}
+				};				
+				NuGetPack(project.ToString(), settings);
 			}
 		}
-	}
+});
 
+Task("NugetPush")
+.IsDependentOn("NugetPack")
+.Does(() =>{
+	var nupkgs = GetFiles($"{nupkgDir}/*.nupkg");
+	Information("Need to push {0} packages", nupkgs.Count);
+	if(!String.IsNullOrWhiteSpace(nugetApiKey)) {
+		foreach(var nupkg in nupkgs) {
+			Information("Pushing {0}", nupkg);
+			NuGetPush(nupkg, new NuGetPushSettings {
+				Source = nugetSource,
+				ApiKey = nugetApiKey
+			});
+		}
+	} else {
+		Information("NugetApiKey is not set. Can't push.");
+		throw new Exception("NugetApiKey is not set. Can't push.");
+	}
 });
 
-Task("SemanticRelease")
+Task("CopyToArtifacts")
 .Does(() =>{
-	Npx("semantic-release", requiredSemanticVersionPackages);
+	foreach(var project in projects) {
+		if(!project.GetDirectory().ToString().EndsWith(".Tests")
+		&& !FileExists($"{project.GetDirectory()}/{project.GetFilenameWithoutExtension()}.nuspec")
+		&& DirectoryExists(project.GetDirectory()))
+		{
+			Information("Copying {0}/* to {1}", $"{project.GetDirectory()}/bin/{configuration}", artifactsDir);
+			CopyDirectory($"{project.GetDirectory()}/bin/{configuration}/", artifactsDir);
+		}
+	}
 });
 
-Task("Linter")
-.Description("Run DupFinder and InspectCode")
-.IsDependentOn("DupFinder")
-.IsDependentOn("InspectCode");
+Task("NugetPushLocal")
+.IsDependentOn("NugetPack")
+.Does(() =>{	
+	var nupkgs = GetFiles($"{nupkgDir}/*.nupkg");
+	foreach(var nupkg in nupkgs) {
+		if(!DirectoryExists(localNugetFeed)) {
+			CreateDirectory(localNugetFeed);
+		}
+		CopyFile(nupkg.ToString(), $"{localNugetFeed}\\{nupkg.GetFilename()}");
+	}
+});
 
-Task("LinterAndTest")
-.Description("Run Linter and Tests")
-.IsDependentOn("Linter")
-.IsDependentOn("Test");
+Task("Prerelease")
+.IsDependentOn("Build")
+.IsDependentOn("CopyToArtifacts")
+.IsDependentOn("NugetPushLocal");
+
+Task("Release")
+.IsDependentOn("NugetPack")
+.IsDependentOn("CopyToArtifacts")
+.IsDependentOn("NugetPushLocal")
+.IsDependentOn("NugetPush");
 
 Task("Default")
-.IsDependentOn("Clean")
-.IsDependentOn("Restore")
-.IsDependentOn("DupFinder")
-.IsDependentOn("InspectCode")
-.IsDependentOn("Build")
 .IsDependentOn("Test");
 
-//////////////////////////////////////////////////////////////////////
-// EXECUTION
-//////////////////////////////////////////////////////////////////////
 RunTarget(target);
-
-///////////////////////////////////////////////////////////////////////////////
-// Helpers
-///////////////////////////////////////////////////////////////////////////////
-string ExtractNextSemanticVersionNumber(string[] semanticReleaseOutput) {
-	var extractRegEx = new System.Text.RegularExpressions.Regex("^.+next release version is (?<SemanticVersionNumber>.*)$");
-
-	return semanticReleaseOutput.Select(line =>extractRegEx.Match(line).Groups["SemanticVersionNumber"].Value).Where(line =>!string.IsNullOrWhiteSpace(line)).SingleOrDefault();
-}
diff --git a/build.ps1 b/build.ps1
index 7f1f813d74cf6c0826517482757c38b86e0467b3..f83382e8e4092ba6cf32a47f9dfa4e211c878430 100644
--- a/build.ps1
+++ b/build.ps1
@@ -1,3 +1,24 @@
+#The MIT License (MIT)
+#
+#Copyright (c) 2014 - 2016 Patrik Svensson, Mattias Karlsson, Gary Ewan Park and contributors
+#
+#Permission is hereby granted, free of charge, to any person obtaining a copy of
+#this software and associated documentation files (the "Software"), to deal in
+#the Software without restriction, including without limitation the rights to
+#use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+#the Software, and to permit persons to whom the Software is furnished to do so,
+#subject to the following conditions:
+#
+#The above copyright notice and this permission notice shall be included in all
+#copies or substantial portions of the Software.
+#
+#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+#FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+#COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+#IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+#CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
 ##########################################################################
 # This is the Cake bootstrapper script for PowerShell.
 # This file was downloaded from https://github.com/cake-build/resources
@@ -25,6 +46,10 @@ Specifies the amount of information to be displayed.
 Shows description about tasks.
 .PARAMETER DryRun
 Performs a dry run.
+.PARAMETER Experimental
+Uses the nightly builds of the Roslyn script engine.
+.PARAMETER Mono
+Uses the Mono Compiler rather than the Roslyn script engine.
 .PARAMETER SkipToolPackageRestore
 Skips restoring of packages.
 .PARAMETER ScriptArgs
@@ -45,28 +70,13 @@ Param(
     [switch]$ShowDescription,
     [Alias("WhatIf", "Noop")]
     [switch]$DryRun,
+    [switch]$Experimental,
+    [switch]$Mono,
     [switch]$SkipToolPackageRestore,
     [Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)]
     [string[]]$ScriptArgs
 )
 
-# Attempt to set highest encryption available for SecurityProtocol.
-# PowerShell will not set this by default (until maybe .NET 4.6.x). This
-# will typically produce a message for PowerShell v2 (just an info
-# message though)
-try {
-    # Set TLS 1.2 (3072), then TLS 1.1 (768), then TLS 1.0 (192), finally SSL 3.0 (48)
-    # Use integers because the enumeration values for TLS 1.2 and TLS 1.1 won't
-    # exist in .NET 4.0, even though they are addressable if .NET 4.5+ is
-    # installed (.NET 4.5 is an in-place upgrade).
-    # PowerShell Core already has support for TLS 1.2 so we can skip this if running in that.
-    if (-not $IsCoreCLR) {
-        [System.Net.ServicePointManager]::SecurityProtocol = 3072 -bor 768 -bor 192 -bor 48
-    }
-  } catch {
-    Write-Output 'Unable to set PowerShell to use TLS 1.2 and TLS 1.1 due to old .NET Framework installed. If you see underlying connection closed or trust errors, you may need to upgrade to .NET Framework 4.5+ and PowerShell v3'
-  }
-
 [Reflection.Assembly]::LoadWithPartialName("System.Security") | Out-Null
 function MD5HashFile([string] $filePath)
 {
@@ -96,7 +106,7 @@ function GetProxyEnabledWebClient
 {
     $wc = New-Object System.Net.WebClient
     $proxy = [System.Net.WebRequest]::GetSystemWebProxy()
-    $proxy.Credentials = [System.Net.CredentialCache]::DefaultCredentials
+    $proxy.Credentials = [System.Net.CredentialCache]::DefaultCredentials        
     $wc.Proxy = $proxy
     return $wc
 }
@@ -121,16 +131,15 @@ $MODULES_PACKAGES_CONFIG = Join-Path $MODULES_DIR "packages.config"
 # Make sure tools folder exists
 if ((Test-Path $PSScriptRoot) -and !(Test-Path $TOOLS_DIR)) {
     Write-Verbose -Message "Creating tools directory..."
-    New-Item -Path $TOOLS_DIR -Type Directory | Out-Null
+    New-Item -Path $TOOLS_DIR -Type directory | out-null
 }
 
 # Make sure that packages.config exist.
 if (!(Test-Path $PACKAGES_CONFIG)) {
-    Write-Verbose -Message "Downloading packages.config..."
-    try {
+    Write-Verbose -Message "Downloading packages.config..."    
+    try {        
         $wc = GetProxyEnabledWebClient
-        $wc.DownloadFile("https://cakebuild.net/download/bootstrapper/packages", $PACKAGES_CONFIG)
-    } catch {
+        $wc.DownloadFile("https://cakebuild.net/download/bootstrapper/packages", $PACKAGES_CONFIG) } catch {
         Throw "Could not download packages.config."
     }
 }
@@ -158,12 +167,7 @@ if (!(Test-Path $NUGET_EXE)) {
 }
 
 # Save nuget.exe path to environment to be available to child processed
-$env:NUGET_EXE = $NUGET_EXE
-$env:NUGET_EXE_INVOCATION = if ($IsLinux -or $IsMacOS) {
-    "mono `"$NUGET_EXE`""
-} else {
-    "`"$NUGET_EXE`""
-}
+$ENV:NUGET_EXE = $NUGET_EXE
 
 # Restore tools from NuGet?
 if(-Not $SkipToolPackageRestore.IsPresent) {
@@ -171,17 +175,15 @@ if(-Not $SkipToolPackageRestore.IsPresent) {
     Set-Location $TOOLS_DIR
 
     # Check for changes in packages.config and remove installed tools if true.
-    [string] $md5Hash = MD5HashFile $PACKAGES_CONFIG
+    [string] $md5Hash = MD5HashFile($PACKAGES_CONFIG)
     if((!(Test-Path $PACKAGES_CONFIG_MD5)) -Or
-    ($md5Hash -ne (Get-Content $PACKAGES_CONFIG_MD5 ))) {
+      ($md5Hash -ne (Get-Content $PACKAGES_CONFIG_MD5 ))) {
         Write-Verbose -Message "Missing or changed package.config hash..."
-        Get-ChildItem -Exclude packages.config,nuget.exe,Cake.Bakery |
-        Remove-Item -Recurse
+        Remove-Item * -Recurse -Exclude packages.config,nuget.exe
     }
 
     Write-Verbose -Message "Restoring tools from NuGet..."
-    
-    $NuGetOutput = Invoke-Expression "& $env:NUGET_EXE_INVOCATION install -ExcludeVersion -OutputDirectory `"$TOOLS_DIR`""
+    $NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -OutputDirectory `"$TOOLS_DIR`""
 
     if ($LASTEXITCODE -ne 0) {
         Throw "An error occurred while restoring NuGet tools."
@@ -190,7 +192,7 @@ if(-Not $SkipToolPackageRestore.IsPresent) {
     {
         $md5Hash | Out-File $PACKAGES_CONFIG_MD5 -Encoding "ASCII"
     }
-    Write-Verbose -Message ($NuGetOutput | Out-String)
+    Write-Verbose -Message ($NuGetOutput | out-string)
 
     Pop-Location
 }
@@ -201,13 +203,13 @@ if (Test-Path $ADDINS_PACKAGES_CONFIG) {
     Set-Location $ADDINS_DIR
 
     Write-Verbose -Message "Restoring addins from NuGet..."
-    $NuGetOutput = Invoke-Expression "& $env:NUGET_EXE_INVOCATION install -ExcludeVersion -OutputDirectory `"$ADDINS_DIR`""
+    $NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -OutputDirectory `"$ADDINS_DIR`""
 
     if ($LASTEXITCODE -ne 0) {
         Throw "An error occurred while restoring NuGet addins."
     }
 
-    Write-Verbose -Message ($NuGetOutput | Out-String)
+    Write-Verbose -Message ($NuGetOutput | out-string)
 
     Pop-Location
 }
@@ -218,13 +220,13 @@ if (Test-Path $MODULES_PACKAGES_CONFIG) {
     Set-Location $MODULES_DIR
 
     Write-Verbose -Message "Restoring modules from NuGet..."
-    $NuGetOutput = Invoke-Expression "& $env:NUGET_EXE_INVOCATION install -ExcludeVersion -OutputDirectory `"$MODULES_DIR`""
+    $NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -OutputDirectory `"$MODULES_DIR`""
 
     if ($LASTEXITCODE -ne 0) {
         Throw "An error occurred while restoring NuGet modules."
     }
 
-    Write-Verbose -Message ($NuGetOutput | Out-String)
+    Write-Verbose -Message ($NuGetOutput | out-string)
 
     Pop-Location
 }
@@ -234,11 +236,6 @@ if (!(Test-Path $CAKE_EXE)) {
     Throw "Could not find Cake.exe at $CAKE_EXE"
 }
 
-$CAKE_EXE_INVOCATION = if ($IsLinux -or $IsMacOS) {
-    "mono `"$CAKE_EXE`""
-} else {
-    "`"$CAKE_EXE`""
-}
 
 
 # Build Cake arguments
@@ -248,9 +245,11 @@ if ($Configuration) { $cakeArguments += "-configuration=$Configuration" }
 if ($Verbosity) { $cakeArguments += "-verbosity=$Verbosity" }
 if ($ShowDescription) { $cakeArguments += "-showdescription" }
 if ($DryRun) { $cakeArguments += "-dryrun" }
+if ($Experimental) { $cakeArguments += "-experimental" }
+if ($Mono) { $cakeArguments += "-mono" }
 $cakeArguments += $ScriptArgs
 
 # Start Cake
 Write-Host "Running build script..."
-Invoke-Expression "& $CAKE_EXE_INVOCATION $($cakeArguments -join " ")"
+&$CAKE_EXE $cakeArguments
 exit $LASTEXITCODE
diff --git a/docs/ESLintConvention.md b/docs/ESLintConvention.md
deleted file mode 100644
index 001dba56ac6f0f96234f03d0278f618826728495..0000000000000000000000000000000000000000
--- a/docs/ESLintConvention.md
+++ /dev/null
@@ -1,45 +0,0 @@
-## ESLint Convention
-
-Make the changes to the code and tests and then commit to your branch. Be sure to follow the commit message conventions.
-
-Commit message summaries must follow this basic format:
-
-```
-Tag: Message (fixes #1234)
-```
-
-`Tag` should not be confused with git tag.
-`Message` should not be confused with git commit message.
-
-The `Tag` is one of the following:
-
-* `Fix` - for a bug fix.
-* `Update` - for a backwards-compatible enhancement.
-* `Breaking` - for a backwards-incompatible enhancement.
-* `Docs` - changes to documentation only.
-* `Build` - changes to build process only.
-* `New` - implemented a new feature.
-* `Upgrade` - for a dependency upgrade.
-
-The message summary should be a one-sentence description of the change. The issue number should be mentioned at the end. * The commit message should say "(fixes #1234)" at the end of the description if it closes out an existing issue (replace 1234 with the issue number). If the commit doesn't completely fix the issue, then use `(refs #1234)` instead of `(fixes #1234)`.
-
-Here are some good commit message summary examples:
-
-```
-Build: Update Travis to only test Node 0.10 (refs #734)
-Fix: Semi rule incorrectly flagging extra semicolon (fixes #840)
-Upgrade: Esprima to 1.2, switch to using Esprima comment attachment (fixes #730)
-```
-
-The commit message format is important because these messages are used to create a changelog for each release. The tag and issue number help to create more consistent and useful changelogs.
-
-Based on https://github.com/eslint/eslint.github.io/blob/master/docs/developer-guide/contributing.md#step-2-make-your-changes
-
-[npm-image]: https://badge.fury.io/js/conventional-changelog-eslint.svg
-[npm-url]: https://npmjs.org/package/conventional-changelog-eslint
-[travis-image]: https://travis-ci.org/stevemao/conventional-changelog-eslint.svg?branch=master
-[travis-url]: https://travis-ci.org/stevemao/conventional-changelog-eslint
-[daviddm-image]: https://david-dm.org/stevemao/conventional-changelog-eslint.svg?theme=shields.io
-[daviddm-url]: https://david-dm.org/stevemao/conventional-changelog-eslint
-[coveralls-image]: https://coveralls.io/repos/stevemao/conventional-changelog-eslint/badge.svg
-[coveralls-url]: https://coveralls.io/r/stevemao/conventional-changelog-eslint
\ No newline at end of file
diff --git a/docs/home.md b/docs/home.md
deleted file mode 100644
index e57a4ee9c07e6ca3f79756079043959585835658..0000000000000000000000000000000000000000
--- a/docs/home.md
+++ /dev/null
@@ -1,31 +0,0 @@
-## C# Template
-
-This template includes:
-
-* Automatic building using cake
-* Automatic testing with NUnit
-* Automatic linting with Resharper
-* Automatic documentation publishing using Gitlab CI / CD and a self written script which puts the docs in the docs folder to the wiki
-* Automatic releases using semantic-release ([ESLint Code Convention](ESLintConvention)), cake and Gitlab CI / CD
-
-## What you need to do
-
-Place you C# project solution file in .src/.
-Make sure Create directory for solution is unticked.
-
-![alt text](images/create_project.png "Create a new Project")
-
-Delete unused docs and update this README.
-
-Add [NUnit](nunit) tests to your solution.
-
-## Building
-
-Build this project by running either the build.ps1 or the build<span></span>.sh script.
-The project will be build and tested.
-
-### Links 
-
-*  [Commit convention](ESLintConvention)
-*  [Everything possible with markup](testdoc)
-*  [Adding NUnit tests](nunit)
diff --git a/docs/images/add_a_package.png b/docs/images/add_a_package.png
deleted file mode 100644
index e8e8ed2121edfc81d8fb2e4f3e03ed4807c66eea..0000000000000000000000000000000000000000
Binary files a/docs/images/add_a_package.png and /dev/null differ
diff --git a/docs/images/add_a_reference.png b/docs/images/add_a_reference.png
deleted file mode 100644
index 4ee38c9951bc5739297b78abb2c82113286f6e71..0000000000000000000000000000000000000000
Binary files a/docs/images/add_a_reference.png and /dev/null differ
diff --git a/docs/images/create_class_library.png b/docs/images/create_class_library.png
deleted file mode 100644
index 89a252c6e358c73fb9b7299464f851e69127285a..0000000000000000000000000000000000000000
Binary files a/docs/images/create_class_library.png and /dev/null differ
diff --git a/docs/images/create_project.png b/docs/images/create_project.png
deleted file mode 100644
index f7ae1a1701c9287d5f7a959bf856f55966293081..0000000000000000000000000000000000000000
Binary files a/docs/images/create_project.png and /dev/null differ
diff --git a/docs/images/select_framework.png b/docs/images/select_framework.png
deleted file mode 100644
index bba5b07168b73cb1005150aad92d6d925bada649..0000000000000000000000000000000000000000
Binary files a/docs/images/select_framework.png and /dev/null differ
diff --git a/docs/images/select_project.png b/docs/images/select_project.png
deleted file mode 100644
index 6f42cc3a18e89d6e2a26cd76de9730f39feb51bf..0000000000000000000000000000000000000000
Binary files a/docs/images/select_project.png and /dev/null differ
diff --git a/docs/images/test_code.png b/docs/images/test_code.png
deleted file mode 100644
index e9d9b5f88107c03fb19d4d2c6567981d25658154..0000000000000000000000000000000000000000
Binary files a/docs/images/test_code.png and /dev/null differ
diff --git a/docs/nunit.md b/docs/nunit.md
deleted file mode 100644
index 020e56f85510b1319edbe89e76cdd0891b5abe43..0000000000000000000000000000000000000000
--- a/docs/nunit.md
+++ /dev/null
@@ -1,33 +0,0 @@
-## Add NUnit Tests
-
-### Add Nunit test adapter
-1.  Choose **Tools > Extensions and Updates**
-2.  In the **Extensions and Updates** dialog box, expand the **Online** category and then **Visual Studio Marketplace**. Then, choose **Tools > Testing**.
-2.  Select the **NUnit test adapter** and then choose **Download.**
-### Add Tests
-
-1.  Create a class library project and add it to your solution.
-
-    For convinience name it like your main project and add **.Tests** as a suffix.
-    ![alt text](images/create_class_library.png "Select Class Library")
-
-2.  Install the plug-in. In **Solution Explorer**, select the class library project, and then choose **Manage NuGet Packages** from its right-click or context menu.
-
-    ![alt text](images/add_a_package.png "Add a package")
-
-3.  In the **NuGet Package Manager** window, search for and select the plug-in (NUnit), and then choose **Install**.
-    ![alt text](images/select_framework.png "Select Project")
-
-    The framework is now referenced in your project under **References**.
-
-4.  From the class library project's **References** node, select **Add Reference**.
-
-    ![alt text](images/add_a_reference.png "Add a reference")
-
-5. In the **Reference Manager** dialog box, select the project that contains the code you'll test.
-
-    ![alt text](images/select_project.png "Select Project")
-
-6. Code your unit test.
-    
-    ![alt text](images/test_code.png "Test Code")
diff --git a/docs/testdoc.md b/docs/testdoc.md
deleted file mode 100644
index 938b6eb3d01ae251f10a000bda25fd4538d87d7a..0000000000000000000000000000000000000000
--- a/docs/testdoc.md
+++ /dev/null
@@ -1,78 +0,0 @@
-It's very easy to make some words **bold** and other words *italic* with Markdown. You can even [link to Google!](http://google.com)
-
-Sometimes you want numbered lists:
-
-1. One
-2. Two
-3. Three
-
-Sometimes you want bullet points:
-
-* Start a line with a star
-* Profit!
-
-Alternatively,
-
-- Dashes work just as well
-- And if you have sub points, put two spaces before the dash or star:
-  - Like this
-  - And this
-
-If you want to embed images, this is how you do it:
-
-![Image of Yaktocat](https://octodex.github.com/images/yaktocat.png)
-
-# Structured documents
-
-Sometimes it's useful to have different levels of headings to structure your documents. Start lines with a `#` to create headings. Multiple `##` in a row denote smaller heading sizes.
-
-### This is a third-tier heading
-
-You can use one `#` all the way up to `######` six for different heading sizes.
-
-If you'd like to quote someone, use the > character before the line:
-
-> Coffee. The finest organic suspension ever devised... I beat the Borg with it.
-> - Captain Janeway
-
-[200~There are many different ways to style code with GitHub's markdown. If you have inline code blocks, wrap them in backticks: `var example = true`.  If you've got a longer block of code, you can indent with four spaces:
-
-    if (isAwesome){
-      return true
-    }
-
-GitHub also supports something called code fencing, which allows for multiple lines without indentation:
-
-```
-if (isAwesome){
-  return true
-}
-```
-
-And if you'd like to use syntax highlighting, include the language:
-
-```javascript
-if (isAwesome){
-  return true
-}
-```
-
-GitHub supports many extras in Markdown that help you reference and link to people. If you ever want to direct a comment at someone, you can prefix their name with an @ symbol: Hey @kneath — love your sweater!
-
-But I have to admit, tasks lists are my favorite:
-
-- [x] This is a complete item
-- [ ] This is an incomplete item
-
-When you include a task list in the first comment of an Issue, you will see a helpful progress bar in your list of issues. It works in Pull Requests, too!
-
-And, of course emoji!
-GitHub supports many extras in Markdown that help you reference and link to people. If you ever want to direct a comment at someone, you can prefix their name with an @ symbol: Hey @kneath — love your sweater!
-
-But I have to admit, tasks lists are my favorite:
-
- This is a complete item
- This is an incomplete item
-When you include a task list in the first comment of an Issue, you will see a helpful progress bar in your list of issues. It works in Pull Requests, too!
-
-And, of course emoji!
diff --git a/publishDocs.ps1 b/publishDocs.ps1
deleted file mode 100644
index f49b3b93e477ca9d57f7b1163b2bcf246f86d35d..0000000000000000000000000000000000000000
--- a/publishDocs.ps1
+++ /dev/null
@@ -1,19 +0,0 @@
-param(
-    $token
-)
-
-$remoteUrl = git config --get remote.origin.url
-$remoteUrl = $remoteUrl.replace("git@", "")
-$remoteUrl = $remoteUrl -replace "https(.*?)@",""
-$remoteUrl = $remoteUrl.replace(":", "/")
-$remoteUrl = $remoteUrl.replace(".git", ".wiki.git")
-
-$temporaryFolderName = "publishDocsTempFolder"
-
-git clone "https://gitlab-ci-token:$($token)@$($remoteUrl)" $temporaryFolderName
-cd $temporaryFolderName
-Remove-Item *
-cp -r ../docs/* ./
-git add . 
-git commit -m "Docs: Documentation Update" 
-git push
\ No newline at end of file
diff --git a/src/Logging.Tests/Properties/AssemblyInfo.cs b/src/Logging.Tests/Properties/AssemblyInfo.cs
index 009252a34ed27670da7a43521544ebc75bcfbc6b..729495e25772ea612907b4907ef0e5070cf82124 100644
--- a/src/Logging.Tests/Properties/AssemblyInfo.cs
+++ b/src/Logging.Tests/Properties/AssemblyInfo.cs
@@ -9,8 +9,8 @@ using System.Reflection;
 [assembly: AssemblyDescription("Logging.Tests is a part of the CoScInE group.")]
 [assembly: AssemblyCompany("IT Center, RWTH Aachen University")]
 [assembly: AssemblyProduct("Logging.Tests")]
-[assembly: AssemblyVersion("1.0.1.0")]
-[assembly: AssemblyFileVersion("1.0.1.0")]
-[assembly: AssemblyInformationalVersion("1.0.1.0")]
+[assembly: AssemblyVersion("1.1.0")]
+[assembly: AssemblyFileVersion("1.1.0")]
+[assembly: AssemblyInformationalVersion("1.1.0-topic-671-readab0009")]
 [assembly: AssemblyCopyright("2020 IT Center, RWTH Aachen University")]
 
diff --git a/src/Logging/AnalyticsLogObject.cs b/src/Logging/AnalyticsLogObject.cs
new file mode 100644
index 0000000000000000000000000000000000000000..dae2b44d0936b26fe5d0f9c35d972f61bf78a27c
--- /dev/null
+++ b/src/Logging/AnalyticsLogObject.cs
@@ -0,0 +1,61 @@
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Coscine.Logging
+{
+    [Serializable]
+    public class AnalyticsLogObject
+    {
+        public string Type { get; set; }
+
+        public string Operation { get; set; }
+
+        // Default is the current time
+        public DateTime Timestamp { get; set; } = DateTime.UtcNow;
+
+        public string UserId { get; set; }
+
+        public string RoleId { get; set; }
+
+        public string SessionId { get; set; }
+
+        public string ClientCorrolationId { get; set; }
+
+        public string ProjectId { get; set; }
+
+        public string ResourceId { get; set; }
+
+        public string FileId { get; set; }
+
+        public List<string> ProjectList { get; set; }
+
+        public List<string> ResourceList { get; set; }
+
+        public List<string> UserList { get; set; }
+
+        public AnalyticsLogObject (string type, string operation, DateTime timestamp, string userId, string roleId, string sessionId, string clientCorrolationId, string projectId, string resourceId, string fileId, List<string> projectList, List<string> resourceList, List<string> userList)
+        {
+            Type = type;
+            Operation = operation;
+            Timestamp = timestamp;
+            UserId = userId;
+            RoleId = roleId;
+            SessionId = sessionId;
+            ClientCorrolationId = clientCorrolationId;
+            ProjectId = projectId;
+            ResourceId = resourceId;
+            FileId = fileId;
+            ProjectList = projectList;
+            ResourceList = resourceList;
+            UserList = userList;
+        }
+
+        public AnalyticsLogObject()
+        {
+        }
+    }
+}
diff --git a/src/Logging/CoscineLogger.cs b/src/Logging/CoscineLogger.cs
index 88a714ac947d6d864525c389d9219369ca91758c..2e4b4075cd9c48a34f192016e609defcb9710767 100644
--- a/src/Logging/CoscineLogger.cs
+++ b/src/Logging/CoscineLogger.cs
@@ -9,6 +9,8 @@ using System.Text.RegularExpressions;
 using NLog.Config;
 using Microsoft.Extensions.Logging;
 using NLog.LayoutRenderers;
+using Newtonsoft.Json.Linq;
+using Newtonsoft.Json;
 
 namespace Coscine.Logging
 {
@@ -19,140 +21,21 @@ namespace Coscine.Logging
 
         private const LogType defaultLogType = LogType.Low;
 
-        private static bool[] activeLoglevels = new bool[Enum.GetNames(typeof(LogType)).Length];
-
-        // Keys for the database string
-        private const string DbDataSourceKey = "coscine/global/db_data_source";
-        private const string DbNameKey = "coscine/global/db_name";
-        private const string DbUserIdKey = "coscine/global/db_user_id";
-        private const string DbPasswordKey = "coscine/global/db_password";
-
-        // path for the file logger
-        private const string FileLoggerPath = "coscine/global/logging/fileloggerpath";
-
-        // keys for the loglevels
-        private const string LogLevelKeyDebug = "coscine/global/logging/levels/debug";
-        private const string LogLevelKeyLow = "coscine/global/logging/levels/low";
-        private const string LogLevelKeyMedium = "coscine/global/logging/levels/medium";
-        private const string LogLevelKeyHigh = "coscine/global/logging/levels/high";
-        private const string LogLevelKeyCritical = "coscine/global/logging/levels/critical";
-        private const string LogLevelKeyAnalytics = "coscine/global/logging/levels/analytics";
-        private const string LogLevelKeyReporting = "coscine/global/logging/levels/reporting";
-
-
         public CoscineLogger(Microsoft.Extensions.Logging.ILogger logger)
         {
-            UpdateActiveLogs();
+            CoscineLoggerConfiguration.UpdateActiveLogs();
+            
             _logger = logger;
         }
 
-        public static void SetConfig()
+        public void AnalyticsLog(AnalyticsLogObject analyticsLogObject)
         {
-            LayoutRenderer.Register<LogLevelLayoutRenderer>("CoscineLogLevel");
-
-            var config = new LoggingConfiguration();
-
-
-            var targetFileLogger = new FileTarget
-            {
-                Name = "fileTarget",
-                FileName = GetStringFromConsul(FileLoggerPath),
-                Layout = "${date:universalTime=true}|${mdlc:ClientTimeStamp}|${CoscineLogLevel}|${message}|${mdlc:User}|${mdlc:Uri}|${machinename}|${activityid}|${mdlc:Status}|${callsite}|${exception:format=message}${exception:format=stackTrace}"
-            };
-
-
-            var targetDatabase = new DatabaseTarget
-            {
-                Name = "database",
-                ConnectionString = CoscineLogger.GetDbConnectionString(),
-                CommandText = @"insert into dbo.Log ( [ServerTimeStamp], [ClientTimeStamp], [LogLevel], [Message], [Stacktrace], [UserId], [URI], [Server], [CorrolationId], [Status], [Source]) 
-            values (
-            CAST( @serverTimeStamp AS DATETIME2),
-            CASE WHEN @clientTimeStamp = '' THEN NULL ELSE CAST( @clientTimeStamp AS DATETIME2) END, 
-            @level,
-            @message, 
-            @stacktrace, 
-            CASE WHEN @userId = '' THEN NULL ELSE convert(uniqueidentifier, @userId) END, 
-            @uri, 
-            @server, 
-            CASE WHEN @corrolationId = '' THEN NULL ELSE convert(uniqueidentifier, @corrolationId) END, 
-            @status, 
-            @source)"
-
-            };
-            targetDatabase.Parameters.Add(new DatabaseParameterInfo("@serverTimeStamp", new NLog.Layouts.SimpleLayout("${date:universalTime=true}")));
-            targetDatabase.Parameters.Add(new DatabaseParameterInfo("@clientTimeStamp", new NLog.Layouts.SimpleLayout("${mdlc:ClientTimeStamp}")));
-            targetDatabase.Parameters.Add(new DatabaseParameterInfo("@level", new NLog.Layouts.SimpleLayout("${CoscineLogLevel}")));
-            targetDatabase.Parameters.Add(new DatabaseParameterInfo("@message", new NLog.Layouts.SimpleLayout("${message}")));
-            targetDatabase.Parameters.Add(new DatabaseParameterInfo("@stackTrace", new NLog.Layouts.SimpleLayout("${exception:format=message}${exception:format=stackTrace}")));
-            targetDatabase.Parameters.Add(new DatabaseParameterInfo("@userId", new NLog.Layouts.SimpleLayout("${mdlc:User}")));
-            targetDatabase.Parameters.Add(new DatabaseParameterInfo("@uri", new NLog.Layouts.SimpleLayout("${mdlc:Uri}")));
-            targetDatabase.Parameters.Add(new DatabaseParameterInfo("@server", new NLog.Layouts.SimpleLayout("${machinename}")));
-            targetDatabase.Parameters.Add(new DatabaseParameterInfo("@corrolationId", new NLog.Layouts.SimpleLayout("${activityid}")));
-            targetDatabase.Parameters.Add(new DatabaseParameterInfo("@status", new NLog.Layouts.SimpleLayout("${mdlc:Status}")));
-            targetDatabase.Parameters.Add(new DatabaseParameterInfo("@source", new NLog.Layouts.SimpleLayout("${callsite}")));
-            targetDatabase.Parameters.Add(new DatabaseParameterInfo("@type", new NLog.Layouts.SimpleLayout("${exception:format=type}")));
-            targetDatabase.Parameters.Add(new DatabaseParameterInfo("@innerException", new NLog.Layouts.SimpleLayout("${exception:format=:innerFormat=ShortType,Message,Method:MaxInnerExceptionLevel=1:InnerExceptionSeparator=}")));
-            targetDatabase.Parameters.Add(new DatabaseParameterInfo("@additionalInfo", new NLog.Layouts.SimpleLayout("${message}")));
-
-            var targetConsole = new NLog.Targets.ConsoleTarget
-            {
-                Name = "console",
-                Layout = "${date:universalTime=true}|${mdlc:ClientTimeStamp}|${CoscineLogLevel}|${message}|${mdlc:User}|${mdlc:Uri}|${machinename}|${activityid}|${mdlc:Status}|${callsite}|${exception:format=message}${exception:format=stackTrace}"
-            };
-
-
-            config.AddTarget("fileLogger", targetFileLogger);
-            config.AddTarget("databaseLogger", targetDatabase);
-            config.AddTarget("consoleLogger", targetConsole);
-
-
-            var blockAllDebug = new LoggingRule("blockAllDebug");
-            blockAllDebug.SetLoggingLevels(LogLevel.Debug, LogLevel.Debug);
-            blockAllDebug.LoggerNamePattern = "*";
-
-            var blockAllTrace = new LoggingRule("blockAllTrace");
-            blockAllTrace.SetLoggingLevels(LogLevel.Trace, LogLevel.Trace);
-            blockAllTrace.LoggerNamePattern = "*";
-
-            var blockAllWarning = new LoggingRule("blockAllWarning");
-            blockAllWarning.SetLoggingLevels(LogLevel.Warn, LogLevel.Warn);
-            blockAllWarning.LoggerNamePattern = "*";
-
-            var blockAllError = new LoggingRule("blockAllError");
-            blockAllError.SetLoggingLevels(LogLevel.Error, LogLevel.Error);
-            blockAllError.LoggerNamePattern = "*";
-
-            var blockAllFatal = new LoggingRule("blockAllFatal");
-            blockAllFatal.SetLoggingLevels(LogLevel.Fatal, LogLevel.Fatal);
-            blockAllFatal.LoggerNamePattern = "*";
-
-            var blockAllInformation = new LoggingRule("blockAllInformation");
-            blockAllInformation.SetLoggingLevels(LogLevel.Info, LogLevel.Info);
-            blockAllInformation.LoggerNamePattern = "*";
-
-
-            var ruleFileLogger = new LoggingRule("*", LogLevel.Error, LogLevel.Fatal, targetFileLogger);
-            var ruleConsole = new LoggingRule("*", LogLevel.Error, LogLevel.Fatal, targetConsole);
-            var ruleDatabase = new LoggingRule("*", LogLevel.Trace, LogLevel.Fatal, targetDatabase);
-
-            config.LoggingRules.Add(blockAllDebug);
-            config.LoggingRules.Add(blockAllTrace);
-            config.LoggingRules.Add(blockAllWarning);
-            config.LoggingRules.Add(blockAllError);
-            config.LoggingRules.Add(blockAllFatal);
-            config.LoggingRules.Add(blockAllInformation);
-
-            config.LoggingRules.Add(ruleFileLogger);
-            config.LoggingRules.Add(ruleConsole);
-            config.LoggingRules.Add(ruleDatabase);
-
-            LogManager.Configuration = config;
-
-            UpdateActiveLogs();
+            analyticsLogObject.ClientCorrolationId = CoscineLoggerMetadata.GetClientCorrolationId();
+            analyticsLogObject.UserId = CoscineLoggerMetadata.GetUserId();
+            analyticsLogObject.SessionId = CoscineLoggerMetadata.GetSessionId();
+            Log(LogType.Analytics, null, JsonConvert.SerializeObject(analyticsLogObject), null);
         }
 
-
         public void Log()
         {
             Log(defaultLogType, null, null, null);
@@ -230,9 +113,9 @@ namespace Coscine.Logging
 
         public void Log(LogType messageType, Type context, string message, Exception exception)
         {
-            UpdateActiveLogs();
+            CoscineLoggerConfiguration.UpdateActiveLogs();
 
-            if (!activeLoglevels[(int)messageType])
+            if (!CoscineLoggerConfiguration.IsLogLevelActivated(messageType))
             {
                 return;
             }
@@ -265,7 +148,6 @@ namespace Coscine.Logging
                     logLevel = Microsoft.Extensions.Logging.LogLevel.Information;
                     break;
                 default:
-                    messageType = LogType.Low;
                     logLevel = Microsoft.Extensions.Logging.LogLevel.Trace;
                     break;
             }
@@ -274,133 +156,16 @@ namespace Coscine.Logging
 
         }
 
-
-        public static void SetUserId(string userId = "00000000-0000-0000-0000-000000000000")
-        {
-            if (IsGuid(userId))
-            {
-                MappedDiagnosticsLogicalContext.Set("User", userId);
-            }
-            else
-            {
-                MappedDiagnosticsLogicalContext.Set("User", "");
-            }
-        }
-
-        public static void SetUserId(Guid userId)
-        {
-            CoscineLogger.SetUserId(userId.ToString());
-        }
-
-        public static void SetAnalytics(bool active)
+        private static void SetAnalytics(bool active)
         {
             var value = active ? "true" : "false";
             MappedDiagnosticsLogicalContext.Set("Analytics", value);
         }
 
-        public static void SetReporting(bool active)
+        private static void SetReporting(bool active)
         {
             var value = active ? "true" : "false";
             MappedDiagnosticsLogicalContext.Set("Reporting", value);
         }
-
-        public static void SetUri(string uri = "")
-        {
-            MappedDiagnosticsLogicalContext.Set("Uri", uri);
-        }
-
-        public static void SetCorrolationId(string corrolationId = "00000000-0000-0000-0000-000000000000")
-        {
-            if (IsGuid(corrolationId))
-            {
-                Trace.CorrelationManager.ActivityId = new Guid(corrolationId);
-            }
-            else
-            {
-                Trace.CorrelationManager.ActivityId = new Guid("00000000-0000-0000-0000-000000000000");
-            }
-        }
-
-        public static void SetCorrolationId()
-        {
-            Trace.CorrelationManager.ActivityId = Guid.NewGuid();
-        }
-
-        public static void SetCorrolationId(Guid corrolationId)
-        {
-            CoscineLogger.SetCorrolationId(corrolationId.ToString());
-        }
-
-        public static void SetStatus(string status = "")
-        {
-            MappedDiagnosticsLogicalContext.Set("Status", status);
-        }
-
-        public static void SetClientTimeStamp(string clientTimeStamp = "")
-        {
-            MappedDiagnosticsLogicalContext.Set("ClientTimeStamp", clientTimeStamp);
-        }
-
-        private static bool IsGuid(string guid)
-        {
-            var match = Regex.Match(guid, @"^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$",
-            RegexOptions.IgnoreCase);
-            return match.Success;
-        }
-
-        private static void UpdateActiveLogs()
-        {
-            activeLoglevels[(int)LogType.Debug] = !GetStringFromConsul(LogLevelKeyDebug).Equals("0");
-            activeLoglevels[(int)LogType.Low] = !GetStringFromConsul(LogLevelKeyLow).Equals("0");
-            activeLoglevels[(int)LogType.Medium] = !GetStringFromConsul(LogLevelKeyMedium).Equals("0");
-            activeLoglevels[(int)LogType.High] = !GetStringFromConsul(LogLevelKeyHigh).Equals("0");
-            activeLoglevels[(int)LogType.Critical] = !GetStringFromConsul(LogLevelKeyCritical).Equals("0");
-            activeLoglevels[(int)LogType.Analytics] = !GetStringFromConsul(LogLevelKeyAnalytics).Equals("0");
-            activeLoglevels[(int)LogType.Reporting] = !GetStringFromConsul(LogLevelKeyReporting).Equals("0");
-
-            var config = LogManager.Configuration;
-            config.FindRuleByName("blockAllInformation").Final = !activeLoglevels[(int)LogType.Analytics] && !activeLoglevels[(int)LogType.Reporting];
-            config.FindRuleByName("blockAllDebug").Final = !activeLoglevels[(int)LogType.Debug];
-            config.FindRuleByName("blockAllTrace").Final = !activeLoglevels[(int)LogType.Low];
-            config.FindRuleByName("blockAllWarning").Final = !activeLoglevels[(int)LogType.Medium];
-            config.FindRuleByName("blockAllError").Final = !activeLoglevels[(int)LogType.High];
-            config.FindRuleByName("blockAllFatal").Final = !activeLoglevels[(int)LogType.Critical];
-
-            LogManager.Configuration = config;
-            LogManager.ReconfigExistingLoggers();
-        }
-
-        public static bool LogLevelIsActivated(LogType logType)
-        {
-            return activeLoglevels[(int)logType];
-        }
-
-        private static string GetDbConnectionString()
-        {
-            var dbDataSource = GetStringFromConsul(DbDataSourceKey);
-            var dbDatabase = GetStringFromConsul(DbNameKey);
-            var dbUserId = GetStringFromConsul(DbUserIdKey);
-            var dbPassword = GetStringFromConsul(DbPasswordKey);
-            return $"Data Source={dbDataSource}; Database={dbDatabase}; User Id={dbUserId}; Password={dbPassword};";
-        }
-
-        private static string GetStringFromConsul(string key)
-        {
-            using (var client = new ConsulClient())
-            {
-                var getPair = client.KV.Get(key);
-
-                getPair.Wait();
-
-                var returnValue = getPair.Result.Response.Value;
-
-                if (returnValue != null)
-                {
-                    return Encoding.UTF8.GetString(returnValue, 0, returnValue.Length);
-                }
-                return null;
-
-            }
-        }
     }
 }
diff --git a/src/Logging/CoscineLoggerConfiguration.cs b/src/Logging/CoscineLoggerConfiguration.cs
new file mode 100644
index 0000000000000000000000000000000000000000..1c8849d1f312af420be5b23fab53c2ef62b50b96
--- /dev/null
+++ b/src/Logging/CoscineLoggerConfiguration.cs
@@ -0,0 +1,213 @@
+using Consul;
+using NLog;
+using NLog.Config;
+using NLog.LayoutRenderers;
+using NLog.Targets;
+using LogLevel = NLog.LogLevel;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Coscine.Logging
+{
+    public class CoscineLoggerConfiguration
+    {
+        // Keys for the database string
+        private const string DbDataSourceKey = "coscine/global/db_data_source";
+        private const string DbNameKey = "coscine/global/db_name";
+        private const string DbUserIdKey = "coscine/global/db_user_id";
+        private const string DbPasswordKey = "coscine/global/db_password";
+
+        // path for the file logger
+        private const string FileLoggerPath = "coscine/global/logging/fileloggerpath";
+
+        // keys for the loglevels
+        private const string LogLevelKeyDebug = "coscine/global/logging/levels/debug";
+        private const string LogLevelKeyLow = "coscine/global/logging/levels/low";
+        private const string LogLevelKeyMedium = "coscine/global/logging/levels/medium";
+        private const string LogLevelKeyHigh = "coscine/global/logging/levels/high";
+        private const string LogLevelKeyCritical = "coscine/global/logging/levels/critical";
+        private const string LogLevelKeyAnalytics = "coscine/global/logging/levels/analytics";
+        private const string LogLevelKeyReporting = "coscine/global/logging/levels/reporting";
+
+
+        private static readonly bool[] activeLoglevels = new bool[Enum.GetNames(typeof(LogType)).Length];
+
+        public static bool IsLogLevelActivated(LogType logType)
+        {
+            return activeLoglevels[(int)logType];
+        }
+
+        public static void SetConfig()
+        {
+            LayoutRenderer.Register<LogLevelLayoutRenderer>("CoscineLogLevel");
+
+            var config = new LoggingConfiguration();
+
+
+            var targetFileLogger = new FileTarget
+            {
+                Name = "fileTarget",
+                FileName = GetStringFromConsul(FileLoggerPath),
+                Layout = "${date:universalTime=true}|${mdlc:ClientTimeStamp}|${CoscineLogLevel}|${message}|${mdlc:User}|${mdlc:Uri}|${machinename}|${activityid}|${mdlc:Status}|${callsite}|${exception:format=message}${exception:format=stackTrace}"
+            };
+
+
+            var targetDatabase = new DatabaseTarget
+            {
+                Name = "database",
+                ConnectionString = CoscineLoggerConfiguration.GetDbConnectionString(),
+                CommandText = @"insert into dbo.Log ( [ServerTimeStamp], [ClientTimeStamp], [LogLevel], [Message], [Stacktrace], [UserId], [URI], [Server], [CorrolationId], [Status], [Source]) 
+            values (
+            CAST( @serverTimeStamp AS DATETIME2),
+            CASE WHEN @clientTimeStamp = '' THEN NULL ELSE CAST( @clientTimeStamp AS DATETIME2) END, 
+            @level,
+            @message, 
+            @stacktrace, 
+            CASE WHEN @userId = '' THEN NULL ELSE convert(uniqueidentifier, @userId) END, 
+            @uri, 
+            @server, 
+            CASE WHEN @corrolationId = '' THEN NULL ELSE convert(uniqueidentifier, @corrolationId) END, 
+            @status, 
+            @source)"
+
+            };
+            targetDatabase.Parameters.Add(new DatabaseParameterInfo("@serverTimeStamp", new NLog.Layouts.SimpleLayout("${date:universalTime=true}")));
+            targetDatabase.Parameters.Add(new DatabaseParameterInfo("@clientTimeStamp", new NLog.Layouts.SimpleLayout("${mdlc:ClientTimeStamp}")));
+            targetDatabase.Parameters.Add(new DatabaseParameterInfo("@level", new NLog.Layouts.SimpleLayout("${CoscineLogLevel}")));
+            targetDatabase.Parameters.Add(new DatabaseParameterInfo("@message", new NLog.Layouts.SimpleLayout("${message}")));
+            targetDatabase.Parameters.Add(new DatabaseParameterInfo("@stackTrace", new NLog.Layouts.SimpleLayout("${exception:format=message}${exception:format=stackTrace}")));
+            targetDatabase.Parameters.Add(new DatabaseParameterInfo("@userId", new NLog.Layouts.SimpleLayout("${mdlc:User}")));
+            targetDatabase.Parameters.Add(new DatabaseParameterInfo("@uri", new NLog.Layouts.SimpleLayout("${mdlc:Uri}")));
+            targetDatabase.Parameters.Add(new DatabaseParameterInfo("@server", new NLog.Layouts.SimpleLayout("${machinename}")));
+            targetDatabase.Parameters.Add(new DatabaseParameterInfo("@corrolationId", new NLog.Layouts.SimpleLayout("${activityid}")));
+            targetDatabase.Parameters.Add(new DatabaseParameterInfo("@status", new NLog.Layouts.SimpleLayout("${mdlc:Status}")));
+            targetDatabase.Parameters.Add(new DatabaseParameterInfo("@source", new NLog.Layouts.SimpleLayout("${callsite}")));
+            targetDatabase.Parameters.Add(new DatabaseParameterInfo("@type", new NLog.Layouts.SimpleLayout("${exception:format=type}")));
+            targetDatabase.Parameters.Add(new DatabaseParameterInfo("@innerException", new NLog.Layouts.SimpleLayout("${exception:format=:innerFormat=ShortType,Message,Method:MaxInnerExceptionLevel=1:InnerExceptionSeparator=}")));
+            targetDatabase.Parameters.Add(new DatabaseParameterInfo("@additionalInfo", new NLog.Layouts.SimpleLayout("${message}")));
+
+            var targetConsole = new NLog.Targets.ConsoleTarget
+            {
+                Name = "console",
+                Layout = "${date:universalTime=true}|${mdlc:ClientTimeStamp}|${CoscineLogLevel}|${message}|${mdlc:User}|${mdlc:Uri}|${machinename}|${activityid}|${mdlc:Status}|${callsite}|${exception:format=message}${exception:format=stackTrace}"
+            };
+
+
+            config.AddTarget("fileLogger", targetFileLogger);
+            config.AddTarget("databaseLogger", targetDatabase);
+            config.AddTarget("consoleLogger", targetConsole);
+
+
+            var blockAllDebug = new LoggingRule("blockAllDebug");
+            blockAllDebug.SetLoggingLevels(LogLevel.Debug, LogLevel.Debug);
+            blockAllDebug.LoggerNamePattern = "*";
+
+            var blockAllTrace = new LoggingRule("blockAllTrace");
+            blockAllTrace.SetLoggingLevels(LogLevel.Trace, LogLevel.Trace);
+            blockAllTrace.LoggerNamePattern = "*";
+
+            var blockAllWarning = new LoggingRule("blockAllWarning");
+            blockAllWarning.SetLoggingLevels(LogLevel.Warn, LogLevel.Warn);
+            blockAllWarning.LoggerNamePattern = "*";
+
+            var blockAllError = new LoggingRule("blockAllError");
+            blockAllError.SetLoggingLevels(LogLevel.Error, LogLevel.Error);
+            blockAllError.LoggerNamePattern = "*";
+
+            var blockAllFatal = new LoggingRule("blockAllFatal");
+            blockAllFatal.SetLoggingLevels(LogLevel.Fatal, LogLevel.Fatal);
+            blockAllFatal.LoggerNamePattern = "*";
+
+            var blockAllInformation = new LoggingRule("blockAllInformation");
+            blockAllInformation.SetLoggingLevels(LogLevel.Info, LogLevel.Info);
+            blockAllInformation.LoggerNamePattern = "*";
+
+
+            var ruleFileLogger = new LoggingRule("*", LogLevel.Error, LogLevel.Fatal, targetFileLogger);
+            var ruleConsole = new LoggingRule("*", LogLevel.Error, LogLevel.Fatal, targetConsole);
+            var ruleDatabase = new LoggingRule("*", LogLevel.Trace, LogLevel.Fatal, targetDatabase);
+
+            config.LoggingRules.Add(blockAllDebug);
+            config.LoggingRules.Add(blockAllTrace);
+            config.LoggingRules.Add(blockAllWarning);
+            config.LoggingRules.Add(blockAllError);
+            config.LoggingRules.Add(blockAllFatal);
+            config.LoggingRules.Add(blockAllInformation);
+
+            config.LoggingRules.Add(ruleFileLogger);
+            config.LoggingRules.Add(ruleConsole);
+            config.LoggingRules.Add(ruleDatabase);
+
+            LogManager.Configuration = config;
+
+            UpdateActiveLogs();
+        }
+
+
+        public static void UpdateActiveLogs()
+        {
+            activeLoglevels[(int)LogType.Debug] = !GetStringFromConsul(LogLevelKeyDebug, "0").Equals("0");
+            activeLoglevels[(int)LogType.Low] = !GetStringFromConsul(LogLevelKeyLow, "0").Equals("0");
+            activeLoglevels[(int)LogType.Medium] = !GetStringFromConsul(LogLevelKeyMedium, "0").Equals("0");
+            activeLoglevels[(int)LogType.High] = !GetStringFromConsul(LogLevelKeyHigh, "1").Equals("0");
+            activeLoglevels[(int)LogType.Critical] = !GetStringFromConsul(LogLevelKeyCritical, "1").Equals("0");
+            activeLoglevels[(int)LogType.Analytics] = !GetStringFromConsul(LogLevelKeyAnalytics, "0").Equals("0");
+            activeLoglevels[(int)LogType.Reporting] = !GetStringFromConsul(LogLevelKeyReporting, "0").Equals("0");
+
+            var config = LogManager.Configuration;
+            config.FindRuleByName("blockAllInformation").Final = !activeLoglevels[(int)LogType.Analytics] && !activeLoglevels[(int)LogType.Reporting];
+            config.FindRuleByName("blockAllDebug").Final = !activeLoglevels[(int)LogType.Debug];
+            config.FindRuleByName("blockAllTrace").Final = !activeLoglevels[(int)LogType.Low];
+            config.FindRuleByName("blockAllWarning").Final = !activeLoglevels[(int)LogType.Medium];
+            config.FindRuleByName("blockAllError").Final = !activeLoglevels[(int)LogType.High];
+            config.FindRuleByName("blockAllFatal").Final = !activeLoglevels[(int)LogType.Critical];
+
+            LogManager.Configuration = config;
+            LogManager.ReconfigExistingLoggers();
+        }
+
+        private static string GetDbConnectionString()
+        {
+            var dbDataSource = GetStringFromConsul(DbDataSourceKey);
+            var dbDatabase = GetStringFromConsul(DbNameKey);
+            var dbUserId = GetStringFromConsul(DbUserIdKey);
+            var dbPassword = GetStringFromConsul(DbPasswordKey);
+            return $"Data Source={dbDataSource}; Database={dbDatabase}; User Id={dbUserId}; Password={dbPassword};";
+        }
+
+        private static string GetStringFromConsul(string key)
+        {
+            using (var client = new ConsulClient())
+            {
+                var getPair = client.KV.Get(key);
+
+                getPair.Wait();
+
+                if (getPair.Result.Response?.Value != null)
+                {
+                    var value = getPair.Result.Response.Value;
+                    return Encoding.UTF8.GetString(value, 0, value.Length);
+                }
+                else
+                {
+                    // TODO: Add logging that key has not been found
+                    return null;
+                }
+            }
+        }
+
+        private static string GetStringFromConsul(string key, string defaultValue)
+        {
+            var value = GetStringFromConsul(key);
+            if (value == null)
+            {
+                // TODO: Add logging that default value has been used
+                return defaultValue;
+            }
+            return value;
+        }
+    }
+}
diff --git a/src/Logging/CoscineLoggerMetadata.cs b/src/Logging/CoscineLoggerMetadata.cs
new file mode 100644
index 0000000000000000000000000000000000000000..3e8593784f1fc2e7dfe647755945df04377aeb64
--- /dev/null
+++ b/src/Logging/CoscineLoggerMetadata.cs
@@ -0,0 +1,113 @@
+using NLog;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+
+namespace Coscine.Logging
+{
+    public class CoscineLoggerMetadata
+    {
+        public static void SetUserId(string userId = "00000000-0000-0000-0000-000000000000")
+        {
+            if (IsGuid(userId))
+            {
+                MappedDiagnosticsLogicalContext.Set("User", userId);
+            }
+            else
+            {
+                MappedDiagnosticsLogicalContext.Set("User", "");
+            }
+        }
+
+        public static void SetUserId(Guid userId)
+        {
+            CoscineLoggerMetadata.SetUserId(userId.ToString());
+        }
+
+        public static string GetUserId()
+        {
+            return MappedDiagnosticsLogicalContext.Get("User");
+        }
+
+        public static void SetAnalytics(bool active)
+        {
+            var value = active ? "true" : "false";
+            MappedDiagnosticsLogicalContext.Set("Analytics", value);
+        }
+
+        public static void SetReporting(bool active)
+        {
+            var value = active ? "true" : "false";
+            MappedDiagnosticsLogicalContext.Set("Reporting", value);
+        }
+
+        public static void SetUri(string uri = "")
+        {
+            MappedDiagnosticsLogicalContext.Set("Uri", uri);
+        }
+
+        public static void SetCorrolationId()
+        {
+            Trace.CorrelationManager.ActivityId = Guid.NewGuid();
+        }
+
+        public static void SetClientCorrolationId(string clientCorrolationId = "00000000-0000-0000-0000-000000000000")
+        {
+            if (IsGuid(clientCorrolationId))
+            {
+                MappedDiagnosticsLogicalContext.Set("ClientCorrolationId", clientCorrolationId);
+            }
+            else
+            {
+                MappedDiagnosticsLogicalContext.Set("ClientCorrolationId", "00000000-0000-0000-0000-000000000000");
+            }
+        }
+
+        public static void SetClientCorrolationId()
+        {
+            MappedDiagnosticsLogicalContext.Set("ClientCorrolationId", Guid.NewGuid());
+        }
+
+        public static void SetClientCorrolationId(Guid clientCorrolationId)
+        {
+            CoscineLoggerMetadata.SetClientCorrolationId(clientCorrolationId.ToString());
+        }
+
+        public static string GetClientCorrolationId()
+        {
+            return MappedDiagnosticsLogicalContext.Get("ClientCorrolationId");
+        }
+
+
+        public static void SetSessionsId(string sessionId = "")
+        {
+            MappedDiagnosticsLogicalContext.Set("SessionId", sessionId);
+        }
+
+        public static string GetSessionId()
+        {
+            return MappedDiagnosticsLogicalContext.Get("SessionId");
+        }
+
+        public static void SetStatus(string status = "")
+        {
+            MappedDiagnosticsLogicalContext.Set("Status", status);
+        }
+
+        public static void SetClientTimeStamp(string clientTimeStamp = "")
+        {
+            MappedDiagnosticsLogicalContext.Set("ClientTimeStamp", clientTimeStamp);
+        }
+
+        private static bool IsGuid(string guid)
+        {
+            var match = Regex.Match(guid, @"^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$",
+            RegexOptions.IgnoreCase);
+            return match.Success;
+        }
+    }
+}
diff --git a/src/Logging/Logging.csproj b/src/Logging/Logging.csproj
index 5941eb7aacf846fad892533c69083c29d07f00aa..38fc62301d7a9829ab41fd77613eb03c9fd4ef34 100644
--- a/src/Logging/Logging.csproj
+++ b/src/Logging/Logging.csproj
@@ -43,6 +43,9 @@
     <Reference Include="Microsoft.Extensions.Logging.Abstractions, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
       <HintPath>..\packages\Microsoft.Extensions.Logging.Abstractions.2.2.0\lib\netstandard2.0\Microsoft.Extensions.Logging.Abstractions.dll</HintPath>
     </Reference>
+    <Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
+      <HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
+    </Reference>
     <Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
       <HintPath>..\packages\NLog.4.6.8\lib\net45\NLog.dll</HintPath>
     </Reference>
@@ -64,7 +67,10 @@
     <Reference Include="System.Xml" />
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="AnalyticsLogObject.cs" />
     <Compile Include="CoscineLogger.cs" />
+    <Compile Include="CoscineLoggerConfiguration.cs" />
+    <Compile Include="CoscineLoggerMetadata.cs" />
     <Compile Include="LogLevelLayoutRenderer.cs" />
     <Compile Include="LogType.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
diff --git a/src/Logging/Properties/AssemblyInfo.cs b/src/Logging/Properties/AssemblyInfo.cs
index 674e6192251a7b6f37040fd7a945721425b0126d..d0b2af41fb94c7a5728f0032b4bcd0799db370b5 100644
--- a/src/Logging/Properties/AssemblyInfo.cs
+++ b/src/Logging/Properties/AssemblyInfo.cs
@@ -9,8 +9,8 @@ using System.Reflection;
 [assembly: AssemblyDescription("Logging is a part of the CoScInE group.")]
 [assembly: AssemblyCompany("IT Center, RWTH Aachen University")]
 [assembly: AssemblyProduct("Logging")]
-[assembly: AssemblyVersion("1.0.1.0")]
-[assembly: AssemblyFileVersion("1.0.1.0")]
-[assembly: AssemblyInformationalVersion("1.0.1.0")]
+[assembly: AssemblyVersion("1.1.0")]
+[assembly: AssemblyFileVersion("1.1.0")]
+[assembly: AssemblyInformationalVersion("1.1.0-topic-671-readab0009")]
 [assembly: AssemblyCopyright("2020 IT Center, RWTH Aachen University")]
 
diff --git a/src/Logging/packages.config b/src/Logging/packages.config
index 7fcf9f86bdc44872105c6d6c41cde1171fb0f661..ca50963dc2c75c910274d683a06249abfa041b82 100644
--- a/src/Logging/packages.config
+++ b/src/Logging/packages.config
@@ -2,6 +2,7 @@
 <packages>
   <package id="Consul" version="0.7.2.6" targetFramework="net472" />
   <package id="Microsoft.Extensions.Logging.Abstractions" version="2.2.0" targetFramework="net461" />
+  <package id="Newtonsoft.Json" version="12.0.3" targetFramework="net461" />
   <package id="NLog" version="4.6.8" targetFramework="net472" />
   <package id="NLog.Config" version="4.6.8" targetFramework="net472" />
   <package id="NLog.Schema" version="4.6.8" targetFramework="net472" />