private static DumpType MapDumpType(Models.DumpType dumpType) { switch (dumpType) { case Models.DumpType.Full: return(DumpType.Full); case Models.DumpType.WithHeap: return(DumpType.WithHeap); case Models.DumpType.Triage: return(DumpType.Triage); case Models.DumpType.Mini: return(DumpType.Normal); default: throw new ArgumentException( string.Format( CultureInfo.InvariantCulture, Strings.ErrorMessage_UnexpectedType, nameof(DumpType), dumpType), nameof(dumpType)); } }
public async Task <Stream> DumpAsync(IEndpointInfo endpointInfo, Models.DumpType mode, CancellationToken token) { if (endpointInfo == null) { throw new ArgumentNullException(nameof(endpointInfo)); } string dumpTempFolder = _storageOptions.CurrentValue.DumpTempFolder; // Ensure folder exists before issue command. if (!Directory.Exists(dumpTempFolder)) { Directory.CreateDirectory(dumpTempFolder); } string dumpFilePath = Path.Combine(dumpTempFolder, FormattableString.Invariant($"{Guid.NewGuid()}_{endpointInfo.ProcessId}")); DumpType dumpType = MapDumpType(mode); IDisposable operationRegistration = null; // Only track operation status for endpoints from a listening server because: // 1) Each process only ever has a single instance of an IEndpointInfo // 2) Only the listening server will query the dump service for the operation status of an endpoint. if (IsListenMode) { // This is a quick fix to prevent the polling algorithm in the ServerEndpointInfoSource // from removing IEndpointInfo instances when they don't respond in a timely manner to // a dump operation causing the runtime to temporarily be unresponsive. Long term, this // concept should be folded into RequestLimitTracker with registered endpoint information // and allowing to query the status of an endpoint for a given artifact. operationRegistration = _operationTrackerService.Register(endpointInfo); } try { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { // Get the process Process process = Process.GetProcessById(endpointInfo.ProcessId); await Dumper.CollectDumpAsync(process, dumpFilePath, dumpType); } else { var client = new DiagnosticsClient(endpointInfo.Endpoint); await client.WriteDumpAsync(dumpType, dumpFilePath, logDumpGeneration : false, token); } } finally { operationRegistration?.Dispose(); } return(new AutoDeleteFileStream(dumpFilePath)); }
public Task <ActionResult> CaptureDump( [FromQuery] int?pid = null, [FromQuery] Guid?uid = null, [FromQuery] string name = null, [FromQuery] Models.DumpType type = Models.DumpType.WithHeap, [FromQuery] string egressProvider = null) { ProcessKey?processKey = GetProcessKey(pid, uid, name); return(InvokeForProcess(async processInfo => { string dumpFileName = DumpUtilities.GenerateDumpFileName(); if (string.IsNullOrEmpty(egressProvider)) { Stream dumpStream = await _dumpService.DumpAsync(processInfo.EndpointInfo, type, HttpContext.RequestAborted); _logger.WrittenToHttpStream(); //Compression is done automatically by the response //Chunking is done because the result has no content-length return File(dumpStream, ContentTypes.ApplicationOctetStream, dumpFileName); } else { KeyValueLogScope scope = Utilities.CreateArtifactScope(Utilities.ArtifactType_Dump, processInfo.EndpointInfo); return await SendToEgress(new EgressOperation( token => _dumpService.DumpAsync(processInfo.EndpointInfo, type, token), egressProvider, dumpFileName, processInfo.EndpointInfo, ContentTypes.ApplicationOctetStream, scope), limitKey: Utilities.ArtifactType_Dump); } }, processKey, Utilities.ArtifactType_Dump)); }