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());
                        }
                    }
        }