public async Task PerformanceLive() { using (var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync()) { var indexes = GetIndexesToReportOn().ToArray(); var receiveBuffer = new ArraySegment <byte>(new byte[1024]); var receive = webSocket.ReceiveAsync(receiveBuffer, Database.DatabaseShutdown); using (var ms = new MemoryStream()) using (var collector = new LiveIndexingPerformanceCollector(Database, Database.DatabaseShutdown, indexes)) { // 1. Send data to webSocket without making UI wait upon openning webSocket await SendDataOrHeartbeatToWebSocket(receive, webSocket, collector, ms, 100); // 2. Send data to webSocket when available while (Database.DatabaseShutdown.IsCancellationRequested == false) { if (await SendDataOrHeartbeatToWebSocket(receive, webSocket, collector, ms, 4000) == false) { break; } } } } }
public async Task PerformanceLive() { using (var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync()) { var indexNames = GetIndexesToReportOn().Select(x => x.Name).ToList(); if (GetBoolValueQueryString("includeSideBySide", false) ?? false) { // user requested to track side by side indexes as well // add extra names to indexNames list var complementaryIndexes = new HashSet <string>(); foreach (var indexName in indexNames) { if (indexName.StartsWith(Constants.Documents.Indexing.SideBySideIndexNamePrefix, StringComparison.OrdinalIgnoreCase)) { complementaryIndexes.Add(indexName.Substring(Constants.Documents.Indexing.SideBySideIndexNamePrefix.Length)); } else { complementaryIndexes.Add(Constants.Documents.Indexing.SideBySideIndexNamePrefix + indexName); } } indexNames.AddRange(complementaryIndexes); } var receiveBuffer = new ArraySegment <byte>(new byte[1024]); var receive = webSocket.ReceiveAsync(receiveBuffer, Database.DatabaseShutdown); using (var ms = new MemoryStream()) using (var collector = new LiveIndexingPerformanceCollector(Database, indexNames)) { // 1. Send data to webSocket without making UI wait upon opening webSocket await collector.SendStatsOrHeartbeatToWebSocket(receive, webSocket, ContextPool, ms, 100); // 2. Send data to webSocket when available while (Database.DatabaseShutdown.IsCancellationRequested == false) { if (await collector.SendStatsOrHeartbeatToWebSocket(receive, webSocket, ContextPool, ms, 4000) == false) { break; } } } } }
public async Task CanObtainRecentIndexingPerformance() { using (var store = GetDocumentStore()) { store.Initialize(); new UsersByName().Execute(store); using (var session = store.OpenSession()) { session.Store(new User { Name = "First" }, "users/1"); session.Store(new User { Name = "Second" }, "users/2"); session.SaveChanges(); } WaitForIndexing(store); var database = await GetDocumentDatabaseInstanceFor(store); var index = database.IndexStore.GetIndex("Users/ByName"); var collector = new LiveIndexingPerformanceCollector(database, database.DatabaseShutdown, new[] { index }); var tuple = await collector.Stats.TryDequeueAsync(TimeSpan.FromSeconds(1)); Assert.True(tuple.Item1); var stats = tuple.Item2; Assert.Equal(1, stats.Count); var usersStats = stats[0]; Assert.Equal("Users/ByName", usersStats.Name); Assert.Equal(2, usersStats.Performance.Select(x => x.InputCount).Sum()); } }
private async Task <bool> SendDataOrHeartbeatToWebSocket(Task <WebSocketReceiveResult> receive, WebSocket webSocket, LiveIndexingPerformanceCollector collector, MemoryStream ms, int timeToWait) { if (receive.IsCompleted || webSocket.State != WebSocketState.Open) { return(false); } var tuple = await collector.Stats.TryDequeueAsync(TimeSpan.FromMilliseconds(timeToWait)); if (tuple.Item1 == false) { await webSocket.SendAsync(WebSocketHelper.Heartbeat, WebSocketMessageType.Text, true, Database.DatabaseShutdown); return(true); } ms.SetLength(0); using (ContextPool.AllocateOperationContext(out JsonOperationContext context)) using (var writer = new BlittableJsonTextWriter(context, ms)) { writer.WritePerformanceStats(context, tuple.Item2); } ms.TryGetBuffer(out ArraySegment <byte> bytes); await webSocket.SendAsync(bytes, WebSocketMessageType.Text, true, Database.DatabaseShutdown); return(true); }
public async Task CanObtainLiveIndexingPerformanceStats() { using (var store = GetDocumentStore()) { store.Initialize(); var database = await GetDocumentDatabaseInstanceFor(store); new UsersByName().Execute(store); var index = database.IndexStore.GetIndex("Users/ByName"); var collector = new LiveIndexingPerformanceCollector(database, database.DatabaseShutdown, new[] { index }); using (var session = store.OpenSession()) { session.Store(new User { Name = "First" }, "users/1"); session.Store(new User { Name = "Second" }, "users/2"); session.SaveChanges(); } WaitForIndexing(store); var dequeueCount = 0; var tuple = await collector.Stats.TryDequeueAsync(TimeSpan.FromSeconds(5)); Assert.True(tuple.Item1); dequeueCount++; var usersStats = tuple.Item2[0]; while (true) { if (usersStats.Performance.Select(x => x.InputCount).Sum() == 2) { break; } tuple = await collector.Stats.TryDequeueAsync(TimeSpan.FromSeconds(10)); dequeueCount++; if (tuple.Item1 == false) { break; } Assert.Equal(1, tuple.Item2.Count); usersStats = tuple.Item2[0]; } Assert.Equal("Users/ByName", usersStats.Name); var sum = usersStats.Performance.Select(x => x.InputCount).Sum(); Assert.True(sum == 2, $"Can\'t find indexing performance stats, after {dequeueCount} tries. Sum was: {sum}"); } }