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 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); } } }
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)) { await 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; await using (var entryStream = entry.Open()) await using (var writer = new AsyncBlittableJsonTextWriter(context, entryStream)) { using (var endpointOutput = await localEndpointClient.InvokeAndReadObjectAsync(route, context, endpointParameters)) { context.Write(writer, endpointOutput); await writer.FlushAsync(); await entryStream.FlushAsync(); } } } catch (Exception e) { await DebugInfoPackageUtils.WriteExceptionAsZipEntryAsync(e, archive, entryName.Replace(".json", string.Empty)); } } } ms.Position = 0; await ms.CopyToAsync(ResponseBodyStream()); } } }
internal static async Task InvokeAndWriteToArchive(ZipArchive archive, JsonOperationContext jsonOperationContext, LocalEndpointClient localEndpointClient, RouteInformation route, string path, Dictionary <string, Microsoft.Extensions.Primitives.StringValues> endpointParameters = null, CancellationToken token = default) { try { var response = await localEndpointClient.InvokeAsync(route, endpointParameters); var entryName = DebugInfoPackageUtils.GetOutputPathFromRouteInformation(route, path, response.ContentType == "text/plain" ? "txt" : "json"); var entry = archive.CreateEntry(entryName); entry.ExternalAttributes = ((int)(FilePermissions.S_IRUSR | FilePermissions.S_IWUSR)) << 16; using (var entryStream = entry.Open()) { if (response.ContentType == "text/plain") { await response.Body.CopyToAsync(entryStream, token); } else { await using (var writer = new AsyncBlittableJsonTextWriter(jsonOperationContext, entryStream)) { var endpointOutput = await jsonOperationContext.ReadForMemoryAsync(response.Body, $"read/local endpoint/{route.Path}"); jsonOperationContext.Write(writer, endpointOutput); await writer.FlushAsync(); } } await entryStream.FlushAsync(token); } } catch (OperationCanceledException) { throw; } catch (Exception e) { //precaution, ideally this exception should never be thrown if (e is InvalidStartOfObjectException) { e = new InvalidOperationException("Expected to find a blittable object as a result of debug endpoint, but found something else (see inner exception for details). This should be investigated as all RavenDB endpoints are supposed to return an object.", e); } await DebugInfoPackageUtils.WriteExceptionAsZipEntryAsync(e, archive, DebugInfoPackageUtils.GetOutputPathFromRouteInformation(route, path, null)); } }
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()); } } }
private async Task WriteDatabaseRecord(ZipArchive archive, string databaseName, JsonOperationContext jsonOperationContext, TransactionOperationContext transactionCtx, CancellationToken token = default) { var entryName = DebugInfoPackageUtils.GetOutputPathFromRouteInformation("/database-record", databaseName, "json"); try { var entry = archive.CreateEntry(entryName); entry.ExternalAttributes = ((int)(FilePermissions.S_IRUSR | FilePermissions.S_IWUSR)) << 16; await using (var entryStream = entry.Open()) await using (var writer = new AsyncBlittableJsonTextWriter(jsonOperationContext, entryStream)) { jsonOperationContext.Write(writer, GetDatabaseRecordForDebugPackage(transactionCtx, databaseName)); await writer.FlushAsync(); await entryStream.FlushAsync(token); } } catch (Exception e) { await DebugInfoPackageUtils.WriteExceptionAsZipEntryAsync(e, archive, entryName); } }
private string GetFileNameWithoutExtension(RouteInformation route, string prefixFolder) { return(DebugInfoPackageUtils.GetOutputPathFromRouteInformation(route, prefixFolder, null)); }