在xamarin项目中使用Serilog入门

xmd2e60i  于 2022-12-07  发布在  其他
关注(0)|答案(2)|浏览(162)

我正在尝试为xamarin项目设置日志系统,我有以下代码

Log.Logger = new LoggerConfiguration()
               .MinimumLevel.Debug()
               .WriteTo.Console()
               .CreateLogger();

            Log.Information("Hello, world!");

            int a = 10, b = 0;
            try
            {
                Log.Debug("Dividing {A} by {B}", a, b);
                Console.WriteLine(a / b);
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Something went wrong");
            }
            finally
            {
                Log.CloseAndFlush();
            }

我在App构造函数中编写了这个代码,以便首先对其进行测试,但它抛出了一个运行时错误,该错误显示

System.PlatformNotSupportedException:'在此平台上不支持该操作。'

如果我删除了.WriteTo.Console(),它就可以工作了,所以我假设我必须配置一个控制台或类似的东西?

66bbxpm5

66bbxpm51#

您正在使用的Serilog.Sinks.Console接收器在您的平台上不可用。相反,就像Jason在评论中建议的那样,您将需要使用不同的接收器。
根据您实际想要实现的目标,您可能希望陷入

  • 档案
  • 调试输出
  • 设备日志

所有这些场景都有接收器,对于更复杂的场景也有接收器,在这些场景中,您希望将日志流传输到外部服务(如Elastic Search或其他服务)。
但是,并非所有 * 平台都提供Console,您应该选择更合适的接收器。

pbgvytdp

pbgvytdp2#

相关性

1.从NuGet安装Serilog.Sinks.XamarinGitHub
1.从NuGet安装IOFlextils

在本机项目中配置Serilog

Xamarin.IOS中的一个选项

Log.Logger = new LoggerConfiguration()
.WriteTo.NSLog()
.CreateLogger();

Xamarin.安卓系统

Log.Logger = new LoggerConfiguration()
.WriteTo.AndroidLog()
.Enrich.WithProperty(Constants.SourceContextPropertyName, "MyCustomTag") //Sets the Tag field.
.CreateLogger();

大楼

因此,假设您希望实现一些将日志记录到本地日志控制台以及sqlite数据库的功能,您可能希望通过各种后台工作线程远程访问日志。

常量. cs
public static class Constants
{
    private const string LogDatabaseFileName = "logs.db3";

    public const SQLite.SQLiteOpenFlags Flags =
        // open the database in read/write mode
        SQLite.SQLiteOpenFlags.ReadWrite |
        // create the database if it doesn't exist
        SQLite.SQLiteOpenFlags.Create |
        // enable multi-threaded database access
        SQLite.SQLiteOpenFlags.SharedCache;

    public static string LogDatabasePath
    {
        get
        {
            var basePath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
            return Path.Combine(basePath, LogDatabaseFileName);
        }
    }
}

日志. cs

public class Log : BaseSyncEntity<long>
{
    /// <summary>
    /// TODO: Document
    /// </summary>
    public string Message { get; set; }
    
    /// <summary>
    /// TODO: Document
    /// </summary>
    public string MessageTemplate { get; set; }
    
    /// <summary>
    /// TODO: Document
    /// </summary>
    public string Level { get; set; }

    /// <summary>
    /// TODO: Document
    /// </summary>
    public DateTime TimeStamp { get; set; }
    
    /// <summary>
    /// TODO: Document
    /// </summary>
    public string Exception { get; set; }
    
    /// <summary>
    /// TODO: Document
    /// </summary>
    public string Properties { get; set; }

    /// <summary>
    /// TODO: Document
    /// </summary>
    public string RenderedMessage { get; set; }
}

日志数据库. cs

public class LogDatabase
{
    private static readonly Lazy<SQLiteAsyncConnection> LazyInitializer =
        new Lazy<SQLiteAsyncConnection>(() => new SQLiteAsyncConnection(Constants.LogDatabasePath, Constants.Flags));

    private static SQLiteAsyncConnection Database => LazyInitializer.Value;

    private static bool _initialized = false;

    private Type[] _tables =
    {
        typeof(Log),
    };

    public LogDatabase()
    {
        InitializeAsync().SafeFireAndForget(false);
    }

    async Task InitializeAsync()
    {
        if (!_initialized)
            if (!Database.TableMappings.Any(m => this._tables.Any(t => m.MappedType.Name == nameof(t))))
            {
                foreach (var t in this._tables) await Database.CreateTableAsync(t, CreateFlags.None);
                _initialized = true;
            }
    }

    #region Log

    /// <summary>
    /// TODO: Document
    /// </summary>
    /// <param name="state"></param>
    /// <param name="limit"></param>
    /// <returns></returns>
    public async Task<Log[]> GetLogsAsync(EntityState state, int limit = 10)
    {
        return await Database.Table<Log>().Where(x => x.State == state)
            .Take(limit)
            .OrderBy(x => x.Id)
            .ToArrayAsync();
    }

    /// <summary>
    /// TODO: Documentation
    /// </summary>
    /// <param name="log"></param>
    /// <returns></returns>
    public Task<int> SaveAsync(Log log)
    {
        return log.Id <= 0 ? Database.InsertAsync(log) : Database.UpdateAsync(log);
    }

    #endregion
}

Xamarin.安卓主活动. cs

using System;
using Android.App;
using Android.Content.PM;
using Android.Runtime;
using Android.OS;
using Android.Views;
using AndroidX.Work;
using Xamarin.Forms;
using Android.Content;
using Java.Util.Concurrent;
using Serilog;

namespace GenericApp.Droid
{
[Activity(Label = "Generic App", 
          Icon = "@mipmap/icon", 
          Theme = "@style/MainTheme",
          ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize,
          WindowSoftInputMode = SoftInput.StateHidden)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
    private DataWedgeReceiver _dataWedge;
    private App _app;
    /// <summary>
    /// Lifecycle method.
    /// </summary>
    /// <param name="savedInstanceState"></param>
    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);

        Xamarin.Essentials.Platform.Init(this, savedInstanceState);
        global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
        _app = new App();
        LoadApplication(_app);
        DependencyService.Register<IConnection, ConnectionService>();

        #region Periodic Work Requests

        WorkManager.GetInstance(this).CancelAllWork();

        #endregion

        App.IntentScanningAvailable = IsAppInstalled("com.symbol.datawedge");

        if (App.IntentScanningAvailable)
        {
            _dataWedge = new DataWedgeReceiver();
            _dataWedge.ScanReceived += (sender, data) =>
            {
                MessagingCenter.Send(_app, "com.sw.mobile.BARCODE_SCAN", data);
            };
        }
        
        Log.Logger = new LoggerConfiguration()
            .WriteTo.AndroidLog()
            .WriteTo.SQLiteNetPcl(Constants.LogDatabasePath, storeTimestampInUtc: true, batchSize:1)
            .Enrich.WithProperty(App.KeyAppId, App.AppId)
            .Enrich.WithProperty(App.KeyAppVersion, App.AppVersion)
            .CreateLogger();
    }

    bool IsAppInstalled(string packageName)
    {
        try
        {
            PackageManager.GetPackageInfo(packageName, PackageInfoFlags.Activities);
            return true;
        }
        catch (PackageManager.NameNotFoundException ex)
        {
            Log.Error(nameof(MainActivity), ex, ex.StackTrace);
        }
        catch (Exception e)
        {
            Log.Error(nameof(MainActivity), e.Message);
        }

        return false;
    }

    PeriodicWorkRequest GetWorkRequest<T>(string tag, int minutes) where T : Worker
    {
        return PeriodicWorkRequest.Builder.From<T>(TimeSpan.FromMinutes(minutes)).AddTag(tag).Build();
    }

    void RegisterWorkerSubscription<T>(Type type, string message, string tag) 
        where T : BaseWorker
    {
        MessagingCenter.Subscribe<T>(this, message, (page) =>
        {
            var request = new OneTimeWorkRequest.Builder(type)
                .AddTag(tag)
                .SetInputData(new AndroidX.Work.Data.Builder().PutString("arg_msg", message).Build())
                .Build();
            WorkManager.GetInstance(this).BeginUniqueWork(tag, ExistingWorkPolicy.Keep, request).Enqueue();
        });
    }

    void RegisterSubscription<T>(Type type, string message, string tag) 
        where T : BaseViewModel
    {
        MessagingCenter.Subscribe<T>(this, message, (page) =>
        {
            var request = new OneTimeWorkRequest.Builder(type)
                .AddTag(tag)
                .SetInputData(new AndroidX.Work.Data.Builder().PutString("arg_msg", message).Build())
                .Build();
            WorkManager.GetInstance(this).BeginUniqueWork(tag, ExistingWorkPolicy.Keep, request).Enqueue();
        });
    }

    /// <summary>
    /// TODO: Documentation
    /// </summary>
    /// <param name="requestCode"></param>
    /// <param name="permissions"></param>
    /// <param name="grantResults"></param>
    public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
    {
        Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);

        base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    protected override void OnStart()
    {
        base.OnStart();
    }

    protected override void OnResume()
    {
        base.OnResume();
        if (App.IntentScanningAvailable && _dataWedge != null)
        {
            var filter = new IntentFilter(DataWedgeReceiver.IntentAction);
            filter.AddCategory(DataWedgeReceiver.IntentCategory);
            Android.App.Application.Context.RegisterReceiver(_dataWedge, filter);
        }
    }

    protected override void OnPause()
    {
        if(App.IntentScanningAvailable && _dataWedge != null)
            Android.App.Application.Context.UnregisterReceiver(_dataWedge);
        
        base.OnPause();
    }

    protected override void OnStop()
    {
        base.OnStop();
    }

    protected override void OnDestroy()
    {
        base.OnDestroy();
    }
}
}

相关问题