private void GenerateLogMessageForFile(FileInfo fileInfo)
        {
            if (fileInfo.Name.StartsWith("irc.rizon.net"))
            {
                logger.Log(
                    LogLevel.Info,
                    "Skipping log file, that appears to be log from IRC (unsupported), file name: " + fileInfo.FullName,
                    this,
                    null);
            }

            else if (fileInfo.Name.StartsWith("test."))
            {
                logger.Log(
                    LogLevel.Info,
                    "Skipping log file, that appears to be from test server (unsupported), file name: "
                    + fileInfo.FullName,
                    this,
                    null);
            }
            else
            {
                logger.Log(
                    LogLevel.Warn,
                    "Skipping file that had parsing errors, file name: " + fileInfo.FullName,
                    this,
                    null);
            }
        }
예제 #2
0
        public void Unsubscribe(string characterName, EventHandler <LogsMonitorEventArgs> eventHandler)
        {
            if (characterName == null)
            {
                logger.Log(LogLevel.Error,
                           string.Format("Unsubscribe attempted with null characterName, handler details: {0} ",
                                         eventHandler.MethodInformationToString()),
                           this,
                           null);
                return;
            }

            try
            {
                var manager = GetManager(new CharacterName(characterName));
                manager.RemoveSubscription(eventHandler);
            }
            catch (DataNotFoundException exception)
            {
                logger.Log(LogLevel.Info,
                           string.Format(
                               "Could not unsubscribe an event handler from logs monitor for character {0}. No manager found for this character. , handler details: {1}",
                               characterName,
                               eventHandler.MethodInformationToString()),
                           this,
                           exception);
            }
        }
예제 #3
0
        public override ScanResult Execute(LogSearchParameters logSearchParameters, JobCancellationManager jobCancellationManager)
        {
            try
            {
                var scanner = logsScannerFactory.Create(logSearchParameters, jobCancellationManager);
                var results = scanner.Scan();

                try
                {
                    persistentLibrary.SaveChanged();
                }
                catch (Exception exception)
                {
                    logger.Log(LogLevel.Error, "Error at saving persistent data for WurmLogsHistory", this, exception);
                }

                return(results);
            }
            catch (Exception exception)
            {
                var canceledException = exception as OperationCanceledException;
                if (canceledException == null)
                {
                    logger.Log(LogLevel.Error,
                               string.Format("Error during scan job execution, search params: {0}", logSearchParameters),
                               this,
                               exception);
                }
                throw;
            }
        }
예제 #4
0
        public IList <LogEntry> ParseLinesFromLogsScan(IReadOnlyList <string> lines, DateTime dayStamp)
        {
            List <LogEntry> result        = new List <LogEntry>(lines.Count);
            DateTime?       previousStamp = null;

            foreach (var line in lines)
            {
                if (IsLoggingStartedLine(line))
                {
                    continue;
                }
                // maybe just empty line (eg. happens on examining signs)
                if (string.IsNullOrWhiteSpace(line))
                {
                    continue;
                }
                TimeSpan?parsedTime   = null;
                DateTime?currentStamp = null;
                try
                {
                    parsedTime = ParsingHelper.GetTimestampFromLogLine(line);
                }
                catch (Exception exception)
                {
                    logger.Log(LogLevel.Warn, "Found log line with unparseable timestamp, line may be ignored.", this, exception);
                }

                string source  = ParsingHelper.TryParseSourceFromLogLine(line);
                string content = ParsingHelper.TryParseContentFromLogLine(line);
                if (parsedTime.HasValue)
                {
                    currentStamp = new DateTime(dayStamp.Year,
                                                dayStamp.Month,
                                                dayStamp.Day,
                                                parsedTime.Value.Hours,
                                                parsedTime.Value.Minutes,
                                                parsedTime.Value.Seconds);
                }
                else if (previousStamp.HasValue)
                {
                    currentStamp = previousStamp.Value;
                }

                if (currentStamp.HasValue)
                {
                    previousStamp = currentStamp;

                    LogEntry entry = new LogEntry(currentStamp.Value, source, content);
                    result.Add(entry);
                }
            }
            return(result);
        }
예제 #5
0
        async Task FindLatestDumpForServerGroup(ServerGroup serverGroup)
        {
            var beginDate = Time.Get.LocalNowOffset;

            var maxBackDate = Time.Get.LocalNow - MaxDaysBack;

            SkillDumpInfo[] dumps = new SkillDumpInfo[0];
            if (skillDumpsDirectory.Exists)
            {
                dumps = skillDumpsDirectory.GetFiles().Select(ConvertFileInfoToSkillDumpInfo)
                        .Where(info => info != null && info.Stamp > maxBackDate)
                        .OrderByDescending(info => info.Stamp)
                        .ToArray();
            }

            SkillDump foundDump = null;

            foreach (var dumpInfo in dumps)
            {
                var server = await character.TryGetHistoricServerAtLogStampAsync(dumpInfo.Stamp).ConfigureAwait(false);

                if (server != null)
                {
                    if (server.ServerGroup == serverGroup)
                    {
                        foundDump = new RealSkillDump(serverGroup, dumpInfo, logger);
                        break;
                    }
                }
                else
                {
                    logger.Log(LogLevel.Info,
                               "Could not identify server for skill dump: " + dumpInfo.FileInfo.FullName,
                               this,
                               null);
                }
            }

            if (foundDump != null)
            {
                latestSkillDumps[serverGroup] = foundDump;
            }
            else
            {
                // if nothing found, place a stub to prevent another file search
                latestSkillDumps[serverGroup] = new StubSkillDump(serverGroup);
            }

            lastRebuild = beginDate;
        }
예제 #6
0
        /// <summary>
        /// Attempts to parse server name from a log entry.
        /// Null if parsing failed.
        /// </summary>
        /// <param name="logEntry"></param>
        /// <param name="logger">Optional, will log parsing errors.</param>
        /// <param name="sourceCharacterName">Optional, will be appended to log message.</param>
        /// <returns></returns>
        public static ServerStamp TryGetServerFromLogEntry(this LogEntry logEntry, IWurmApiLogger logger = null, CharacterName sourceCharacterName = null)
        {
            ServerStamp result = null;

            // attempt some faster matchers first, before trying actual parse
            if (Regex.IsMatch(logEntry.Content, @"other players are online", RegexOptions.Compiled))
            {
                result = TryGetMatchResult(TryMatch1(logEntry), logEntry);
                if (result == null)
                {
                    result = TryGetMatchResult(TryMatch2(logEntry), logEntry);
                }
                if (result == null)
                {
                    logger?.Log(
                        LogLevel.Warn,
                        string.Format(
                            "ServerHistoryProvider found 'other players are online' log line, but could not parse it. Character: {0} Entry: {1}",
                            sourceCharacterName,
                            logEntry),
                        "ServerParsingHelper",
                        null);
                }
            }
            return(result);
        }
예제 #7
0
        void JobRunner()
        {
            while (true)
            {
                Thread.Sleep(CycleDelayMillis);
                if (stop)
                {
                    return;
                }
                TaskHandle[] allTasks;

                lock (locker)
                {
                    allTasks = tasks.ToArray();
                }

                foreach (var taskHandle in allTasks)
                {
                    try
                    {
                        taskHandle.TryExecute();
                    }
                    catch (Exception exception)
                    {
                        logger.Log(LogLevel.Error, "Error during task execution: " + taskHandle.Description, this, exception);
                    }
                }
            }
        }
        public QueuedJobsSyncRunner([NotNull] JobExecutor <TJobContext, TResult> jobExecutor, IWurmApiLogger logger)
        {
            if (jobExecutor == null)
            {
                throw new ArgumentNullException(nameof(jobExecutor));
            }
            this.jobExecutor = jobExecutor;

            searchJobTask = new Task((token) =>
            {
                var internalCancellationToken = cancellationTokenSource.Token;
                while (true)
                {
                    var signalled = jobSignaller.WaitOne(jobExecutor.IdleJobTreshhold);
                    if (internalCancellationToken.IsCancellationRequested)
                    {
                        CancelAllRemainingJobs();
                        return;
                    }
                    if (!signalled)
                    {
                        try
                        {
                            jobExecutor.IdleJob(internalCancellationToken);
                        }
                        catch (Exception exception)
                        {
                            logger.Log(LogLevel.Error, "Regular job has thrown unhandled exception.", this,
                                       exception);
                        }
                    }
                    ScanJob job;
                    while (jobQueue.TryDequeue(out job))
                    {
                        if (internalCancellationToken.IsCancellationRequested)
                        {
                            CancelAllRemainingJobs();
                            return;
                        }
                        try
                        {
                            var cancellationManager = new JobCancellationManager(internalCancellationToken,
                                                                                 job.ExternalCancellationToken);
                            var result = this.jobExecutor.Execute(job.JobContext, cancellationManager);
                            job.SetResult(result);
                        }
                        catch (Exception exception)
                        {
                            job.SetException(exception);
                        }
                    }
                    if (internalCancellationToken.IsCancellationRequested)
                    {
                        CancelAllRemainingJobs();
                        return;
                    }
                }
            }, TaskCreationOptions.LongRunning);
            searchJobTask.Start();
        }
예제 #9
0
 public void TriggerInstantly <TEventArgs>(EventHandler <TEventArgs> handler, object source, TEventArgs args) where TEventArgs : EventArgs
 {
     eventMarshaller.Marshal(() =>
     {
         try
         {
             handler?.Invoke(source, args);
         }
         catch (Exception exception)
         {
             logger.Log(LogLevel.Error,
                        "EventMarshaller has thrown an unhandled exception on instant handler invocation", this,
                        exception);
         }
     });
 }
예제 #10
0
        private List <LogEntry> GetEntries(
            IEnumerable <LogFileInfo> logFileInfos,
            CharacterMonthlyLogHeuristics heuristicsFileMap)
        {
            var parsingHelper = logFileParserFactory.Create();

            List <LogEntry> result = new List <LogEntry>();

            foreach (LogFileInfo logFileInfo in logFileInfos)
            {
                if (logFileInfo.LogFileDate.LogSavingType == LogSavingType.Monthly)
                {
                    ParseMonthlyFile(heuristicsFileMap, logFileInfo, result, parsingHelper);
                }
                else if (logFileInfo.LogFileDate.LogSavingType == LogSavingType.Daily)
                {
                    ParseDailyFile(logFileInfo, result, parsingHelper);
                }
                else
                {
                    logger.Log(
                        LogLevel.Warn,
                        string.Format(
                            "LogsScanner encountered and skipped file with unsupported saving type, type: {0}, file: {1}",
                            logFileInfo.LogFileDate.LogSavingType,
                            logFileInfo.FullPath),
                        this,
                        null);
                }

                cancellationManager.ThrowIfCancelled();
            }
            return(result);
        }
 public void Handle(ErrorContext errorContext)
 {
     logger.Log(LogLevel.Error,
                "Persistent object deserialization error, will ignore and use defaults, error details: "
                + errorContext.GetErrorDetailsAsString(), "WurmApi", null);
     errorContext.Decision = Decision.IgnoreErrorsAndReturnDefaultsForMissingData;
 }
예제 #12
0
 public void Marshal(Action action)
 {
     Task.Factory.StartNew(action)
     .ContinueWith(
         task =>
         logger.Log(LogLevel.Error, "Event handler has caused an unhandled exception", "WurmApi",
                    task.Exception), TaskContinuationOptions.OnlyOnFaulted);
 }
예제 #13
0
        internal WurmLogFiles(IWurmCharacterDirectories wurmCharacterDirectories, IWurmApiLogger logger, IWurmLogDefinitions wurmLogDefinitions,
                              [NotNull] IInternalEventAggregator eventAggregator, [NotNull] IInternalEventInvoker internalEventInvoker,
                              [NotNull] TaskManager taskManager, [NotNull] IWurmPaths wurmPaths)
        {
            if (wurmCharacterDirectories == null)
            {
                throw new ArgumentNullException(nameof(wurmCharacterDirectories));
            }
            if (logger == null)
            {
                throw new ArgumentNullException(nameof(logger));
            }
            if (wurmLogDefinitions == null)
            {
                throw new ArgumentNullException(nameof(wurmLogDefinitions));
            }
            if (eventAggregator == null)
            {
                throw new ArgumentNullException(nameof(eventAggregator));
            }
            if (internalEventInvoker == null)
            {
                throw new ArgumentNullException(nameof(internalEventInvoker));
            }
            if (taskManager == null)
            {
                throw new ArgumentNullException(nameof(taskManager));
            }
            if (wurmPaths == null)
            {
                throw new ArgumentNullException(nameof(wurmPaths));
            }
            this.wurmCharacterDirectories = wurmCharacterDirectories;
            this.logger               = logger;
            this.wurmLogDefinitions   = wurmLogDefinitions;
            this.eventAggregator      = eventAggregator;
            this.internalEventInvoker = internalEventInvoker;
            this.taskManager          = taskManager;
            this.wurmPaths            = wurmPaths;

            try
            {
                Refresh();
            }
            catch (Exception exception)
            {
                logger.Log(LogLevel.Error, "Error at initial WurmLogFiles refresh", this, exception);
            }

            eventAggregator.Subscribe(this);

            taskHandle = new TaskHandle(Refresh, "WurmLogFiles refresh");
            taskManager.Add(taskHandle);

            taskHandle.Trigger();
        }
예제 #14
0
        void ClearDir(string directoryPath, IWurmApiLogger logger)
        {
            var di = new DirectoryInfo(directoryPath);

            if (di.Exists)
            {
                di.Delete(recursive: true);
                logger.Log(LogLevel.Info, "Clearing cache completed for dir " + directoryPath, this, null);
            }
        }
예제 #15
0
        Dictionary <string, float> ParseDump()
        {
            var fileLines = File.ReadAllLines(dumpInfo.FileInfo.FullName);
            Dictionary <string, float> skills = new Dictionary <string, float>();
            var parser = new SkillEntryParser(logger);

            foreach (var line in fileLines)
            {
                if (line.StartsWith("Skills") ||
                    line.StartsWith("Characteristics") ||
                    line.StartsWith("Religion") ||
                    line.StartsWith("-----"))
                {
                    continue;
                }
                var match     = Regex.Match(line, @"(.+): (.+) .+ .+", RegexOptions.Compiled | RegexOptions.CultureInvariant);
                var skillName = match.Groups[1].Value.Trim();
                if (string.IsNullOrEmpty(skillName))
                {
                    logger.Log(LogLevel.Error,
                               string.Format("Unparseable skill name in dump file {0}, raw line: {1}",
                                             dumpInfo.FileInfo.FullName,
                                             line),
                               this,
                               null);
                    continue;
                }
                var level = parser.TryParseFloatInvariant(match.Groups[2].Value);
                if (level == null)
                {
                    logger.Log(LogLevel.Error,
                               string.Format("Unparseable skill value in dump file {0}, raw line: {1}",
                                             dumpInfo.FileInfo.FullName,
                                             line),
                               this,
                               null);
                    continue;
                }
                skills[WurmSkills.NormalizeSkillName(skillName)] = level.Value;
            }
            return(skills);
        }
예제 #16
0
        internal WurmConfigs(
            [NotNull] IWurmConfigDirectories wurmConfigDirectories,
            [NotNull] IWurmApiLogger logger, [NotNull] IPublicEventInvoker publicEventInvoker,
            [NotNull] IInternalEventAggregator eventAggregator, [NotNull] TaskManager taskManager)
        {
            if (wurmConfigDirectories == null)
            {
                throw new ArgumentNullException(nameof(wurmConfigDirectories));
            }
            if (logger == null)
            {
                throw new ArgumentNullException(nameof(logger));
            }
            if (publicEventInvoker == null)
            {
                throw new ArgumentNullException(nameof(publicEventInvoker));
            }
            if (eventAggregator == null)
            {
                throw new ArgumentNullException(nameof(eventAggregator));
            }
            if (taskManager == null)
            {
                throw new ArgumentNullException(nameof(taskManager));
            }
            this.wurmConfigDirectories = wurmConfigDirectories;
            this.logger             = logger;
            this.publicEventInvoker = publicEventInvoker;
            this.eventAggregator    = eventAggregator;
            this.taskManager        = taskManager;

            onAvailableConfigsChanged = publicEventInvoker.Create(
                () => AvailableConfigsChanged.SafeInvoke(this, EventArgs.Empty),
                WurmApiTuningParams.PublicEventMarshallerDelay);
            onAnyConfigChanged = publicEventInvoker.Create(
                () => AnyConfigChanged.SafeInvoke(this, EventArgs.Empty),
                WurmApiTuningParams.PublicEventMarshallerDelay);

            try
            {
                Refresh();
            }
            catch (Exception exception)
            {
                logger.Log(LogLevel.Error, "Error at initial configs update", this, exception);
            }

            taskHandle = new TaskHandle(Refresh, "WurmConfigs update");
            taskManager.Add(taskHandle);

            eventAggregator.Subscribe(this);

            taskHandle.Trigger();
        }
예제 #17
0
        public void ProcessLine(string line, long lastReadLineStartPosition)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(line))
                {
                    var currentDay = records.Any() ? records.Last().Day : 0;
                    records.Add(new Record(currentDay, lastReadLineStartPosition));
                }
                else if (line.StartsWith("Logging started", StringComparison.Ordinal))
                {
                    var lastDay  = records.Any() ? records.Last().Day : 0;
                    var dayStamp = ParsingHelper.GetDateFromLogFileLoggingStarted(line);

                    ReadjustPreviousRecords(lastDay, dayStamp);

                    records.Add(new Record(dayStamp.Day, lastReadLineStartPosition));
                    LastLogLineStamp = TimeSpan.Zero;
                }
                else
                {
                    var currentDay = records.Any() ? records.Last().Day : 0;
                    var lineStamp  = ParsingHelper.GetTimestampFromLogLine(line);

                    if (OverflowsToNextDay(lineStamp))
                    {
                        LastLogLineStamp = TimeSpan.Zero;
                        if (!(OverflowsBeyondToday(currentDay + 1) || OverflowsBeyondMaxMonth(currentDay + 1)))
                        {
                            currentDay++;
                        }
                    }
                    else
                    {
                        LastLogLineStamp = lineStamp;
                    }

                    records.Add(new Record(currentDay, lastReadLineStartPosition));
                }
            }
            catch (WurmApiException exception)
            {
                // this line must be added to records, because lastReadLineStartPosition
                var currentDay = records.Any() ? records.Last().Day : 0;
                records.Add(new Record(currentDay, lastReadLineStartPosition));
                // ignore this line
                logger.Log(
                    LogLevel.Warn,
                    string.Format("Unexpected exception while parsing line: {0}", line),
                    this,
                    exception);
            }
        }
예제 #18
0
        async void UpdateCurrentServer()
        {
            try
            {
                var server = await character.TryGetCurrentServerAsync().ConfigureAwait(false);

                if (server != null)
                {
                    currentServer = server;
                }
                else
                {
                    logger.Log(LogLevel.Warn, "Current server unknown for: " + character.Name.Capitalized, this, null);
                }
            }
            catch (Exception exception)
            {
                logger.Log(LogLevel.Error, "error on updating current server", this, exception);
            }
            await Task.Run(() => currentServerLookupFinished.TrySetResult(Time.Get.LocalNow));
        }
예제 #19
0
        internal WurmConfig(string gameSettingsFullPath, [NotNull] IPublicEventInvoker publicEventMarshaller,
                            [NotNull] TaskManager taskManager, IWurmApiLogger logger)
        {
            if (gameSettingsFullPath == null)
            {
                throw new ArgumentNullException(nameof(gameSettingsFullPath));
            }
            if (taskManager == null)
            {
                throw new ArgumentNullException(nameof(taskManager));
            }
            gameSettingsFileInfo = new FileInfo(gameSettingsFullPath);
            if (gameSettingsFileInfo.Directory == null)
            {
                throw new WurmApiException("gameSettingsFileInfo.Directory is null, provided file raw path: "
                                           + gameSettingsFullPath);
            }
            Name = gameSettingsFileInfo.Directory.Name;

            this.taskManager = taskManager;

            onConfigChanged = publicEventMarshaller.Create(() => ConfigChanged.SafeInvoke(this, EventArgs.Empty),
                                                           WurmApiTuningParams.PublicEventMarshallerDelay);

            configReader = new ConfigReader(this);

            try
            {
                Refresh();
            }
            catch (Exception exception)
            {
                logger.Log(LogLevel.Error, "Error at initial config update: " + Name, this, exception);
            }

            configFileWatcher = new FileSystemWatcher(gameSettingsFileInfo.Directory.FullName)
            {
                Filter       = gameSettingsFileInfo.Name,
                NotifyFilter = NotifyFilters.Size | NotifyFilters.LastWrite
            };
            configFileWatcher.Changed            += ConfigFileWatcherOnChanged;
            configFileWatcher.Created            += ConfigFileWatcherOnChanged;
            configFileWatcher.Deleted            += ConfigFileWatcherOnChanged;
            configFileWatcher.Renamed            += ConfigFileWatcherOnChanged;
            configFileWatcher.EnableRaisingEvents = true;

            taskHandle = new TaskHandle(Refresh, "WurmConfig update: " + Name);
            taskManager.Add(taskHandle);

            taskHandle.Trigger();
        }
 private bool ShouldFileBeMonitored(LogFileInfo file, DateTime localNow)
 {
     if (file.LogFileDate.LogSavingType == LogSavingType.Daily)
     {
         return(file.LogFileDate.DateTime.Year == localNow.Year &&
                file.LogFileDate.DateTime.Month == localNow.Month &&
                file.LogFileDate.DateTime.Day == localNow.Day);
     }
     else if (file.LogFileDate.LogSavingType == LogSavingType.Monthly)
     {
         return(file.LogFileDate.DateTime.Year == localNow.Year &&
                file.LogFileDate.DateTime.Month == localNow.Month);
     }
     else
     {
         if (!loggedUnknownFiles.Contains(file.FullPath))
         {
             logger.Log(LogLevel.Warn, "CharacterLogsMonitorEngine found file with unknown saving type: " + file.FullPath, this, null);
             loggedUnknownFiles.Add(file.FullPath);
         }
         return(false);
     }
 }
예제 #21
0
        public void ProcessLine(string line, long lastReadLineStartPosition)
        {
            AssertResultNotTaken();

            LineCounter++;
            try
            {
                if (line.StartsWith("Logging started", StringComparison.Ordinal))
                {
                    var dayStamp = ParsingHelper.GetDateFromLogFileLoggingStarted(line);
                    if (dayStamp.Day > CurrentDay)
                    {
                        CurrentDay = dayStamp.Day;
                        LastLogLineStamp = TimeSpan.Zero;
                        AdvanceDays(line, lastReadLineStartPosition);
                    }
                    else if (firstLoggingStartedFound && dayStamp.Day < CurrentDay)
                    {
                        //seems the logs have invalid timestamps, we need to flag for rollback
                        RollbackHeuristics(dayStamp.Day);
                    }
                    firstLoggingStartedFound = true;
                }
                else
                {
                    var lineStamp = ParsingHelper.GetTimestampFromLogLine(line);
                    if (lineStamp < LastLogLineStamp
                        && ParsingHelper.AreMoreThanOneHourAppartOnSameDay(lineStamp, LastLogLineStamp))
                    {
                        CurrentDay++;
                        LastLogLineStamp = TimeSpan.Zero;
                        AdvanceDays(line, lastReadLineStartPosition);
                    }
                    else
                    {
                        LastLogLineStamp = lineStamp;
                    }
                }
            }
            catch (WurmApiException exception)
            {
                // ignore this line
                logger.Log(
                    LogLevel.Warn,
                    string.Format("Unexpected exception while parsing line: {0}", line),
                    this,
                    exception);
            }
        }
예제 #22
0
        /// <summary>
        /// </summary>
        /// <param name="fileInfo"></param>
        /// <returns></returns>
        public LogFileInfo Create(FileInfo fileInfo)
        {
            // should never throw

            var    dateFromLogFileName = ParsingHelper.TryGetDateFromLogFileName(fileInfo.Name);
            var    typeFromLogFileName = wurmLogDefinitions.TryGetTypeFromLogFileName(fileInfo.Name);
            string pmRecipient         = null;

            if (typeFromLogFileName == LogType.Pm)
            {
                pmRecipient = ParsingHelper.TryParsePmRecipientFromFileName(fileInfo.Name);
            }

            bool parsingError = false;

            if (dateFromLogFileName.LogSavingType == LogSavingType.Unknown ||
                dateFromLogFileName.DateTime == DateTime.MinValue)
            {
                parsingError = true;
                logger.Log(LogLevel.Info, "Detected issues with parsing log date for file " + fileInfo.FullName, this, null);
            }

            if (typeFromLogFileName == LogType.Unspecified)
            {
                parsingError = true;
                logger.Log(LogLevel.Info, "Detected issues with parsing log type for file " + fileInfo.FullName, this, null);
            }

            return(new LogFileInfo(
                       fileInfo.FullName,
                       fileInfo.Name,
                       dateFromLogFileName,
                       typeFromLogFileName,
                       parsingError,
                       pmRecipient));
        }
예제 #23
0
        async Task <IWurmServer> TryGetServerAtStamp(DateTime dateTime)
        {
            var result = await character.TryGetHistoricServerAtLogStampAsync(dateTime).ConfigureAwait(false);

            if (result == null)
            {
                logger.Log(LogLevel.Info,
                           string.Format("Server could not be identified for character {0} at stamp {1}",
                                         character.Name.Capitalized,
                                         dateTime),
                           this,
                           null);
                return(null);
            }
            return(result);
        }
예제 #24
0
        private void SyncWebData()
        {
            var allServers = wurmServerList.All.ToArray();

            List <KeyValuePair <WurmServerInfo, Task <WebDataExtractionResult> > > jobs = new List <KeyValuePair <WurmServerInfo, Task <WebDataExtractionResult> > >();

            foreach (var wurmServerInfo in allServers)
            {
                var info = wurmServerInfo;
                var task = Task.Factory.StartNew(() => extractor.Extract(info));
                jobs.Add(new KeyValuePair <WurmServerInfo, Task <WebDataExtractionResult> >(wurmServerInfo, task));
            }
            foreach (var job in jobs)
            {
                try
                {
                    var result = job.Value.Result;
                    dataCache[result.ServerName] = new TimeDetails()
                    {
                        ServerDate = new ServerDateStamped()
                        {
                            WurmDateTime = result.WurmDateTime,
                            Stamp        = result.LastUpdated
                        },
                        ServerUptime = new ServerUptimeStamped()
                        {
                            Uptime = result.ServerUptime,
                            Stamp  = result.LastUpdated
                        }
                    };
                }
                catch (Exception exception)
                {
                    logger.Log(
                        LogLevel.Warn,
                        "WurmServer-LiveLogs Error at web data extraction for server: " + job.Key,
                        this,
                        exception);
                }
            }
            lastSync = Time.Get.LocalNowOffset;
        }
예제 #25
0
        public void ReportIssue(TKey key)
        {
            int count;

            lock (locker)
            {
                count = issueCounts.GetOrAdd(key, () => 0);
                count++;
                issueCounts[key] = count;
            }
            if (count >= issueTreshhold)
            {
                logger.Log(LogLevel.Warn,
                           string.Format("{1} > Adding key {0} to blacklist because at least {2} issues were reported. " +
                                         "List will be reset after application restart.",
                                         key,
                                         description,
                                         count),
                           this,
                           null);
            }
        }
예제 #26
0
        List <Exception> AddNewFileManagers(string[] allDirNames, IReadOnlyDictionary <CharacterName, WurmCharacterLogFiles> oldMap, Dictionary <CharacterName, WurmCharacterLogFiles> newMap)
        {
            List <Exception> exceptions = new List <Exception>();

            foreach (var dirName in allDirNames)
            {
                var charName = new CharacterName(dirName);
                WurmCharacterLogFiles logFiles;
                if (!oldMap.TryGetValue(charName, out logFiles))
                {
                    try
                    {
                        var fullDirPathForCharacter = wurmCharacterDirectories.GetFullDirPathForCharacter(charName);
                        var logsDirPath             = Path.Combine(fullDirPathForCharacter, wurmPaths.LogsDirName);

                        logFiles = new WurmCharacterLogFiles(
                            charName,
                            logsDirPath,
                            logger,
                            new LogFileInfoFactory(wurmLogDefinitions, logger),
                            internalEventInvoker,
                            taskManager);

                        newMap.Add(charName, logFiles);
                    }
                    catch (Exception exception)
                    {
                        logger.Log(LogLevel.Error, "Error at WurmLogFiles refresh for character: " + charName, this, exception);
                        exceptions.Add(exception);
                    }
                }
                else
                {
                    newMap.Add(charName, logFiles);
                }
            }

            return(exceptions);
        }
예제 #27
0
        void Refresh()
        {
            var di      = new DirectoryInfo(DirectoryFullPath);
            var allDirs = di.GetDirectories().Where(info => (info.Attributes & FileAttributes.Hidden) == 0);
            var newMap  = new Dictionary <string, string>();

            foreach (var directoryInfo in allDirs)
            {
                if (directoryBlacklist.IsOnBlacklist(directoryInfo.FullName))
                {
                    continue;
                }
                try
                {
                    validateDirectory(directoryInfo.FullName, wurmPaths);
                    newMap.Add(directoryInfo.Name.ToUpperInvariant(), directoryInfo.FullName);
                }
                catch (ValidationException exception)
                {
                    directoryBlacklist.ReportIssue(directoryInfo.FullName);
                    logger.Log(LogLevel.Warn, "Validation issue", this, exception);
                    // todo: need to log this as warning, solving with quick solution
                    // consider: extend AggregateException to carry logging level and handle that universally in TaskManager
                    task.SetErrorAndRetrigger();
                }
            }

            var oldDirs = dirNameToFullPathMap.Select(pair => pair.Key).OrderBy(s => s).ToArray();
            var newDirs = newMap.Select(pair => pair.Key).OrderBy(s => s).ToArray();

            var changed = !oldDirs.SequenceEqual(newDirs);

            if (changed)
            {
                dirNameToFullPathMap = newMap;
                OnDirectoriesChanged();
            }
        }
예제 #28
0
        public WurmLogsMonitor([NotNull] IWurmLogFiles wurmLogFiles, [NotNull] IWurmApiLogger logger,
                               [NotNull] IPublicEventInvoker publicEventInvoker, [NotNull] IInternalEventAggregator internalEventAggregator,
                               [NotNull] IWurmCharacterDirectories wurmCharacterDirectories,
                               [NotNull] InternalEventInvoker internalEventInvoker, [NotNull] TaskManager taskManager,
                               [NotNull] LogFileStreamReaderFactory logFileStreamReaderFactory)
        {
            if (wurmLogFiles == null)
            {
                throw new ArgumentNullException(nameof(wurmLogFiles));
            }
            if (logger == null)
            {
                throw new ArgumentNullException(nameof(logger));
            }
            if (publicEventInvoker == null)
            {
                throw new ArgumentNullException(nameof(publicEventInvoker));
            }
            if (internalEventAggregator == null)
            {
                throw new ArgumentNullException(nameof(internalEventAggregator));
            }
            if (wurmCharacterDirectories == null)
            {
                throw new ArgumentNullException(nameof(wurmCharacterDirectories));
            }
            if (internalEventInvoker == null)
            {
                throw new ArgumentNullException(nameof(internalEventInvoker));
            }
            if (taskManager == null)
            {
                throw new ArgumentNullException(nameof(taskManager));
            }
            if (logFileStreamReaderFactory == null)
            {
                throw new ArgumentNullException(nameof(logFileStreamReaderFactory));
            }
            this.wurmLogFiles               = wurmLogFiles;
            this.logger                     = logger;
            this.publicEventInvoker         = publicEventInvoker;
            this.internalEventAggregator    = internalEventAggregator;
            this.wurmCharacterDirectories   = wurmCharacterDirectories;
            this.internalEventInvoker       = internalEventInvoker;
            this.taskManager                = taskManager;
            this.logFileStreamReaderFactory = logFileStreamReaderFactory;

            try
            {
                Rebuild();
            }
            catch (Exception exception)
            {
                logger.Log(LogLevel.Error, "Error at WurmLogsMonitor initial rebuild", this, exception);
            }

            internalEventAggregator.Subscribe(this);

            taskHandle = new TaskHandle(Rebuild, "WurmLogsMonitor rebuild");
            taskManager.Add(taskHandle);

            updater = new Task(() =>
            {
                while (true)
                {
                    if (stop)
                    {
                        return;
                    }
                    Thread.Sleep(500);
                    if (stop)
                    {
                        return;
                    }

                    try
                    {
                        foreach (var logsMonitorEngineManager in characterNameToEngineManagers.Values)
                        {
                            logsMonitorEngineManager.Update(allEventSubscriptionsTsafe);
                        }
                    }
                    catch (Exception exception)
                    {
                        logger.Log(LogLevel.Error, "WurmLogsMonitor 'updater' task crashed", this, exception);
                    }
                }
            }, TaskCreationOptions.LongRunning);
            updater.Start();

            taskHandle.Trigger();
        }
예제 #29
0
        void EnsureScanned()
        {
            if (scanned)
            {
                return;
            }

            var maxScanSince  = Time.Get.LocalNowOffset.AddDays(-30);
            var lastScanSince = logHistorySaved.LastScanDate.AddDaysSnapToMinMax(-1);
            var scanSince     = lastScanSince < maxScanSince ? maxScanSince : lastScanSince;

            var allChars = wurmCharacterDirectories.GetAllCharacters();

            foreach (var characterName in allChars)
            {
                var searchResults = wurmLogsHistory.Scan(
                    new LogSearchParameters()
                {
                    CharacterName = characterName.Normalized,
                    MinDate       = scanSince.DateTime,
                    MaxDate       = Time.Get.LocalNow,
                    LogType       = LogType.Event
                });
                foreach (var searchResult in searchResults)
                {
                    var upt = parser.TryParseUptime(searchResult);
                    if (upt != null)
                    {
                        var server = wurmServerHistory.TryGetServer(characterName, searchResult.Timestamp);
                        if (server != null)
                        {
                            logHistorySaved.UpdateHistoric(server, upt);
                        }
                        else
                        {
                            wurmApiLogger.Log(LogLevel.Info,
                                              string.Format("Server not found for character {0} at timestamp {1}",
                                                            characterName,
                                                            searchResult.Timestamp),
                                              this,
                                              null);
                        }
                    }
                    var wdt = parser.TryParseWurmDateTime(searchResult);
                    if (wdt != null)
                    {
                        var server = wurmServerHistory.TryGetServer(characterName, searchResult.Timestamp);
                        if (server != null)
                        {
                            logHistorySaved.UpdateHistoric(server, wdt);
                        }
                        else
                        {
                            wurmApiLogger.Log(LogLevel.Info,
                                              string.Format("Server not found for character {0} at timestamp {1}",
                                                            characterName,
                                                            searchResult.Timestamp),
                                              this,
                                              null);
                        }
                    }
                }
            }

            scanned = true;
        }
예제 #30
0
        /// <summary>
        /// Attempts to parse log entry into a skill gain information.
        /// Returns null if entry was not recognized as related to skill gains.
        /// </summary>
        /// <param name="wurmLogEntry"></param>
        /// <returns></returns>
        public SkillInfo TryParseSkillInfoFromLogLine(LogEntry wurmLogEntry)
        {
            if (wurmLogEntry.Content.Contains("increased") | wurmLogEntry.Content.Contains("decreased"))
            {
                if (wurmLogEntry.Content.EndsWith("affinity", StringComparison.InvariantCulture))
                {
                    logger.Log(LogLevel.Info,
                               "Skill message appears to inform about affinity, not supported. Raw entry: " + wurmLogEntry,
                               this,
                               null);
                    return(null);
                }

                var match = Regex.Match(wurmLogEntry.Content,
                                        @"^(.+) (?:increased|decreased)(.*) to (\d+(?:\,|\.)\d+|\d+).*$",
                                        RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
                string skillName;
                float? parsedLevel;
                float? parsedGain = null;
                if (match.Success)
                {
                    skillName = match.Groups[1].Value;

                    if (string.IsNullOrWhiteSpace(skillName))
                    {
                        logger.Log(LogLevel.Error,
                                   "Skill name was parsed to empty string, raw entry: " + wurmLogEntry,
                                   this,
                                   null);
                        return(null);
                    }

                    var rawSkillGain = match.Groups[2].Value;

                    // check if 'by xx.xx' can be present in this entry
                    rawSkillGain = rawSkillGain.Trim();
                    if (rawSkillGain.Length > 3 && rawSkillGain.StartsWith("by "))
                    {
                        //try parse the skill gain
                        parsedGain = TryParseFloatInvariant(rawSkillGain.Remove(0, 3).Trim());

                        if (parsedGain == null)
                        {
                            logger.Log(LogLevel.Error,
                                       "Skill gain appears to be in log entry content, but could not be parsed, raw string: " + rawSkillGain
                                       + " raw entry: " + wurmLogEntry,
                                       this,
                                       null);
                        }
                    }

                    var rawSkillLevel = match.Groups[3].Value;

                    parsedLevel = TryParseFloatInvariant(rawSkillLevel);

                    if (parsedLevel == null)
                    {
                        logger.Log(LogLevel.Error,
                                   "Skill level could not be parsed, raw value: " + rawSkillLevel
                                   + " raw entry: " + wurmLogEntry,
                                   this,
                                   null);
                        return(null);
                    }
                }
                else
                {
                    logger.Log(LogLevel.Error,
                               "Skill gain/loss message could not be parsed, raw entry: " + wurmLogEntry,
                               this,
                               null);
                    return(null);
                }

                return(new SkillInfo(skillName, parsedLevel.Value, wurmLogEntry.Timestamp, parsedGain));
            }
            else
            {
                return(null);
            }
        }