/// <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);
        }
Exemple #2
0
        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);
        }
Exemple #3
0
        /// <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);
        }
Exemple #4
0
        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));
        }
Exemple #5
0
        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);
        }
Exemple #7
0
        /// <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);
        }
Exemple #8
0
 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);
 }
Exemple #10
0
        /// <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)}"));
        }