1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-03 17:56:21 +03:00

0029451: Information Message Alert to debug an algorithm or object functionality

- 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.
This commit is contained in:
nds 2020-10-02 14:17:59 +03:00 committed by bugmaster
parent dba9887351
commit 6522304c17
37 changed files with 2734 additions and 81 deletions

View File

@ -425,6 +425,7 @@ void Draw_Appli(int argc, char** argv, const FDraw_InitAppli Draw_InitAppli)
// standard commands
// *****************************************************************
Draw::BasicCommands(theCommands);
Draw::MessageCommands(theCommands);
Draw::VariableCommands(theCommands);
Draw::UnitCommands(theCommands);
if (!Draw_Batch) Draw::GraphicCommands(theCommands);

View File

@ -201,6 +201,9 @@ public: //! @name methods loading standard command sets
//! 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);

View File

@ -23,6 +23,7 @@
void Draw::Commands (Draw_Interpretor& theCommands)
{
Draw::BasicCommands(theCommands);
Draw::MessageCommands(theCommands);
Draw::VariableCommands(theCommands);
Draw::GraphicCommands(theCommands);
Draw::PloadCommands(theCommands);

View File

@ -0,0 +1,388 @@
// 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);
}

View File

@ -43,6 +43,7 @@ Draw_Marker2D.hxx
Draw_Marker3D.cxx
Draw_Marker3D.hxx
Draw_MarkerShape.hxx
Draw_MessageCommands.cxx
Draw_Number.cxx
Draw_Number.hxx
Draw_PInterp.hxx

View File

@ -1,16 +1,33 @@
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
@ -22,6 +39,8 @@ Message_PrinterOStream.cxx
Message_PrinterOStream.hxx
Message_PrinterSystemLog.cxx
Message_PrinterSystemLog.hxx
Message_PrinterToReport.cxx
Message_PrinterToReport.hxx
Message_ProgressIndicator.cxx
Message_ProgressIndicator.hxx
Message_ProgressRange.hxx
@ -30,8 +49,6 @@ Message_ProgressSentry.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

View File

@ -17,10 +17,21 @@
#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 :
@ -49,3 +60,86 @@ TCollection_AsciiString Message::FillTime (const Standard_Integer hour,
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;
}

View File

@ -18,6 +18,14 @@
#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
@ -76,6 +84,45 @@ public:
//! 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

View File

@ -14,6 +14,7 @@
// commercial license or contractual agreement.
#include <Message_Alert.hxx>
#include <Standard_Dump.hxx>
IMPLEMENT_STANDARD_RTTIEXT(Message_Alert,Standard_Transient)
@ -48,3 +49,12 @@ Standard_Boolean Message_Alert::Merge (const Handle(Message_Alert)& /*theTarget*
// 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)
}

View File

@ -54,6 +54,9 @@ public:
//! 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)
};

View File

@ -0,0 +1,116 @@
// 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())
}
}

View File

@ -0,0 +1,88 @@
// 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

View File

@ -0,0 +1,47 @@
// 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)
}

View File

@ -0,0 +1,52 @@
// 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

View File

@ -0,0 +1,256 @@
// 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)
}
}

View File

@ -0,0 +1,97 @@
// 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

View File

@ -0,0 +1,41 @@
// 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())
}

View File

@ -0,0 +1,46 @@
// 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

View File

@ -0,0 +1,52 @@
// 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)
}

View File

@ -0,0 +1,45 @@
// 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

View File

@ -0,0 +1,183 @@
// 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())
}
}
}

View File

@ -0,0 +1,81 @@
// 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

View File

@ -0,0 +1,110 @@
// 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);
}
}

View File

@ -0,0 +1,80 @@
// 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

View File

@ -17,6 +17,7 @@
#include <Message_Printer.hxx>
#include <Message_PrinterOStream.hxx>
#include <Standard_Dump.hxx>
IMPLEMENT_STANDARD_RTTIEXT(Message_Messenger,Standard_Transient)
@ -125,9 +126,25 @@ void Message_Messenger::Send (const Standard_CString theString,
//=======================================================================
//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
{
@ -158,3 +175,31 @@ void Message_Messenger::Send (const TCollection_ExtendedString& theString,
}
}
}
//=======================================================================
//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())
}

View File

@ -76,7 +76,7 @@ public:
{
if (myMessenger)
{
myMessenger->Send(myStream.str().c_str(), myGravity);
myMessenger->Send(myStream, myGravity);
}
myStream.str(std::string()); // empty the buffer for possible reuse
}
@ -177,6 +177,10 @@ public:
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;
@ -188,6 +192,9 @@ public:
//! 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); }
@ -218,6 +225,9 @@ public:
//! 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;

View File

@ -0,0 +1,34 @@
// 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

View File

@ -15,6 +15,7 @@
#include <Message_Printer.hxx>
#include <Standard_Dump.hxx>
#include <TCollection_AsciiString.hxx>
#include <TCollection_ExtendedString.hxx>
@ -67,3 +68,31 @@ void Message_Printer::Send (const TCollection_AsciiString& theString,
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);
}
}

View File

@ -23,6 +23,8 @@
#include <Standard_Transient.hxx>
#include <Standard_Boolean.hxx>
#include <Standard_CString.hxx>
#include <Standard_SStream.hxx>
class TCollection_ExtendedString;
class TCollection_AsciiString;
@ -65,13 +67,23 @@ public:
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;

View File

@ -0,0 +1,120 @@
// 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);
}

View File

@ -0,0 +1,75 @@
// 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

View File

@ -14,9 +14,18 @@
// 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)
@ -26,6 +35,8 @@ IMPLEMENT_STANDARD_RTTIEXT(Message_Report,Standard_Transient)
//=======================================================================
Message_Report::Message_Report ()
: myLimit (-1),
myIsActiveInMessenger (Standard_False)
{
}
@ -36,28 +47,28 @@ Message_Report::Message_Report ()
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))
{
// if merged successfully, just return
if (aType == anIt.Value()->DynamicType() && theAlert->Merge (anIt.Value()))
return;
return;
}
// remove alerts under the report only
const Message_ListOfAlert& anAlerts = aCompositeAlert->Alerts (theGravity);
if (anAlerts.Extent() > myLimit)
{
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);
}
//=======================================================================
@ -68,9 +79,11 @@ void Message_Report::AddAlert (Message_Gravity theGravity, const Handle(Message_
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);
}
//=======================================================================
@ -95,26 +108,131 @@ Standard_Boolean Message_Report::HasAlert (const Handle(Standard_Type)& theType)
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 :
//=======================================================================
void Message_Report::Clear ()
Standard_Boolean Message_Report::IsActiveInMessenger (const Handle(Message_Messenger)&) const
{
for (unsigned int i = 0; i < sizeof(myAlerts)/sizeof(myAlerts[0]); ++i)
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)
{
myAlerts[i].Clear();
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::RemoveLevel (Message_Level* theLevel)
{
for (int aLevelIndex = myAlertLevels.Size(); aLevelIndex >= 1; aLevelIndex--)
{
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;
}
}
}
@ -122,34 +240,66 @@ void Message_Report::Clear ()
//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);
}
}
@ -173,19 +323,17 @@ void Message_Report::Dump (Standard_OStream& theOS)
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", );
// 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;
}
if (compositeAlerts().IsNull())
{
return;
}
dumpMessages (theOS, theGravity, compositeAlerts());
}
//=======================================================================
@ -195,9 +343,9 @@ void Message_Report::Dump (Standard_OStream& theOS, Message_Gravity theGravity)
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);
}
}
@ -208,19 +356,12 @@ void Message_Report::SendMessages (const Handle(Message_Messenger)& theMessenger
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());
}
//=======================================================================
@ -230,9 +371,9 @@ void Message_Report::SendMessages (const Handle(Message_Messenger)& theMessenger
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);
}
}
@ -248,3 +389,102 @@ void Message_Report::Merge (const Handle(Message_Report)& theOther, Message_Grav
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)
}

View File

@ -17,12 +17,18 @@
#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.
@ -46,7 +52,8 @@ DEFINE_STANDARD_HANDLE(Message_Report, MMgt_TShared)
//! 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:
@ -67,6 +74,28 @@ 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 ();
@ -76,6 +105,25 @@ public:
//! 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);
@ -97,15 +145,36 @@ public:
//! 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

View File

@ -1,5 +1,7 @@
TopoDS.hxx
TopoDS.lxx
TopoDS_AlertAttribute.hxx
TopoDS_AlertAttribute.cxx
TopoDS_Builder.cxx
TopoDS_Builder.hxx
TopoDS_Builder.lxx

View File

@ -0,0 +1,69 @@
// 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)
}

View File

@ -0,0 +1,61 @@
// 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

28
tests/demo/draw/messenger Normal file
View File

@ -0,0 +1,28 @@
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"