10#include <boost/algorithm/string/replace.hpp>
11#include <boost/any.hpp>
12#include <boost/iterator/iterator_traits.hpp>
13#include <boost/type_index/type_index_facade.hpp>
22#include <unordered_map>
23#include <unordered_set>
28#include "sparta/report/Report.hpp"
29#include "sparta/utils/Utils.hpp"
30#include "sparta/report/format/BaseFormatter.hpp"
35#include "sparta/log/NotificationSource.hpp"
38 class SimulationConfiguration;
39 class ReportStatsCollector;
42namespace sparta::trigger {
43 class SkippedAnnotatorBase;
51 class FormatterFactory;
60 namespace statistics {
69 typedef std::unordered_map<std::string, boost::any> NamedExtensions;
70 typedef std::unordered_map<std::string, std::string> TriggerKeyValues;
71 typedef std::unordered_map<std::string, std::string> MetaDataKeyValues;
79 typedef std::pair<Report*, report::format::BaseFormatter*> inst_t;
86 std::set<const Report*> triggered_reports_;
96 std::set<const Report*> idle_reports_;
101 std::map<std::string, std::shared_ptr<report::format::BaseFormatter>> formatters_;
107 std::shared_ptr<statistics::ReportStatisticsArchive> report_archive_;
113 std::shared_ptr<statistics::StreamNode> streaming_stats_root_;
121 bool updateReportActiveState_(
const Report * r);
127 std::vector<inst_t> instantiations_;
134 const sparta::report::format::FormatterFactory* fact_;
151 class DescUpdateTracker {
153 void enable(
const Scheduler * scheduler);
154 bool checkIfDuplicateUpdate();
165 DescUpdateTracker update_tracker_;
171 std::shared_ptr<sparta::trigger::SkippedAnnotatorBase> skipped_annotator_;
176 bool report_stopped_ =
false;
182 bool enabled_ =
true;
191 std::string orig_dest_file_;
207 bool legacy_reports_enabled_ =
true;
214 bool uses_sprintf_notif_trigger_ =
false;
220 std::vector<std::string> sprintf_notif_trigger_dest_files_;
228 void sweepSimDbStats_();
236 void skipSimDbStats_();
340 const std::string& _def_file,
341 const std::string& _dest_file,
342 const std::string& _format=
"text");
384 return orig_dest_file_;
394 const std::string & dir);
411 report_stopped_ =
true;
418 auto comma_sep_files = [](
const std::vector<std::string>& dest_files)
420 std::ostringstream oss;
422 for (
const auto& s : dest_files)
434 auto _dest_files = sprintf_notif_trigger_dest_files_.empty() ?
435 (orig_dest_file_.empty() ?
dest_file : orig_dest_file_) :
436 comma_sep_files(sprintf_notif_trigger_dest_files_);
438 std::stringstream ss;
440 <<
"\" -> \"" << _dest_files <<
"\"";
442 ss <<
" (format=" <<
format <<
")";
470 std::ostream* out=
nullptr);
477 return instantiations_;
487 const std::vector<Report*> & pending_reports =
488 boost::any_cast<const std::vector<Report*>&>(iter->second);
490 return pending_reports;
504 std::unordered_set<Report*> all(pending.begin(), pending.end());
505 for (
const auto & cur : current) {
506 all.insert(cur.first);
508 return std::vector<Report*>(all.begin(), all.end());
526 legacy_reports_enabled_ =
false;
572 uses_sprintf_notif_trigger_ =
true;
580 return uses_sprintf_notif_trigger_;
633 const std::string& sim_name,
637 typedef std::vector<ReportDescriptor> ReportDescVec;
638 typedef std::vector<std::pair<std::string, std::string>> ReportYamlReplacements;
673 const std::string desc_name = getDescriptorName_(rd);
674 auto iter = indices_by_descriptor_name_.find(desc_name);
675 if (iter != indices_by_descriptor_name_.end()) {
678 if (rep_descs_.at(iter->second).isEnabled()) {
680 desc_name <<
"' already exists in this configuration";
683 indices_by_descriptor_name_[desc_name] = rep_descs_.size();
694 rep_descs_.push_back(rd);
695 rep_descs_.back().enabled_ =
true;
699 template <
class... Args>
707 for (
auto &rd : rep_descs_) {
715 for (
const auto & rep_desc : rep_descs_) {
716 if (rep_desc.isEnabled()) {
730 bool contains(
const std::string & desc_name)
const {
731 auto iter = indices_by_descriptor_name_.find(desc_name);
732 if (iter == indices_by_descriptor_name_.end()) {
735 const auto replaced_desc_name = replaceDotsWithUnderscores_(desc_name);
736 iter = indices_by_descriptor_name_.find(replaced_desc_name);
741 if (iter == indices_by_descriptor_name_.end()) {
747 return rep_descs_.at(iter->second).isEnabled();
752 auto idx = getDescriptorIndexByName_(desc_name);
753 return rep_descs_.at(idx);
765 std::vector<std::string> names;
766 for (
const auto & rd : indices_by_descriptor_name_) {
767 if (rep_descs_.at(rd.second).isEnabled()) {
768 names.push_back(rd.first);
775 std::deque<ReportDescriptor>::iterator
begin() {
776 return rep_descs_.begin();
780 std::deque<ReportDescriptor>::const_iterator
begin()
const {
781 return rep_descs_.cbegin();
785 std::deque<ReportDescriptor>::iterator
end() {
786 return rep_descs_.end();
790 std::deque<ReportDescriptor>::const_iterator
end()
const {
791 return rep_descs_.cend();
796 return replaceDotsWithUnderscores_(rd.
dest_file);
799 std::string replaceDotsWithUnderscores_(
const std::string & str)
const {
800 std::string replaced = str;
801 boost::replace_all(replaced,
".",
"_");
805 size_t getDescriptorIndexByName_(
const std::string & desc_name)
const {
806 auto iter = indices_by_descriptor_name_.find(desc_name);
807 if (iter == indices_by_descriptor_name_.end()) {
810 const auto replaced_desc_name = replaceDotsWithUnderscores_(desc_name);
811 iter = indices_by_descriptor_name_.find(replaced_desc_name);
814 if (iter == indices_by_descriptor_name_.end()) {
815 throw SpartaException(
816 "No descriptor named '") << desc_name <<
"' exists";
823 if (!rep_descs_.at(iter->second).isEnabled()) {
824 throw SpartaException(
"The descriptor named '") << desc_name
825 <<
"' has already been disabled";
830 std::deque<ReportDescriptor> rep_descs_;
831 std::unordered_map<std::string, size_t> indices_by_descriptor_name_;
893 void republishReportCollection_();
896 void finishPythonInteraction_();
899 void disallowChangesToDescriptors_();
912 bool allow_descriptor_changes_ =
true;
920 const std::string & replacements_yaml);
928 const std::string & def_file,
954 const std::string & def_file,
956 const ReportYamlReplacements & placeholder_key_value_pairs);
963 const std::string & def_string,
File that defines the Clock class.
Exception class for all of Sparta.
Basic Node framework in sparta device tree composite pattern.
File that defines a ValidValue.
TreeNode which represents the root ("top") of a device tree.
A class that lets you schedule events now and in the future.
Used to construct and throw a standard C++ exception. Inherits from std::exception.
Accepts a sprintf-style format string like "%s_%i.json" and uses the arguments given to postNotificat...
Node in a composite tree representing a sparta Tree item.
Configuration applicator class that is used for configuring a simulator's reports....
void addMemoryReportsFromYaml(const std::string &yaml_file)
const ReportDescriptorCollection * getDescriptors() const
Access the underlying report descriptors.
ReportDescriptorCollection * getDescriptors()
Access the underlying report descriptors.
void showAllReportDescriptorInfo()
Pretty print information about all app::ReportDescriptor's.
void serializeAllDescriptorsToYaml()
void addReportsFromYaml(const std::string &yaml_file)
void removeReportByName(const std::string &rd_name)
void addReport(const ReportDescriptor &rd)
Add one report descriptor to this collection.
This collection of ReportDescriptors is designed to never deallocate memory once it has been allocate...
std::vector< std::string > getAllDescriptorNames() const
bool contains(const std::string &desc_name) const
void removeDescriptorByName(const std::string &desc_name)
std::deque< ReportDescriptor >::const_iterator begin() const
Iterator access.
size_t size() const
Get the number of enabled descriptors in this collection.
ReportDescriptor & getDescriptorByName(const std::string &desc_name)
Access a descriptor by the app::ReportDescriptor's "dest_file".
std::deque< ReportDescriptor >::iterator end()
Iterator access.
std::deque< ReportDescriptor >::iterator begin()
Iterator access.
void push_back(const ReportDescriptor &rd)
Add one report descriptor to this collection.
std::deque< ReportDescriptor >::const_iterator end() const
Iterator access.
void emplace_back(Args &&... args)
Add one report descriptor to this collection.
bool empty() const
See if there are any enabled descriptors in this collection.
void clear()
Remove (disable) all descriptors from this collection.
Describes one or more report to instantiate.
~ReportDescriptor()
Destructor (note that triggered reports are automatically flushed)
MetaDataKeyValues header_metadata_
Metadata to include in report headers.
uint32_t getUsageCount() const
Returns the usage count (incremented by addInstantiation)
const std::string & getDescriptorDefFile() const
Getter for this descriptor's def_file, e.g. "simple_stats.yaml".
std::string format
Optional formatting string (how to write to the file). This is converted to lower-case at constructio...
std::vector< Report * > getAllInstantiations() const
Returns all report instantiations, including those already instantiated (no report start trigger) and...
std::string computeFilename(const Report *r, const std::string &sim_name, uint32_t idx) const
Computes the filename to which this reportdescriptor will be saved using any necessary variables in t...
uint32_t writeOutput(std::ostream *out=nullptr)
Saves all of the instantiations whose formatters do not support 'update' to their respective destinat...
bool configSimDbReports(app::ReportStatsCollector *collector)
Get ready for SimDB report collection.
void disableLegacyReports()
In MAP v2.1, we provide report systems for both legacy reports and SimDB-exported reports....
void capUpdatesToOncePerTick(const Scheduler *scheduler)
Instruct this descriptor to automatically ignore any "duplicate" updates that occur at the exact same...
report::format::BaseFormatter * addInstantiation(Report *r, Simulation *sim, std::ostream *out=nullptr)
Tracks a report instantiated based on this descriptor and allocates a new formatter for it....
const std::string & getDescriptorFormat() const
Getter for this descriptor's format, e.g. "json_reduced".
std::string dest_file
Destination filename to which report will be written. Later this will represent other types of destin...
uint32_t getNumWrites() const
Returns the number of writes done on this report descriptor's instantiated report formatters.
uint32_t getNumUpdates() const
Returns the number of updates done on this report descriptor's instantiated report formatters.
void teardown()
Called when the ReportRepository is shutting down.
std::vector< Report * > getPendingInstantiations() const
Returns a vector of reports that have not been instantiated yet, but will be when this report descrip...
static const char * GLOBAL_KEYWORD
Global search scope node keyword for report locations.
std::string name
The name of this report.
bool usesSprintfNotifTrigger() const
Returns whether this descriptor uses a 'sprintf-notif' trigger.
ReportDescriptor & operator=(const ReportDescriptor &)=default
Allow assignment.
std::string loc_pattern
Node location string (pattern) on which report should be generated. Typically "" or top.
ReportDescriptor(const std::string &_loc_pattern, const std::string &_def_file, const std::string &_dest_file, const std::string &_format="text")
Construct a report decsriptor.
void clearDestinationFiles(const Simulation &sim)
Clears all destination files that will be filled with instances of this report descriptor.
ReportDescriptor(const ReportDescriptor &)=default
Allow construction.
void disable()
Calling this method causes the simulation to skip this descriptor when it is setting up its reports....
const std::string & getDescriptorDestFile() const
Getter for this descriptor's dest_file, e.g. "out.json".
const std::string & getDescriptorOrigDestFile() const
This descriptor may have had its dest_file changed when the the Simulation::setupReports() method was...
bool isEnabled() const
See if this descriptor is enabled or not. Disabling a descriptor means that it will be filtered from ...
std::vector< inst_t > getInstantiations() const
Returns the vector of instantiated reports based on this descriptor.
NamedExtensions extensions_
Key-value extensions used by parsers to bind opaque report configurations to descriptors.
void setUsesSprintfNotifTrigger(SprintfNotificationSource *notif_src)
Marks this descriptor as using a 'sprintf-notif' trigger, meaning dest_file is a sprintf-style format...
static bool isValidFormatName(const std::string &format)
Determines if format is a valid name for formatter. This allows the command line parser to disregard ...
void skipOutput()
Let the descriptor know to skip over one update of data.
std::shared_ptr< statistics::ReportStatisticsArchive > logOutputValuesToArchive(const std::string &dir)
Tell the descriptor to send all of its writeOutput / updateOutput statistics values to a binary archi...
std::string def_file
Filename of report definition. If '@', auto generates reports with all counters and stats of loc_patt...
uint32_t writeOutput(const std::string &filename)
Overload used only by descriptors bound to a 'sprintf-notif' trigger. Writes all non-updatable instan...
std::shared_ptr< statistics::StreamNode > createRootStatisticsStream()
Create and return a StreamNode object that sits at the top of a tree hierarchy that describes the Rep...
const std::string & getDescriptorName() const
Getter for this report's name.
void ignoreFurtherUpdates()
Report descriptors may be triggered to stop early - ensure no further updates are written to disk.
std::string stringize() const
Represents this descriptor as a string.
const std::string & getDescriptorPattern() const
Getter for this descriptor's pattern, e.g. "_global".
void setSkippedAnnotator(std::shared_ptr< sparta::trigger::SkippedAnnotatorBase > annotator)
Give this descriptor a specific annotator subclass for printing skipped update information to reports...
uint32_t updateOutput(std::ostream *out=nullptr)
Updates all of the instantiations whose formatters support 'update', possibly by writing to the desti...
Configuration applicator class that is used for configuring a simulator. Works in conjunction with sp...
Class that is the "top level" or starting point for simulation.
This class coordinates live SPARTA simulations (source) with binary output archives (sink).
When a simulation is configured to stream its statistics values for asynchronous processing,...
Provides a wrapper around a value to ensure that the value is assigned.
Sparta Application framework.
ReportDescVec createDescriptorsFromFile(const std::string &def_file, TreeNode *context)
Given a multi-report definition YAML file, parse it out into individual descriptors,...
ReportYamlReplacements createReplacementsFromYaml(const std::string &replacements_yaml)
Parse a YAML file containing key-value pairs into a single ReportYamlReplacements data structure.
ReportDescVec createDescriptorsFromDefinitionString(const std::string &def_string, TreeNode *context)
Given a multi-report definition string, parse it out into individual descriptors.
ReportDescVec createDescriptorsFromFileWithPlaceholderReplacements(const std::string &def_file, TreeNode *context, const ReportYamlReplacements &placeholder_key_value_pairs)
This method is similar to "createDescriptorsFromFile()", except that it can be used for report yaml f...
Macros for handling exponential backoff.