-
Notifications
You must be signed in to change notification settings - Fork 84
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
GetCompressedLogs- how to for xamarin.forms project? #117
Comments
It looks like that in the article something is missing. he didnt mention how to get LogManager. My code below isnt working because i am not sure if it is correct to use StreamingFileTarget as i am getting exception regarding it.
|
I think I'm trying to do the same (or a similar?) thing... I have the following method that gets the compressed logs (in my LogManager class, in a .NET Standard library):
And the following code that calls it (in my Xamarin mobile app):
The issue I'm having is if I try to log a message first, and then get the compressed logs, it deadlocks. See minimal, reproducible example in pull request #118. I tried most (all?) of the potential solutions at https://stackoverflow.com/questions/9343594/how-to-call-asynchronous-method-from-synchronous-method-in-c, but nothing worked for me. Except for adding ConfigureAwait(false) to a couple of places in this library....The changes in pull request #118. I'm thinking of maybe using the following code as a temporary workaround:
(Where streamingFileTarget is a class member, set to new StreamingFileTarget() when the logging is configured.) It calls CloseAllOpenStreamsInternal() and GetCompressedLogsInternal(), same as GetCompressedLogs() but without the locking. I'm hoping that this will work well enough until a fix is implemented to this library. |
I'm using metrolog to attach logs to AppCenter, this is what I am doing (I'm using Prism.Dryioc): in App.xaml.cs: ```csharp
using LogLevel = MetroLog.LogLevel;
namespace Whatever
{
public partial class App
{
private static ILogger log;
public App(IPlatformInitializer initializer)
: base(initializer)
{
}
protected override async void OnInitialized()
{
InitializeComponent();
var result = await NavigationService.NavigateAsync("NavigationPage/MainPage");
if (result.Exception != null)
{
throw result.Exception;
}
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
RegisterInfrastructure(containerRegistry);
RegisterDomain(containerRegistry);
RegisterNavigation(containerRegistry);
}
private static void RegisterInfrastructure(IContainerRegistry containerRegistry)
{
InitializeAppCenter();
log = InitializeLogger();
containerRegistry.RegisterInstance<Prism.Logging.ILogger>(new PrismLoggerWrapper(log));
containerRegistry.RegisterSingleton<IAppInfo, AppInfoImplementation>();
}
private static void RegisterDomain(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterSingleton<ILightService, LightServiceMock>();
}
private static void RegisterNavigation(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterForNavigation<NavigationPage>();
containerRegistry.RegisterForNavigation<MainPage, MainPageViewModel>();
containerRegistry.RegisterForNavigation<LightEditPage, LightEditPageViewModel>();
}
private static void InitializeAppCenter()
{
#if RELEASE
if (PlatformService.IsEmulator)
{
return;
}
Crashes.GetErrorAttachments = report =>
{
var compressedLogs = LoggerFactory.GetCompressedLogs();
return new[]
{
ErrorAttachmentLog.AttachmentWithBinary(
compressedLogs.ToArray(),
"logs.zip",
"application/x-zip-compressed"),
};
};
AppCenter.Start(
"ios=XXXXX;android=XXXXX",
typeof(Analytics),
typeof(Crashes),
typeof(Distribute));
#endif
}
private static ILogger InitializeLogger()
{
var config = new LoggingConfiguration();
#if RELEASE
// Will be stored in: $"MetroLog{Path.DirectorySeparatorChar}MetroLogs{Path.DirectorySeparatorChar}Log.log"
if (!PlatformService.IsEmulator)
{
config.AddTarget(LogLevel.Info, LogLevel.Fatal, new StreamingFileTarget { RetainDays = 2 });
}
else
{
config.AddTarget(LogLevel.Debug, LogLevel.Fatal, new DebugTarget());
}
#else
config.AddTarget(LogLevel.Debug, LogLevel.Fatal, new DebugTarget());
#endif
LoggerFactory.Initialize(config);
var logger = LoggerFactory.GetLogger(nameof(App));
TaskMonitorConfiguration.ErrorHandler = (t, m, e) => logger.Error(m, e);
return logger;
}
}
} LoggerFactory.cs using System;
using System.IO;
using System.Threading.Tasks;
using MetroLog;
namespace Whatever.Infrastructure.Logging
{
public static class LoggerFactory
{
private static ILogManager logManager;
public static void Initialize(LoggingConfiguration configuration)
{
logManager = LogManagerFactory.CreateLogManager(configuration);
}
public static ILogger GetLogger(string loggerName)
{
if (logManager == null)
{
throw new InvalidOperationException("LogFactory must be Initialized before creating any logger");
}
return logManager.GetLogger(loggerName);
}
public static ILogger TryGetLogger(string loggerName)
{
if (logManager == null)
{
return new ConsoleLogger();
}
return logManager.GetLogger(loggerName);
}
public static MemoryStream GetCompressedLogs()
{
Stream compressedLogs = null;
Task.Run(async () => compressedLogs = await logManager.GetCompressedLogs()).Wait();
return (MemoryStream)compressedLogs;
}
}
} |
lol didn't see it was my blog post referenced in this thread. |
@roubachof, yeah, it was your article that started us down this road :) many thanks!! MetroLog (and that GetCompressedLogs-deadlock workaround that I mentioned) seems to be working quite well, so far, fingers crossed. Hopefully, this will help us to get better info about why our app is crashing. |
I have to revisit this 2 years already since I posted this and I couldn't achieve it before. So you are saying that you solved the deadlock problem and it is working fine for you? Have you had chance to test for ios also? |
@EmilAlipiev, yeah, we tested the GetCompressedLogs-deadlock workaround on Android, iOS, and Windows (UWP). It seems to be working fine on all of these platforms. But it would be nice to have a permanent fix for this; #118 may help, but may also be incomplete. (Note: We only tested this PR's changes on Windows, so there may be additional changes that are needed to get this to work on Android and iOS, and also maybe for other scenarios that we didn't test for on Windows.) Also, since you mentioned iOS, on Android and iOS, GetCompressedLogs will throw an exception if the log folder doesn't exist. We ensure that a message is logged (see the Configure method, in the code below) before we call GetCompressedLogs, so that the log folder exists. (Note: MetroLog.Shared.WinRT\FileTarget.cs, GetCompressedLogsInternal(), used by Windows, calls EnsureInitializedAsync(), but MetroLog.NetFx\FileTarget.cs, used by Android and iOS, doesn't.) Just in case it helps, the following is our LogManager class. (Note: I modified it before posting it here; hopefully it works okay.). If you're running into other issues, let us know, we may be able to help. LogManager.cs:
The above code is used like:
|
@EmilAlipiev you can use the LoggerFactory I attached. I use them in a lot of apps and never had any deadlock issues |
@roubachof, did you try logging a message before you get the compressed logs? See minimal, reproducible example in pull request #118. |
@sdiaman1 yes of course, I use the LoggerFactory in multiple apps that compressed logs on crash and sen them to appcenter |
@roubachof, did you try the minimal, reproducible example in pull request #118, does it not deadlock? For example, if you're only getting the compressed logs for App Center crash reports, and you're not logging any messages immediately before that (at app startup), then you might never run into this issue. |
Nope cause I'm using my LoggerFactory to get thé compressed logs |
you will be able to use the MetroLog.Maui package when you will migrate to maui :) |
Hi,
I am trying to implement attachments on crashes using metrolog. There is this blog post written but either it doesnt work i dont understand the exact implementation. https://devblogs.microsoft.com/appcenter/give-your-crashes-a-context-through-logs-attachments/
Basically in the post title with "App Center Brings Logs and Crash Together
The Idea".
I tried to implement this on xamarin.forms project. I am not sure code given there is for .net standard code or platform specific. However I tried both even using a DI to android project and get the manager and memorystream from there but still doesnt work. I dont see any attachment for my testcrash. Is there a better information regarding this how can make it work zip attachment in xamarin.forms projects?
my code would like as below,
in android project
In the shared standard project
Would this work? Do i understand things correct?
The text was updated successfully, but these errors were encountered: