Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
PersistedEventLog.cs
1using System;
3using System.Text;
4using System.Threading;
5using System.Threading.Tasks;
9
11{
17 {
18 private Timer timer;
19 private int eventLifetimeDays;
20 private string defaultFacility;
21 private string defaultFacilityDigest = null;
22
29 : this(EventLifetimeDays, null, string.Empty, string.Empty)
30 {
31 }
32
39 public PersistedEventLog(int EventLifetimeDays, TimeSpan? CleanupTime)
40 : this(EventLifetimeDays, CleanupTime, string.Empty, string.Empty)
41 {
42 }
43
52 public PersistedEventLog(int EventLifetimeDays, TimeSpan? CleanupTime, string DefaultFacility, string DefaultFacilityKey)
53 : base("Persisted Event Log")
54 {
55 if (EventLifetimeDays <= 0)
56 throw new ArgumentOutOfRangeException("The lifetime must be a positive number of days.", nameof(EventLifetimeDays));
57
58 this.eventLifetimeDays = EventLifetimeDays;
59 this.defaultFacility = DefaultFacility;
60 this.defaultFacilityDigest = this.ComputeDigest(DefaultFacilityKey);
61
62 if (CleanupTime.HasValue)
63 this.TurnOnDailyPurge(EventLifetimeDays, CleanupTime.Value);
64 else
65 this.timer = null;
66 }
67
73 public void TurnOnDailyPurge(int EventLifetimeDays, TimeSpan CleanupTime)
74 {
75 this.TurnOffDailyPurge();
76
77 if (CleanupTime < TimeSpan.Zero || CleanupTime.TotalDays >= 1.0)
78 throw new ArgumentOutOfRangeException("Invalid time.", nameof(CleanupTime));
79
80 int MillisecondsPerDay = 1000 * 60 * 60 * 24;
81 int MsUntilNext = (int)((DateTime.Today.AddDays(1).Add(CleanupTime) - DateTime.Now).TotalMilliseconds + 0.5);
82
83 this.eventLifetimeDays = EventLifetimeDays;
84 this.timer = new Timer(this.DoCleanup, null, MsUntilNext, MillisecondsPerDay);
85 }
86
91 public bool TurnOffDailyPurge()
92 {
93 if (!(this.timer is null))
94 {
95 this.timer.Dispose();
96 this.timer = null;
97
98 return true;
99 }
100 else
101 return false;
102 }
103
107 public override Task DisposeAsync()
108 {
109 this.TurnOffDailyPurge();
110 return base.DisposeAsync();
111 }
112
113 private async void DoCleanup(object P)
114 {
115 try
116 {
117 await this.DeleteOld(DateTime.UtcNow.AddDays(-this.eventLifetimeDays));
118 }
119 catch (Exception ex)
120 {
121 Log.Exception(ex);
122 }
123 }
124
131 public Task<int> DeleteOld(DateTime Limit)
132 {
133 return DeleteOld(this.ObjectID, Limit);
134 }
135
143 public static async Task<int> DeleteOld(string ObjectId, DateTime Limit)
144 {
145 int NrEvents = await Database.Delete<PersistedEvent>(
146 new FilterFieldLesserOrEqualTo("Timestamp", Limit));
147
148 if (NrEvents > 0)
149 {
150 KeyValuePair<string, object>[] Tags = new KeyValuePair<string, object>[]
151 {
152 new KeyValuePair<string, object>("Limit", Limit),
153 new KeyValuePair<string, object>("NrEvents", NrEvents)
154 };
155
156 if (NrEvents == 1)
157 Log.Informational("Deleting 1 event from the database.", ObjectId, Tags);
158 else
159 Log.Informational("Deleting " + NrEvents.ToString() + " events from the database.", ObjectId, Tags);
160 }
161
162 return NrEvents;
163 }
164
173 public Task<IEnumerable<PersistedEvent>> GetEvents(int Offset, int MaxCount, DateTime From, DateTime To)
174 {
175 return Database.Find<PersistedEvent>(Offset, MaxCount, new FilterAnd(
176 new FilterFieldGreaterOrEqualTo("Timestamp", From),
177 new FilterFieldLesserOrEqualTo("Timestamp", To)), "-Timestamp");
178 }
179
189 public Task<IEnumerable<PersistedEvent>> GetEventsOfType(int Offset, int MaxCount, EventType Type, DateTime From, DateTime To)
190 {
191 return Database.Find<PersistedEvent>(Offset, MaxCount, new FilterAnd(
192 new FilterFieldGreaterOrEqualTo("Type", Type),
193 new FilterFieldGreaterOrEqualTo("Timestamp", From),
194 new FilterFieldLesserOrEqualTo("Timestamp", To)), "-Timestamp");
195 }
196
206 public Task<IEnumerable<PersistedEvent>> GetEventsOfObject(int Offset, int MaxCount, string Object, DateTime From, DateTime To)
207 {
208 return Database.Find<PersistedEvent>(Offset, MaxCount, new FilterAnd(
209 new FilterFieldGreaterOrEqualTo("Object", Object),
210 new FilterFieldGreaterOrEqualTo("Timestamp", From),
211 new FilterFieldLesserOrEqualTo("Timestamp", To)), "-Timestamp");
212 }
213
223 public Task<IEnumerable<PersistedEvent>> GetEventsOfActor(int Offset, int MaxCount, string Actor, DateTime From, DateTime To)
224 {
225 return Database.Find<PersistedEvent>(Offset, MaxCount, new FilterAnd(
226 new FilterFieldGreaterOrEqualTo("Actor", Actor),
227 new FilterFieldGreaterOrEqualTo("Timestamp", From),
228 new FilterFieldLesserOrEqualTo("Timestamp", To)), "-Timestamp");
229 }
230
240 public Task<IEnumerable<PersistedEvent>> GetEventsOfEventId(int Offset, int MaxCount, string EventId, DateTime From, DateTime To)
241 {
242 return Database.Find<PersistedEvent>(Offset, MaxCount, new FilterAnd(
243 new FilterFieldGreaterOrEqualTo("EventId", EventId),
244 new FilterFieldGreaterOrEqualTo("Timestamp", From),
245 new FilterFieldLesserOrEqualTo("Timestamp", To)), "-Timestamp");
246 }
247
257 public Task<IEnumerable<PersistedEvent>> GetEventsOfFacility(int Offset, int MaxCount, string Facility, DateTime From, DateTime To)
258 {
259 return Database.Find<PersistedEvent>(Offset, MaxCount, new FilterAnd(
260 new FilterFieldGreaterOrEqualTo("Facility", Facility),
261 new FilterFieldGreaterOrEqualTo("Timestamp", From),
262 new FilterFieldLesserOrEqualTo("Timestamp", To)), "-Timestamp");
263 }
264
268 public int EventLifetimeDays => this.eventLifetimeDays;
269
274 public override async Task Queue(Event Event)
275 {
277
278 if (string.IsNullOrEmpty(PersistedEvent.Facility))
279 PersistedEvent.Facility = this.defaultFacility;
280
282 }
283
291 public void SetDefaultFacility(string DefaultFacility, string DefaultFacilityKey)
292 {
293 if (this.defaultFacility != DefaultFacility)
294 {
295 if (!string.IsNullOrEmpty(this.defaultFacility))
296 {
297 if (this.ComputeDigest(DefaultFacilityKey) != this.defaultFacilityDigest)
298 throw new UnauthorizedAccessException("Unauthorized to change the default facility.");
299 }
300
301 this.defaultFacility = DefaultFacility;
302 this.defaultFacilityDigest = this.ComputeDigest(DefaultFacilityKey);
303 }
304 }
305
306 private string ComputeDigest(string Key)
307 {
308 return Hashes.ComputeSHA256HashString(Encoding.UTF8.GetBytes(Key + ":" + this.defaultFacility));
309 }
310
311 internal static int ArchiveDays
312 {
313 get
314 {
315 if (registeredLog is null)
316 {
317 foreach (IEventSink Sink in Log.Sinks)
318 {
319 if (Sink is PersistedEventLog PersistedEventLog)
320 {
321 registeredLog = PersistedEventLog;
322 break;
323 }
324 }
325
326 if (registeredLog is null)
327 return 90;
328 }
329
330 return registeredLog.eventLifetimeDays;
331 }
332 }
333
334 private static PersistedEventLog registeredLog = null;
335 }
336}
Class representing an event.
Definition: Event.cs:11
Base class for event sinks.
Definition: EventSink.cs:9
Static class managing the application event log. Applications and services log events on this static ...
Definition: Log.cs:14
static IEventSink[] Sinks
Registered sinks.
Definition: Log.cs:132
static void Exception(Exception Exception, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, params KeyValuePair< string, object >[] Tags)
Logs an exception. Event type will be determined by the severity of the exception.
Definition: Log.cs:1657
static void Informational(string Message, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, string StackTrace, params KeyValuePair< string, object >[] Tags)
Logs an informational event.
Definition: Log.cs:344
virtual string ObjectID
Object ID, used when logging events.
Definition: LogObject.cs:26
Class representing a persisted event.
string Facility
Facility can be either a facility in the network sense or in the system sense.
Creates an even sink that stores incoming (logged) events in the local object database,...
Task< int > DeleteOld(DateTime Limit)
Deletes old events. This method is called once a day automatically. It can also be called manually to...
Task< IEnumerable< PersistedEvent > > GetEventsOfEventId(int Offset, int MaxCount, string EventId, DateTime From, DateTime To)
Gets events relating to a specific event identity between two timepoints, ordered by descending times...
Task< IEnumerable< PersistedEvent > > GetEventsOfObject(int Offset, int MaxCount, string Object, DateTime From, DateTime To)
Gets events beloinging to a specific object between two timepoints, ordered by descending timestamp.
Task< IEnumerable< PersistedEvent > > GetEventsOfActor(int Offset, int MaxCount, string Actor, DateTime From, DateTime To)
Gets events relating to a specific actor between two timepoints, ordered by descending timestamp.
PersistedEventLog(int EventLifetimeDays, TimeSpan? CleanupTime, string DefaultFacility, string DefaultFacilityKey)
Creates an even sink that stores incoming (logged) events in the local object database,...
int EventLifetimeDays
Number of days to store events in the database.
Task< IEnumerable< PersistedEvent > > GetEventsOfType(int Offset, int MaxCount, EventType Type, DateTime From, DateTime To)
Gets events of a specific type between two timepoints, ordered by descending timestamp.
PersistedEventLog(int EventLifetimeDays, TimeSpan? CleanupTime)
Creates an even sink that stores incoming (logged) events in the local object database,...
override Task DisposeAsync()
IDisposableAsync.DisposeAsync()
void TurnOnDailyPurge(int EventLifetimeDays, TimeSpan CleanupTime)
Turns on the daily purge of old events.
PersistedEventLog(int EventLifetimeDays)
Creates an even sink that stores incoming (logged) events in the local object database,...
Task< IEnumerable< PersistedEvent > > GetEvents(int Offset, int MaxCount, DateTime From, DateTime To)
Gets events between two timepoints, ordered by descending timestamp.
static async Task< int > DeleteOld(string ObjectId, DateTime Limit)
Deletes old events. This method is called once a day automatically. It can also be called manually to...
Task< IEnumerable< PersistedEvent > > GetEventsOfFacility(int Offset, int MaxCount, string Facility, DateTime From, DateTime To)
Gets events relating to a specific facility between two timepoints, ordered by descending timestamp.
bool TurnOffDailyPurge()
Turns off the daily purge of old events.
override async Task Queue(Event Event)
Queues an event to be output.
void SetDefaultFacility(string DefaultFacility, string DefaultFacilityKey)
Sets the default facility. The default facility can only be reset by a caller presenting the same key...
Static interface for database persistence. In order to work, a database provider has to be assigned t...
Definition: Database.cs:21
static async Task Delete(object Object)
Deletes an object in the database.
Definition: Database.cs:1291
static Task< IEnumerable< object > > Find(string Collection, params string[] SortOrder)
Finds objects in a given collection.
Definition: Database.cs:238
static async Task Insert(object Object)
Inserts an object into the default collection of the database.
Definition: Database.cs:97
This filter selects objects that conform to all child-filters provided.
Definition: FilterAnd.cs:10
This filter selects objects that have a named field greater or equal to a given value.
This filter selects objects that have a named field lesser or equal to a given value.
Contains methods for simple hash calculations.
Definition: Hashes.cs:57
static string ComputeSHA256HashString(byte[] Data)
Computes the SHA-256 hash of a block of binary data.
Definition: Hashes.cs:449
Interface for all event sinks.
Definition: IEventSink.cs:9
EventType
Type of event.
Definition: EventType.cs:7