Skip to content
Browse files

Get zip file stream from logs in log dir

  • Loading branch information...
1 parent ddba886 commit 13209b6dad34e69aed318de24ea521da11d68bd2 @onovotny committed
View
4 MetroLog.NetCore.SQLite/MetroLog.NetCore.SQLite.csproj
@@ -106,8 +106,8 @@
<SDKReference Include="Microsoft.VCLibs, Version=11.0">
<Name>Microsoft Visual C++ Runtime Package</Name>
</SDKReference>
- <SDKReference Include="SQLite.WinRT, Version=3.7.14">
- <Name>SQLite for Windows Runtime</Name>
+ <SDKReference Include="SQLite.WinRT, Version=3.7.14.1">
+ <Name>SQLite for Windows Runtime %28SQLite.WinRT, Version=3.7.14.1%29</Name>
</SDKReference>
</ItemGroup>
<ItemGroup>
View
20 MetroLog.NetCore.Tests/FileSnapshotTests.cs
@@ -35,5 +35,25 @@ public class FileSnapshotTargetTests
Assert.True(contents.Contains("Testing file write..."));
Assert.True(contents.Contains("An exception message..."));
}
+
+ [Fact]
+ public async Task TestGetZipFile()
+ {
+ var target = new FileSnapshotTarget();
+ // send through a log entry...
+ var op = await target.WriteAsync(new LogWriteContext(),
+ new LogEventInfo(LogLevel.Fatal, "TestLogger", "Testing file write...", new InvalidOperationException("An exception message...")));
+
+ var folder = await FileSnapshotTarget.EnsureInitializedAsync();
+
+ var str = await target.GetCompressedLogs();
+
+ var file = await ApplicationData.Current.TemporaryFolder.CreateFileAsync("logs.zip", CreationCollisionOption.ReplaceExisting);
+
+ using (var stream = (await file.OpenAsync(FileAccessMode.ReadWrite)).AsStream())
+ {
+ await str.CopyToAsync(stream);
+ }
+ }
}
}
View
1 MetroLog.NetCore/MetroLog.NetCore.csproj
@@ -123,6 +123,7 @@
<Compile Include="WinRTFileTarget.cs" />
<Compile Include="XamlApplicationState.cs" />
<Compile Include="XamlExtensionMethods.cs" />
+ <Compile Include="ZipFile.cs" />
</ItemGroup>
<ItemGroup>
<None Include="..\MetroLog.snk">
View
11 MetroLog.NetCore/WinRTFileTarget.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
+using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
@@ -33,6 +34,16 @@ protected WinRTFileTarget(Layout layout) : base(layout)
return _logFolder;
}
+ protected override async Task<Stream> GetCompressedLogsInternal()
+ {
+ var ms = new MemoryStream();
+
+ await ZipFile.CreateFromDirectory(_logFolder, ms);
+ ms.Position = 0;
+
+ return ms;
+ }
+
protected override Task EnsureInitialized()
{
View
114 MetroLog.NetCore/ZipFile.cs
@@ -0,0 +1,114 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.IO.Compression;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Windows.Storage;
+
+namespace MetroLog
+{
+ static class ZipFile
+ {
+ public static Task CreateFromDirectory(IStorageFolder source, Stream destinationArchive)
+ {
+ return DoCreateFromDirectory(source, destinationArchive, new CompressionLevel?(), null);
+ }
+
+
+ private static async Task DoCreateFromDirectory(IStorageFolder source, Stream destinationArchive, CompressionLevel? compressionLevel, Encoding entryNameEncoding)
+ {
+ var notCreated = true;
+
+ var fullName = source.Path;
+
+ using (var destination = await Open(destinationArchive, ZipArchiveMode.Create, entryNameEncoding))
+ {
+ foreach (var item in await source.GetStorageItemsRecursive())
+ {
+ notCreated = false;
+ var length = item.Path.Length - fullName.Length;
+ var entryName = item.Path.Substring(fullName.Length, length).TrimStart('\\', '/');
+
+ if (item is IStorageFile)
+ {
+ var entry = await DoCreateEntryFromFile(destination, (IStorageFile)item, entryName, compressionLevel);
+ }
+ else
+ {
+ destination.CreateEntry(entryName + '\\');
+ }
+ }
+ }
+ }
+
+
+ public static Task<ZipArchive> OpenRead(Stream archive)
+ {
+ return Open(archive, ZipArchiveMode.Read);
+ }
+
+ public static async Task<ZipArchive> Open(Stream archive, ZipArchiveMode mode, Encoding entryNameEncoding = null)
+ {
+ if (archive == null) throw new ArgumentNullException("archive");
+
+ return new ZipArchive(archive, mode, true, entryNameEncoding);
+ }
+
+ private static async Task<bool> IsDirEmpty(IStorageFolder possiblyEmptyDir)
+ {
+ return (await possiblyEmptyDir.GetFilesAsync()).Count == 0;
+ }
+
+ private static async Task<IEnumerable<IStorageItem>> GetStorageItemsRecursive(this IStorageFolder parent)
+ {
+ var list = new List<IStorageItem>();
+
+ var stack = new Stack<IStorageFolder>();
+ stack.Push(parent);
+
+ while (stack.Count > 0)
+ {
+ var current = stack.Pop();
+
+ var files = await current.GetFilesAsync();
+ if (files.Count > 0)
+ list.AddRange(files);
+ else
+ list.Add(current);
+
+ foreach (var subdir in await current.GetFoldersAsync())
+ {
+ stack.Push(subdir);
+ }
+
+ }
+
+ return list;
+ }
+
+ private static async Task<ZipArchiveEntry> DoCreateEntryFromFile(ZipArchive destination, IStorageFile sourceFile, string entryName, CompressionLevel? compressionLevel)
+ {
+ if (destination == null)
+ throw new ArgumentNullException("destination");
+ if (sourceFile == null)
+ throw new ArgumentNullException("sourceFile");
+ if (entryName == null)
+ throw new ArgumentNullException("entryName");
+ using (Stream stream = (await sourceFile.OpenReadAsync()).AsStream())
+ {
+ ZipArchiveEntry zipArchiveEntry = compressionLevel.HasValue ? destination.CreateEntry(entryName, compressionLevel.Value) : destination.CreateEntry(entryName);
+ DateTime dateTime = sourceFile.DateCreated.UtcDateTime; //File.GetLastWriteTime(sourceFileName);
+ if (dateTime.Year < 1980 || dateTime.Year > 2107)
+ dateTime = new DateTime(1980, 1, 1, 0, 0, 0);
+ zipArchiveEntry.LastWriteTime = (DateTimeOffset)dateTime;
+ using (Stream destination1 = zipArchiveEntry.Open())
+ {
+ await stream.CopyToAsync(destination1);
+ }
+ return zipArchiveEntry;
+ }
+ }
+ }
+}
View
21 MetroLog.NetFx/FileTarget.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
+using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Text;
@@ -29,6 +30,23 @@ public string PathUnderAppData
}
}
+ protected override async Task<Stream> GetCompressedLogsInternal()
+ {
+ var ms = new MemoryStream();
+
+ using (var a = new ZipArchive(ms, ZipArchiveMode.Create, true))
+ {
+ foreach (var file in _logFolder.GetFiles())
+ {
+ a.CreateEntryFromFile(file.FullName, file.Name);
+ }
+ }
+
+ ms.Position = 0;
+
+ return ms;
+ }
+
protected FileTarget(Layout layout) : base(layout)
{
_appDataPath = GetUserAppDataPath();
@@ -107,7 +125,8 @@ private static string GetUserAppDataPath()
var path = string.Empty;
// Get the .EXE assembly
- var assm = Assembly.GetEntryAssembly();
+ var assm = Assembly.GetEntryAssembly() ?? Assembly.GetExecutingAssembly();
+
// Build the User App Data Path
path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), assm.GetName().Name);
View
2 MetroLog.NetFx/MetroLog.NetFx.csproj
@@ -38,6 +38,8 @@
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
+ <Reference Include="System.IO.Compression" />
+ <Reference Include="System.IO.Compression.FileSystem" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
View
2 MetroLog.NetFx/StreamingFileTarget.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
+using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@@ -29,6 +30,7 @@ public StreamingFileTarget(Layout layout) : base(layout)
protected override Task WriteTextToFileCore(StreamWriter file, string contents)
{
+ // ZipFile sf;
return file.WriteLineAsync(contents);
}
}
View
28 MetroLog.Tests/Tests/LogManagerTests.cs
@@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
+using System.IO;
using System.Linq;
using System.Text;
+using System.Threading.Tasks;
using MetroLog.Internal;
using Xunit;
@@ -40,9 +42,33 @@ public void TestLoggerCreated()
// call...
var logger = manager.GetLogger<LogManagerTests>();
-
+
// check...
Assert.True(called);
}
+
+ [Fact]
+ public async Task TestGetZipNetFile()
+ {
+
+ var manager = new LogManager(LogManagerFactory.CreateLibraryDefaultSettings());
+ manager.DefaultConfiguration.AddTarget(LogLevel.Trace, LogLevel.Fatal, new StreamingFileTarget());
+
+ var logger = (ILoggerAsync)manager.GetLogger("test");
+ // send through a log entry...
+ await logger.DebugAsync("Test Message");
+
+ var str = await manager.GetCompressedLogs();
+
+ var file =
+ new FileInfo(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory, Environment.SpecialFolderOption.None), "logs.zip"));
+
+
+
+ using (var stream = file.Create())
+ {
+ await str.CopyToAsync(stream);
+ }
+ }
}
}
View
26 MetroLog.WinRT/Logger.cs
@@ -1,11 +1,15 @@
using System;
using System.Collections.Generic;
+using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using MetroLog.Targets;
+using Windows.Foundation;
+using Windows.Storage;
+using Windows.Storage.Streams;
using IPclLogger = MetroLog.ILogger;
using PclLogLevel = MetroLog.LogLevel;
@@ -36,6 +40,28 @@ static Logger()
});
}
+ /// <summary>
+ /// Returns a zip file stream of compressed logs
+ /// </summary>
+ /// <returns></returns>
+ public static IAsyncOperation<IRandomAccessStream> GetCompressedLogs()
+ {
+ return GetCompressedLogsInternal().AsAsyncOperation();
+ }
+
+ private static async Task<IRandomAccessStream> GetCompressedLogsInternal()
+ {
+ using (var stream = await _logManager.Value.GetCompressedLogs())
+ {
+ // Copy to a WinRT buffer
+ var dest = new InMemoryRandomAccessStream();
+ await stream.CopyToAsync(dest.AsStreamForWrite());
+ dest.Seek(0);
+
+ return dest;
+ }
+ }
+
private static void OnLogMessageInternal(string message)
{
var evt = OnLogMessage;
View
9 MetroLog/ILogManager.cs
@@ -1,4 +1,5 @@
-using MetroLog.Targets;
+using System.IO;
+using MetroLog.Targets;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -16,5 +17,11 @@ public interface ILogManager
ILogger GetLogger(string name, LoggingConfiguration config = null);
event EventHandler<LoggerEventArgs> LoggerCreated;
+
+ /// <summary>
+ /// Returns a zip archive stream of the logs folder
+ /// </summary>
+ /// <returns>Null if no file logger is attached</returns>
+ Task<Stream> GetCompressedLogs();
}
}
View
19 MetroLog/Internal/LogManager.cs
@@ -1,9 +1,10 @@
using System;
using System.Collections.Generic;
-using System.Diagnostics;
+using System.IO;
using System.Linq;
-using System.Runtime.CompilerServices;
using System.Text;
+using System.Threading.Tasks;
+using MetroLog.Targets;
namespace MetroLog.Internal
{
@@ -15,6 +16,20 @@ internal class LogManager : ILogManager
private readonly object _loggersLock = new object();
public event EventHandler<LoggerEventArgs> LoggerCreated;
+
+ public Task<Stream> GetCompressedLogs()
+ {
+ // get the first file target if there is one
+
+ var fsb = DefaultConfiguration.GetTargets().OfType<FileTargetBase>().FirstOrDefault();
+
+ if (fsb != null)
+ {
+ return fsb.GetCompressedLogs();
+ }
+
+ return Task.FromResult<Stream>(null);
+ }
internal const string DateTimeFormat = "o";
View
6 MetroLog/Targets/FileTargetBase.cs
@@ -44,6 +44,12 @@ protected FileTargetBase(Layout layout)
protected abstract Task EnsureInitialized();
protected abstract Task DoCleanup(Regex pattern, DateTime threshold);
+ protected abstract Task<Stream> GetCompressedLogsInternal();
+
+ internal Task<Stream> GetCompressedLogs()
+ {
+ return GetCompressedLogsInternal();
+ }
private async Task CheckCleanupAsync()
{

0 comments on commit 13209b6

Please sign in to comment.
Something went wrong with that request. Please try again.