public void HandleUpdateRequestProperly(string section, SystemErrorsUpdateRequest.EType type) { using (FileDeleter fd = new FileDeleter(Extensions.GetTempDBFile())) { Database db = new Database(new Context(fd.Fi)); Initializer init = new Initializer(null); init.Initialize(db); RequestBus bus = new RequestBus(); EventLogResponder responder = new EventLogResponder() { DB = db }; bus.Subscribe(responder); using (SQLiteConnection conn = db.Connection) { conn.Open(); string new_path = $"machine_name.{section}.max_event_log"; System.DateTime dt = GenerateTime(2019, 2, 20, 12, 23, 34, 456789); EventLogData eld = new EventLogData(); eld.Insert(dt, 22334455); eld.Insert(dt, 22334456); SystemErrorsUpdateRequest req = new SystemErrorsUpdateRequest("machine_name", type); req.LogData.Assign(eld); bus.MakeRequest(req); Assert.True(req.IsHandled); Attribute attr = new Attribute(); string x = attr.Get(new_path, conn); Assert.False(string.IsNullOrEmpty(x)); EventLogData eld2 = JsonConvert.DeserializeObject <EventLogData>(x); Assert.NotNull(eld); Assert.False(eld2.MaxRecordNumber.HasValue); Assert.Equal(dt, eld2.MaxDate); List <ulong> record_numbers = eld2.MaxDateToRecordNumbers[dt]; Assert.NotNull(record_numbers); Assert.Equal(2, record_numbers.Count); // Sort just in case they got put in the list in a different order record_numbers.Sort(); Assert.Equal((ulong)22334455, record_numbers[0]); Assert.Equal((ulong)22334456, record_numbers[1]); } } }
public override void HandleRequest(Request request) { if (request is SystemErrorsInfoRequest == false && request is SystemErrorsUpdateRequest == false) { return; } Database db = DB != null ? DB : new Database(); using (SQLiteConnection conn = db.Connection) { conn.Open(); if (request is SystemErrorsInfoRequest) { HandleInfoRequest(request as SystemErrorsInfoRequest, conn); } else if (request is SystemErrorsUpdateRequest) { SystemErrorsUpdateRequest sys_request = request as SystemErrorsUpdateRequest; Attribute attr = new Attribute(); string machine_name = sys_request.MachineName.Replace(' ', '_').ToLower(); string section = sys_request.Type.ToString().ToLower(); string max_eventlog_path = $"{machine_name}.{section}.max_event_log"; attr.Set(max_eventlog_path, JsonConvert.SerializeObject(sys_request.LogData, Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }), conn); sys_request.Handled(); } } }
public override CollectedData OnAcquire() { List <Data> data = new List <Data>(); GenericEventLogCollector.ELogs logfile = GenericEventLogCollector.ELogs.System; if (Context.Type == ECollectorType.ApplicationErrors) { logfile = GenericEventLogCollector.ELogs.Application; } // In order to figure out if the query is failing (due to a credentials problem or the machine // being offline, for example), or there just not being any new errors since the last // time we queried, ask for RecordNumber >= the max record # we've // already received. This way, we should get at least 1 record that we can ignore if // we've already received it. // https://docs.microsoft.com/en-us/windows/desktop/WmiSdk/wql-operators Stopwatch watch = Stopwatch.StartNew(); GenericEventLogCollector collector = new GenericEventLogCollector(RemoteInfo, logfile, true, m_log_data); List <EventLogRecord> records = collector.Retrieve(); if (records.Count == 0) { // Nothing new...why? I've seen two conditions: // 1) The machine has been rebuilt and the records numbers on that machine are // lower than what we've already received. As long as the time field is used // that shouldn't be a problem. // 2) There haven't been any system/application errors since the date or record number // we got when we did the SystemErrorsInfoRequest. // To solve this let's re-gather events, but don't limit the query to EventType=1 (errors) // and just grab the most recent event of whatever type. collector = new GenericEventLogCollector(RemoteInfo, logfile, false, m_log_data); records = collector.Retrieve(); } records.ForEach(r => { // If somehow the RecordNumber < the max record # we // have so far, then it's likely the machine was rebuilt // or the record number rolled over (hard to do when the max // is 18,446,744,073,709,551,615, that means if there were 100 // events per second, the number would roll over after // 5.8 billion years...not gonna worry about that). Trace.WriteLine(JsonConvert.SerializeObject(r)); // Make sure we always insert the record into m_log_data even if it's // not an error record. But don't put it in data unless it's an error record. if (r.EventType == 1 && m_log_data.ContainsRecordNumber(r.RecordNumber) == false) { data.Add(r.AsData(Context)); } m_log_data.Insert(r.TimeGeneratedAsDateTimeOffset, r.RecordNumber); }); long elapsed = watch.ElapsedMilliseconds; long ms_per_record = elapsed / (data.Count == 0 ? 1 : data.Count); string msg = $"EventLogCollector [{m_machine_name} -- {logfile}]: collected {data.Count} of {records.Count} in {elapsed} ms ({ms_per_record} ms per record)"; m_log.Debug(msg); //ApplicationEventLog log = new ApplicationEventLog(); //log.LogInformation(msg); m_log_data.Cleanup(); SystemErrorsUpdateRequest.EType req_type = SystemErrorsUpdateRequest.EType.System; switch (CollectorType) { case ECollectorType.ApplicationErrors: req_type = SystemErrorsUpdateRequest.EType.Application; break; case ECollectorType.SystemErrors: req_type = SystemErrorsUpdateRequest.EType.System; break; default: throw new Exception($"EventLogCollector.OnAcquire: failure to handle type conversion from {CollectorType}"); } SystemErrorsUpdateRequest request = new SystemErrorsUpdateRequest(m_machine_name, req_type); request.LogData.Assign(m_log_data); RequestBus.Instance.MakeRequest(request); // We want to report that we collected data if we got something, even if it wasn't an error record return(new CollectedData(Context, records.Count > 0, data)); }