Пример #1
0
        private static async Task WriteForDatabase(ZipArchive archive, JsonOperationContext context, 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;

                    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, path ?? databaseName);
                }
            }
        }
Пример #2
0
        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;

                    await using (var entryStream = entry.Open())
                        await using (var writer = new AsyncBlittableJsonTextWriter(context, entryStream))
                            using (var endpointOutput = await localEndpointClient.InvokeAndReadObjectAsync(route, context))
                            {
                                context.Write(writer, endpointOutput);
                                await writer.FlushAsync();

                                await entryStream.FlushAsync();
                            }
                }
                catch (Exception e)
                {
                    await DebugInfoPackageUtils.WriteExceptionAsZipEntryAsync(e, archive, entryRoute);
                }
            }
        }
Пример #3
0
        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;

                await 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();
                await DebugInfoPackageUtils.WriteExceptionAsZipEntryAsync(e, archive, prefix);
            }
        }
Пример #4
0
        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 GetClusterWideInfoPackage()
        {
            var contentDisposition = $"attachment; filename={DateTime.UtcNow:yyyy-MM-dd H:mm:ss} Cluster Wide.zip";

            HttpContext.Response.Headers["Content-Disposition"] = contentDisposition;
            HttpContext.Response.Headers["Content-Type"]        = "application/zip";

            var token       = CreateOperationToken();
            var operationId = GetLongQueryString("operationId", false) ?? ServerStore.Operations.GetNextOperationId();

            await ServerStore.Operations.AddOperation(null, "Created debug package for all cluster nodes", Operations.Operations.OperationType.DebugPackage, async _ =>
            {
                using (ServerStore.ContextPool.AllocateOperationContext(out TransactionOperationContext transactionOperationContext))
                    using (ServerStore.ContextPool.AllocateOperationContext(out JsonOperationContext jsonOperationContext))
                        using (transactionOperationContext.OpenReadTransaction())
                        {
                            await using (var ms = new MemoryStream())
                            {
                                using (var archive = new ZipArchive(ms, ZipArchiveMode.Create, true))
                                {
                                    var topology = ServerStore.GetClusterTopology(transactionOperationContext);

                                    foreach (var(tag, url) in topology.AllNodes)
                                    {
                                        try
                                        {
                                            await WriteDebugInfoPackageForNodeAsync(jsonOperationContext, archive, tag, url, Server.Certificate.Certificate);
                                        }
                                        catch (Exception e)
                                        {
                                            await DebugInfoPackageUtils.WriteExceptionAsZipEntryAsync(e, archive, $"Node - [{tag}]");
                                        }
                                    }
                                }

                                ms.Position = 0;
                                await ms.CopyToAsync(ResponseBodyStream(), token.Token);
                            }
                        }

                return(null);
            }, operationId, token : token);
        }
        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);
            }
        }
Пример #8
0
        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;
            HttpContext.Response.Headers["Content-Type"]        = "application/zip";

            var token       = CreateOperationToken();
            var operationId = GetLongQueryString("operationId", false) ?? ServerStore.Operations.GetNextOperationId();

            await ServerStore.Operations.AddOperation(null, "Created debug package for all cluster nodes", Operations.Operations.OperationType.DebugPackage, async _ =>
            {
                using (ServerStore.ContextPool.AllocateOperationContext(out TransactionOperationContext transactionOperationContext))
                    using (ServerStore.ContextPool.AllocateOperationContext(out JsonOperationContext jsonOperationContext))
                        using (transactionOperationContext.OpenReadTransaction())
                        {
                            await using (var ms = new MemoryStream())
                            {
                                using (var archive = new ZipArchive(ms, ZipArchiveMode.Create, true))
                                {
                                    var localEndpointClient = new LocalEndpointClient(Server);

                                    await 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;

                                        await using (var entryStream = entry.Open())
                                        {
                                            await localMemoryStream.CopyToAsync(entryStream);
                                            await entryStream.FlushAsync();
                                        }
                                    }

                                    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}]";
                                                await DebugInfoPackageUtils.WriteExceptionAsZipEntryAsync(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}]";
                                                await DebugInfoPackageUtils.WriteExceptionAsZipEntryAsync(e, archive, entryName);
                                            }
                                        }
                                    }
                                }

                                ms.Position = 0;
                                await ms.CopyToAsync(ResponseBodyStream());
                            }
                        }

                return(null);
            }, operationId, token : token);
        }