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]);
                }
            }
        }
Beispiel #2
0
        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));
        }