/// <summary> /// Verify the message for the checksum and build ids. Dispatch a mismatch exception if checksum or build id does not match /// </summary> internal bool Verify <TFrom, TTo>(Request <TFrom, TTo> request, string senderBuildId) where TFrom : IBondSerializable, new() where TTo : IBondSerializable, new() { if (!string.Equals(BuildId, senderBuildId, StringComparison.OrdinalIgnoreCase)) { request.DispatchException(new BuildXLException(I($"{BuildIdMismatchExceptionMessage}: Self={BuildId}, Sender={senderBuildId}"))); return(false); } var message = request.Message; uint expectedChecksum = message.GetChecksum(); uint computedChecksum = ComputeChecksum(message, out var size); Counters.AddToCounter(DistributionCounter.ReceivedMessageSizeBytes, size); if (expectedChecksum != computedChecksum) { Counters.IncrementCounter(DistributionCounter.ServerChecksumMismatchCount); request.DispatchException(new BuildXLException(ChecksumMismatchExceptionMessage)); return(false); } return(true); }
public void EnumCounters() { var collection = new CounterCollection <TestCounters>(); XAssert.IsTrue(CounterCollection <TestCounters> .IsStopwatch(TestCounters.SomeTime)); XAssert.IsFalse(CounterCollection <TestCounters> .IsStopwatch(TestCounters.SomeCount)); // Increase the time using (collection.StartStopwatch(TestCounters.SomeTime)) { Thread.Sleep(1); } TimeSpan elapsed = collection.GetElapsedTime(TestCounters.SomeTime); XAssert.IsTrue(elapsed.Ticks > 0); XAssert.AreEqual <long>(0, collection.GetCounterValue(TestCounters.SomeCount)); collection.AddToCounter(TestCounters.SomeCount, 2); XAssert.AreEqual(elapsed, collection.GetElapsedTime(TestCounters.SomeTime)); XAssert.AreEqual <long>(2, collection.GetCounterValue(TestCounters.SomeCount)); TimeSpan delta = new TimeSpan(100); collection.AddToCounter(TestCounters.SomeTime, delta); TimeSpan newElapsed = collection.GetElapsedTime(TestCounters.SomeTime); // note: must not check if `newElapsed == elapsed.Add(delta)` because // `AddToCounter(); GetElapsedTime()` is lossy due to float-point arithmetic XAssert.IsTrue(newElapsed > elapsed); }
/// <summary> /// Stores cache descriptor metadata for pip /// </summary> public virtual async Task <Possible <ContentHash> > TryStoreMetadataAsync(PipCacheDescriptorV2Metadata metadata) { BoxRef <long> metadataSize = new BoxRef <long>(); var result = await ArtifactContentCache.TrySerializeAndStoreContent(metadata.ToEntry(), metadataSize); if (result.Succeeded) { Counters.IncrementCounter(PipCachingCounter.StoredMetadataCount); Counters.AddToCounter(PipCachingCounter.StoredMetadataSize, metadataSize.Value); } return(result); }
public void TestAverage() { var clock = new MemoryClock(); var activityTracker = new ActivityTracker <MyCounters>(clock, TimeSpan.FromSeconds(10)); var collection = new CounterCollection <MyCounters>(); // Initial rates are (total: 0, ratePerSecond: 0) Dictionary <MyCounters, (long total, double ratePerSecond)> rates = activityTracker.GetRates(); rates[MyCounters.Value1].Should().Be((0, 0)); rates[MyCounters.Value2].Should().Be((0, 0)); clock.AddSeconds(1); collection.AddToCounter(MyCounters.Value1, 1); collection.AddToCounter(MyCounters.Value2, 2); activityTracker.ProcessSnapshot(collection); rates = activityTracker.GetRates(); // Totals should be changed, but the rates are still 0. We don't have enough data. rates[MyCounters.Value1].Should().Be((1, 0)); rates[MyCounters.Value2].Should().Be((2, 0)); clock.AddSeconds(1); collection.AddToCounter(MyCounters.Value1, 1); collection.AddToCounter(MyCounters.Value2, 2); activityTracker.ProcessSnapshot(collection); rates = activityTracker.GetRates(); rates[MyCounters.Value1].Should().Be((2, 1)); rates[MyCounters.Value2].Should().Be((4, 2)); // Moving the time to the end of the window clock.AddSeconds(9); collection.AddToCounter(MyCounters.Value1, 2); collection.AddToCounter(MyCounters.Value2, 4); activityTracker.ProcessSnapshot(collection); rates = activityTracker.GetRates(); rates[MyCounters.Value1].Should().Be((4, 0.3)); rates[MyCounters.Value2].Should().Be((8, 0.6)); // Move even further, should have only one record in the window. clock.AddSeconds(3); rates = activityTracker.GetRates(); rates[MyCounters.Value1].Should().Be((4, 0)); rates[MyCounters.Value2].Should().Be((8, 0)); clock.AddSeconds(2); // 5 seconds since the last snapshot collection.AddToCounter(MyCounters.Value1, 5); collection.AddToCounter(MyCounters.Value2, 10); activityTracker.ProcessSnapshot(collection); rates = activityTracker.GetRates(); rates[MyCounters.Value1].Should().Be((9, 1)); rates[MyCounters.Value2].Should().Be((18, 2)); }
private async Task <IIpcResult> ParseAndExecuteCommandAsync(int id, IIpcOperation operation) { string cmdLine = operation.Payload; m_logger.Verbose($"Command received. Request #{id}, CommandLine: {cmdLine}"); ConfiguredCommand conf; using (m_counters.StartStopwatch(DaemonCounter.ParseArgsDuration)) { conf = ParseArgs(cmdLine, m_parser); } IIpcResult result; using (var duration = m_counters.StartStopwatch(DaemonCounter.ServerActionDuration)) { result = await conf.Command.ServerAction(conf, this); result.ActionDuration = duration.Elapsed; } TimeSpan queueDuration = operation.Timestamp.Daemon_BeforeExecuteTime - operation.Timestamp.Daemon_AfterReceivedTime; m_counters.AddToCounter(DaemonCounter.QueueDurationMs, (long)queueDuration.TotalMilliseconds); return(result); }
public static CounterCollection <TEnum> operator +(CounterCollection <TEnum> x, CounterCollection <TEnum> y) { var result = new CounterCollection <TEnum>(); foreach (var value in EnumTraits <TEnum> .EnumerateValues()) { if (IsStopwatch(value)) { result.AddToCounter(value, x.GetElapsedTime(value) + y.GetElapsedTime(value)); } result.AddToCounter(value, x.GetCounterValue(value) + y.GetCounterValue(value)); } return(result); }
/// <inheritdoc /> public async Task <AddDebugEntryResult> AddFileAsync(SymbolFile symbolFile) { Contract.Requires(symbolFile.IsIndexed, "File has not been indexed."); m_counters.IncrementCounter(SymbolClientCounter.NumAddFileRequests); if (symbolFile.DebugEntries.Count == 0) { // If there are no debug entries, ask bxl to log a message and return early. Analysis.IgnoreResult(await m_apiClient.LogMessage(I($"File '{symbolFile.FullFilePath}' does not contain symbols and will not be added to '{RequestName}'."), isWarning: false)); m_counters.IncrementCounter(SymbolClientCounter.NumFilesWithoutDebugEntries); return(AddDebugEntryResult.NoSymbolData); } await EnsureRequestIdAndDomainIdAreInitalizedAsync(); List <DebugEntry> result; using (m_counters.StartStopwatch(SymbolClientCounter.TotalAssociateTime)) { try { result = await m_symbolClient.CreateRequestDebugEntriesAsync( RequestId, symbolFile.DebugEntries.Select(e => CreateDebugEntry(e, m_domainId)), // First, we create debug entries with ThrowIfExists behavior not to silence the collision errors. DebugEntryCreateBehavior.ThrowIfExists, CancellationToken); } catch (DebugEntryExistsException) { string message = $"[SymbolDaemon] File: '{symbolFile.FullFilePath}' caused collision. " + (m_debugEntryCreateBehavior == DebugEntryCreateBehavior.ThrowIfExists ? string.Empty : $"SymbolDaemon will retry creating debug entry with {m_debugEntryCreateBehavior} behavior"); if (m_debugEntryCreateBehavior == DebugEntryCreateBehavior.ThrowIfExists) { // Log an error message in SymbolDaemon log file m_logger.Error(message); throw new DebugEntryExistsException(message); } // Log a message in SymbolDaemon log file m_logger.Verbose(message); result = await m_symbolClient.CreateRequestDebugEntriesAsync( RequestId, symbolFile.DebugEntries.Select(e => CreateDebugEntry(e, m_domainId)), m_debugEntryCreateBehavior, CancellationToken); } } var entriesWithMissingBlobs = result.Where(e => e.Status == DebugEntryStatus.BlobMissing).ToList(); if (entriesWithMissingBlobs.Count > 0) { // All the entries are based on the same file, so we need to call upload only once. // make sure that the file is on disk (it might not be on disk if we got DebugEntries from cache/metadata file) var file = await symbolFile.EnsureMaterializedAsync(); BlobIdentifierWithBlocks uploadResult; using (m_counters.StartStopwatch(SymbolClientCounter.TotalUploadTime)) { uploadResult = await m_symbolClient.UploadFileAsync( m_domainId, // uploading to the location set by the symbol service entriesWithMissingBlobs[0].BlobUri, RequestId, symbolFile.FullFilePath, entriesWithMissingBlobs[0].BlobIdentifier, CancellationToken); } m_counters.IncrementCounter(SymbolClientCounter.NumFilesUploaded); m_counters.AddToCounter(SymbolClientCounter.TotalUploadSize, file.Length); m_logger.Info($"File: '{symbolFile.FullFilePath}' -- upload result: {uploadResult}"); entriesWithMissingBlobs.ForEach(entry => entry.BlobDetails = uploadResult); using (m_counters.StartStopwatch(SymbolClientCounter.TotalAssociateAfterUploadTime)) { entriesWithMissingBlobs = await m_symbolClient.CreateRequestDebugEntriesAsync( RequestId, entriesWithMissingBlobs, m_debugEntryCreateBehavior, CancellationToken); } Contract.Assert(entriesWithMissingBlobs.All(e => e.Status != DebugEntryStatus.BlobMissing), "Entries with non-success code are present."); return(AddDebugEntryResult.UploadedAndAssociated); } m_counters.IncrementCounter(SymbolClientCounter.NumFilesAssociated); return(AddDebugEntryResult.Associated); }
public void UpdateCounters(CounterCollection <FileContentTableCounters> counters) { counters.AddToCounter(FileContentTableCounters.NumUpdatedUsnEntriesByJournalScanning, UpdatedUsnEntryByJournalScanningCount); counters.AddToCounter(FileContentTableCounters.NumRemovedEntriesByJournalScanning, RemovedEntryByJournalScanningCount); }
/// <summary> /// Logs a process sub phase and ensures the time is recored in the Counters /// </summary> public static void LogSubPhaseDuration(LoggingContext context, Pip pip, SandboxedProcessCounters counter, TimeSpan duration, string extraInfo = "") { Counters.AddToCounter(counter, duration); Logger.Log.LogPhaseDuration(context, pip.FormattedSemiStableHash, counter.ToString(), duration.ToString(), extraInfo); }
/// <summary> /// Takes a list of sealed directories, searches their contents for special manifest files, parses each of them to obtain /// a list of files to materialize, and finally requests from BuildXL's ApiServer to materialize them. /// </summary> private async Task <IIpcResult> RegisterManifestInternalAsync(ConfiguredCommand conf) { m_counters.IncrementCounter(MaterializationDaemonCounter.RegisterManifestRequestCount); var directoryPaths = Directory.GetValues(conf.Config).ToArray(); var directoryIds = DirectoryId.GetValues(conf.Config).ToArray(); var directoryFilters = DirectoryContentFilter.GetValues(conf.Config).ToArray(); if (directoryPaths.Length != directoryIds.Length || directoryPaths.Length != directoryFilters.Length) { return(new IpcResult( IpcResultStatus.GenericError, I($"Directory counts don't match: #directories = {directoryPaths.Length}, #directoryIds = {directoryIds.Length}, #directoryFilters = {directoryFilters.Length}"))); } if (ApiClient == null) { return(new IpcResult(IpcResultStatus.GenericError, "ApiClient is not initialized")); } var possibleFilters = InitializeFilters(directoryFilters); if (!possibleFilters.Succeeded) { return(new IpcResult(IpcResultStatus.ExecutionError, possibleFilters.Failure.Describe())); } var initializedFilters = possibleFilters.Result; var possibleManifestFiles = await GetUniqueFilteredDirectoryContentAsync(directoryPaths, directoryIds, initializedFilters); if (!possibleManifestFiles.Succeeded) { return(new IpcResult(IpcResultStatus.ExecutionError, possibleManifestFiles.Failure.Describe())); } var manifestFiles = possibleManifestFiles.Result; var sw = Stopwatch.StartNew(); List <string> filesToMaterialize = null; try { // ensure that the manifest files are actually present on disk using (m_counters.StartStopwatch(MaterializationDaemonCounter.RegisterManifestFileMaterializationDuration)) { await m_actionQueue.ForEachAsync( manifestFiles, async (manifest, i) => { m_counters.AddToCounter(MaterializationDaemonCounter.RegisterManifestFileMaterializationQueueDuration, sw.ElapsedMilliseconds); await MaterializeFileAsync(manifest.Artifact, manifest.FileName, ignoreMaterializationFailures: false); }); } Possible <List <string> > possibleFiles; using (m_counters.StartStopwatch(MaterializationDaemonCounter.ManifestParsingOuterDuration)) { m_counters.AddToCounter(MaterializationDaemonCounter.ManifestParsingTotalFiles, possibleManifestFiles.Result.Count); possibleFiles = await ParseManifestFilesAsync(manifestFiles); if (!possibleFiles.Succeeded) { return(new IpcResult(IpcResultStatus.ExecutionError, possibleFiles.Failure.Describe())); } m_counters.AddToCounter(MaterializationDaemonCounter.ManifestParsingReferencedTotalFiles, possibleFiles.Result.Count); } filesToMaterialize = possibleFiles.Result; sw = Stopwatch.StartNew(); using (m_counters.StartStopwatch(MaterializationDaemonCounter.RegisterManifestReferencedFileMaterializationDuration)) { await m_actionQueue.ForEachAsync( filesToMaterialize, async (file, i) => { // Since these file paths are not real build artifacts (i.e., just strings constructed by a parser), // they might not be "known" to BuildXL, and because of that, BuildXL won't be able to materialize them. // Manifests are known to contain references to files that are not produced during a build, so we are // ignoring materialization failures for such files. We are doing this so we won't fail IPC pips and // a build could succeed. // If there are real materialization errors (e.g., cache failure), the daemon relies on BuildXL logging // the appropriate error events and failing the build. m_counters.AddToCounter(MaterializationDaemonCounter.RegisterManifestReferencedFileMaterializationQueueDuration, sw.ElapsedMilliseconds); await MaterializeFileAsync(FileArtifact.Invalid, file, ignoreMaterializationFailures: true); }); } } catch (Exception e) { return(new IpcResult( IpcResultStatus.GenericError, e.ToStringDemystified())); } // Note: we are not claiming here that all the files in filesToMaterialize were materialized cause we are ignoring materialization failures. // The real materialization status will be logged during execution of the Finalize command. return(IpcResult.Success( $"Processed paths ({filesToMaterialize.Count}):{Environment.NewLine}{string.Join(Environment.NewLine, filesToMaterialize)}")); }