private static async Task WriteForDatabase(ZipArchive archive, JsonOperationContext jsonOperationContext, LocalEndpointClient localEndpointClient, string databaseName, string path = null) { var endpointParameters = new Dictionary <string, Microsoft.Extensions.Primitives.StringValues> { { "database", new Microsoft.Extensions.Primitives.StringValues(databaseName) } }; foreach (var route in DebugInfoPackageUtils.Routes.Where(x => x.TypeOfRoute == RouteInformation.RouteType.Databases)) { try { var entry = archive.CreateEntry(DebugInfoPackageUtils.GetOutputPathFromRouteInformation(route, path ?? databaseName)); entry.ExternalAttributes = ((int)(FilePermissions.S_IRUSR | FilePermissions.S_IWUSR)) << 16; using (var entryStream = entry.Open()) using (var writer = new BlittableJsonTextWriter(jsonOperationContext, entryStream)) { using (var endpointOutput = await localEndpointClient.InvokeAndReadObjectAsync(route, jsonOperationContext, endpointParameters)) { jsonOperationContext.Write(writer, endpointOutput); writer.Flush(); await entryStream.FlushAsync(); } } } catch (Exception e) { DebugInfoPackageUtils.WriteExceptionAsZipEntry(e, archive, path ?? databaseName); } } }
private async Task WriteServerWide(ZipArchive archive, JsonOperationContext context, LocalEndpointClient localEndpointClient, string prefix) { //theoretically this could be parallelized, //however ZipArchive allows only one archive entry to be open concurrently foreach (var route in DebugInfoPackageUtils.Routes.Where(x => x.TypeOfRoute == RouteInformation.RouteType.None)) { var entryRoute = DebugInfoPackageUtils.GetOutputPathFromRouteInformation(route, prefix); try { var entry = archive.CreateEntry(entryRoute); entry.ExternalAttributes = ((int)(FilePermissions.S_IRUSR | FilePermissions.S_IWUSR)) << 16; using (var entryStream = entry.Open()) using (var writer = new BlittableJsonTextWriter(context, entryStream)) using (var endpointOutput = await localEndpointClient.InvokeAndReadObjectAsync(route, context)) { context.Write(writer, endpointOutput); writer.Flush(); await entryStream.FlushAsync(); } } catch (Exception e) { DebugInfoPackageUtils.WriteExceptionAsZipEntry(e, archive, entryRoute); } } }
private static async Task WriteLogFile(ZipArchive archive) { var prefix = $"{_serverWidePrefix}/{DateTime.UtcNow:yyyy-MM-dd H:mm:ss}.txt"; try { var entry = archive.CreateEntry(prefix, CompressionLevel.Optimal); entry.ExternalAttributes = ((int)(FilePermissions.S_IRUSR | FilePermissions.S_IWUSR)) << 16; using (var entryStream = entry.Open()) { LoggingSource.Instance.AttachPipeSink(entryStream); await Task.Delay(15000); LoggingSource.Instance.DetachPipeSink(); await entryStream.FlushAsync(); } } catch (Exception e) { LoggingSource.Instance.DetachPipeSink(); DebugInfoPackageUtils.WriteExceptionAsZipEntry(e, archive, prefix); } }
public async Task GetInfoPackage() { var contentDisposition = $"attachment; filename={DateTime.UtcNow:yyyy-MM-dd H:mm:ss} - Database [{Database.Name}].zip"; HttpContext.Response.Headers["Content-Disposition"] = contentDisposition; using (ServerStore.ContextPool.AllocateOperationContext(out JsonOperationContext context)) { using (var ms = new MemoryStream()) { using (var archive = new ZipArchive(ms, ZipArchiveMode.Create, true)) { var localEndpointClient = new LocalEndpointClient(Server); var endpointParameters = new Dictionary <string, Microsoft.Extensions.Primitives.StringValues> { { "database", new Microsoft.Extensions.Primitives.StringValues(Database.Name) } }; var feature = HttpContext.Features.Get <IHttpAuthenticationFeature>() as RavenServer.AuthenticateConnection; Debug.Assert(feature != null); var routes = DebugInfoPackageUtils.GetAuthorizedRoutes(feature, Database.Name) .Where(x => x.TypeOfRoute == RouteInformation.RouteType.Databases); foreach (RouteInformation route in routes) { var entryName = DebugInfoPackageUtils.GetOutputPathFromRouteInformation(route, null); try { var entry = archive.CreateEntry(entryName); entry.ExternalAttributes = ((int)(FilePermissions.S_IRUSR | FilePermissions.S_IWUSR)) << 16; using (var entryStream = entry.Open()) using (var writer = new BlittableJsonTextWriter(context, entryStream)) { using (var endpointOutput = await localEndpointClient.InvokeAndReadObjectAsync(route, context, endpointParameters)) { context.Write(writer, endpointOutput); writer.Flush(); await entryStream.FlushAsync(); } } } catch (Exception e) { DebugInfoPackageUtils.WriteExceptionAsZipEntry(e, archive, entryName.Replace(".json", string.Empty)); } } } ms.Position = 0; await ms.CopyToAsync(ResponseBodyStream()); } } }
public async Task GetInfoPackage() { var contentDisposition = $"attachment; filename={DateTime.UtcNow:yyyy-MM-dd H:mm:ss} - Database [{Database.Name}].zip"; HttpContext.Response.Headers["Content-Disposition"] = contentDisposition; using (ServerStore.ContextPool.AllocateOperationContext(out JsonOperationContext context)) { using (var ms = new MemoryStream()) { using (var archive = new ZipArchive(ms, ZipArchiveMode.Create, true)) { var localEndpointClient = new LocalEndpointClient(Server); var endpointParameters = new Dictionary <string, StringValues> { { "database", new StringValues(Database.Name) } }; foreach (var route in DebugInfoPackageUtils.Routes.Where(x => x.TypeOfRoute == RouteInformation.RouteType.Databases)) { var entryName = DebugInfoPackageUtils.GetOutputPathFromRouteInformation(route, null); try { var entry = archive.CreateEntry(entryName); using (var entryStream = entry.Open()) using (var writer = new BlittableJsonTextWriter(context, entryStream)) { using (var endpointOutput = await localEndpointClient.InvokeAndReadObjectAsync(route, context, endpointParameters)) { context.Write(writer, endpointOutput); writer.Flush(); await entryStream.FlushAsync(); } } } catch (Exception e) { DebugInfoPackageUtils.WriteExceptionAsZipEntry(e, archive, entryName.Replace(".json", string.Empty)); } } } ms.Position = 0; await ms.CopyToAsync(ResponseBodyStream()); } } }
public async Task GetClusterWideInfoPackage() { var contentDisposition = $"attachment; filename={DateTime.UtcNow:yyyy-MM-dd H:mm:ss} Cluster Wide.zip"; HttpContext.Response.Headers["Content-Disposition"] = contentDisposition; using (ServerStore.ContextPool.AllocateOperationContext(out TransactionOperationContext transactionOperationContext)) using (ServerStore.ContextPool.AllocateOperationContext(out JsonOperationContext jsonOperationContext)) using (transactionOperationContext.OpenReadTransaction()) { using (var ms = new MemoryStream()) { using (var archive = new ZipArchive(ms, ZipArchiveMode.Create, true)) { var localEndpointClient = new LocalEndpointClient(Server); using (var localMemoryStream = new MemoryStream()) { //assuming that if the name tag is empty var nodeName = $"Node - [{ServerStore.NodeTag ?? "Empty node tag"}]"; using (var localArchive = new ZipArchive(localMemoryStream, ZipArchiveMode.Create, true)) { await WriteServerWide(localArchive, jsonOperationContext, localEndpointClient, _serverWidePrefix); await WriteForAllLocalDatabases(localArchive, jsonOperationContext, localEndpointClient); await WriteLogFile(localArchive); } localMemoryStream.Position = 0; var entry = archive.CreateEntry($"{nodeName}.zip"); entry.ExternalAttributes = ((int)(FilePermissions.S_IRUSR | FilePermissions.S_IWUSR)) << 16; using (var entryStream = entry.Open()) { localMemoryStream.CopyTo(entryStream); entryStream.Flush(); } } var databaseNames = ServerStore.Cluster.GetDatabaseNames(transactionOperationContext); var topology = ServerStore.GetClusterTopology(transactionOperationContext); //this means no databases are defined in the cluster //in this case just output server-wide endpoints from all cluster nodes if (databaseNames.Count == 0) { foreach (var tagWithUrl in topology.AllNodes) { if (tagWithUrl.Value.Contains(ServerStore.GetNodeHttpServerUrl())) { continue; } try { await WriteDebugInfoPackageForNodeAsync( jsonOperationContext, archive, tag : tagWithUrl.Key, url : tagWithUrl.Value, certificate : Server.Certificate.Certificate, databaseNames : null); } catch (Exception e) { var entryName = $"Node - [{tagWithUrl.Key}]"; DebugInfoPackageUtils.WriteExceptionAsZipEntry(e, archive, entryName); } } } else { var nodeUrlToDatabaseNames = CreateUrlToDatabaseNamesMapping(transactionOperationContext, databaseNames); foreach (var urlToDatabaseNamesMap in nodeUrlToDatabaseNames) { if (urlToDatabaseNamesMap.Key.Contains(ServerStore.GetNodeHttpServerUrl())) { continue; //skip writing local data, we do it separately } try { await WriteDebugInfoPackageForNodeAsync( jsonOperationContext, archive, tag : urlToDatabaseNamesMap.Value.Item2, url : urlToDatabaseNamesMap.Key, databaseNames : urlToDatabaseNamesMap.Value.Item1, certificate : Server.Certificate.Certificate); } catch (Exception e) { var entryName = $"Node - [{urlToDatabaseNamesMap.Value.Item2}]"; DebugInfoPackageUtils.WriteExceptionAsZipEntry(e, archive, entryName); } } } } ms.Position = 0; await ms.CopyToAsync(ResponseBodyStream()); } } }