Forum Xamarin.Forms

Logging with Xamarin PCL

I'd like to incorporate some logging into my Xamarin app, and I'm having trouble understanding the options available and how best to leverage them. I've seen examples that use System.Console and System.Diagnostics to write log messages that appear in the Application Output window in Xamarin Studio when debugging. However those classes don't appear to be available from within a PCL project. Am I missing something or do I have to roll my own cross-platform Console abstraction?

It's also not clear to me what relationship, if any, Console logging has with the native logging implementations. On iOS NSLog and asl_log are available to write to the system log. On android there is android.util.Log. Is there a cross platform logging framework available that can write to the appropriate platform-specific API?

Posts

  • Thanks Stephane. I've tried Debug.WriteLine on iOS and I do see my messages in the app output in Xamarin Studio. However, when I connect with the Xcode organizer to view the console output on the device, those messages don't appear. Any idea why?

  • So I did some more testing and apparently System.Diagnostics.Debug.WriteLine only works when debugging the application. In an installed app, those messages are not written to NSLog or android.util.Log, and I'm not aware of any switch to turn this on. However, there are cases where it is desirable to write a log message when debugging is unavailable. The apparent lack of support for Console.WriteLine in PCL projects makes this problematic. In my case, I was running into a problem where my application ran fine in the debugger, but not when deployed Ad-Hoc via a .ipa.

    I ended up writing a platform-specific "ConsoleLogWriter" class in my iOS project that simply writes to Console.WriteLine and wiring that up at runtime to a logging class in my PCL project. It was just a few lines of code for me to write, but I think this functionality should be provided by Xamarin for PCL projects.

  • threadythready CAMember ✭✭✭

    Any news on this? Looks like this is still the case.

  • JakubArnold.8011JakubArnold.8011 CZMember ✭✭

    Apart from using Debug.WriteLine, you could also use the DependencyService to implement custom logging on each platform. See http://developer.xamarin.com/guides/cross-platform/xamarin-forms/dependency-service/

  • JakubArnold.8011JakubArnold.8011 CZMember ✭✭

    Apart from using Debug.WriteLine, you could also use the DependencyService to implement custom logging on each platform. See http://developer.xamarin.com/guides/cross-platform/xamarin-forms/dependency-service/

  • mattdnamattdna AUMember

    I am unit testing a PCL library (using nunit). The unit test project is also a PCL, and therefore I can't use Console.Writeline, and I'm not aware of any way of injecting a dependency service into a PCL unit test.
    If I use Debug.WriteLine(), the output doesn't appear in my test Output window.

    Am I missing something?
    Does anyone have any suggestions as to how I can log to the Test Output window from within a PCL unit test?

  • NMackayNMackay GBInsider, University admin

    Xamarin insights can be useful for this.

    Certainly during dev it managed to trap some errors that I didn't get in the studio debugger. It's really handy.

    https://xamarin.com/insights

  • Anurag.9113Anurag.9113 USMember ✭✭

    I have found Insights to be least helpful. I wish I could route debug.writelines to a custom logger. You can do that in iOS. All NSLogs can be routed to a custom log.

  • adamkempadamkemp USInsider, Developer Group Leader mod
  • adamkempadamkemp USInsider, Developer Group Leader mod

    But remember that Debug.* methods are compiled away in non-debug builds. Never use Debug.* methods for logging information you would want in a production build. Instead use Trace.*, which goes to the same place but doesn't get compiled away.

  • PhilipOGormanPhilipOGorman USMember ✭✭✭

    Is there any software that acts like NLog or log4net? That actually writes an application specific file to disk?
    I cant use insights - my apps are quite often used offline.

  • NMackayNMackay GBInsider, University admin

    @PhilipOGorman

    Why not use SQLite for storing that info?

  • PhilipOGormanPhilipOGorman USMember ✭✭✭

    @NMackay good idea - although sql has always scared me, I wonder if there are portable version of document style DB avaliable (Raven, mongo).

    I'll have a look around

  • NMackayNMackay GBInsider, University admin
    edited April 2016

    @PhilipOGorman

    SQLite is easy enough to get up and running. You need to use the dependency service but it's easy enough. I use it to store users favorites, preferences etc.

  • AdrianKnightAdrianKnight USMember ✭✭✭✭

    @adamkemp Is Trace available in PCL?

  • PhilipOGormanPhilipOGorman USMember ✭✭✭
    edited November 2016

    We have started to use Common.Logging as our logging abstraction, our PCL are run on desktop, mono, ios and android so this is very useful. For mobile app we started to use serilog https://serilog.net/, someone has written a sink for xamarin: https://github.com/serilog/serilog-sinks-xamarin also someone has added it to common logging https://github.com/CaptiveAire/Common.Logging.Serilog. The file sink also works which is really useful in testing, https://github.com/serilog/serilog-sinks-rollingfile

    Log.Logger = new LoggerConfiguration() .WriteTo.RollingFile(Path.Combine(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath, "JCA_log-{Date}.txt") ,outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] {Message}{NewLine}{Exception}") .WriteTo.AndroidLog() .CreateLogger();

  • KazimotoKazimoto USMember ✭✭

    My solution for Android with Debug.WriteLine("Log...") to view in "Android Device Monitor":

    public class LogTraceListener : System.Diagnostics.TraceListener
    {
        public override void Write(string message)
        {
            Android.Util.Log.WriteLine(Android.Util.LogPriority.Debug, "MyApp", message);
        }
    
        public override void WriteLine(string message)
        {
            Android.Util.Log.WriteLine(Android.Util.LogPriority.Debug, "MyApp", message);
        }
    }
    
    
    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
    {
        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);
            System.Diagnostics.Debug.Listeners.Add(new LogTraceListener());
         }
    }
    
  • KazimotoKazimoto USMember ✭✭

    Another solution that works in release mode in "Android Device Monitor":

    public interface IDebugger
    {
        void WriteLine(string message);
    }
    
    [assembly: Xamarin.Forms.Dependency(typeof(MyLib.Xamarin.Debugger))]
    namespace MyLib.Xamarin
    {
        public class Debugger : IDebugger
        {
            public void WriteLine(string message)
            {
                Android.Util.Log.Debug("MyApp", message);
            }
        }
    }
    
    public class MyDebugger
    {
        public static void WriteLine(string message)
        {
            IDebugger debugger = DependencyService.Get<IDebugger>(DependencyFetchTarget.GlobalInstance);
            debugger.WriteLine(message)
        }
    }
    
  • EmilyChristyEmilyChristy GBMember ✭✭

    @PhilipOGorman said:
    We have started to use Common.Logging as our logging abstraction, our PCL are run on desktop, mono, ios and android so this is very useful. For mobile app we started to use serilog https://serilog.net/, someone has written a sink for xamarin: https://github.com/serilog/serilog-sinks-xamarin also someone has added it to common logging https://github.com/CaptiveAire/Common.Logging.Serilog. The file sink also works which is really useful in testing, https://github.com/serilog/serilog-sinks-rollingfile

    Log.Logger = new LoggerConfiguration() .WriteTo.RollingFile(Path.Combine(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath, "JCA_log-{Date}.txt") ,outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] {Message}{NewLine}{Exception}") .WriteTo.AndroidLog() .CreateLogger();

    Hi @PhilipOGorman,

    Could you share details of how you got this working? I'm implementing SeriLog in a Xamarin PCL project and can see the Android logs fine, but not the logs from the PCL. Where do the log files appear? And do you manage to log them to a device file from the PCL?

  • PhilipOGormanPhilipOGorman USMember ✭✭✭

    @EmilyChristy it's a little convoluted because we wanted the logging to be portable. Anyway here is what we did:

    Any class that need logging is injected with the following interface:

    using Common.Logging;
    
    namespace Portable.Common.Tools
    {
        public interface ILogProvider
        {
            ILog GetLogger<T>();
        }
    }
    

    To get a portable version of ILog you'll need "Common.Logging" version="3.4.0-Beta2"

    So now all your classes need is a reference to ILogProvider and ILog

    Now you'll need to create the ILogProvider on Android. To do this I had to fork and update this repo:
    https://github.com/CaptiveAire/Common.Logging.Serilog
    I updated it to use the latest "Common.Logging" version="3.4.0-Beta2". Then I repackaged it into my own nuget.

    Here is the code for the android serilog ILogProvider :

        public class SeriLogProvider : ILogProvider
        {
            public SeriLogProvider()
            {
                // syncronous for more accurate time stamps
                //Log.Logger = new LoggerConfiguration()
                //    .WriteTo.RollingFile(Path.Combine(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath, "JCA_log-{Date}.txt")
                //    ,outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] [{SourceContext}] {Message}{NewLine}{Exception}")
                //    .WriteTo.AndroidLog()
                //    .CreateLogger();
    
                // asyncronous for better performance, at shut down call Log.CloseAndFlush();
                // Because the memory buffer may contain events that have not yet been written to the target sink, it is important to call Log.CloseAndFlush() or Logger.Dispose() when the application exits.
                Log.Logger = new LoggerConfiguration()
                    .MinimumLevel.Debug()
                    .WriteTo.Async(a => a.RollingFile(Path.Combine(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath, "TestReprogramming/Logs/Reprogramming_LOG-{Date}.txt")
                    , outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] [{SourceContext}] {Message}{NewLine}{Exception}"))
                    .WriteTo.AndroidLog()
                    .CreateLogger();
    
                LogManager.Adapter = new SerilogFactoryAdapter(Log.Logger);
            }
            public ILog GetLogger<T>()
            {
                return LogManager.GetLogger<T>();
            }
    
            public void CloseAndFlush()
            {
                Log.CloseAndFlush();
            }
        }
    
  • PavlickPavlick USMember ✭✭

    NLog works just fine with Android and iOS projects. For UWP you can use MetroLog which is very similar with NLog but on a smaller scale. Use DependencyService in your shared code to get platform dependent implementation.
    Google "LOGGING WITH NLOG IN XAMARIN FORMS" for NLog example and add MetroLog specific classes to your UWP project.
    Both NLog and MetroLog can be installed through NuGet.

  • Where can I see the message that writeline has?

  • batmacibatmaci DEMember ✭✭✭✭✭

    @Pavlick said:
    NLog works just fine with Android and iOS projects. For UWP you can use MetroLog which is very similar with NLog but on a smaller scale. Use DependencyService in your shared code to get platform dependent implementation.
    Google "LOGGING WITH NLOG IN XAMARIN FORMS" for NLog example and add MetroLog specific classes to your UWP project.
    Both NLog and MetroLog can be installed through NuGet.

    Old post. probably your comment was outdated but i would like to ask MetroLog claims to support xamarin.android and ios. anyone used it? Nlog nuget package looks like too big in size. I dont want to add extra weigh on app size.

Sign In or Register to comment.