- Added possibility to send stream information and transient object into Message_Messenger. Message_Printer will process it if needed.
- Add Message_PrinterToReport to send messenger information into Message_Report.
- Extended Message_Report to collect hierarchical alerts, to be able to collect some metrics during alerts processing.
- Added Message_AlertExtended to prepare hierarchical alerts with custom attributes. One attribute for one alert.
- Added Message_CompositeAlerts class to handle a container of alerts.
- Added Message_Level to start a new hierarchical level by creating an instance, stop by destricting.
- Added Message_Attribute and inheritors to store custom information about alert like object, stream, shape, some metrics.
- Implement Message_AttributeAlert to collect start/stop information about active metrics of Message_Report. This kind of attribute is created if at least one metric is active in the report.
- Add Message_MetricType enumeration with possible kinds of metrics in report.
- Implement DumpJson for Message_Report to store all collected alerts into stream.
- Added draw commands for Message_Report, Message_Messenger.
// standard commands
// *****************************************************************
Draw::BasicCommands(theCommands);
+ Draw::MessageCommands(theCommands);
Draw::VariableCommands(theCommands);
Draw::UnitCommands(theCommands);
if (!Draw_Batch) Draw::GraphicCommands(theCommands);
//! Defines Draw basic commands
Standard_EXPORT static void BasicCommands (Draw_Interpretor& I);
+ //! Defines Draw message commands
+ Standard_EXPORT static void MessageCommands (Draw_Interpretor& I);
+
//! Defines Draw variables handling commands.
Standard_EXPORT static void VariableCommands (Draw_Interpretor& I);
void Draw::Commands (Draw_Interpretor& theCommands)
{
Draw::BasicCommands(theCommands);
+ Draw::MessageCommands(theCommands);
Draw::VariableCommands(theCommands);
Draw::GraphicCommands(theCommands);
Draw::PloadCommands(theCommands);
--- /dev/null
+// Copyright (c) 2020 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <Draw.hxx>
+#include <Draw_Printer.hxx>
+
+#include <Message.hxx>
+#include <Message_Messenger.hxx>
+#include <Message_PrinterOStream.hxx>
+#include <Message_PrinterSystemLog.hxx>
+#include <Message_PrinterToReport.hxx>
+#include <Message_Report.hxx>
+#include <NCollection_Shared.hxx>
+#include <Standard_Dump.hxx>
+
+//==============================================================================
+//function : printerType
+//purpose :
+//==============================================================================
+static Standard_Boolean printerType (const TCollection_AsciiString& theTypeName,
+ Handle(Standard_Type)& theType)
+{
+ if (theTypeName == "ostream")
+ {
+ theType = STANDARD_TYPE(Message_PrinterOStream);
+ return Standard_True;
+ }
+ else if (theTypeName == "systemlog")
+ {
+ theType = STANDARD_TYPE(Message_PrinterSystemLog);
+ return Standard_True;
+ }
+ else if (theTypeName == "report")
+ {
+ theType = STANDARD_TYPE(Message_PrinterToReport);
+ return Standard_True;
+ }
+ else if (theTypeName == "draw")
+ {
+ theType = STANDARD_TYPE(Draw_Printer);
+ return Standard_True;
+ }
+
+ return Standard_False;
+}
+
+//==============================================================================
+//function : createPrinter
+//purpose :
+//==============================================================================
+static Handle(Message_Printer) createPrinter (const Handle(Standard_Type)& theType, Draw_Interpretor& theDI)
+{
+ const TCollection_AsciiString aTypeName (theType->Name());
+ if (aTypeName == STANDARD_TYPE(Message_PrinterOStream)->Name())
+ {
+ return new Message_PrinterOStream();
+ }
+ else if (aTypeName == STANDARD_TYPE(Message_PrinterSystemLog)->Name())
+ {
+ return new Message_PrinterSystemLog ("draw_messages");
+ }
+ else if (aTypeName == STANDARD_TYPE(Message_PrinterToReport)->Name())
+ {
+ Handle(Message_PrinterToReport) aMessagePrinter = new Message_PrinterToReport();
+ const Handle(Message_Report)& aReport = Message::DefaultReport (Standard_True);
+ aMessagePrinter->SetReport (aReport);
+ return aMessagePrinter;
+ }
+ else if (aTypeName == STANDARD_TYPE(Draw_Printer)->Name())
+ {
+ return new Draw_Printer (theDI);
+ }
+ return Handle(Message_Printer)();
+}
+
+//==============================================================================
+//function : SendMessage
+//purpose :
+//==============================================================================
+static Standard_Integer SendMessage (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
+{
+ if (theArgNb < 2)
+ {
+ theDI << "Error: wrong number of arguments";
+ return 1;
+ }
+
+ const Handle(Message_Messenger)& aMessenger = Message::DefaultMessenger();
+ for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
+ {
+ TCollection_AsciiString anArg (theArgVec[anArgIter]);
+ anArg.LowerCase();
+ aMessenger->Send (anArg);
+ }
+
+ return 0;
+}
+
+//==============================================================================
+//function : PrintMessenger
+//purpose :
+//==============================================================================
+static Standard_Integer PrintMessenger (Draw_Interpretor& theDI, Standard_Integer, const char**)
+{
+ const Handle(Message_Messenger)& aMessenger = Message::DefaultMessenger();
+
+ Standard_SStream aSStream;
+ aMessenger->DumpJson (aSStream);
+ theDI << aSStream;
+ std::cout << aSStream.str() << std::endl;
+
+ return 0;
+}
+
+//==============================================================================
+//function : SetMessagePrinter
+//purpose :
+//==============================================================================
+static Standard_Integer SetMessagePrinter (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
+{
+ if (theArgNb < 2)
+ {
+ theDI << "Error: wrong number of arguments";
+ return 1;
+ }
+
+ Standard_Boolean toAddPrinter = Standard_True;
+ NCollection_List<TCollection_AsciiString> aPrinterTypes;
+ const Handle(Message_Messenger)& aMessenger = Message::DefaultMessenger();
+ for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
+ {
+ TCollection_AsciiString anArg (theArgVec[anArgIter]);
+ anArg.LowerCase();
+ if (anArg == "-state")
+ {
+ if (anArgIter + 1 < theArgNb
+ && Draw::ParseOnOff (theArgVec[anArgIter + 1], toAddPrinter))
+ {
+ ++anArgIter;
+ }
+ }
+ else if (anArg == "-type"
+ && anArgIter + 1 < theArgNb)
+ {
+ TCollection_AsciiString aVal (theArgVec[++anArgIter]);
+ aPrinterTypes.Append (aVal);
+ }
+ else
+ {
+ theDI << "Syntax error: unknown argument '" << theArgVec[anArgIter] << "'";
+ return 1;
+ }
+ }
+
+ for (NCollection_List<TCollection_AsciiString>::Iterator anIterator (aPrinterTypes); anIterator.More(); anIterator.Next())
+ {
+ Handle(Standard_Type) aPrinterType;
+ if (!printerType (anIterator.Value(), aPrinterType))
+ {
+ theDI << "Syntax error: unknown printer type '" << anIterator.Value() << "'";
+ return 1;
+ }
+
+ if (toAddPrinter)
+ {
+ Handle(Message_Printer) aPrinter = createPrinter (aPrinterType, theDI);
+ aMessenger->AddPrinter (aPrinter);
+ if (!Handle(Message_PrinterToReport)::DownCast(aPrinter).IsNull())
+ {
+ Message::DefaultReport (Standard_False)->UpdateActiveInMessenger();
+ }
+ }
+ else
+ {
+ aMessenger->RemovePrinters (aPrinterType);
+ }
+ }
+ return 0;
+}
+
+//==============================================================================
+//function : ClearReport
+//purpose :
+//==============================================================================
+static Standard_Integer ClearReport(Draw_Interpretor& theDI, Standard_Integer theArgNb, const char**)
+{
+ if (theArgNb < 1)
+ {
+ theDI << "Error: wrong number of arguments";
+ return 1;
+ }
+
+ const Handle(Message_Report)& aReport = Message::DefaultReport (Standard_False);
+ if (aReport.IsNull())
+ {
+ theDI << "Error: report is no created";
+ return 1;
+ }
+
+ aReport->Clear();
+ return 0;
+}
+
+//==============================================================================
+//function : SetReportMetric
+//purpose :
+//==============================================================================
+static Standard_Integer SetReportMetric(Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
+{
+ if (theArgNb < 1)
+ {
+ theDI << "Error: wrong number of arguments";
+ return 1;
+ }
+
+ const Handle(Message_Report)& aReport = Message::DefaultReport (Standard_True);
+ if (aReport.IsNull())
+ {
+ return 1;
+ }
+
+ aReport->ClearMetrics();
+ for (int i = 1; i < theArgNb; i++)
+ {
+ Standard_Integer aMetricId = Draw::Atoi (theArgVec[i]);
+ if (aMetricId < Message_MetricType_ThreadCPUUserTime || aMetricId > Message_MetricType_MemHeapUsage)
+ {
+ theDI << "Error: unrecognized message metric: " << aMetricId;
+ return 1;
+ }
+ aReport->SetActiveMetric ((Message_MetricType)aMetricId, Standard_True);
+ }
+ return 0;
+}
+
+//==============================================================================
+//function : CollectMetricMessages
+//purpose :
+//==============================================================================
+static Standard_Integer CollectMetricMessages(Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
+{
+ static Handle(NCollection_Shared<Message_Level>) MyLevel;
+
+ if (theArgNb < 1)
+ {
+ theDI << "Error: wrong number of arguments";
+ return 1;
+ }
+
+ Standard_Boolean toActivate = Standard_False;
+ for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
+ {
+ TCollection_AsciiString anArg (theArgVec[anArgIter]);
+ anArg.LowerCase();
+ if (anArg == "-activate")
+ {
+ if (anArgIter + 1 < theArgNb
+ && Draw::ParseOnOff (theArgVec[anArgIter + 1], toActivate))
+ {
+ ++anArgIter;
+ }
+ }
+ }
+ if (toActivate)
+ {
+ if (!MyLevel.IsNull())
+ {
+ theDI << "Error: collecting already activated";
+ return 1;
+ }
+ MyLevel = new NCollection_Shared<Message_Level>("Level");
+ }
+ else
+ {
+ if (!MyLevel)
+ {
+ theDI << "Error: collecting was not activated";
+ return 1;
+ }
+ MyLevel.Nullify();
+ MyLevel = 0;
+ }
+ return 0;
+}
+
+//==============================================================================
+//function : PrintReport
+//purpose :
+//==============================================================================
+static Standard_Integer PrintReport(Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
+{
+ if (theArgNb < 1)
+ {
+ theDI << "Error: wrong number of arguments";
+ return 1;
+ }
+
+ const Handle(Message_Report)& aReport = Message::DefaultReport (Standard_False);
+ if (aReport.IsNull())
+ {
+ theDI << "Error: report is no created";
+ return 1;
+ }
+
+ for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
+ {
+ TCollection_AsciiString anArgCase (theArgVec[anArgIter]);
+ anArgCase.LowerCase();
+ if (anArgCase == "-messenger")
+ {
+ aReport->SendMessages (Message::DefaultMessenger());
+ }
+ else if (anArgCase == "-dump"
+ || anArgCase == "-print")
+ {
+ Standard_SStream aSStream;
+ aReport->Dump (aSStream);
+ theDI << aSStream;
+ }
+ else if (anArgCase == "-dumpjson")
+ {
+ Standard_SStream aSStream;
+ aReport->DumpJson (aSStream);
+ theDI << aSStream;
+ }
+ }
+
+ return 0;
+}
+
+void Draw::MessageCommands(Draw_Interpretor& theCommands)
+{
+ static Standard_Boolean Done = Standard_False;
+ if (Done) return;
+ Done = Standard_True;
+
+ const char* group = "DRAW Message Commands";
+
+ theCommands.Add("PrintMessenger",
+ "PrintMessenger"
+ "\n\t\t: Prints DumpJson information about messenger.",
+ __FILE__, PrintMessenger, group);
+
+ theCommands.Add("SetMessagePrinter",
+ "SetMessagePrinter [-type ostream|systemlog|report|draw] [-state {on|off}=on]"
+ "\n\t\t: Sets or removes the printer in messenger."
+ "\n\t\t: Option -type set type of printer. Printers are applied with And combination."
+ "\n\t\t: Option -state add or remove printer",
+ __FILE__, SetMessagePrinter, group);
+
+ theCommands.Add("SendMessage",
+ "SendMessage text [text ...]"
+ "\n Sends the text into the messenger.\n",
+ __FILE__, SendMessage, group);
+
+ theCommands.Add("ClearReport",
+ "Removes all alerts in default printer",
+ __FILE__, ClearReport, group);
+
+ theCommands.Add("SetReportMetric",
+ "SetReportMetric [metric ...] \n Activate report metrics, deactivate all if there are no parameters.\n"
+ "\n\t\t: metric is a value of Message_MetricType, e.g. 1 is Message_MetricType_UserTimeCPU" ,
+ __FILE__, SetReportMetric, group);
+
+ theCommands.Add("CollectMetricMessages",
+ "CollectMetricMessages [-activate {0|1}]"
+ "\n Start metric collection by 1, stop by 0. Result is placed in metric attributes of message report.\n",
+ __FILE__, CollectMetricMessages, group);
+
+ theCommands.Add("PrintReport",
+ "PrintReport [-messenger] [-dump] [-dumpJson]"
+ "\n\t\t: Send report content to default messenger or stream"
+ "\n\t\t: Output options:"
+ "\n\t\t: -messenger Prints the information about report into messenger."
+ "\n\t\t: -dump Prints Dump information about report."
+ "\n\t\t: -dumpJson Prints DumpJson information about report.",
+ __FILE__, PrintReport, group);
+}
Draw_Marker3D.cxx
Draw_Marker3D.hxx
Draw_MarkerShape.hxx
+Draw_MessageCommands.cxx
Draw_Number.cxx
Draw_Number.hxx
Draw_PInterp.hxx
Message.cxx
Message.hxx
+Message_Alert.cxx
+Message_Alert.hxx
+Message_AlertExtended.cxx
+Message_AlertExtended.hxx
Message_Algorithm.cxx
Message_Algorithm.hxx
Message_Algorithm.lxx
Message_ConsoleColor.hxx
+Message_Attribute.cxx
+Message_Attribute.hxx
+Message_AttributeMeter.cxx
+Message_AttributeMeter.hxx
+Message_AttributeObject.cxx
+Message_AttributeObject.hxx
+Message_AttributeStream.cxx
+Message_AttributeStream.hxx
+Message_CompositeAlerts.cxx
+Message_CompositeAlerts.hxx
Message_ExecStatus.hxx
Message_Gravity.hxx
Message_HArrayOfMsg.hxx
+Message_Level.cxx
+Message_Level.hxx
Message_ListIteratorOfListOfMsg.hxx
Message_ListOfMsg.hxx
Message_Messenger.cxx
Message_Messenger.hxx
+Message_MetricType.hxx
Message_Msg.cxx
Message_Msg.hxx
Message_Msg.lxx
Message_PrinterOStream.hxx
Message_PrinterSystemLog.cxx
Message_PrinterSystemLog.hxx
+Message_PrinterToReport.cxx
+Message_PrinterToReport.hxx
Message_ProgressIndicator.cxx
Message_ProgressIndicator.hxx
Message_ProgressRange.hxx
Message_SequenceOfPrinters.hxx
Message_Status.hxx
Message_StatusType.hxx
-Message_Alert.cxx
-Message_Alert.hxx
Message_ListOfAlert.hxx
Message_Report.cxx
Message_Report.hxx
#include <Message.hxx>
#include <Message_Messenger.hxx>
+#include <Message_Report.hxx>
#include <TCollection_AsciiString.hxx>
#include <stdio.h>
#include <string.h>
+
+namespace
+{
+ static Standard_CString Message_Table_PrintMetricTypeEnum[10] =
+ {
+ "NONE", "UserTimeCPU", "SystemTimeInfo", "MemPrivate", "MemVirtual",
+ "MemWorkingSet", "MemWorkingSetPeak", "MemSwapUsage", "MemSwapUsagePeak", "MemHeapUsage"
+ };
+}
+
//=======================================================================
//function : DefaultMessenger
//purpose :
Sprintf (t, "%.2fs", second);
return TCollection_AsciiString (t);
}
+
+//=======================================================================
+//function : DefaultReport
+//purpose :
+//=======================================================================
+const Handle(Message_Report)& Message::DefaultReport(const Standard_Boolean theToCreate)
+{
+ static Handle(Message_Report) MyReport;
+ if (MyReport.IsNull() && theToCreate)
+ {
+ MyReport = new Message_Report();
+ }
+ return MyReport;
+}
+
+//=======================================================================
+//function : MetricToString
+//purpose :
+//=======================================================================
+Standard_CString Message::MetricToString (const Message_MetricType theType)
+{
+ return Message_Table_PrintMetricTypeEnum[theType];
+}
+
+//=======================================================================
+//function : MetricFromString
+//purpose :
+//=======================================================================
+Standard_Boolean Message::MetricFromString (const Standard_CString theString,
+ Message_MetricType& theGravity)
+{
+ TCollection_AsciiString aName (theString);
+ for (Standard_Integer aMetricIter = 0; aMetricIter <= Message_MetricType_MemHeapUsage; ++aMetricIter)
+ {
+ Standard_CString aMetricName = Message_Table_PrintMetricTypeEnum[aMetricIter];
+ if (aName == aMetricName)
+ {
+ theGravity = Message_MetricType (aMetricIter);
+ return Standard_True;
+ }
+ }
+ return Standard_False;
+}
+
+// =======================================================================
+// function : ToOSDMetric
+// purpose :
+// =======================================================================
+Standard_Boolean Message::ToOSDMetric (const Message_MetricType theMetric, OSD_MemInfo::Counter& theMemInfo)
+{
+ switch (theMetric)
+ {
+ case Message_MetricType_MemPrivate: theMemInfo = OSD_MemInfo::MemPrivate; break;
+ case Message_MetricType_MemVirtual: theMemInfo = OSD_MemInfo::MemVirtual; break;
+ case Message_MetricType_MemWorkingSet: theMemInfo = OSD_MemInfo::MemWorkingSet; break;
+ case Message_MetricType_MemWorkingSetPeak: theMemInfo = OSD_MemInfo::MemWorkingSetPeak; break;
+ case Message_MetricType_MemSwapUsage: theMemInfo = OSD_MemInfo::MemSwapUsage; break;
+ case Message_MetricType_MemSwapUsagePeak: theMemInfo = OSD_MemInfo::MemSwapUsagePeak; break;
+ case Message_MetricType_MemHeapUsage: theMemInfo = OSD_MemInfo::MemHeapUsage; break;
+ default: return Standard_False;
+ }
+ return Standard_True;
+}
+
+// =======================================================================
+// function : ToMessageMetric
+// purpose :
+// =======================================================================
+Standard_Boolean Message::ToMessageMetric (const OSD_MemInfo::Counter theMemInfo, Message_MetricType& theMetric)
+{
+ switch (theMemInfo)
+ {
+ case OSD_MemInfo::MemPrivate: theMetric = Message_MetricType_MemPrivate; break;
+ case OSD_MemInfo::MemVirtual: theMetric = Message_MetricType_MemVirtual; break;
+ case OSD_MemInfo::MemWorkingSet: theMetric = Message_MetricType_MemWorkingSet; break;
+ case OSD_MemInfo::MemWorkingSetPeak: theMetric = Message_MetricType_MemWorkingSetPeak; break;
+ case OSD_MemInfo::MemSwapUsage: theMetric = Message_MetricType_MemSwapUsage; break;
+ case OSD_MemInfo::MemSwapUsagePeak: theMetric = Message_MetricType_MemSwapUsagePeak; break;
+ case OSD_MemInfo::MemHeapUsage: theMetric = Message_MetricType_MemHeapUsage; break;
+ default: return Standard_False;
+ }
+ return Standard_True;
+}
#define _Message_HeaderFile
#include <Message_Messenger.hxx>
+#include <Message_Gravity.hxx>
+#include <Message_MetricType.hxx>
+#include <NCollection_Vector.hxx>
+#include <OSD_MemInfo.hxx>
+
+#include <TCollection_AsciiString.hxx>
+
+class Message_Report;
//! Defines
//! - tools to work with messages
//! 3. (0, 0, 4.5 ) returns "4.50s"
Standard_EXPORT static TCollection_AsciiString FillTime (const Standard_Integer Hour, const Standard_Integer Minute, const Standard_Real Second);
+public:
+ //! returns the only one instance of Report
+ //! When theToCreate is true - automatically creates message report when not exist.
+ Standard_EXPORT static const Handle(Message_Report)& DefaultReport (const Standard_Boolean theToCreate = Standard_False);
+
+ //! Determines the metric from the given string identifier.
+ //! @param theString string identifier
+ //! @param theType detected type of metric
+ //! @return TRUE if string identifier is known
+ Standard_EXPORT static Standard_Boolean MetricFromString (const Standard_CString theString,
+ Message_MetricType& theType);
+
+ //! Returns the string name for a given metric type.
+ //! @param theType metric type
+ //! @return string identifier from the list of Message_MetricType
+ Standard_EXPORT static Standard_CString MetricToString (const Message_MetricType theType);
+
+ //! Returns the metric type from the given string identifier.
+ //! @param theString string identifier
+ //! @return metric type or Message_MetricType_None if string identifier is invalid
+ static Message_MetricType MetricFromString (const Standard_CString theString)
+ {
+ Message_MetricType aMetric = Message_MetricType_None;
+ MetricFromString (theString, aMetric);
+ return aMetric;
+ }
+
+ //! Converts message metric to OSD memory info type.
+ //! @param theMetric [in] message metric
+ //! @param theMemInfo [out] filled memory info type
+ //! @return true if converted
+ static Standard_EXPORT Standard_Boolean ToOSDMetric (const Message_MetricType theMetric, OSD_MemInfo::Counter& theMemInfo);
+
+ //! Converts OSD memory info type to message metric.
+ //! @param theMemInfo [int] memory info type
+ //! @param theMetric [out] filled message metric
+ //! @return true if converted
+ static Standard_EXPORT Standard_Boolean ToMessageMetric (const OSD_MemInfo::Counter theMemInfo, Message_MetricType& theMetric);
+
};
#endif // _Message_HeaderFile
// commercial license or contractual agreement.
#include <Message_Alert.hxx>
+#include <Standard_Dump.hxx>
IMPLEMENT_STANDARD_RTTIEXT(Message_Alert,Standard_Transient)
// by default, merge trivially
return Standard_True;
}
+
+//=======================================================================
+//function : DumpJson
+//purpose :
+//=======================================================================
+void Message_Alert::DumpJson (Standard_OStream& theOStream, Standard_Integer) const
+{
+ OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
+}
//! Base implementation always returns true.
virtual Standard_EXPORT Standard_Boolean Merge (const Handle(Message_Alert)& theTarget);
+ //! Dumps the content of me into the stream
+ virtual Standard_EXPORT void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const;
+
// OCCT RTTI
DEFINE_STANDARD_RTTIEXT(Message_Alert,Standard_Transient)
};
--- /dev/null
+// Copyright (c) 2020 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <Message_AlertExtended.hxx>
+
+#include <Message_Attribute.hxx>
+#include <Message_CompositeAlerts.hxx>
+#include <Message_Report.hxx>
+
+#include <Precision.hxx>
+#include <Standard_Assert.hxx>
+#include <Standard_Dump.hxx>
+
+IMPLEMENT_STANDARD_RTTIEXT(Message_AlertExtended, Message_Alert)
+
+//=======================================================================
+//function : AddAlert
+//purpose :
+//=======================================================================
+Handle(Message_Alert) Message_AlertExtended::AddAlert (const Handle(Message_Report)& theReport,
+ const Handle(Message_Attribute)& theAttribute,
+ const Message_Gravity theGravity)
+{
+ Handle(Message_AlertExtended) anAlert = new Message_AlertExtended();
+ anAlert->SetAttribute (theAttribute);
+ theReport->AddAlert (theGravity, anAlert);
+ return anAlert;
+}
+
+//=======================================================================
+//function : GetMessageKey
+//purpose :
+//=======================================================================
+Standard_CString Message_AlertExtended::GetMessageKey() const
+{
+ if (myAttribute.IsNull())
+ {
+ return Message_Alert::GetMessageKey();
+ }
+ return myAttribute->GetMessageKey();
+}
+
+//=======================================================================
+//function : CompositeAlerts
+//purpose :
+//=======================================================================
+Handle(Message_CompositeAlerts) Message_AlertExtended::CompositeAlerts (const Standard_Boolean theToCreate)
+{
+ if (myCompositAlerts.IsNull() && theToCreate)
+ {
+ myCompositAlerts = new Message_CompositeAlerts();
+ }
+ return myCompositAlerts;
+}
+
+//=======================================================================
+//function : SupportsMerge
+//purpose :
+//=======================================================================
+Standard_Boolean Message_AlertExtended::SupportsMerge() const
+{
+ if (myCompositAlerts.IsNull())
+ {
+ return Standard_True;
+ }
+
+ // hierarchical alerts can not be merged
+ for (int aGravIter = Message_Trace; aGravIter <= Message_Fail; ++aGravIter)
+ {
+ if (!myCompositAlerts->Alerts ((Message_Gravity)aGravIter).IsEmpty())
+ {
+ return Standard_False;
+ }
+ }
+
+ return Standard_True;
+}
+
+//=======================================================================
+//function : Merge
+//purpose :
+//=======================================================================
+Standard_Boolean Message_AlertExtended::Merge (const Handle(Message_Alert)& /*theTarget*/)
+{
+ // by default, merge trivially
+ return Standard_False;
+}
+
+//=======================================================================
+//function : DumpJson
+//purpose :
+//=======================================================================
+void Message_AlertExtended::DumpJson (Standard_OStream& theOStream,
+ Standard_Integer theDepth) const
+{
+ OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
+
+ if (!myCompositAlerts.IsNull())
+ {
+ OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, myCompositAlerts.get())
+ }
+ if (!myAttribute.IsNull())
+ {
+ OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, myAttribute.get())
+ }
+}
--- /dev/null
+// Copyright (c) 2020 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _Message_AlertExtended_HeaderFile
+#define _Message_AlertExtended_HeaderFile
+
+#include <Message_Alert.hxx>
+#include <Message_Gravity.hxx>
+#include <TCollection_AsciiString.hxx>
+
+class Message_Attribute;
+class Message_Report;
+
+class Message_CompositeAlerts;
+
+//! Inherited class of Message_Alert with some additional information.
+//! It has Message_Attributes to provide the alert name, and other custom information
+//! It has a container of composite alerts, if the alert might provide
+//! sub-alerts collecting.
+class Message_AlertExtended : public Message_Alert
+{
+public:
+ //! Creates new instance of the alert and put it into report with Message_Info gravity.
+ //! It does nothing if such kind of gravity is not active in the report
+ //! @param theReport the message report where new alert is placed
+ //! @param theAttribute container of additional values of the alert
+ //! @return created alert or NULL if Message_Info is not active in report
+ Standard_EXPORT static Handle(Message_Alert) AddAlert (const Handle(Message_Report)& theReport,
+ const Handle(Message_Attribute)& theAttribute,
+ const Message_Gravity theGravity);
+
+public:
+ //! Empty constructor
+ Message_AlertExtended() : Message_Alert() {}
+
+ //! Return a C string to be used as a key for generating text user messages describing this alert.
+ //! The messages are generated with help of Message_Msg class, in Message_Report::Dump().
+ //! Base implementation returns dynamic type name of the instance.
+ Standard_EXPORT virtual Standard_CString GetMessageKey() const Standard_OVERRIDE;
+
+ //! Returns container of the alert attributes
+ const Handle(Message_Attribute)& Attribute() const { return myAttribute; }
+
+ //! Sets container of the alert attributes
+ //! @param theAttributes an attribute values
+ void SetAttribute (const Handle(Message_Attribute)& theAttribute) { myAttribute = theAttribute; }
+
+ //! Returns class provided hierarchy of alerts if created or create if the parameter is true
+ //! @param theToCreate if composite alert has not been created for this alert, it should be created
+ //! @return instance or NULL
+ Standard_EXPORT Handle(Message_CompositeAlerts) CompositeAlerts (const Standard_Boolean theToCreate = Standard_False);
+
+ //! Return true if this type of alert can be merged with other
+ //! of the same type to avoid duplication.
+ //! Hierarchical alerts can not be merged
+ //! Basis implementation returns true.
+ Standard_EXPORT virtual Standard_Boolean SupportsMerge() const Standard_OVERRIDE;
+
+ //! If possible, merge data contained in this alert to theTarget.
+ //! Base implementation always returns false.
+ //! @return True if merged
+ Standard_EXPORT virtual Standard_Boolean Merge (const Handle(Message_Alert)& theTarget) Standard_OVERRIDE;
+
+ //! Dumps the content of me into the stream
+ virtual Standard_EXPORT void DumpJson (Standard_OStream& theOStream,
+ Standard_Integer theDepth = -1) const Standard_OVERRIDE;
+
+ DEFINE_STANDARD_RTTIEXT(Message_AlertExtended, Message_Alert)
+
+protected:
+
+ Handle(Message_CompositeAlerts) myCompositAlerts; //!< class provided hierarchical structure of alerts
+ Handle(Message_Attribute) myAttribute; //!< container of the alert attributes
+};
+
+DEFINE_STANDARD_HANDLE(Message_AlertExtended, Message_Alert)
+
+#endif // _Message_Alert_HeaderFile
--- /dev/null
+// Copyright (c) 2020 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <Message_Attribute.hxx>
+
+#include <Standard_Assert.hxx>
+#include <Standard_Dump.hxx>
+
+IMPLEMENT_STANDARD_RTTIEXT(Message_Attribute, Standard_Transient)
+
+//=======================================================================
+//function : Constructor
+//purpose :
+//=======================================================================
+Message_Attribute::Message_Attribute (const TCollection_AsciiString& theName)
+: myName (theName)
+{
+}
+
+//=======================================================================
+//function : GetMessageKey
+//purpose :
+//=======================================================================
+Standard_CString Message_Attribute::GetMessageKey() const
+{
+ return !myName.IsEmpty() ? myName.ToCString() : "";
+}
+
+//=======================================================================
+//function : DumpJson
+//purpose :
+//=======================================================================
+void Message_Attribute::DumpJson (Standard_OStream& theOStream, Standard_Integer) const
+{
+ OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
+ OCCT_DUMP_FIELD_VALUE_STRING (theOStream, myName)
+}
--- /dev/null
+// Copyright (c) 2020 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _Message_Attribute_HeaderFile
+#define _Message_Attribute_HeaderFile
+
+#include <Standard_Transient.hxx>
+#include <TCollection_AsciiString.hxx>
+
+DEFINE_STANDARD_HANDLE(Message_Attribute, Standard_Transient)
+
+//! Additional information of extended alert attribute
+//! To provide other custom attribute container, it might be redefined.
+class Message_Attribute : public Standard_Transient
+{
+ DEFINE_STANDARD_RTTIEXT(Message_Attribute, Standard_Transient)
+public:
+ //! Empty constructor
+ Standard_EXPORT Message_Attribute (const TCollection_AsciiString& theName = TCollection_AsciiString());
+
+ //! Return a C string to be used as a key for generating text user messages describing this alert.
+ //! The messages are generated with help of Message_Msg class, in Message_Report::Dump().
+ //! Base implementation returns dynamic type name of the instance.
+ Standard_EXPORT virtual Standard_CString GetMessageKey() const;
+
+ //! Returns custom name of alert if it is set
+ //! @return alert name
+ const TCollection_AsciiString& GetName() const { return myName; }
+
+ //! Sets the custom name of alert
+ //! @param theName a name for the alert
+ void SetName (const TCollection_AsciiString& theName) { myName = theName; }
+
+ //! Dumps the content of me into the stream
+ virtual Standard_EXPORT void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const;
+
+private:
+ TCollection_AsciiString myName; //!< alert name, if defined is used in GetMessageKey
+
+};
+
+#endif // _Message_Attribute_HeaderFile
--- /dev/null
+// Copyright (c) 2020 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <Message_AttributeMeter.hxx>
+
+#include <Message_AlertExtended.hxx>
+#include <Message.hxx>
+#include <Message_Report.hxx>
+#include <OSD_Chronometer.hxx>
+
+#include <Precision.hxx>
+#include <Standard_Dump.hxx>
+
+IMPLEMENT_STANDARD_RTTIEXT(Message_AttributeMeter, Message_Attribute)
+
+//=======================================================================
+//function : Constructor
+//purpose :
+//=======================================================================
+Message_AttributeMeter::Message_AttributeMeter (const TCollection_AsciiString& theName)
+: Message_Attribute(theName)
+{
+}
+
+//=======================================================================
+//function : HasMetric
+//purpose :
+//=======================================================================
+Standard_Boolean Message_AttributeMeter::HasMetric (const Message_MetricType& theMetric) const
+{
+ return myMetrics.Contains (theMetric);
+}
+
+//=======================================================================
+//function : IsMetricValid
+//purpose :
+//=======================================================================
+Standard_Boolean Message_AttributeMeter::IsMetricValid (const Message_MetricType& theMetric) const
+{
+ return Abs (StartValue(theMetric) - UndefinedMetricValue()) > Precision::Confusion() &&
+ Abs (StopValue (theMetric) - UndefinedMetricValue()) > Precision::Confusion();
+}
+
+//=======================================================================
+//function : StartValue
+//purpose :
+//=======================================================================
+Standard_Real Message_AttributeMeter::StartValue (const Message_MetricType& theMetric) const
+{
+ if (!HasMetric (theMetric))
+ {
+ return UndefinedMetricValue();
+ }
+
+ return myMetrics.Seek (theMetric)->first;
+}
+
+//=======================================================================
+//function : SetStartValue
+//purpose :
+//=======================================================================
+void Message_AttributeMeter::SetStartValue (const Message_MetricType& theMetric, const Standard_Real theValue)
+{
+ if (StartToStopValue* aValPtr = myMetrics.ChangeSeek (theMetric))
+ {
+ aValPtr->first = theValue;
+ }
+ else
+ {
+ myMetrics.Add (theMetric, std::make_pair (theValue, UndefinedMetricValue()));
+ }
+}
+
+//=======================================================================
+//function : StopValue
+//purpose :
+//=======================================================================
+Standard_Real Message_AttributeMeter::StopValue (const Message_MetricType& theMetric) const
+{
+ if (!HasMetric (theMetric))
+ {
+ return UndefinedMetricValue();
+ }
+ return myMetrics.Seek (theMetric)->second;
+}
+
+//=======================================================================
+//function : SetStopValue
+//purpose :
+//=======================================================================
+void Message_AttributeMeter::SetStopValue (const Message_MetricType& theMetric, const Standard_Real theValue)
+{
+ if (StartToStopValue* aValPtr = myMetrics.ChangeSeek (theMetric))
+ {
+ aValPtr->second = theValue;
+ }
+}
+
+//=======================================================================
+//function : SetAlertMetrics
+//purpose :
+//=======================================================================
+void Message_AttributeMeter::SetAlertMetrics (const Handle(Message_AlertExtended)& theAlert,
+ const Standard_Boolean theStartValue)
+{
+ if (theAlert.IsNull())
+ {
+ return;
+ }
+
+ Handle(Message_AttributeMeter) aMeterAttribute = Handle(Message_AttributeMeter)::DownCast (theAlert->Attribute());
+ if (aMeterAttribute.IsNull())
+ {
+ return;
+ }
+
+ Handle(Message_Report) aReport = Message::DefaultReport (Standard_True);
+ const NCollection_IndexedMap<Message_MetricType>& anActiveMetrics = aReport->ActiveMetrics();
+
+ // time metrics
+ if (anActiveMetrics.Contains (Message_MetricType_ProcessCPUUserTime) ||
+ anActiveMetrics.Contains (Message_MetricType_ProcessCPUSystemTime) ||
+ anActiveMetrics.Contains (Message_MetricType_ThreadCPUUserTime) ||
+ anActiveMetrics.Contains (Message_MetricType_ThreadCPUSystemTime))
+ {
+ if (anActiveMetrics.Contains (Message_MetricType_ProcessCPUUserTime) ||
+ anActiveMetrics.Contains (Message_MetricType_ProcessCPUSystemTime))
+ {
+ Standard_Real aProcessUserTime, aProcessSystemTime;
+ OSD_Chronometer::GetProcessCPU (aProcessUserTime, aProcessSystemTime);
+ if (anActiveMetrics.Contains (Message_MetricType_ProcessCPUUserTime))
+ {
+ if (theStartValue)
+ {
+ aMeterAttribute->SetStartValue (Message_MetricType_ProcessCPUUserTime, aProcessUserTime);
+ }
+ else
+ {
+ aMeterAttribute->SetStopValue (Message_MetricType_ProcessCPUUserTime, aProcessUserTime);
+ }
+ }
+ if (anActiveMetrics.Contains (Message_MetricType_ProcessCPUSystemTime))
+ {
+ if (theStartValue)
+ {
+ aMeterAttribute->SetStartValue (Message_MetricType_ProcessCPUSystemTime, aProcessSystemTime);
+ }
+ else
+ {
+ aMeterAttribute->SetStopValue (Message_MetricType_ProcessCPUSystemTime, aProcessSystemTime);
+ }
+ }
+ }
+ if (anActiveMetrics.Contains (Message_MetricType_ThreadCPUUserTime) ||
+ anActiveMetrics.Contains (Message_MetricType_ThreadCPUSystemTime))
+ {
+ Standard_Real aThreadUserTime, aThreadSystemTime;
+ OSD_Chronometer::GetThreadCPU (aThreadUserTime, aThreadSystemTime);
+ if (anActiveMetrics.Contains (Message_MetricType_ThreadCPUUserTime))
+ {
+ if (theStartValue)
+ {
+ aMeterAttribute->SetStartValue (Message_MetricType_ThreadCPUUserTime, aThreadUserTime);
+ }
+ else
+ {
+ aMeterAttribute->SetStopValue (Message_MetricType_ThreadCPUUserTime, aThreadUserTime);
+ }
+ }
+ if (anActiveMetrics.Contains (Message_MetricType_ThreadCPUSystemTime))
+ {
+ if (theStartValue)
+ {
+ aMeterAttribute->SetStartValue (Message_MetricType_ThreadCPUSystemTime, aThreadSystemTime);
+ }
+ else
+ {
+ aMeterAttribute->SetStopValue (Message_MetricType_ThreadCPUSystemTime, aThreadSystemTime);
+ }
+ }
+ }
+ }
+
+ // memory metrics
+ OSD_MemInfo aMemInfo (Standard_False);
+ aMemInfo.SetActive (Standard_False);
+ NCollection_IndexedMap<OSD_MemInfo::Counter> aCounters;
+ for (NCollection_IndexedMap<Message_MetricType>::Iterator anIterator (anActiveMetrics); anIterator.More(); anIterator.Next())
+ {
+ OSD_MemInfo::Counter anInfoCounter;
+ if (!Message::ToOSDMetric (anIterator.Value(), anInfoCounter))
+ {
+ continue;
+ }
+
+ aCounters.Add (anInfoCounter);
+ aMemInfo.SetActive (anInfoCounter, Standard_True);
+ }
+ if (aCounters.IsEmpty())
+ {
+ return;
+ }
+
+ aMemInfo.Update();
+ Message_MetricType aMetricType;
+ for (NCollection_IndexedMap<OSD_MemInfo::Counter>::Iterator anIterator (aCounters); anIterator.More(); anIterator.Next())
+ {
+ if (!Message::ToMessageMetric (anIterator.Value(), aMetricType))
+ {
+ continue;
+ }
+
+ if (theStartValue)
+ {
+ aMeterAttribute->SetStartValue (aMetricType, (Standard_Real)aMemInfo.ValuePreciseMiB (anIterator.Value()));
+ }
+ else
+ {
+ aMeterAttribute->SetStopValue (aMetricType, (Standard_Real)aMemInfo.ValuePreciseMiB (anIterator.Value()));
+ }
+ }
+}
+
+//=======================================================================
+//function : DumpJson
+//purpose :
+//=======================================================================
+void Message_AttributeMeter::DumpJson (Standard_OStream& theOStream,
+ Standard_Integer theDepth) const
+{
+ OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
+ OCCT_DUMP_BASE_CLASS (theOStream, theDepth, Message_Attribute)
+
+ for (NCollection_IndexedDataMap<Message_MetricType, StartToStopValue>::Iterator anIterator (myMetrics);
+ anIterator.More(); anIterator.Next())
+ {
+ Message_MetricType aMetricType = anIterator.Key();
+ OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, aMetricType)
+
+ Standard_Real aStartValue = anIterator.Value().first;
+ OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, aStartValue)
+
+ Standard_Real aStopValue = anIterator.Value().second;
+ OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, aStopValue)
+ }
+}
--- /dev/null
+// Copyright (c) 2020 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _Message_AttributeMeter_HeaderFile
+#define _Message_AttributeMeter_HeaderFile
+
+#include <Message_Attribute.hxx>
+#include <Message_MetricType.hxx>
+
+#include <NCollection_IndexedDataMap.hxx>
+
+class Message_Alert;
+class Message_AlertExtended;
+
+//! Alert object storing alert metrics values.
+//! Start and stop values for each metric.
+class Message_AttributeMeter : public Message_Attribute
+{
+public:
+
+ //! Returns default value of the metric when it is not defined
+ //! @return undefined value
+ static Standard_Real UndefinedMetricValue() { return -1.0; }
+
+public:
+
+ //! Constructor with string argument
+ Standard_EXPORT Message_AttributeMeter (const TCollection_AsciiString& theName = TCollection_AsciiString());
+
+ //! Checks whether the attribute has values for the metric
+ //! @param theMetric [in] metric type
+ //! @return true if the metric values exist in the attribute
+ Standard_EXPORT Standard_Boolean HasMetric (const Message_MetricType& theMetric) const;
+
+ //! Returns true when both values of the metric are set.
+ //! @param theMetric [in] metric type
+ //! @return true if metric values are valid
+ Standard_EXPORT Standard_Boolean IsMetricValid (const Message_MetricType& theMetric) const;
+
+ //! Returns start value for the metric
+ //! @param theMetric [in] metric type
+ //! @return real value
+ Standard_EXPORT Standard_Real StartValue (const Message_MetricType& theMetric) const;
+
+ //! Sets start values for the metric
+ //! @param theMetric [in] metric type
+ Standard_EXPORT void SetStartValue (const Message_MetricType& theMetric, const Standard_Real theValue);
+
+ //! Returns stop value for the metric
+ //! @param theMetric [in] metric type
+ //! @return real value
+ Standard_EXPORT Standard_Real StopValue (const Message_MetricType& theMetric) const;
+
+ //! Sets stop values for the metric
+ //! @param theMetric [in] metric type
+ Standard_EXPORT void SetStopValue (const Message_MetricType& theMetric, const Standard_Real theValue);
+
+public:
+
+ //! Sets start values of default report metrics into the alert
+ //! @param theAlert an alert
+ static void StartAlert (const Handle(Message_AlertExtended)& theAlert) { SetAlertMetrics (theAlert, Standard_True); }
+
+ //! Sets stop values of default report metrics into the alert
+ //! @param theAlert an alert
+ static void StopAlert (const Handle(Message_AlertExtended)& theAlert) { SetAlertMetrics (theAlert, Standard_False); }
+
+ //! Sets current values of default report metrics into the alert.
+ //! Processed oly alert with Message_AttributeMeter attribute
+ //! @param theAlert an alert
+ //! @param theStartValue flag, if true, the start value is collected otherwise stop
+ static Standard_EXPORT void SetAlertMetrics (const Handle(Message_AlertExtended)& theAlert,
+ const Standard_Boolean theStartValue);
+
+ //! Dumps the content of me into the stream
+ virtual Standard_EXPORT void DumpJson (Standard_OStream& theOStream,
+ Standard_Integer theDepth = -1) const Standard_OVERRIDE;
+
+ DEFINE_STANDARD_RTTIEXT(Message_AttributeMeter, Message_Attribute)
+
+private:
+
+ typedef std::pair<Standard_Real, Standard_Real> StartToStopValue;
+ NCollection_IndexedDataMap<Message_MetricType, StartToStopValue> myMetrics; //!< computed metrics
+};
+
+#endif // _Message_AttributeMeter_HeaderFile
--- /dev/null
+// Copyright (c) 2020 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <Message_AttributeObject.hxx>
+#include <Standard_Dump.hxx>
+
+IMPLEMENT_STANDARD_RTTIEXT(Message_AttributeObject, Message_Attribute)
+
+//=======================================================================
+//function : Constructor
+//purpose :
+//=======================================================================
+Message_AttributeObject::Message_AttributeObject (const Handle(Standard_Transient)& theObject,
+ const TCollection_AsciiString& theName)
+: Message_Attribute(theName)
+{
+ myObject = theObject;
+}
+
+//=======================================================================
+//function : DumpJson
+//purpose :
+//=======================================================================
+void Message_AttributeObject::DumpJson (Standard_OStream& theOStream,
+ Standard_Integer theDepth) const
+{
+ OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
+ OCCT_DUMP_BASE_CLASS (theOStream, theDepth, Message_Attribute)
+
+ OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, myObject.get())
+}
--- /dev/null
+// Copyright (c) 2020 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _Message_AttributeObject_HeaderFile
+#define _Message_AttributeObject_HeaderFile
+
+#include <Message_Attribute.hxx>
+
+class Standard_Transient;
+
+//! Alert object storing a transient object
+class Message_AttributeObject : public Message_Attribute
+{
+ DEFINE_STANDARD_RTTIEXT(Message_AttributeObject, Message_Attribute)
+public:
+ //! Constructor with string argument
+ Standard_EXPORT Message_AttributeObject (const Handle(Standard_Transient)& theObject,
+ const TCollection_AsciiString& theName = TCollection_AsciiString());
+
+ //! Returns object
+ //! @return the object instance
+ const Handle(Standard_Transient)& Object() const { return myObject; }
+
+ //! Sets the object
+ //! @param theObject an instance
+ void SetObject (const Handle(Standard_Transient)& theObject) { myObject = theObject; }
+
+ //! Dumps the content of me into the stream
+ virtual Standard_EXPORT void DumpJson (Standard_OStream& theOStream,
+ Standard_Integer theDepth = -1) const Standard_OVERRIDE;
+
+private:
+ Handle(Standard_Transient) myObject; //!< alert object
+};
+
+#endif // _Message_AttributeObject_HeaderFile
--- /dev/null
+// Copyright (c) 2020 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <Message_AttributeStream.hxx>
+#include <Standard_Dump.hxx>
+
+IMPLEMENT_STANDARD_RTTIEXT(Message_AttributeStream, Message_Attribute)
+
+//=======================================================================
+//function : Constructor
+//purpose :
+//=======================================================================
+Message_AttributeStream::Message_AttributeStream (const Standard_SStream& theStream,
+ const TCollection_AsciiString& theName)
+: Message_Attribute(theName)
+{
+ SetStream (theStream);
+}
+
+//=======================================================================
+//function : SetStream
+//purpose :
+//=======================================================================
+void Message_AttributeStream::SetStream (const Standard_SStream& theStream)
+{
+ myStream.str ("");
+ myStream << theStream.str().c_str();
+}
+
+//=======================================================================
+//function : DumpJson
+//purpose :
+//=======================================================================
+void Message_AttributeStream::DumpJson (Standard_OStream& theOStream,
+ Standard_Integer theDepth) const
+{
+ OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
+ OCCT_DUMP_BASE_CLASS (theOStream, theDepth, Message_Attribute)
+
+ TCollection_AsciiString aStream = Standard_Dump::Text (myStream);
+ OCCT_DUMP_FIELD_VALUE_STRING (theOStream, aStream)
+}
--- /dev/null
+// Copyright (c) 2020 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _Message_AttributeStream_HeaderFile
+#define _Message_AttributeStream_HeaderFile
+
+#include <Message_Attribute.hxx>
+
+#include <Standard_SStream.hxx>
+
+//! Alert object storing stream value
+class Message_AttributeStream : public Message_Attribute
+{
+ DEFINE_STANDARD_RTTIEXT(Message_AttributeStream, Message_Attribute)
+public:
+
+ //! Constructor with string argument
+ Standard_EXPORT Message_AttributeStream (const Standard_SStream& theStream,
+ const TCollection_AsciiString& theName = TCollection_AsciiString());
+
+ //! Returns stream value
+ const Standard_SStream& Stream() const { return myStream; }
+
+ //! Sets stream value
+ Standard_EXPORT void SetStream (const Standard_SStream& theStream);
+
+ //! Dumps the content of me into the stream
+ virtual Standard_EXPORT void DumpJson (Standard_OStream& theOStream,
+ Standard_Integer theDepth = -1) const Standard_OVERRIDE;
+
+private:
+ Standard_SStream myStream; //!< container of values
+};
+
+#endif // _Message_AttributeStream_HeaderFile
--- /dev/null
+// Copyright (c) 2020 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <Message_CompositeAlerts.hxx>
+
+#include <Message_AlertExtended.hxx>
+#include <Standard_Assert.hxx>
+#include <Standard_Dump.hxx>
+
+IMPLEMENT_STANDARD_RTTIEXT(Message_CompositeAlerts, Standard_Transient)
+
+//=======================================================================
+//function : Alerts
+//purpose :
+//=======================================================================
+const Message_ListOfAlert& Message_CompositeAlerts::Alerts (const Message_Gravity theGravity) const
+{
+ static const Message_ListOfAlert anEmptyList;
+ Standard_ASSERT_RETURN (theGravity >= 0 && size_t(theGravity) < sizeof(myAlerts)/sizeof(myAlerts[0]),
+ "Requesting alerts for gravity not in valid range", anEmptyList);
+ return myAlerts[theGravity];
+}
+
+//=======================================================================
+//function : AddAlert
+//purpose :
+//=======================================================================
+Standard_Boolean Message_CompositeAlerts::AddAlert (Message_Gravity theGravity, const Handle(Message_Alert)& theAlert)
+{
+ Standard_ASSERT_RETURN (! theAlert.IsNull(), "Attempt to add null alert", Standard_False);
+ Standard_ASSERT_RETURN (theGravity >= 0 && size_t(theGravity) < sizeof(myAlerts)/sizeof(myAlerts[0]),
+ "Adding alert with gravity not in valid range", Standard_False);
+
+ Message_ListOfAlert& aList = myAlerts[theGravity];
+ if (theAlert->SupportsMerge() && ! aList.IsEmpty())
+ {
+ // merge is performed only for alerts of exactly same type
+ const Handle(Standard_Type)& aType = theAlert->DynamicType();
+ for (Message_ListOfAlert::Iterator anIt(aList); anIt.More(); anIt.Next())
+ {
+ // if merged successfully, just return
+ if (aType == anIt.Value()->DynamicType() && theAlert->Merge (anIt.Value()))
+ return Standard_False;
+ }
+ }
+
+ // if not merged, just add to the list
+ aList.Append (theAlert);
+ return Standard_True;
+}
+
+//=======================================================================
+//function : RemoveAlert
+//purpose :
+//=======================================================================
+Standard_Boolean Message_CompositeAlerts::RemoveAlert (Message_Gravity theGravity,
+ const Handle(Message_Alert)& theAlert)
+{
+ Standard_ASSERT_RETURN (! theAlert.IsNull(), "Attempt to add null alert", Standard_False);
+ Standard_ASSERT_RETURN (theGravity >= 0 && size_t(theGravity) < sizeof(myAlerts)/sizeof(myAlerts[0]),
+ "Adding alert with gravity not in valid range", Standard_False);
+
+ Message_ListOfAlert& anAlerts = myAlerts[theGravity];
+ if (!anAlerts.Contains (theAlert))
+ {
+ return Standard_False;
+ }
+
+ return anAlerts.Remove (theAlert);
+}
+
+//=======================================================================
+//function : HasAlerts
+//purpose :
+//=======================================================================
+Standard_Boolean Message_CompositeAlerts::HasAlert (const Handle(Message_Alert)& theAlert)
+{
+ for (int aGravIter = Message_Trace; aGravIter <= Message_Fail; ++aGravIter)
+ {
+ const Message_ListOfAlert& anAlerts = Alerts ((Message_Gravity)aGravIter);
+ if (anAlerts.Contains (theAlert))
+ {
+ return Standard_True;
+ }
+ }
+ return Standard_False;
+}
+
+//=======================================================================
+//function : HasAlerts
+//purpose :
+//=======================================================================
+Standard_Boolean Message_CompositeAlerts::HasAlert (const Handle(Standard_Type)& theType, Message_Gravity theGravity)
+{
+ Standard_ASSERT_RETURN (theGravity >= 0 && size_t(theGravity) < sizeof(myAlerts)/sizeof(myAlerts[0]),
+ "Requesting alerts for gravity not in valid range", Standard_False);
+
+ for (Message_ListOfAlert::Iterator anIt (myAlerts[theGravity]); anIt.More(); anIt.Next())
+ {
+ if (anIt.Value()->IsInstance(theType))
+ {
+ return Standard_True;
+ }
+ }
+ return Standard_False;
+}
+
+//=======================================================================
+//function : Clear
+//purpose :
+//=======================================================================
+void Message_CompositeAlerts::Clear()
+{
+ for (unsigned int i = 0; i < sizeof(myAlerts)/sizeof(myAlerts[0]); ++i)
+ {
+ myAlerts[i].Clear();
+ }
+}
+
+//=======================================================================
+//function : Clear
+//purpose :
+//=======================================================================
+void Message_CompositeAlerts::Clear (Message_Gravity theGravity)
+{
+ Standard_ASSERT_RETURN (theGravity >= 0 && size_t(theGravity) < sizeof(myAlerts)/sizeof(myAlerts[0]),
+ "Requesting alerts for gravity not in valid range", );
+ myAlerts[theGravity].Clear();
+}
+
+//=======================================================================
+//function : Clear
+//purpose :
+//=======================================================================
+void Message_CompositeAlerts::Clear (const Handle(Standard_Type)& theType)
+{
+ for (unsigned int i = 0; i < sizeof(myAlerts)/sizeof(myAlerts[0]); ++i)
+ {
+ for (Message_ListOfAlert::Iterator anIt (myAlerts[i]); anIt.More(); )
+ {
+ if (anIt.Value().IsNull() || anIt.Value()->IsInstance (theType))
+ {
+ myAlerts[i].Remove (anIt);
+ }
+ else
+ {
+ anIt.More();
+ }
+ }
+ }
+}
+
+//=======================================================================
+//function : DumpJson
+//purpose :
+//=======================================================================
+void Message_CompositeAlerts::DumpJson (Standard_OStream& theOStream,
+ Standard_Integer theDepth) const
+{
+ OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
+
+ for (unsigned int i = 0; i < sizeof(myAlerts)/sizeof(myAlerts[0]); ++i)
+ {
+ Message_Gravity aGravity = (Message_Gravity)i;
+ OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, aGravity)
+
+ for (Message_ListOfAlert::Iterator anIt (myAlerts[i]); anIt.More(); anIt.Next())
+ {
+ const Handle(Message_Alert)& anAlert = anIt.Value();
+ OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, anAlert.get())
+ }
+ }
+}
--- /dev/null
+// Copyright (c) 2020 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _Message_CompositeAlerts_HeaderFile
+#define _Message_CompositeAlerts_HeaderFile
+
+#include <Message_Alert.hxx>
+#include <Message_Gravity.hxx>
+#include <Message_ListOfAlert.hxx>
+#include <Standard_Transient.hxx>
+
+//! Class providing container of alerts
+class Message_CompositeAlerts : public Standard_Transient
+{
+ DEFINE_STANDARD_RTTIEXT(Message_CompositeAlerts, Standard_Transient)
+public:
+ //! Empty constructor
+ Message_CompositeAlerts() {}
+
+ //! Returns list of collected alerts with specified gravity
+ Standard_EXPORT const Message_ListOfAlert& Alerts (const Message_Gravity theGravity) const;
+
+ //! Add alert with specified gravity. If the alert supports merge it will be merged.
+ //! @param theGravity an alert gravity
+ //! @param theAlert an alert to be added as a child alert
+ //! @return true if the alert is added or merged
+ Standard_EXPORT Standard_Boolean AddAlert (Message_Gravity theGravity,
+ const Handle(Message_Alert)& theAlert);
+
+ //! Removes alert with specified gravity.
+ //! @param theGravity an alert gravity
+ //! @param theAlert an alert to be removed from the children
+ //! @return true if the alert is removed
+ Standard_EXPORT Standard_Boolean RemoveAlert (Message_Gravity theGravity,
+ const Handle(Message_Alert)& theAlert);
+
+ //! Returns true if the alert belong the list of the child alerts.
+ //! @param theAlert an alert to be checked as a child alert
+ //! @return true if the alert is found in a container of children
+ Standard_EXPORT Standard_Boolean HasAlert (const Handle(Message_Alert)& theAlert);
+
+ //! Returns true if specific type of alert is recorded with specified gravity
+ //! @param theType an alert type
+ //! @param theGravity an alert gravity
+ //! @return true if the alert is found in a container of children
+ Standard_EXPORT Standard_Boolean HasAlert (const Handle(Standard_Type)& theType,
+ Message_Gravity theGravity);
+
+ //! Clears all collected alerts
+ Standard_EXPORT void Clear();
+
+ //! Clears collected alerts with specified gravity
+ //! @param theGravity an alert gravity
+ Standard_EXPORT void Clear (Message_Gravity theGravity);
+
+ //! Clears collected alerts with specified type
+ //! @param theType an alert type
+ Standard_EXPORT void Clear (const Handle(Standard_Type)& theType);
+
+ //! Dumps the content of me into the stream
+ Standard_EXPORT void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const;
+
+protected:
+ // store messages in a lists sorted by gravity;
+ // here we rely on knowledge that Message_Fail is the last element of the enum
+ Message_ListOfAlert myAlerts[Message_Fail + 1]; //!< container of child alert for each type of gravity
+};
+
+DEFINE_STANDARD_HANDLE(Message_CompositeAlerts, Standard_Transient)
+
+#endif // _Message_CompositeAlerts_HeaderFile
--- /dev/null
+// Copyright (c) 2019 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <Message_Level.hxx>
+
+#include <Message.hxx>
+#include <Message_AlertExtended.hxx>
+#include <Message_CompositeAlerts.hxx>
+#include <Message_AttributeMeter.hxx>
+#include <Message_Messenger.hxx>
+#include <Message_Report.hxx>
+
+#include <OSD_Chronometer.hxx>
+#include <OSD_MemInfo.hxx>
+
+//=======================================================================
+//function : Constructor
+//purpose :
+//=======================================================================
+Message_Level::Message_Level (const TCollection_AsciiString& theName)
+{
+ const Handle(Message_Report)& aDefaultReport = Message::DefaultReport();
+ if (!aDefaultReport.IsNull() && aDefaultReport->IsActiveInMessenger())
+ {
+ aDefaultReport->AddLevel (this, theName);
+ }
+}
+
+//=======================================================================
+//function : Destructor
+//purpose :
+//=======================================================================
+Message_Level::~Message_Level()
+{
+ remove();
+}
+
+//=======================================================================
+//function : SetRootAlert
+//purpose :
+//=======================================================================
+void Message_Level::SetRootAlert (const Handle(Message_AlertExtended)& theAlert,
+ const Standard_Boolean isRequiredToStart)
+{
+ myRootAlert = theAlert;
+ if (isRequiredToStart)
+ {
+ Message_AttributeMeter::StartAlert (myRootAlert);
+ }
+}
+
+//=======================================================================
+//function : AddAlert
+//purpose :
+//=======================================================================
+Standard_Boolean Message_Level::AddAlert (const Message_Gravity theGravity,
+ const Handle(Message_Alert)& theAlert)
+{
+ Handle(Message_AlertExtended) anAlertExtended = Handle(Message_AlertExtended)::DownCast (theAlert);
+ if (anAlertExtended.IsNull())
+ {
+ return Standard_False;
+ }
+
+ // looking for the parent of the parameter alert to release the previous alert
+ Handle(Message_AlertExtended) aRootAlert = myRootAlert;
+ Handle(Message_CompositeAlerts) aCompositeAlert = aRootAlert->CompositeAlerts (Standard_True);
+
+ // update metrics of the previous alert
+ Message_AttributeMeter::StopAlert (myLastAlert);
+
+ myLastAlert = anAlertExtended;
+ // set start metrics of the new alert
+ Message_AttributeMeter::StartAlert (myLastAlert);
+
+ // add child alert
+ aCompositeAlert->AddAlert (theGravity, theAlert);
+
+ return Standard_True;
+}
+
+//=======================================================================
+//function : remove
+//purpose :
+//=======================================================================
+void Message_Level::remove()
+{
+ const Handle(Message_Report)& aDefaultReport = Message::DefaultReport();
+ if (aDefaultReport.IsNull() || !aDefaultReport->IsActiveInMessenger())
+ {
+ return;
+ }
+
+ Message_AttributeMeter::StopAlert (myLastAlert);
+
+ if (!Message::DefaultReport().IsNull())
+ {
+ Message::DefaultReport()->RemoveLevel (this);
+ }
+}
--- /dev/null
+// Copyright (c) 2019 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _Message_Level_HeaderFile
+#define _Message_Level_HeaderFile
+
+#include <Message.hxx>
+#include <Message_AlertExtended.hxx>
+#include <Message_Gravity.hxx>
+#include <Message_Messenger.hxx>
+#include <Message_MetricType.hxx>
+
+#include <NCollection_DataMap.hxx>
+#include <Standard.hxx>
+
+//! This class is an instance of Sentry to create a level in a message report
+//! Constructor of the class add new (active) level in the report, destructor removes it
+//! While the level is active in the report, new alerts are added below the level root alert.
+//!
+//! The first added alert is a root alert, other are added below the root alert
+//!
+//! If alert has Message_AttributeMeter attribute, active metrics of the default report are stored in
+//! the attribute: start value of metric on adding alert, stop on adding another alert or closing (delete) the level
+//! in the report.
+//!
+//! Processing of this class is implemented in Message_Report, it is used only inside it.
+//! Levels using should be only through using OCCT_ADD_MESSAGE_LEVEL_SENTRY only. No other code is required outside.
+class Message_Level
+{
+public:
+ //! Constructor.
+ //! One string key is used for all alert meters.
+ //! The perf meter is not started automatically, it will be done in AddAlert() method
+ Standard_EXPORT Message_Level (const TCollection_AsciiString& theName = TCollection_AsciiString());
+
+ //! Assures stopping upon destruction
+ Standard_EXPORT ~Message_Level();
+
+ //! Returns root alert of the level
+ //! @return alert instance or NULL
+ const Handle(Message_AlertExtended)& RootAlert() const { return myRootAlert; }
+
+ //! Sets the root alert. Starts collects alert metrics if active.
+ //! @param theAlert an alert
+ Standard_EXPORT void SetRootAlert (const Handle(Message_AlertExtended)& theAlert,
+ const Standard_Boolean isRequiredToStart);
+
+ //! Adds new alert on the level. Stops the last alert metric, appends the alert and starts the alert metrics collecting.
+ //! Sets root alert beforehand this method using, if the root is NULL, it does nothing.
+ //! @param theGravity an alert gravity
+ //! @param theAlert an alert
+ //! @return true if alert is added
+ Standard_EXPORT Standard_Boolean AddAlert (const Message_Gravity theGravity,
+ const Handle(Message_Alert)& theAlert);
+
+private:
+ //! Remove the current level from the report. It stops metric collecting for the last and the root alerts.
+ Standard_EXPORT void remove();
+
+private:
+ Handle(Message_AlertExtended) myRootAlert; //!< root alert
+ Handle(Message_AlertExtended) myLastAlert; //!< last added alert on the root alert
+};
+
+//! @def MESSAGE_NEW_LEVEL
+//! Creates a new level instance of Sentry. This row should be inserted before messages using in the method.
+#define OCCT_ADD_MESSAGE_LEVEL_SENTRY(theMessage) \
+ Message_Level aLevel(theMessage);
+
+#endif // _Message_Level_HeaderFile
#include <Message_Printer.hxx>
#include <Message_PrinterOStream.hxx>
+#include <Standard_Dump.hxx>
IMPLEMENT_STANDARD_RTTIEXT(Message_Messenger,Standard_Transient)
//=======================================================================
//function : Send
-//purpose :
+//purpose :
//=======================================================================
+void Message_Messenger::Send (const Standard_SStream& theStream,
+ const Message_Gravity theGravity) const
+{
+ for (Message_SequenceOfPrinters::Iterator aPrinterIter (myPrinters); aPrinterIter.More(); aPrinterIter.Next())
+ {
+ const Handle(Message_Printer)& aPrinter = aPrinterIter.Value();
+ if (!aPrinter.IsNull())
+ {
+ aPrinter->SendStringStream (theStream, theGravity);
+ }
+ }
+}
+//=======================================================================
+//function : Send
+//purpose :
+//=======================================================================
void Message_Messenger::Send (const TCollection_AsciiString& theString,
const Message_Gravity theGravity) const
{
}
}
}
+
+//=======================================================================
+//function : Send
+//purpose :
+//=======================================================================
+void Message_Messenger::Send (const Handle(Standard_Transient)& theObject,
+ const Message_Gravity theGravity) const
+{
+ for (Message_SequenceOfPrinters::Iterator aPrinterIter (myPrinters); aPrinterIter.More(); aPrinterIter.Next())
+ {
+ const Handle(Message_Printer)& aPrinter = aPrinterIter.Value();
+ if (!aPrinter.IsNull())
+ {
+ aPrinter->SendObject (theObject, theGravity);
+ }
+ }
+}
+
+//=======================================================================
+//function : DumpJson
+//purpose :
+//=======================================================================
+void Message_Messenger::DumpJson (Standard_OStream& theOStream, Standard_Integer) const
+{
+ OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
+
+ OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myPrinters.Size())
+}
{
if (myMessenger)
{
- myMessenger->Send(myStream.str().c_str(), myGravity);
+ myMessenger->Send(myStream, myGravity);
}
myStream.str(std::string()); // empty the buffer for possible reuse
}
Standard_EXPORT void Send (const Standard_CString theString,
const Message_Gravity theGravity = Message_Warning) const;
+ //! See above
+ Standard_EXPORT void Send (const Standard_SStream& theStream,
+ const Message_Gravity theGravity = Message_Warning) const;
+
//! See above
Standard_EXPORT void Send (const TCollection_AsciiString& theString,
const Message_Gravity theGravity = Message_Warning) const;
//! Create string buffer for message of specified type
StreamBuffer Send (Message_Gravity theGravity) { return StreamBuffer (this, theGravity); }
+ //! See above
+ Standard_EXPORT void Send (const Handle(Standard_Transient)& theObject, const Message_Gravity theGravity = Message_Warning) const;
+
//! Create string buffer for sending Fail message
StreamBuffer SendFail () { return Send (Message_Fail); }
//! Short-cut to Send (theMessage, Message_Trace)
void SendTrace (const TCollection_AsciiString& theMessage) { Send (theMessage, Message_Trace); }
+ //! Dumps the content of me into the stream
+ Standard_EXPORT void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const;
+
private:
Message_SequenceOfPrinters myPrinters;
--- /dev/null
+// Copyright (c) 2020 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _Message_MetricType_HeaderFile
+#define _Message_MetricType_HeaderFile
+
+//! Specifies kind of report information to collect
+enum Message_MetricType
+{
+ Message_MetricType_None, //!< no computation
+ Message_MetricType_ThreadCPUUserTime, //!< OSD_Chronometer::GetThreadCPU user time
+ Message_MetricType_ThreadCPUSystemTime, //!< OSD_Chronometer::GetThreadCPU system time
+ Message_MetricType_ProcessCPUUserTime, //!< OSD_Chronometer::GetProcessCPU user time
+ Message_MetricType_ProcessCPUSystemTime, //!< OSD_Chronometer::GetProcessCPU system time
+ Message_MetricType_MemPrivate, //!< OSD_MemInfo::MemPrivate
+ Message_MetricType_MemVirtual, //!< OSD_MemInfo::MemVirtual
+ Message_MetricType_MemWorkingSet, //!< OSD_MemInfo::MemWorkingSet
+ Message_MetricType_MemWorkingSetPeak, //!< OSD_MemInfo::MemWorkingSetPeak
+ Message_MetricType_MemSwapUsage, //!< OSD_MemInfo::MemSwapUsage
+ Message_MetricType_MemSwapUsagePeak, //!< OSD_MemInfo::MemSwapUsagePeak
+ Message_MetricType_MemHeapUsage //!< OSD_MemInfo::MemHeapUsage
+};
+
+#endif // _Message_MetricType_HeaderFile
#include <Message_Printer.hxx>
+#include <Standard_Dump.hxx>
#include <TCollection_AsciiString.hxx>
#include <TCollection_ExtendedString.hxx>
send (theString, theGravity);
}
}
+
+//=======================================================================
+//function : SendStringStream
+//purpose :
+//=======================================================================
+void Message_Printer::SendStringStream (const Standard_SStream& theStream,
+ const Message_Gravity theGravity) const
+{
+ if (theGravity >= myTraceLevel)
+ {
+ send (theStream.str().c_str(), theGravity);
+ }
+}
+
+//=======================================================================
+//function : SendObject
+//purpose :
+//=======================================================================
+void Message_Printer::SendObject (const Handle(Standard_Transient)& theObject,
+ const Message_Gravity theGravity) const
+{
+ if (!theObject.IsNull()
+ && theGravity >= myTraceLevel)
+ {
+ send (TCollection_AsciiString (theObject->DynamicType()->Name())
+ + ": " + Standard_Dump::GetPointerInfo (theObject), theGravity);
+ }
+}
#include <Standard_Transient.hxx>
#include <Standard_Boolean.hxx>
#include <Standard_CString.hxx>
+#include <Standard_SStream.hxx>
+
class TCollection_ExtendedString;
class TCollection_AsciiString;
Standard_EXPORT virtual void Send (const TCollection_AsciiString& theString,
const Message_Gravity theGravity) const;
+ //! Send a string message with specified trace level.
+ //! Stream is converted to string value.
+ //! Default implementation calls first method Send().
+ Standard_EXPORT virtual void SendStringStream (const Standard_SStream& theStream, const Message_Gravity theGravity) const;
+
+ //! Send a string message with specified trace level.
+ //! The object is converted to string in format: <object kind> : <object pointer>.
+ //! Default implementation calls first method Send().
+ Standard_EXPORT virtual void SendObject (const Handle(Standard_Transient)& theObject, const Message_Gravity theGravity) const;
+
protected:
//! Empty constructor with Message_Info trace level
Standard_EXPORT Message_Printer();
//! Send a string message with specified trace level.
- //! This method must be redefined in descentant.
+ //! This method must be redefined in descendant.
Standard_EXPORT virtual void send (const TCollection_AsciiString& theString,
const Message_Gravity theGravity) const = 0;
--- /dev/null
+// Copyright (c) 2020 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <Message_PrinterToReport.hxx>
+
+#include <Message.hxx>
+#include <Message_AlertExtended.hxx>
+#include <Message_Attribute.hxx>
+#include <Message_AttributeMeter.hxx>
+#include <Message_AttributeObject.hxx>
+#include <Message_AttributeStream.hxx>
+#include <Message_Report.hxx>
+
+#include <Standard_Dump.hxx>
+#include <TCollection_ExtendedString.hxx>
+
+IMPLEMENT_STANDARD_RTTIEXT(Message_PrinterToReport, Message_Printer)
+
+//=======================================================================
+//function : Report
+//purpose :
+//=======================================================================
+const Handle(Message_Report)& Message_PrinterToReport::Report() const
+{
+ if (!myReport.IsNull())
+ {
+ return myReport;
+ }
+
+ return Message::DefaultReport (Standard_True);
+}
+
+//=======================================================================
+//function : SendStringStream
+//purpose :
+//=======================================================================
+void Message_PrinterToReport::SendStringStream (const Standard_SStream& theStream,
+ const Message_Gravity theGravity) const
+{
+ const Handle(Message_Report)& aReport = Report();
+ if (!aReport->ActiveMetrics().IsEmpty())
+ {
+ sendMetricAlert (theStream.str().c_str(), theGravity);
+ return;
+ }
+ if (Standard_Dump::HasChildKey(Standard_Dump::Text (theStream)))
+ {
+ Message_AlertExtended::AddAlert (aReport, new Message_AttributeStream (theStream, myName), theGravity);
+ myName.Clear();
+ }
+ else
+ {
+ if (!myName.IsEmpty())
+ {
+ TCollection_AsciiString aName = myName;
+ myName.Clear();
+ send (aName, theGravity);
+ }
+ myName = Standard_Dump::Text (theStream);
+ }
+}
+
+//=======================================================================
+//function : SendObject
+//purpose :
+//=======================================================================
+void Message_PrinterToReport::SendObject (const Handle(Standard_Transient)& theObject,
+ const Message_Gravity theGravity) const
+{
+ const Handle(Message_Report)& aReport = Report();
+ if (!aReport->ActiveMetrics().IsEmpty())
+ {
+ sendMetricAlert (myName, theGravity);
+ return;
+ }
+
+ Message_AlertExtended::AddAlert (aReport, new Message_AttributeObject (theObject, myName), theGravity);
+}
+
+//=======================================================================
+//function : send
+//purpose :
+//=======================================================================
+void Message_PrinterToReport::send (const TCollection_AsciiString& theString,
+ const Message_Gravity theGravity) const
+{
+ if (!myName.IsEmpty())
+ {
+ send (myName, theGravity);
+ myName.Clear();
+ }
+
+ const Handle(Message_Report)& aReport = Report();
+ if (!aReport->ActiveMetrics().IsEmpty())
+ {
+ sendMetricAlert (theString, theGravity);
+ return;
+ }
+ Message_AlertExtended::AddAlert (aReport, new Message_Attribute (theString), theGravity);
+}
+
+//=======================================================================
+//function : sendMetricAlert
+//purpose :
+//=======================================================================
+void Message_PrinterToReport::sendMetricAlert (const TCollection_AsciiString theValue,
+ const Message_Gravity theGravity) const
+{
+ Message_AlertExtended::AddAlert (Report(), new Message_AttributeMeter (theValue), theGravity);
+}
--- /dev/null
+// Copyright (c) 2020 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _Message_PrinterToReport_HeaderFile
+#define _Message_PrinterToReport_HeaderFile
+
+#include <Message_Printer.hxx>
+#include <Standard_Address.hxx>
+#include <Standard_OStream.hxx>
+#include <TCollection_AsciiString.hxx>
+
+class Message_Report;
+
+//! Implementation of a message printer associated with Message_Report
+//! Send will create a new alert of the report. If string is sent, an alert is created by Eol only.
+//! The alerts are sent into set report or default report of Message.
+class Message_PrinterToReport : public Message_Printer
+{
+ DEFINE_STANDARD_RTTIEXT(Message_PrinterToReport, Message_Printer)
+public:
+ //! Create printer for redirecting messages into report.
+ Message_PrinterToReport() {}
+
+ //! Destructor
+ virtual ~Message_PrinterToReport() {}
+
+ //! Returns the current or default report
+ Standard_EXPORT const Handle(Message_Report)& Report() const;
+
+ //! Sets the printer report
+ //! @param theReport report for messages processing, if NULL, the default report is used
+ void SetReport (const Handle(Message_Report)& theReport) { myReport = theReport; }
+
+ //! Send a string message with specified trace level.
+ //! Stream is converted to string value.
+ //! Default implementation calls first method Send().
+ Standard_EXPORT virtual void SendStringStream (const Standard_SStream& theStream,
+ const Message_Gravity theGravity) const Standard_OVERRIDE;
+
+ //! Send a string message with specified trace level.
+ //! The object is converted to string in format: <object kind> : <object pointer>.
+ //! The parameter theToPutEol specified whether end-of-line should be added to the end of the message.
+ //! Default implementation calls first method Send().
+ Standard_EXPORT virtual void SendObject (const Handle(Standard_Transient)& theObject,
+ const Message_Gravity theGravity) const Standard_OVERRIDE;
+
+protected:
+
+ //! Send a string message with specified trace level.
+ //! This method must be redefined in descendant.
+ Standard_EXPORT virtual void send (const TCollection_AsciiString& theString,
+ const Message_Gravity theGravity) const Standard_OVERRIDE;
+
+ //! Send an alert with metrics active in the current report
+ Standard_EXPORT void sendMetricAlert (const TCollection_AsciiString theValue,
+ const Message_Gravity theGravity) const;
+
+private:
+ mutable TCollection_AsciiString myName;
+ Handle(Message_Report) myReport; //!< the report for sending alerts
+};
+
+DEFINE_STANDARD_HANDLE(Message_PrinterToReport, Message_Printer)
+
+#endif // _Message_PrinterToReport_HeaderFile
// commercial license or contractual agreement.
#include <Message_Report.hxx>
+
+#include <Message.hxx>
+#include <Message_AlertExtended.hxx>
+#include <Message_AttributeMeter.hxx>
+#include <Message_Attribute.hxx>
+#include <Message_CompositeAlerts.hxx>
#include <Message_Msg.hxx>
#include <Message_Messenger.hxx>
-#include <NCollection_Map.hxx>
+#include <Message_PrinterToReport.hxx>
+
+#include <Precision.hxx>
+#include <Standard_Dump.hxx>
IMPLEMENT_STANDARD_RTTIEXT(Message_Report,Standard_Transient)
//=======================================================================
Message_Report::Message_Report ()
+: myLimit (-1),
+ myIsActiveInMessenger (Standard_False)
{
}
void Message_Report::AddAlert (Message_Gravity theGravity, const Handle(Message_Alert)& theAlert)
{
- Standard_ASSERT_RETURN (! theAlert.IsNull(), "Attempt to add null alert",);
- Standard_ASSERT_RETURN (theGravity >= 0 && size_t(theGravity) < sizeof(myAlerts)/sizeof(myAlerts[0]),
- "Adding alert with gravity not in valid range",);
-
Standard_Mutex::Sentry aSentry (myMutex);
- // iterate by already recorded alerts and try to merge new one with one of those
- Message_ListOfAlert &aList = myAlerts[theGravity];
- if (theAlert->SupportsMerge() && ! aList.IsEmpty())
+ // alerts of the top level
+ if (myAlertLevels.IsEmpty())
{
- // merge is performed only for alerts of exactly same type
- const Handle(Standard_Type)& aType = theAlert->DynamicType();
- for (Message_ListOfAlert::Iterator anIt(aList); anIt.More(); anIt.Next())
+ Handle (Message_CompositeAlerts) aCompositeAlert = compositeAlerts (Standard_True);
+ if (aCompositeAlert->AddAlert (theGravity, theAlert))
+ {
+ return;
+ }
+
+ // remove alerts under the report only
+ const Message_ListOfAlert& anAlerts = aCompositeAlert->Alerts (theGravity);
+ if (anAlerts.Extent() > myLimit)
{
- // if merged successfully, just return
- if (aType == anIt.Value()->DynamicType() && theAlert->Merge (anIt.Value()))
- return;
+ aCompositeAlert->RemoveAlert (theGravity, anAlerts.First());
}
+ return;
}
- // if not merged, just add to the list
- aList.Append (theAlert);
+ // if there are some levels of alerts, the new alert will be placed below the root
+ myAlertLevels.Last()->AddAlert (theGravity, theAlert);
}
//=======================================================================
const Message_ListOfAlert& Message_Report::GetAlerts (Message_Gravity theGravity) const
{
static const Message_ListOfAlert anEmptyList;
- Standard_ASSERT_RETURN (theGravity >= 0 && size_t(theGravity) < sizeof(myAlerts)/sizeof(myAlerts[0]),
- "Requesting alerts for gravity not in valid range", anEmptyList);
- return myAlerts[theGravity];
+ if (myCompositAlerts.IsNull())
+ {
+ return anEmptyList;
+ }
+ return myCompositAlerts->Alerts (theGravity);
}
//=======================================================================
Standard_Boolean Message_Report::HasAlert (const Handle(Standard_Type)& theType, Message_Gravity theGravity)
{
- Standard_ASSERT_RETURN (theGravity >= 0 && size_t(theGravity) < sizeof(myAlerts)/sizeof(myAlerts[0]),
- "Requesting alerts for gravity not in valid range", Standard_False);
- for (Message_ListOfAlert::Iterator anIt (myAlerts[theGravity]); anIt.More(); anIt.Next())
+ if (compositeAlerts().IsNull())
{
- if (anIt.Value()->IsInstance(theType))
- return Standard_True;
+ return Standard_False;
}
- return Standard_False;
+
+ return compositeAlerts()->HasAlert (theType, theGravity);
}
//=======================================================================
-//function : Clear
+//function : IsActiveInMessenger
+//purpose :
+//=======================================================================
+Standard_Boolean Message_Report::IsActiveInMessenger (const Handle(Message_Messenger)&) const
+{
+ return myIsActiveInMessenger;
+}
+
+//=======================================================================
+//function : ActivateInMessenger
+//purpose :
+//=======================================================================
+void Message_Report::ActivateInMessenger (const Standard_Boolean toActivate,
+ const Handle(Message_Messenger)& theMessenger)
+{
+ if (toActivate == IsActiveInMessenger())
+ return;
+
+ myIsActiveInMessenger = toActivate;
+ Handle(Message_Messenger) aMessenger = theMessenger.IsNull() ? Message::DefaultMessenger() : theMessenger;
+ if (toActivate)
+ {
+ Handle (Message_PrinterToReport) aPrinterToReport = new Message_PrinterToReport();
+ aPrinterToReport->SetReport (this);
+ aMessenger->AddPrinter (aPrinterToReport);
+ }
+ else // deactivate
+ {
+ Message_SequenceOfPrinters aPrintersToRemove;
+ for (Message_SequenceOfPrinters::Iterator anIterator (aMessenger->Printers()); anIterator.More(); anIterator.Next())
+ {
+ const Handle(Message_Printer) aPrinter = anIterator.Value();
+ if (aPrinter->IsKind(STANDARD_TYPE (Message_PrinterToReport)) &&
+ Handle(Message_PrinterToReport)::DownCast (aPrinter)->Report() == this)
+ aPrintersToRemove.Append (aPrinter);
+ }
+ for (Message_SequenceOfPrinters::Iterator anIterator (aPrintersToRemove); anIterator.More(); anIterator.Next())
+ {
+ aMessenger->RemovePrinter (anIterator.Value());
+ }
+ }
+}
+
+//=======================================================================
+//function : UpdateActiveInMessenger
+//purpose :
+//=======================================================================
+void Message_Report::UpdateActiveInMessenger (const Handle(Message_Messenger)& theMessenger)
+{
+ Handle(Message_Messenger) aMessenger = theMessenger.IsNull() ? Message::DefaultMessenger() : theMessenger;
+ for (Message_SequenceOfPrinters::Iterator anIterator (aMessenger->Printers()); anIterator.More(); anIterator.Next())
+ {
+ if (anIterator.Value()->IsKind(STANDARD_TYPE (Message_PrinterToReport)) &&
+ Handle(Message_PrinterToReport)::DownCast (anIterator.Value())->Report() == this)
+ {
+ myIsActiveInMessenger = Standard_True;
+ return;
+ }
+ }
+ myIsActiveInMessenger = Standard_False;
+}
+
+//=======================================================================
+//function : AddLevel
+//purpose :
+//=======================================================================
+void Message_Report::AddLevel (Message_Level* theLevel, const TCollection_AsciiString& theName)
+{
+ myAlertLevels.Append (theLevel);
+
+ Handle(Message_AlertExtended) aLevelRootAlert = new Message_AlertExtended();
+
+ Handle(Message_Attribute) anAttribute;
+ if (!ActiveMetrics().IsEmpty())
+ {
+ anAttribute = new Message_AttributeMeter (theName);
+ }
+ else
+ {
+ anAttribute = new Message_Attribute (theName);
+ }
+ aLevelRootAlert->SetAttribute (anAttribute);
+ theLevel->SetRootAlert (aLevelRootAlert, myAlertLevels.Size() == 1);
+
+ if (myAlertLevels.Size() == 1) // this is the first level, so root alert should be pushed in the report composite of alerts
+ {
+ compositeAlerts (Standard_True)->AddAlert (Message_Info, theLevel->RootAlert());
+ }
+ if (myAlertLevels.Size() > 1) // this is the first level, so root alert should be pushed in the report composite of alerts
+ {
+ // root alert of next levels should be pushed under the previous level
+ Message_Level* aPrevLevel = myAlertLevels.Value (myAlertLevels.Size() - 1); // previous level
+ aPrevLevel->AddAlert (Message_Info, aLevelRootAlert);
+ }
+}
+
+//=======================================================================
+//function : RemoveLevel
//purpose :
//=======================================================================
-void Message_Report::Clear ()
+void Message_Report::RemoveLevel (Message_Level* theLevel)
{
- for (unsigned int i = 0; i < sizeof(myAlerts)/sizeof(myAlerts[0]); ++i)
+ for (int aLevelIndex = myAlertLevels.Size(); aLevelIndex >= 1; aLevelIndex--)
{
- myAlerts[i].Clear();
+ Message_Level* aLevel = myAlertLevels.Value (aLevelIndex);
+ if (myAlertLevels.Size() == 1) // the last level, the root item should be stopped
+ {
+ Message_AttributeMeter::StopAlert (aLevel->RootAlert());
+ }
+
+ myAlertLevels.Remove (aLevelIndex);
+ if (aLevel == theLevel)
+ {
+ return;
+ }
}
}
//function : Clear
//purpose :
//=======================================================================
+void Message_Report::Clear()
+{
+ if (compositeAlerts().IsNull())
+ {
+ return;
+ }
+
+ compositeAlerts()->Clear();
+ myAlertLevels.Clear();
+}
+//=======================================================================
+//function : Clear
+//purpose :
+//=======================================================================
void Message_Report::Clear (Message_Gravity theGravity)
{
- Standard_ASSERT_RETURN (theGravity >= 0 && size_t(theGravity) < sizeof(myAlerts)/sizeof(myAlerts[0]),
- "Requesting alerts for gravity not in valid range", );
- myAlerts[theGravity].Clear();
+ if (compositeAlerts().IsNull())
+ {
+ return;
+ }
+
+ compositeAlerts()->Clear (theGravity);
+ myAlertLevels.Clear();
}
//=======================================================================
//function : Clear
//purpose :
//=======================================================================
-
void Message_Report::Clear (const Handle(Standard_Type)& theType)
{
- for (unsigned int i = 0; i < sizeof(myAlerts)/sizeof(myAlerts[0]); ++i)
+ if (compositeAlerts().IsNull())
{
- for (Message_ListOfAlert::Iterator anIt (myAlerts[i]); anIt.More(); )
- {
- if (anIt.Value().IsNull() || anIt.Value()->IsInstance (theType))
- {
- myAlerts[i].Remove (anIt);
- }
- else
- {
- anIt.More();
- }
- }
+ return;
+ }
+
+ compositeAlerts()->Clear (theType);
+ myAlertLevels.Clear();
+}
+
+//=======================================================================
+//function : SetActiveMetric
+//purpose :
+//=======================================================================
+void Message_Report::SetActiveMetric (const Message_MetricType theMetricType,
+ const Standard_Boolean theActivate)
+{
+ if (theActivate == myActiveMetrics.Contains (theMetricType))
+ {
+ return;
+ }
+
+ if (theActivate)
+ {
+ myActiveMetrics.Add (theMetricType);
+ }
+ else
+ {
+ myActiveMetrics.RemoveKey (theMetricType);
}
}
void Message_Report::Dump (Standard_OStream& theOS, Message_Gravity theGravity)
{
- Standard_ASSERT_RETURN (theGravity >= 0 && size_t(theGravity) < sizeof(myAlerts)/sizeof(myAlerts[0]),
- "Requesting alerts for gravity not in valid range", );
+ if (compositeAlerts().IsNull())
+ {
+ return;
+ }
- // report each type of warning only once
- NCollection_Map<Handle(Standard_Type)> aPassedAlerts;
- for (Message_ListOfAlert::Iterator anIt (myAlerts[theGravity]); anIt.More(); anIt.Next())
+ if (compositeAlerts().IsNull())
{
- if (aPassedAlerts.Add (anIt.Value()->DynamicType()))
- {
- Message_Msg aMsg (anIt.Value()->GetMessageKey());
- theOS << aMsg.Original() << std::endl;
- }
+ return;
}
+
+ dumpMessages (theOS, theGravity, compositeAlerts());
}
//=======================================================================
void Message_Report::SendMessages (const Handle(Message_Messenger)& theMessenger)
{
- for (int iGravity = Message_Trace; iGravity <= Message_Fail; ++iGravity)
+ for (int aGravIter = Message_Trace; aGravIter <= Message_Fail; ++aGravIter)
{
- SendMessages (theMessenger, (Message_Gravity)iGravity);
+ SendMessages (theMessenger, (Message_Gravity)aGravIter);
}
}
void Message_Report::SendMessages (const Handle(Message_Messenger)& theMessenger, Message_Gravity theGravity)
{
- Standard_ASSERT_RETURN (theGravity >= 0 && size_t(theGravity) < sizeof(myAlerts)/sizeof(myAlerts[0]),
- "Requesting alerts for gravity not in valid range", );
-
- // report each type of warning only once
- NCollection_Map<Handle(Standard_Type)> aPassedAlerts;
- for (Message_ListOfAlert::Iterator anIt (myAlerts[theGravity]); anIt.More(); anIt.Next())
+ if (compositeAlerts().IsNull())
{
- if (aPassedAlerts.Add (anIt.Value()->DynamicType()))
- {
- Message_Msg aMsg (anIt.Value()->GetMessageKey());
- theMessenger->Send (aMsg, theGravity);
- }
+ return;
}
+
+ sendMessages (theMessenger, theGravity, compositeAlerts());
}
//=======================================================================
void Message_Report::Merge (const Handle(Message_Report)& theOther)
{
- for (int iGravity = Message_Trace; iGravity <= Message_Fail; ++iGravity)
+ for (int aGravIter = Message_Trace; aGravIter <= Message_Fail; ++aGravIter)
{
- Merge (theOther, (Message_Gravity)iGravity);
+ Merge (theOther, (Message_Gravity)aGravIter);
}
}
AddAlert (theGravity, anIt.Value());
}
}
+
+//=======================================================================
+//function : CompositeAlerts
+//purpose :
+//=======================================================================
+const Handle(Message_CompositeAlerts)& Message_Report::compositeAlerts (const Standard_Boolean isCreate)
+{
+ if (myCompositAlerts.IsNull() && isCreate)
+ {
+ myCompositAlerts = new Message_CompositeAlerts();
+ }
+
+ return myCompositAlerts;
+}
+
+//=======================================================================
+//function : sendMessages
+//purpose :
+//=======================================================================
+void Message_Report::sendMessages (const Handle(Message_Messenger)& theMessenger, Message_Gravity theGravity,
+ const Handle(Message_CompositeAlerts)& theCompositeAlert)
+{
+ if (theCompositeAlert.IsNull())
+ {
+ return;
+ }
+
+ const Message_ListOfAlert& anAlerts = theCompositeAlert->Alerts (theGravity);
+ for (Message_ListOfAlert::Iterator anIt (anAlerts); anIt.More(); anIt.Next())
+ {
+ theMessenger->Send (anIt.Value()->GetMessageKey(), theGravity);
+ Handle(Message_AlertExtended) anExtendedAlert = Handle(Message_AlertExtended)::DownCast (anIt.Value());
+ if (anExtendedAlert.IsNull())
+ {
+ continue;
+ }
+
+ Handle(Message_CompositeAlerts) aCompositeAlerts = anExtendedAlert->CompositeAlerts();
+ if (aCompositeAlerts.IsNull())
+ {
+ continue;
+ }
+
+ sendMessages (theMessenger, theGravity, aCompositeAlerts);
+ }
+}
+
+//=======================================================================
+//function : dumpMessages
+//purpose :
+//=======================================================================
+void Message_Report::dumpMessages (Standard_OStream& theOS, Message_Gravity theGravity,
+ const Handle(Message_CompositeAlerts)& theCompositeAlert)
+{
+ if (theCompositeAlert.IsNull())
+ {
+ return;
+ }
+
+ const Message_ListOfAlert& anAlerts = theCompositeAlert->Alerts (theGravity);
+ for (Message_ListOfAlert::Iterator anIt (anAlerts); anIt.More(); anIt.Next())
+ {
+ theOS << anIt.Value()->GetMessageKey() << std::endl;
+
+ Handle(Message_AlertExtended) anExtendedAlert = Handle(Message_AlertExtended)::DownCast (anIt.Value());
+ if (anExtendedAlert.IsNull())
+ {
+ continue;
+ }
+
+ dumpMessages (theOS, theGravity, anExtendedAlert->CompositeAlerts());
+ }
+}
+
+//=======================================================================
+//function : DumpJson
+//purpose :
+//=======================================================================
+void Message_Report::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
+{
+ OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
+
+ if (!myCompositAlerts.IsNull())
+ {
+ OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, myCompositAlerts.get())
+ }
+
+ Standard_Integer anAlertLevels = myAlertLevels.Size();
+ OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, anAlertLevels)
+
+ for (NCollection_IndexedMap<Message_MetricType>::Iterator anIterator (myActiveMetrics); anIterator.More(); anIterator.Next())
+ {
+ Message_MetricType anActiveMetric = anIterator.Value();
+ OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, anActiveMetric)
+ }
+
+ OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myLimit)
+ OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsActiveInMessenger)
+}
#define _Message_Report_HeaderFile
#include <Message_Gravity.hxx>
+#include <Message_Level.hxx>
#include <Message_ListOfAlert.hxx>
+#include <Message_MetricType.hxx>
+#include <NCollection_IndexedMap.hxx>
+#include <NCollection_Sequence.hxx>
#include <Standard_Mutex.hxx>
+class Message_CompositeAlerts;
class Message_Messenger;
class Message_Report;
+
DEFINE_STANDARD_HANDLE(Message_Report, MMgt_TShared)
//! Container for alert messages, sorted according to their gravity.
//! Dump() or in more advanced way, by iterating over lists returned by GetAlerts()
//!
//! - Report can be cleared by methods Clear() (usually after reporting)
-
+//!
+//! Message_PrinterToReport is a printer in Messenger to convert data sent to messenger into report
class Message_Report : public Standard_Transient
{
public:
//! Returns true if specific type of alert is recorded with specified gravity
Standard_EXPORT Standard_Boolean HasAlert (const Handle(Standard_Type)& theType, Message_Gravity theGravity);
+ //! Returns true if a report printer for the current report is registered in the messenger
+ //! @param theMessenger the messenger. If it's NULL, the default messenger is used
+ Standard_EXPORT Standard_Boolean IsActiveInMessenger (const Handle(Message_Messenger)& theMessenger = NULL) const;
+
+ //! Creates an instance of Message_PrinterToReport with the current report and register it in messenger
+ //! @param toActivate if true, activated else deactivated
+ //! @param theMessenger the messenger. If it's NULL, the default messenger is used
+ Standard_EXPORT void ActivateInMessenger (const Standard_Boolean toActivate,
+ const Handle(Message_Messenger)& theMessenger = NULL);
+
+ //! Updates internal flag IsActiveInMessenger.
+ //! It becomes true if messenger contains at least one instance of Message_PrinterToReport.
+ //! @param theMessenger the messenger. If it's NULL, the default messenger is used
+ Standard_EXPORT void UpdateActiveInMessenger (const Handle(Message_Messenger)& theMessenger = NULL);
+
+ //! Add new level of alerts
+ //! @param theLevel a level
+ Standard_EXPORT void AddLevel (Message_Level* theLevel, const TCollection_AsciiString& theName);
+
+ //! Remove level of alerts
+ Standard_EXPORT void RemoveLevel (Message_Level* theLevel);
+
//! Clears all collected alerts
Standard_EXPORT void Clear ();
//! Clears collected alerts with specified type
Standard_EXPORT void Clear (const Handle(Standard_Type)& theType);
+ //! Returns computed metrics when alerts are performed
+ const NCollection_IndexedMap<Message_MetricType>& ActiveMetrics() const { return myActiveMetrics; }
+
+ //! Sets metrics to compute when alerts are performed
+ //! @param theMetrics container of metrics
+ Standard_EXPORT void SetActiveMetric (const Message_MetricType theMetricType, const Standard_Boolean theActivate);
+
+ //! Removes all activated metrics
+ void ClearMetrics() { myActiveMetrics.Clear(); }
+
+ //! Returns maximum number of collecting alerts. If the limit is achieved,
+ //! first alert is removed, the new alert is added in the container.
+ //! @return the limit value
+ Standard_Integer Limit() const { return myLimit; }
+
+ //! Sets maximum number of collecting alerts.
+ //! @param theLimit limit value
+ void SetLimit(const Standard_Integer theLimit) { myLimit = theLimit; }
+
//! Dumps all collected alerts to stream
Standard_EXPORT void Dump (Standard_OStream& theOS);
//! Merges alerts with specified gravity from theOther report into this
Standard_EXPORT void Merge (const Handle(Message_Report)& theOther, Message_Gravity theGravity);
+ //! Dumps the content of me into the stream
+ Standard_EXPORT void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const;
+
// OCCT RTTI
DEFINE_STANDARD_RTTIEXT(Message_Report,Standard_Transient)
+protected:
+ //! Returns class provided hierarchy of alerts if created or create if the parameter is true
+ //! @param isCreate if composite alert has not been created for this alert, it should be created
+ //! @return instance or NULL
+ Standard_EXPORT const Handle(Message_CompositeAlerts)& compositeAlerts (const Standard_Boolean isCreate = Standard_False);
+
+ //! Sends alerts to messenger
+ Standard_EXPORT void sendMessages (const Handle(Message_Messenger)& theMessenger, Message_Gravity theGravity,
+ const Handle(Message_CompositeAlerts)& theCompositeAlert);
+
+ //! Dumps collected alerts with specified gravity to stream
+ Standard_EXPORT void dumpMessages (Standard_OStream& theOS, Message_Gravity theGravity,
+ const Handle(Message_CompositeAlerts)& theCompositeAlert);
+
protected:
Standard_Mutex myMutex;
- // store messages in a lists sorted by gravity;
- // here we rely on knowledge that Message_Fail is the last element of the enum
- Message_ListOfAlert myAlerts[Message_Fail + 1];
+ Handle(Message_CompositeAlerts) myCompositAlerts; //!< container of alerts
+
+ NCollection_Sequence<Message_Level*> myAlertLevels; //!< container of active levels, new alerts are added below the latest level
+ NCollection_IndexedMap<Message_MetricType> myActiveMetrics; //!< metrics to compute on alerts
+
+ Standard_Integer myLimit; //!< Maximum number of collected alerts on the top level
+ Standard_Boolean myIsActiveInMessenger; //! state whether the report is activated in messenger
};
#endif // _Message_Report_HeaderFile
TopoDS.hxx
TopoDS.lxx
+TopoDS_AlertAttribute.hxx
+TopoDS_AlertAttribute.cxx
TopoDS_Builder.cxx
TopoDS_Builder.hxx
TopoDS_Builder.lxx
--- /dev/null
+// Created on: 2018-06-10
+// Created by: Natalia Ermolaeva
+// Copyright (c) 2018-2020 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <TopoDS_AlertAttribute.hxx>
+
+#include <Message_PrinterToReport.hxx>
+
+IMPLEMENT_STANDARD_RTTIEXT(TopoDS_AlertAttribute, Message_Attribute)
+
+//=======================================================================
+//function : TopoDS_AlertAttribute
+//purpose :
+//=======================================================================
+TopoDS_AlertAttribute::TopoDS_AlertAttribute (const TopoDS_Shape& theShape,
+ const TCollection_AsciiString& theName)
+: Message_AttributeStream (Standard_SStream(), theName), myShape (theShape)
+{
+ Standard_SStream aStream;
+ theShape.DumpJson (aStream);
+
+ SetStream (aStream);
+}
+
+//=======================================================================
+//function : Send
+//purpose :
+//=======================================================================
+void TopoDS_AlertAttribute::Send (const Handle(Message_Messenger)& theMessenger,
+ const TopoDS_Shape& theShape)
+{
+ for (Message_SequenceOfPrinters::Iterator aPrinterIter (theMessenger->Printers()); aPrinterIter.More(); aPrinterIter.Next())
+ {
+ const Handle(Message_Printer)& aPrinter = aPrinterIter.Value();
+ if (!aPrinter->IsKind (STANDARD_TYPE (Message_PrinterToReport)))
+ {
+ continue;
+ }
+
+ Handle (Message_PrinterToReport) aPrinterToReport = Handle(Message_PrinterToReport)::DownCast (aPrinter);
+ const Handle(Message_Report)& aReport = aPrinterToReport->Report();
+
+ Message_AlertExtended::AddAlert (aReport, new TopoDS_AlertAttribute (theShape), Message_Info);
+ }
+}
+
+//=======================================================================
+//function : DumpJson
+//purpose :
+//=======================================================================
+void TopoDS_AlertAttribute::DumpJson (Standard_OStream& theOStream,
+ Standard_Integer theDepth) const
+{
+ OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
+ OCCT_DUMP_BASE_CLASS (theOStream, theDepth, Message_Attribute)
+
+ OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myShape)
+}
--- /dev/null
+// Created on: 2018-06-10
+// Created by: Natalia Ermolaeva
+// Copyright (c) 2018-2020 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _TopoDS_AlertAttribute_HeaderFile
+#define _TopoDS_AlertAttribute_HeaderFile
+
+#include <Message_AttributeStream.hxx>
+#include <Message.hxx>
+#include <Message_Messenger.hxx>
+#include <Message_Report.hxx>
+
+#include <TopoDS_Shape.hxx>
+
+class Message_Messenger;
+
+//! Alert attribute object storing TopoDS shape in its field
+class TopoDS_AlertAttribute : public Message_AttributeStream
+{
+ DEFINE_STANDARD_RTTIEXT(TopoDS_AlertAttribute, Message_AttributeStream)
+public:
+ //! Constructor with shape argument
+ Standard_EXPORT TopoDS_AlertAttribute (const TopoDS_Shape& theShape,
+ const TCollection_AsciiString& theName = TCollection_AsciiString());
+
+ //! Returns contained shape
+ const TopoDS_Shape& GetShape() const { return myShape; }
+
+public:
+
+ //! Push shape information into messenger
+ Standard_EXPORT static void Send (const Handle(Message_Messenger)& theMessenger,
+ const TopoDS_Shape& theShape);
+
+ //! Dumps the content of me into the stream
+ Standard_EXPORT void DumpJson (Standard_OStream& theOStream,
+ Standard_Integer theDepth = -1) const Standard_OVERRIDE;
+
+private:
+ TopoDS_Shape myShape;
+};
+
+inline const Handle(Message_Messenger)& operator<< (const Handle(Message_Messenger)& theMessenger,
+ const TopoDS_Shape& theShape)
+{
+ TopoDS_AlertAttribute::Send (theMessenger, theShape);
+ return theMessenger;
+}
+
+#endif // _TopoDS_AlertAttribute_HeaderFile
--- /dev/null
+puts "=================================="
+puts "0029451: Information Message Alert to debug an algorithm or object functionality"
+puts "=================================="
+pload MODELING
+
+#ostream printer
+PrintMessenger
+SendMessage "processing a text message in ostream" "information message" "test faulty message" "warning message"
+
+#report printer
+SetMessagePrinter -type report
+PrintMessenger
+SendMessage "processing a text message in report" "information message" "test faulty message" "warning message"
+
+PrintReport -dumpJson
+
+#report printer with metric
+ClearReport
+SetReportMetric 1 3
+CollectMetricMessages -activate 1
+SendMessage "processing metric report"
+CollectMetricMessages -activate 0
+
+PrintReport -dumpJson
+SetMessagePrinter -type report -state off
+PrintMessenger
+
+puts "TEST COMPLETED"
\ No newline at end of file