我正在使用MvvmCross并使用一些方法在我的报告工具中获得MvxTrace。这次我用的是雷射枪。Raygun让我可以选择在错误信息中添加我想要抛出的额外信息,这就是我认为我必须使用的方法来实现这一点。基本上我想在代码中做这样的事情:
var client = new RaygunClient();
var tags = new List<string> { "myTag" };
var customData = new Dictionary<int, string>() { {1, "**MVXTrace stuff here**"} };
client.Send(exception, tags, customData);
我怎么把这个连接起来?当我看到Trace设置时,我感到困惑。我假设我需要用我用来注入的DebugTrace文件做一些事情。现在它看起来像这样:
public class DebugTrace : IMvxTrace
{
public void Trace(MvxTraceLevel level, string tag, Func<string> message)
{
Debug.WriteLine(tag + ":" + level + ":" + message());
}
public void Trace(MvxTraceLevel level, string tag, string message)
{
Debug.WriteLine(tag + ":" + level + ":" + message);
}
public void Trace(MvxTraceLevel level, string tag, string message, params object[] args)
{
try
{
Debug.WriteLine(string.Format(tag + ":" + level + ":" + message, args));
}
catch (FormatException)
{
Trace(MvxTraceLevel.Error, tag, "Exception during trace of {0} {1} {2}", level, message);
}
}
}
我可以做一些挂钩到IMvxTrace逻辑附加内部异常等到我的RaygunClient?我很难看出是什么导致了特定的错误因为如果我保持原样,我就会得到这样的错误:
[MvxException: Failed to construct and initialize ViewModel for type MyProject.Core.ViewModels.SignatureViewModel from locator MvxDefaultViewModelLocator - check MvxTrace for more information]
Cirrious.MvvmCross.ViewModels.MvxViewModelLoader.LoadViewModel(Cirrious.MvvmCross.ViewModels.MvxViewModelRequest request, IMvxBundle savedState, IMvxViewModelLocator viewModelLocator):0
Cirrious.MvvmCross.ViewModels.MvxViewModelLoader.LoadViewModel(Cirrious.MvvmCross.ViewModels.MvxViewModelRequest request, IMvxBundle savedState):0
Cirrious.MvvmCross.Droid.Views.MvxAndroidViewsContainer.ViewModelFromRequest(Cirrious.MvvmCross.ViewModels.MvxViewModelRequest viewModelRequest, IMvxBundle savedState):0
Cirrious.MvvmCross.Droid.Views.MvxAndroidViewsContainer.CreateViewModelFromIntent(Android.Content.Intent intent, IMvxBundle savedState):0
Cirrious.MvvmCross.Droid.Views.MvxAndroidViewsContainer.Load(Android.Content.Intent intent, IMvxBundle savedState, System.Type viewModelTypeHint):0
Cirrious.MvvmCross.Droid.Views.MvxActivityViewExtensions.LoadViewModel(IMvxAndroidView androidView, IMvxBundle savedState):0
Cirrious.MvvmCross.Droid.Views.MvxActivityViewExtensions+<>c__DisplayClass3.<OnViewCreate>b__1():0
Cirrious.MvvmCross.Views.MvxViewExtensionMethods.OnViewCreate(IMvxView view, System.Func`1 viewModelLoader):0
Cirrious.MvvmCross.Droid.Views.MvxActivityViewExtensions.OnViewCreate(IMvxAndroidView androidView, Android.OS.Bundle bundle):0
Cirrious.MvvmCross.Droid.Views.MvxActivityAdapter.EventSourceOnCreateCalled(System.Object sender, Cirrious.CrossCore.Core.MvxValueEventArgs`1 eventArgs):0
(wrapper delegate-invoke) System.EventHandler`1<Cirrious.CrossCore.Core.MvxValueEventArgs`1<Android.OS.Bundle>>:invoke_void__this___object_TEventArgs (object,Cirrious.CrossCore.Core.MvxValueEventArgs`1<Android.OS.Bundle>)
Cirrious.CrossCore.Core.MvxDelegateExtensionMethods.Raise[Bundle](System.EventHandler`1 eventHandler, System.Object sender, Android.OS.Bundle value):0
Cirrious.CrossCore.Droid.Views.MvxEventSourceActivity.OnCreate(Android.OS.Bundle bundle):0
MyProject.Droid.Views.SignatureView.OnCreate(Android.OS.Bundle bundle):0
Android.App.Activity.n_OnCreate_Landroid_os_Bundle_(IntPtr jnienv, IntPtr native__this, IntPtr native_savedInstanceState):0
(wrapper dynamic-method) object:3af7783d-a44d-471c-84a6-662ebfaea4ae (intptr,intptr,intptr)
这将是非常有帮助的,正如该消息所暗示的,如果我能得到MvxTrace与它跟踪到底为什么初始化这个ViewModel失败。有什么建议吗?
这就是我在Android上的做法。我使用Android.Util.Log
类。这将记录消息到Android设备日志。
public class DebugTrace : IMvxTrace
{
public void Trace(MvxTraceLevel level, string tag, Func<string> message)
{
Trace(level, tag, message());
}
public void Trace(MvxTraceLevel level, string tag, string message)
{
switch (level)
{
case MvxTraceLevel.Diagnostic:
Log.Debug(tag, message);
break;
case MvxTraceLevel.Warning:
Log.Warn(tag, message);
break;
case MvxTraceLevel.Error:
Log.Error(tag, message);
break;
default:
Log.Info(tag, message);
break;
}
}
public void Trace(MvxTraceLevel level, string tag, string message, params object[] args)
{
try
{
Trace(level, tag, string.Format(message, args));
}
catch (FormatException)
{
Trace(MvxTraceLevel.Error, tag, "Exception during trace of {0} {1}", level, message);
}
}
}
您可以使用以下命令获取日志:
public class AndroidLogReader
{
public string ReadLog(string tag)
{
var cmd = "logcat -d";
if (!string.IsNullOrEmpty(tag)) cmd += " -s " + tag;
var process = Java.Lang.Runtime.GetRuntime().Exec(cmd);
using (var sr = new StreamReader(process.InputStream))
{
return sr.ReadToEnd();
}
}
}
我是这样做的:
我有一个BaseView,我正在使用我所有的Android活动。我使用这个BaseView来连接和记录未处理的异常,如下所示:
public abstract class BaseView : MvxActivity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
AppDomain.CurrentDomain.UnhandledException += HandleUnhandledException;
AndroidEnvironment.UnhandledExceptionRaiser += HandleAndroidException;
}
protected void HandleUnhandledException(object sender, UnhandledExceptionEventArgs args)
{
var e = (Exception)args.ExceptionObject;
Mvx.Trace(MvxTraceLevel.Error, "Exception: {0}", e.ToLongString());
var logReader = new AndroidLogReader();
var logMessages = logReader.ReadLog("mvx:E");
var customData = new Dictionary<string, string> { { "logMessage", logMessages } };
var session = SessionController.Instance;
var user = new RaygunIdentifierMessage(session.UserName + " " + session.Company);
var rayMessage = RaygunMessageBuilder.New
.SetEnvironmentDetails()
.SetMachineName(Environment.MachineName)
.SetClientDetails()
.SetExceptionDetails(e)
.SetUser(user)
.SetUserCustomData(customData)
.Build();
RaygunClient.Current.Send(rayMessage);
}
protected void HandleAndroidException(object sender, RaiseThrowableEventArgs e)
{
var exception = e.Exception;
Mvx.Trace(MvxTraceLevel.Error, "Exception: {0}", e.Exception.ToLongString());
var logReader = new AndroidLogReader();
var logMessages = logReader.ReadLog("mvx:E");
var customData = new Dictionary<string, string> { { "logMessage", logMessages } };
var session = SessionController.Instance;
var user = new RaygunIdentifierMessage(session.UserName + " " + session.Company);
var rayMessage = RaygunMessageBuilder.New
.SetEnvironmentDetails()
.SetMachineName(Environment.MachineName)
.SetClientDetails()
.SetExceptionDetails(exception)
.SetUser(user)
.SetUserCustomData(customData)
.Build();
RaygunClient.Current.Send(rayMessage);
}
}
我的DebugTrace.cs看起来像这样:
public class DebugTrace : IMvxTrace
{
public void Trace(MvxTraceLevel level, string tag, Func<string> message)
{
Trace(level, tag, message());
}
public void Trace(MvxTraceLevel level, string tag, string message)
{
switch (level)
{
case MvxTraceLevel.Diagnostic:
Log.Debug(tag, message);
break;
case MvxTraceLevel.Warning:
Log.Warn(tag, message);
break;
case MvxTraceLevel.Error:
Log.Error(tag, message);
break;
default:
Log.Info(tag, message);
break;
}
}
public void Trace(MvxTraceLevel level, string tag, string message, params object[] args)
{
try
{
Trace(level, tag, string.Format(message, args));
}
catch (FormatException)
{
Trace(MvxTraceLevel.Error, tag, "Exception during trace of {0} {1} {2}", level, message);
}
}
}
我的AndroidLogReader看起来是这样的:
public class AndroidLogReader
{
public string ReadLog(string tag)
{
var cmd = "logcat -d";
if (!string.IsNullOrEmpty(tag))
{
cmd += " -s " + tag;
}
var process = Java.Lang.Runtime.GetRuntime().Exec(cmd);
using (var sr = new StreamReader(process.InputStream))
{
return sr.ReadToEnd();
}
}
}
有了这些东西,我现在得到自定义数据附加到我所有的Raygun错误,包括堆栈跟踪从Mvx的所有错误。非常感谢@Kiliman为我指出了实现这一目标的基本要素!