| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- using System.Diagnostics.CodeAnalysis;
- using System.Linq;
- using Content.Server.Database;
- using Content.Shared.Administration.Logs;
- using Content.Shared.Database;
- using Prometheus;
- namespace Content.Server.Administration.Logs;
- public sealed partial class AdminLogManager
- {
- private const int MaxRoundsCached = 3;
- private const int LogListInitialSize = 30_000;
- private readonly int _logTypes = Enum.GetValues<LogType>().Length;
- // TODO ADMIN LOGS make this thread safe or remove thread safety from the main partial class
- private readonly Dictionary<int, List<SharedAdminLog>> _roundsLogCache = new(MaxRoundsCached);
- private readonly Queue<int> _roundsLogCacheQueue = new();
- private static readonly Gauge CacheRoundCount = Metrics.CreateGauge(
- "admin_logs_cache_round_count",
- "How many rounds are in cache.");
- private static readonly Gauge CacheLogCount = Metrics.CreateGauge(
- "admin_logs_cache_log_count",
- "How many logs are in cache.");
- // TODO ADMIN LOGS cache previous {MaxRoundsCached} rounds on startup
- public void CacheNewRound()
- {
- List<SharedAdminLog>? list = null;
- _roundsLogCacheQueue.Enqueue(_currentRoundId);
- if (_roundsLogCacheQueue.Count > MaxRoundsCached)
- {
- var oldestRound = _roundsLogCacheQueue.Dequeue();
- if (_roundsLogCache.Remove(oldestRound, out var oldestList))
- {
- list = oldestList;
- list.Clear();
- }
- }
- list ??= new List<SharedAdminLog>(LogListInitialSize);
- _roundsLogCache.Add(_currentRoundId, list);
- CacheRoundCount.Set(_roundsLogCache.Count);
- }
- private void CacheLog(AdminLog log)
- {
- var players = log.Players.Select(player => player.PlayerUserId).ToArray();
- var record = new SharedAdminLog(log.Id, log.Type, log.Impact, log.Date, log.Message, players);
- CacheLog(record);
- }
- private void CacheLog(SharedAdminLog log)
- {
- // TODO ADMIN LOGS remove redundant data and don't do a dictionary lookup per log
- var cache = _roundsLogCache[_currentRoundId];
- cache.Add(log);
- CacheLogCount.Set(cache.Count);
- }
- private void CacheLogs(IEnumerable<SharedAdminLog> logs)
- {
- var cache = _roundsLogCache[_currentRoundId];
- cache.AddRange(logs);
- CacheLogCount.Set(cache.Count);
- }
- private bool TryGetCache(int roundId, [NotNullWhen(true)] out List<SharedAdminLog>? cache)
- {
- return _roundsLogCache.TryGetValue(roundId, out cache);
- }
- private bool TrySearchCache(LogFilter? filter, [NotNullWhen(true)] out List<SharedAdminLog>? results)
- {
- if (filter?.Round == null || !TryGetCache(filter.Round.Value, out var cache))
- {
- results = null;
- return false;
- }
- // TODO ADMIN LOGS a better heuristic than linq spaghetti
- var query = cache.AsEnumerable();
- query = filter.DateOrder switch
- {
- DateOrder.Ascending => query,
- DateOrder.Descending => query.Reverse(),
- _ => throw new ArgumentOutOfRangeException(nameof(filter),
- $"Unknown {nameof(DateOrder)} value {filter.DateOrder}")
- };
- if (filter.Search != null)
- {
- query = query.Where(log => log.Message.Contains(filter.Search, StringComparison.OrdinalIgnoreCase));
- }
- if (filter.Types != null && filter.Types.Count != _logTypes)
- {
- query = query.Where(log => filter.Types.Contains(log.Type));
- }
- if (filter.Impacts != null)
- {
- query = query.Where(log => filter.Impacts.Contains(log.Impact));
- }
- if (filter.Before != null)
- {
- query = query.Where(log => log.Date < filter.Before);
- }
- if (filter.After != null)
- {
- query = query.Where(log => log.Date > filter.After);
- }
- if (filter.IncludePlayers)
- {
- if (filter.AnyPlayers != null)
- {
- query = query.Where(log =>
- filter.AnyPlayers.Any(filterPlayer => log.Players.Contains(filterPlayer)) ||
- log.Players.Length == 0 && filter.IncludeNonPlayers);
- }
- if (filter.AllPlayers != null)
- {
- query = query.Where(log =>
- filter.AllPlayers.All(filterPlayer => log.Players.Contains(filterPlayer)) ||
- log.Players.Length == 0 && filter.IncludeNonPlayers);
- }
- }
- else
- {
- query = query.Where(log => log.Players.Length == 0);
- }
- if (filter.LogsSent != 0)
- {
- query = query.Skip(filter.LogsSent);
- }
- if (filter.Limit != null)
- {
- query = query.Take(filter.Limit.Value);
- }
- // TODO ADMIN LOGS array pool
- results = query.ToList();
- return true;
- }
- }
|