public async Task GetClusterWideInfoPackageForRemote()
        {
            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);
                                NodeDebugInfoRequestHeader requestHeader;
                                using (var requestHeaderJson =
                                           await transactionOperationContext.ReadForMemoryAsync(HttpContext.Request.Body, "remote-cluster-info-package/read request header"))
                                {
                                    requestHeader = JsonDeserializationServer.NodeDebugInfoRequestHeader(requestHeaderJson);
                                }

                                await WriteServerWide(archive, jsonOperationContext, localEndpointClient, _serverWidePrefix);

                                foreach (var databaseName in requestHeader.DatabaseNames)
                                {
                                    await WriteForDatabase(archive, jsonOperationContext, localEndpointClient, databaseName);
                                }
                            }

                            ms.Position = 0;
                            await ms.CopyToAsync(ResponseBodyStream());
                        }
                    }
        }
Ejemplo n.º 2
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 routes = DebugInfoPackageUtils.GetAuthorizedRoutes(Server, HttpContext, Database.Name)
                                     .Where(x => x.TypeOfRoute == RouteInformation.RouteType.Databases);

                        foreach (var route in routes)
                        {
                            await ServerWideDebugInfoPackageHandler.InvokeAndWriteToArchive(archive, context, localEndpointClient, route, null, endpointParameters);
                        }
                    }

                    ms.Position = 0;
                    await ms.CopyToAsync(ResponseBodyStream());
                }
            }
        }
Ejemplo n.º 3
0
        public async Task GetInfoPackage()
        {
            var contentDisposition = $"attachment; filename={DateTime.UtcNow:yyyy-MM-dd H:mm:ss} - Node [{ServerStore.NodeTag}].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 current server only", Operations.Operations.OperationType.DebugPackage, async _ =>
            {
                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);
                            await WriteServerWide(archive, context, localEndpointClient, _serverWidePrefix);
                            await WriteForAllLocalDatabases(archive, context, localEndpointClient);
                            await WriteLogFile(archive);
                        }

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

                return(null);
            }, operationId, token : token);
        }
Ejemplo n.º 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());
                }
            }
        }
        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());
                }
            }
        }
Ejemplo n.º 6
0
        public async Task GetInfoPackage()
        {
            var contentDisposition = $"attachment; filename={DateTime.UtcNow:yyyy-MM-dd H:mm:ss} - Node [{ServerStore.NodeTag}].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);
                        await WriteServerWide(archive, context, localEndpointClient);
                        await WriteForAllLocalDatabases(archive, context, localEndpointClient);
                    }

                    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());
                        }
                    }
        }
        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 WriteForAllLocalDatabases(ZipArchive archive, JsonOperationContext jsonOperationContext, LocalEndpointClient localEndpointClient, string prefix = null)
        {
            using (ServerStore.ContextPool.AllocateOperationContext(out TransactionOperationContext transactionOperationContext))
                using (transactionOperationContext.OpenReadTransaction())
                {
                    foreach (var databaseName in ServerStore.Cluster.GetDatabaseNames(transactionOperationContext))
                    {
                        using (var rawRecord = ServerStore.Cluster.ReadRawDatabaseRecord(transactionOperationContext, databaseName))
                        {
                            if (rawRecord == null ||
                                rawRecord.Topology.RelevantFor(ServerStore.NodeTag) == false ||
                                rawRecord.IsDisabled ||
                                rawRecord.DatabaseState == DatabaseStateStatus.RestoreInProgress ||
                                IsDatabaseBeingDeleted(ServerStore.NodeTag, rawRecord))
                            {
                                continue;
                            }
                        }

                        var path = !string.IsNullOrWhiteSpace(prefix) ? Path.Combine(prefix, databaseName) : databaseName;
                        await WriteForDatabase(archive, jsonOperationContext, localEndpointClient, databaseName, path);
                    }
                }
        }
        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);
                }
            }
        }
        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));
            }
        }
        private async Task WriteForServerOrDatabase(ZipArchive archive, JsonOperationContext context, LocalEndpointClient localEndpointClient,
                                                    RouteInformation.RouteType routeType, string path, string databaseName,
                                                    Dictionary <string, Microsoft.Extensions.Primitives.StringValues> endpointParameters = null,
                                                    CancellationToken token = default)
        {
            var debugInfoDict = new Dictionary <string, TimeSpan>();

            token.ThrowIfCancellationRequested();

            var routes = DebugInfoPackageUtils.GetAuthorizedRoutes(Server, HttpContext, databaseName).Where(x => x.TypeOfRoute == routeType);

            var id = Guid.NewGuid();

            if (_logger.IsOperationsEnabled)
            {
                _logger.Operations($"Creating Debug Package '{id}' for '{databaseName ?? "Server"}'.");
            }


            foreach (var route in routes)
            {
                Exception ex = null;
                var       sw = Stopwatch.StartNew();

                if (_logger.IsOperationsEnabled)
                {
                    _logger.Operations($"Started gathering debug info from '{route.Path}' for Debug Package '{id}'.");
                }

                try
                {
                    using (var operationToken = new CancellationTokenSource(TimeSpan.FromMinutes(5)))
                        using (var mergedToken = CancellationTokenSource.CreateLinkedTokenSource(operationToken.Token, token))
                        {
                            await InvokeAndWriteToArchive(archive, context, localEndpointClient, route, path, endpointParameters, mergedToken.Token);

                            debugInfoDict[route.Path] = sw.Elapsed;
                        }
                }
                catch (Exception e)
                {
                    ex = e;
                }
                finally
                {
                    if (_logger.IsOperationsEnabled)
                    {
                        _logger.Operations($"Finished gathering debug info from '{route.Path}' for Debug Package '{id}'. Took: {(int)sw.Elapsed.TotalMilliseconds} ms", ex);
                    }
                }
            }

            await DebugInfoPackageUtils.WriteDebugInfoTimesAsZipEntryAsync(debugInfoDict, archive, databaseName);
        }
 private async Task WriteServerInfo(ZipArchive archive, JsonOperationContext jsonOperationContext, LocalEndpointClient localEndpointClient, CancellationToken token = default)
 {
     await WriteForServerOrDatabase(archive, jsonOperationContext, localEndpointClient, RouteInformation.RouteType.None, _serverWidePrefix, null, null, token);
 }
        private async Task WriteDatabaseInfo(ZipArchive archive, JsonOperationContext jsonOperationContext, LocalEndpointClient localEndpointClient,
                                             string databaseName, CancellationToken token = default)
        {
            var endpointParameters = new Dictionary <string, Microsoft.Extensions.Primitives.StringValues>()
            {
                { "database", new Microsoft.Extensions.Primitives.StringValues(databaseName) }
            };

            await WriteForServerOrDatabase(archive, jsonOperationContext, localEndpointClient, RouteInformation.RouteType.Databases, databaseName, databaseName, endpointParameters, token);
        }
        private async Task WriteForAllLocalDatabases(ZipArchive archive, JsonOperationContext jsonOperationContext, LocalEndpointClient localEndpointClient, CancellationToken token = default)
        {
            token.ThrowIfCancellationRequested();

            using (ServerStore.ContextPool.AllocateOperationContext(out TransactionOperationContext context))
                using (context.OpenReadTransaction())
                {
                    foreach (var databaseName in ServerStore.Cluster.GetDatabaseNames(context))
                    {
                        token.ThrowIfCancellationRequested();

                        using (var rawRecord = ServerStore.Cluster.ReadRawDatabaseRecord(context, databaseName))
                        {
                            if (rawRecord == null ||
                                rawRecord.Topology.RelevantFor(ServerStore.NodeTag) == false)
                            {
                                continue;
                            }

                            await WriteDatabaseRecord(archive, databaseName, jsonOperationContext, context, token);

                            if (rawRecord.IsDisabled ||
                                rawRecord.DatabaseState == DatabaseStateStatus.RestoreInProgress ||
                                IsDatabaseBeingDeleted(ServerStore.NodeTag, rawRecord))
                            {
                                continue;
                            }

                            await WriteDatabaseInfo(archive, jsonOperationContext, localEndpointClient, databaseName, token);
                        }
                    }
                }
        }