/// <summary> /// Log system information. /// </summary> public void Output() { try { if (!Directory.Exists(reportsPath)) { logger.LogInfo("Creating directory {SystemReportsDirectoryPath}", reportsPath); Directory.CreateDirectory(reportsPath); } } catch (Exception ex) { logger.LogError(ex, "Failed to create system reports path."); } if (Application.platform == RuntimePlatform.WindowsPlayer) { var outputPath = Path.Combine(reportsPath, "dxdiag.txt"); logger.LogInfo("Saving dxdiag output to " + outputPath); try { System.Diagnostics.Process.Start("dxdiag", "/t " + outputPath); } catch (Exception ex) { logger.LogError(ex, "Failed to run dxdiag"); } } try { var msg = msgTemplate + Screen.resolutions .Select((resolution, i) => "[{ResolutionIndex}] {resolutionWidth} x {resolutionHeight} ({resolutionRefreshRate} hz)") .Join("\r\n"); object[] msgParams = LinqExts.FromItems <object>( Application.dataPath, Application.internetReachability, Application.loadedLevelName, Application.persistentDataPath, Application.platform, Application.unityVersion, SystemInfo.deviceModel, SystemInfo.deviceName, SystemInfo.deviceType, SystemInfo.deviceUniqueIdentifier, SystemInfo.graphicsDeviceID, SystemInfo.graphicsDeviceName, SystemInfo.graphicsDeviceVendor, SystemInfo.graphicsDeviceVendorID, SystemInfo.graphicsDeviceVersion, SystemInfo.graphicsMemorySize, SystemInfo.graphicsPixelFillrate, SystemInfo.graphicsShaderLevel, SystemInfo.npotSupport, SystemInfo.operatingSystem, SystemInfo.processorCount, SystemInfo.processorType, SystemInfo.supportedRenderTargetCount, SystemInfo.supports3DTextures, SystemInfo.supportsAccelerometer, SystemInfo.supportsComputeShaders, SystemInfo.supportsGyroscope, SystemInfo.supportsImageEffects, SystemInfo.supportsInstancing, SystemInfo.supportsLocationService, SystemInfo.supportsRenderTextures, SystemInfo.supportsRenderToCubemap, SystemInfo.supportsShadows, SystemInfo.supportsStencil, SystemInfo.supportsVibration, SystemInfo.systemMemorySize, QualitySettings.names[QualitySettings.GetQualityLevel()] + " (" + QualitySettings.GetQualityLevel() + ")", QualitySettings.names, QualitySettings.activeColorSpace, QualitySettings.anisotropicFiltering, QualitySettings.antiAliasing, QualitySettings.blendWeights, QualitySettings.desiredColorSpace, QualitySettings.lodBias, QualitySettings.masterTextureLimit, QualitySettings.maximumLODLevel, QualitySettings.maxQueuedFrames, QualitySettings.particleRaycastBudget, QualitySettings.pixelLightCount, QualitySettings.shadowCascades, QualitySettings.shadowDistance, QualitySettings.shadowProjection, QualitySettings.softVegetation, QualitySettings.vSyncCount, Screen.currentResolution.width, Screen.currentResolution.height, Screen.currentResolution.refreshRate, Screen.fullScreen ). Concat( Screen.resolutions .SelectMany(resolution => LinqExts.FromItems <object>(resolution.width, resolution.height, resolution.refreshRate) ) ) .ToArray(); logger.LogInfo(msg, msgParams); } catch (Exception ex) { logger.LogError(ex, "Failed to get Unity system info"); } }
public SerilogLogger(LogConfig logConfig, IReflection reflection) { Argument.NotNull(() => logConfig); Argument.NotNull(() => reflection); this.EnableVerbose = logConfig.Verbose; CreateLogsDirectory(); var loggerConfig = new Serilog.LoggerConfiguration(); if (this.EnableVerbose) { loggerConfig = loggerConfig.MinimumLevel.Verbose(); } loggerConfig = loggerConfig.WriteTo.Trace(); var emptyTypeArray = new Type[0]; var emptyObjectArray = new object[0]; var logEnrichers = reflection.FindTypesMarkedByAttributes(LinqExts.FromItems(typeof(LogEnricherAttribute))); loggerConfig = logEnrichers .Select(logEnricherType => logEnricherType.GetConstructor(emptyTypeArray).Invoke(emptyObjectArray)) .Cast <Serilog.Core.ILogEventEnricher>() .Aggregate(loggerConfig, (prevLoggerConfig, logEnricher) => prevLoggerConfig.Enrich.With(logEnricher)); if (logsDirectoryStatus == LogsDirectoryStatus.Created) { loggerConfig.WriteTo.File(Path.Combine(LogsDirectoryPath, "Errors.log"), LogEventLevel.Error); loggerConfig.WriteTo.File(Path.Combine(LogsDirectoryPath, "Info.log"), LogEventLevel.Information); loggerConfig.WriteTo.File(Path.Combine(LogsDirectoryPath, "Verbose.log"), LogEventLevel.Verbose); } if (!string.IsNullOrEmpty(logConfig.LogPostUrl)) { Debug.Log("Sending log messages via HTTP to " + logConfig.LogPostUrl); loggerConfig.WriteTo.Sink(new SerilogHttpSink(logConfig.LogPostUrl)); } else { Debug.Log("Not sending log messages via HTTP"); } foreach (var sinkType in reflection.FindTypesMarkedByAttributes(LinqExts.FromItems(typeof(SerilogSinkAttribute)))) { loggerConfig.WriteTo.Sink((Serilog.Core.ILogEventSink)sinkType.GetConstructor(emptyTypeArray).Invoke(emptyObjectArray)); } this.serilog = loggerConfig.CreateLogger(); LogInfo("Application started at {TimeNow}", DateTime.Now); LogInfo("Logs directory status: {LogsDirectoryStatus}", logsDirectoryStatus); if (logsDirectoryStatus == LogsDirectoryStatus.Failed) { LogError(logsDirectoryCreateException, "Failed to create logs directory {LogsDirectoryPath}", LogsDirectoryPath); } else { LogInfo("Writing logs and reports to {LogsDirectoryPath}", LogsDirectoryPath); } if (this.EnableVerbose) { LogInfo("Verbose logging is enabled."); } else { LogInfo("Verbose logging is not enabled."); } LogSystemInfo(); DeleteOldLogFiles(); // Initialize errors for unhandled promises. Promise.UnhandledException += (s, e) => LogError(e.Exception, "Unhandled error from promise."); Application.RegisterLogCallbackThreaded((msg, stackTrace, type) => { if (!msg.StartsWith(SerilogUnitySink.RSGLogTag)) { switch (type) { case LogType.Assert: case LogType.Error: case LogType.Exception: LogError(msg + "\r\nStack:\r\n{StackTrace}", stackTrace); break; case LogType.Warning: LogWarning(msg + "\r\nStack:\r\n{StackTrace}", stackTrace); break; default: LogInfo(msg + "\r\nStack:\r\n{StackTrace}", stackTrace); break; } } }); }