Ad

MvvmCross Xamarin Android Linking Issue With SerilogLogProvider

- 1 answer

Running into Linker issue again with MvvmCross in Xamarin Android. Recently upgraded to MvvmCross 6.1.2 and started using Serilog. When compile in release mode with “Sdk and User Assemblies”, I got the following error from base.CreateLogProvider() during Android Setup:

The CreateLogProvider() code:

    public override MvxLogProviderType GetDefaultLogProviderType()
        => MvxLogProviderType.Serilog;

    protected override IMvxLogProvider CreateLogProvider()
    {
        Serilog.Log.Logger = new LoggerConfiguration()
            .MinimumLevel.Error()
            .WriteTo.AndroidLog()
            .CreateLogger();

        return base.CreateLogProvider();
    }

EXCEPTION:

    System.Exception: HandleAndroidException ---> System.ArgumentNullException: Value cannot be null.
    Parameter name: method
      at System.Linq.Expressions.Expression.Call(System.Linq.Expressions.Expression instance, System.Reflection.MethodInfo method, System.Linq.Expressions.Expression arg0, System.Linq.Expressions.Expression arg1, System.Linq.Expressions.Expression arg2)[0x0009d] in <c674d6912966428cb26998a802347469>:0 
      at System.Linq.Expressions.Expression.Call(System.Linq.Expressions.Expression instance, System.Reflection.MethodInfo method, System.Collections.Generic.IEnumerable`1[T] arguments) [0x00074] in <c674d6912966428cb26998a802347469>:0 
      at System.Linq.Expressions.Expression.Call(System.Linq.Expressions.Expression instance, System.Reflection.MethodInfo method, System.Linq.Expressions.Expression[] arguments) [0x00000] in <c674d6912966428cb26998a802347469>:0 
      at MvvmCross.Logging.LogProviders.SerilogLogProvider.GetForContextMethodCall() [0x00086] in <df54a54dac96467098c3a9eece96a79b>:0 
      at MvvmCross.Logging.LogProviders.SerilogLogProvider..ctor() [0x00018] in <df54a54dac96467098c3a9eece96a79b>:0 
      at MvvmCross.Core.MvxSetup.CreateLogProvider() [0x00045] in <df54a54dac96467098c3a9eece96a79b>:0 
      at myRouteTracker.Droid.Setup.CreateLogProvider() [0x0002a] in <bdd41c7f90344b17a5e6bc21c3959feb>:0 
      at MvvmCross.Core.MvxSetup.InitializeLoggingServices() [0x00000] in <df54a54dac96467098c3a9eece96a79b>:0 
      at MvvmCross.Core.MvxSetup.InitializePrimary() [0x00016] in <df54a54dac96467098c3a9eece96a79b>:0 
      at MvvmCross.Core.MvxSetupSingleton.StartSetupInitialization() [0x0000a] in <df54a54dac96467098c3a9eece96a79b>:0 
      at MvvmCross.Core.MvxSetupSingleton.InitializeAndMonitor(MvvmCross.Core.IMvxSetupMonitor setupMonitor) [0x00042] in <df54a54dac96467098c3a9eece96a79b>:0 
      at MvvmCross.Droid.Support.V7.AppCompat.MvxSplashScreenAppCompatActivity.OnCreate(Android.OS.Bundle bundle) [0x00019] in <2d476ccd46884988a021d78ffc7a2843>:0 
      at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_(System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_savedInstanceState) [0x0000f] in <1b4c73c9a2864ea8b5827f31fda08c32>:0 
      at(wrapper dynamic-method) System.Object.e043741f-fba6-4072-a6c2-cfc97949a294(intptr, intptr, intptr)
       --- End of inner exception stack trace ---

With other linking issues, I usually try to access the function being stripped out in LinkerPleaseInclude. i.e. MvvmCross.Logging.LogProviders.SerilogLogProvider.GetForContextMethodCall() in this case. However, SerilogLogProvider is an internal class that I could not access.

The last thing I tried is to add Serilog and MvvmCross.Logging.LogProviders to “Skip linking assemblies”. It does not work neither.

Thank you very much for your help in advance.

Regards,

Nick

Ad

Answer

The issue is that SerilogLogProvider uses reflection against Serilog.dll (See GitHub SerilogLogProvider source). Even if you had access to the SerilogLogProvider class it would not help in preventing the linker from stripping away the needed methods. The reason being is that the linker is actually stripping the methods that you need from the Serilog.dll.

You can add the following include to your LinkerPleaseInclude.cs to prevent the linker from stripping out the methods that SerilogLogProvider makes use of.

public void Include(Serilog.ILogger logger)
{
    Serilog.Events.LogEventLevel logEventLevel = Serilog.Events.LogEventLevel.Debug;

    _ = Serilog.Log.ForContext("", "", false);
    _ = Serilog.Context.LogContext.PushProperty("", "", false);
    _ = !logger.IsEnabled(logEventLevel);
    logger.Write(logEventLevel, "", new object[0]);
    logger.Write(logEventLevel, new Exception(), "", new object[0]);
}
Ad
source: stackoverflow.com
Ad