public DatabasesInfoRetriever(ServerStore serverStore, CanAccessDatabase canAccessDatabase) { _serverStore = serverStore; _canAccessDatabase = canAccessDatabase; Initialize(); }
public override DynamicJsonValue ToJsonWithFilter(CanAccessDatabase filter) { var items = new DynamicJsonArray(); foreach (var mountPointUsage in Items) { var usageAsJson = mountPointUsage.ToJsonWithFilter(filter); if (usageAsJson != null) { usageAsJson.RemoveInMemoryPropertyByName(nameof(MountPointUsage.Items)); items.Add(usageAsJson); } } if (items.Count == 0) { return(null); } var json = base.ToJson(); json[nameof(Items)] = items; return(json); }
public DynamicJsonValue ToJsonWithFilter(CanAccessDatabase filter) { var json = ToJsonInternal(); var ravenSize = 0L; var ravenTempBuffersSize = 0L; var items = new DynamicJsonArray(); foreach (var databaseDiskUsage in Items) { if (filter(databaseDiskUsage.Database, requiresWrite: false)) { items.Add(databaseDiskUsage.ToJson()); ravenSize += databaseDiskUsage.Size; ravenTempBuffersSize += databaseDiskUsage.TempBuffersSize; } } if (items.Count == 0) { return(null); } json[nameof(Items)] = items; json[nameof(RavenSize)] = ravenSize; json[nameof(RavenTempBuffersSize)] = ravenTempBuffersSize; return(json); }
public ClusterDashboardConnection(WebSocket webSocket, CanAccessDatabase canAccessDatabase, ClusterDashboardNotifications clusterDashboardNotifications, IMemoryContextPool contextPool, CancellationToken resourceShutdown) : base(webSocket, clusterDashboardNotifications, contextPool, resourceShutdown) { _canAccessDatabase = canAccessDatabase; _clusterDashboardNotifications = clusterDashboardNotifications; _returnReadContext = contextPool.AllocateOperationContext(out _readContext); }
private async Task SendNotifications(CanAccessDatabase canAccessDatabase, WebSocket webSocket) { using (var notifications = new ClusterDashboardNotifications(Server, canAccessDatabase, ServerStore.ServerShutdown)) using (var connection = new ClusterDashboardConnection(webSocket, canAccessDatabase, notifications, ServerStore.ContextPool, ServerStore.ServerShutdown)) { await connection.Handle(); } }
public override DynamicJsonValue ToJsonWithFilter(CanAccessDatabase filter) { var result = new TrafficWatchPayload(); foreach (TrafficWatchItem item in TrafficPerDatabase) { if (filter(item.Database, requiresWrite: false)) { result.Add(item); } } return result.ToJsonInternal(); }
public override DynamicJsonValue ToJsonWithFilter(CanAccessDatabase filter) { var result = new IndexingSpeedPayload(); foreach (IndexingSpeedItem item in IndexingSpeedPerDatabase) { if (filter(item.Database, requiresWrite: false)) { result.Add(item); } } return(result.ToJsonInternal()); }
public override DynamicJsonValue ToJsonWithFilter(CanAccessDatabase filter) { var items = new DynamicJsonArray(); foreach (var indexingSpeedItem in Items) { if (filter(indexingSpeedItem.Database, requiresWrite: false)) { items.Add(indexingSpeedItem.ToJson()); } } if (items.Count == 0) { return(null); } var json = base.ToJson(); json[nameof(Items)] = items; return(json); }
public async Task WriteNotifications(CanAccessDatabase shouldWriteByDb, Task taskHandlingReceiveOfData = null) { var receiveBuffer = new ArraySegment <byte>(new byte[1024]); var receive = taskHandlingReceiveOfData ?? _webSocket.ReceiveAsync(receiveBuffer, _resourceShutdown); var asyncQueue = new AsyncQueue <DynamicJsonValue>(); try { using (_notificationsBase.TrackActions(asyncQueue, this, shouldWriteByDb)) { AfterTrackActionsRegistration?.Invoke(); while (_resourceShutdown.IsCancellationRequested == false) { // we use this to detect client-initialized closure if (receive.IsCompleted) { break; } var tuple = await asyncQueue.TryDequeueAsync(TimeSpan.FromSeconds(5)); if (tuple.Item1 == false) { await SendHeartbeat(); continue; } await WriteToWebSocket(tuple.Item2); } } } catch (OperationCanceledException) { } }
public override DynamicJsonValue ToJsonWithFilter(CanAccessDatabase filter) { var items = new DynamicJsonArray(); foreach (var trafficWatchItem in Items) { if (filter(trafficWatchItem.Database, requiresWrite: false)) { items.Add(trafficWatchItem.ToJson()); } } if (items.Count == 0) { return(null); } var json = base.ToJson(); json[nameof(Items)] = items; json[nameof(AverageRequestDuration)] = AverageRequestDuration; return(json); }
public IDisposable TrackActions(AsyncQueue <DynamicJsonValue> notificationsQueue, IWebsocketWriter webSocketWriter, CanAccessDatabase shouldWriteByDb = null) { var watcher = new ConnectedWatcher { NotificationsQueue = notificationsQueue, Writer = webSocketWriter, Filter = shouldWriteByDb }; lock (_watchersLock) { Watchers.TryAdd(watcher); if (Watchers.Count == 1) { StartBackgroundWorkers(); } if (watcher.Writer is NotificationCenterWebSocketWriter) { if (_state.NumberOfClients == 0) { var copy = _state; // we use interlocked here to make sure that other threads // are immediately exposed to this Interlocked.Exchange(ref _state, new State { NumberOfClients = 1 }); copy.NewWebSocket.TrySetResult(null); } else { Interlocked.Increment(ref _state.NumberOfClients); } } } return(new DisposableAction(() => { lock (_watchersLock) { Watchers.TryRemove(watcher); if (Watchers.Count == 0) { StopBackgroundWorkers(); } if (watcher.Writer is NotificationCenterWebSocketWriter) { var copy = _state; if (Interlocked.Decrement(ref copy.NumberOfClients) == 0) { Interlocked.Exchange(ref _state, new State()); copy.AllWebSocketsRemoved.TrySetResult(null); } } } })); }
public override DynamicJsonValue ToJsonWithFilter(CanAccessDatabase filter) { return(ToJson()); }
public ClusterDashboardNotifications(RavenServer server, CanAccessDatabase canAccessDatabase, CancellationToken shutdown) { _server = server; _shutdown = shutdown; _databasesInfoRetriever = new DatabasesInfoRetriever(server.ServerStore, canAccessDatabase); }
public static IEnumerable <AbstractDashboardNotification> FetchDatabasesInfo(ServerStore serverStore, CanAccessDatabase isValidFor, CancellationToken token) { var databasesInfo = new DatabasesInfo(); var databasesOngoingTasksInfo = new DatabasesOngoingTasksInfo(); var indexingSpeed = new IndexingSpeed(); var trafficWatch = new TrafficWatch(); var drivesUsage = new DrivesUsage(); trafficWatch.AverageRequestDuration = serverStore.Server.Metrics.Requests.AverageDuration.GetRate(); using (serverStore.ContextPool.AllocateOperationContext(out TransactionOperationContext context)) using (context.OpenReadTransaction()) { // 1. Fetch databases info foreach (var databaseTuple in serverStore.Cluster.ItemsStartingWith(context, Constants.Documents.Prefix, 0, long.MaxValue)) { var databaseName = databaseTuple.ItemName.Substring(Constants.Documents.Prefix.Length); if (token.IsCancellationRequested) { yield break; } if (isValidFor != null && isValidFor(databaseName, false) == false) { continue; } if (serverStore.DatabasesLandlord.DatabasesCache.TryGetValue(databaseName, out var databaseTask) == false) { // database does not exist on this server, is offline or disabled SetOfflineDatabaseInfo(serverStore, context, databaseName, databasesInfo, drivesUsage, disabled: DatabasesLandlord.IsDatabaseDisabled(databaseTuple.Value)); continue; } try { var databaseOnline = IsDatabaseOnline(databaseTask, out var database); if (databaseOnline == false) { SetOfflineDatabaseInfo(serverStore, context, databaseName, databasesInfo, drivesUsage, disabled: false); continue; } var rate = (int)RefreshRate.TotalSeconds; var indexingSpeedItem = new IndexingSpeedItem { Database = database.Name, IndexedPerSecond = database.Metrics.MapIndexes.IndexedPerSec.GetRate(rate), MappedPerSecond = database.Metrics.MapReduceIndexes.MappedPerSec.GetRate(rate), ReducedPerSecond = database.Metrics.MapReduceIndexes.ReducedPerSec.GetRate(rate) }; indexingSpeed.Items.Add(indexingSpeedItem); var replicationFactor = GetReplicationFactor(databaseTuple.Value); var documentsStorage = database.DocumentsStorage; var indexStorage = database.IndexStore; var trafficWatchItem = new TrafficWatchItem { Database = database.Name, RequestsPerSecond = (int)database.Metrics.Requests.RequestsPerSec.GetRate(rate), AverageRequestDuration = database.Metrics.Requests.AverageDuration.GetRate(), DocumentWritesPerSecond = (int)database.Metrics.Docs.PutsPerSec.GetRate(rate), AttachmentWritesPerSecond = (int)database.Metrics.Attachments.PutsPerSec.GetRate(rate), CounterWritesPerSecond = (int)database.Metrics.Counters.PutsPerSec.GetRate(rate), TimeSeriesWritesPerSecond = (int)database.Metrics.TimeSeries.PutsPerSec.GetRate(rate), DocumentsWriteBytesPerSecond = database.Metrics.Docs.BytesPutsPerSec.GetRate(rate), AttachmentsWriteBytesPerSecond = database.Metrics.Attachments.BytesPutsPerSec.GetRate(rate), CountersWriteBytesPerSecond = database.Metrics.Counters.BytesPutsPerSec.GetRate(rate), TimeSeriesWriteBytesPerSecond = database.Metrics.TimeSeries.BytesPutsPerSec.GetRate(rate) }; trafficWatch.Items.Add(trafficWatchItem); databasesOngoingTasksInfo.Items.Add(GetOngoingTasksInfoItem(database, serverStore, context, out var ongoingTasksCount)); // TODO: RavenDB-17004 - hash should report on all relevant info var currentEnvironmentsHash = database.GetEnvironmentsHash(); if (CachedDatabaseInfo.TryGetValue(database.Name, out var item) && item.Hash == currentEnvironmentsHash && item.Item.OngoingTasksCount == ongoingTasksCount) { databasesInfo.Items.Add(item.Item); if (item.NextDiskSpaceCheck < SystemTime.UtcNow) { item.MountPoints = new List <Client.ServerWide.Operations.MountPointUsage>(); DiskUsageCheck(item, database, drivesUsage, token); } else { foreach (var cachedMountPoint in item.MountPoints) { UpdateMountPoint(database.Configuration.Storage, cachedMountPoint, database.Name, drivesUsage); } } } else { using (documentsStorage.ContextPool.AllocateOperationContext(out DocumentsOperationContext documentsContext)) using (documentsContext.OpenReadTransaction()) { var databaseInfoItem = new DatabaseInfoItem { Database = database.Name, DocumentsCount = documentsStorage.GetNumberOfDocuments(documentsContext), IndexesCount = database.IndexStore.Count, AlertsCount = database.NotificationCenter.GetAlertCount(), PerformanceHintsCount = database.NotificationCenter.GetPerformanceHintCount(), ReplicationFactor = replicationFactor, ErroredIndexesCount = indexStorage.GetIndexes().Count(index => index.State == IndexState.Error), IndexingErrorsCount = indexStorage.GetIndexes().Sum(index => index.GetErrorCount()), BackupInfo = database.PeriodicBackupRunner?.GetBackupInfo(context), OngoingTasksCount = ongoingTasksCount, Online = true }; databasesInfo.Items.Add(databaseInfoItem); CachedDatabaseInfo[database.Name] = item = new DatabaseInfoCache { Hash = currentEnvironmentsHash, Item = databaseInfoItem }; } DiskUsageCheck(item, database, drivesUsage, token); } } catch (Exception) { SetOfflineDatabaseInfo(serverStore, context, databaseName, databasesInfo, drivesUsage, disabled: false); } } // 2. Fetch <system> info if (isValidFor == null) { var currentSystemHash = serverStore._env.CurrentReadTransactionId; var cachedSystemInfoCopy = CachedSystemInfo; if (currentSystemHash != cachedSystemInfoCopy.Hash || cachedSystemInfoCopy.NextDiskSpaceCheck < SystemTime.UtcNow) { var systemInfo = new SystemInfoCache() { Hash = currentSystemHash, NextDiskSpaceCheck = SystemTime.UtcNow.AddSeconds(30), MountPoints = new List <Client.ServerWide.Operations.MountPointUsage>() }; // Get new data var systemEnv = new StorageEnvironmentWithType("<System>", StorageEnvironmentWithType.StorageEnvironmentType.System, serverStore._env); var systemMountPoints = ServerStore.GetMountPointUsageDetailsFor(systemEnv, includeTempBuffers: true); foreach (var systemPoint in systemMountPoints) { UpdateMountPoint(serverStore.Configuration.Storage, systemPoint, "<System>", drivesUsage); systemInfo.MountPoints.Add(systemPoint); } // Update the cache Interlocked.Exchange(ref CachedSystemInfo, systemInfo); } else { // Use existing data foreach (var systemPoint in cachedSystemInfoCopy.MountPoints) { UpdateMountPoint(serverStore.Configuration.Storage, systemPoint, "<System>", drivesUsage); } } } } yield return(databasesInfo); yield return(databasesOngoingTasksInfo); yield return(indexingSpeed); yield return(trafficWatch); yield return(drivesUsage); }
/// <summary> /// Convert object to DynamicJsonValue but using provided filter /// Return null when filter matches nothing - such message will be skipped /// </summary> public abstract DynamicJsonValue ToJsonWithFilter(CanAccessDatabase filter);