Line data Source code
1 : /*
2 : * ThrottleStream.cxx
3 : * ers
4 : *
5 : * Created by Gordon Crone on 02.08.05.
6 : * Copyright 2004 CERN. All rights reserved.
7 : *
8 : */
9 : #include <boost/lexical_cast.hpp>
10 :
11 : #include <ers/internal/FilterStream.hpp>
12 : #include <ers/internal/Util.hpp>
13 : #include <ers/StreamFactory.hpp>
14 :
15 : #include <ers/internal/ThrottleStream.hpp>
16 :
17 62 : ERS_REGISTER_OUTPUT_STREAM( ers::ThrottleStream, "throttle", format )
18 :
19 31 : ers::ThrottleStream::IssueRecord::IssueRecord()
20 : {
21 31 : reset();
22 31 : }
23 :
24 : void
25 62 : ers::ThrottleStream::IssueRecord::reset()
26 : {
27 62 : m_lastOccurance=0;
28 62 : m_lastReport=0;
29 62 : m_initialCounter=0;
30 62 : m_threshold=10;
31 62 : m_suppressedCounter=0;
32 62 : }
33 :
34 : void
35 0 : ers::ThrottleStream::reportSuppression(IssueRecord& record, const ers::Issue& issue)
36 : {
37 0 : std::ostringstream msgStream;
38 0 : msgStream << " -- " << record.m_suppressedCounter << " similar messages suppressed, last occurrence was at "
39 0 : << record.m_lastOccuranceFormatted;
40 :
41 0 : ers::Issue* suppressedNotice = issue.clone();
42 0 : suppressedNotice->wrap_message( "", msgStream.str());
43 :
44 0 : suppressedNotice->set_severity(issue.severity());
45 0 : chained().write(*suppressedNotice);
46 0 : delete suppressedNotice;
47 :
48 0 : record.m_lastReport = issue.time_t();
49 0 : record.m_suppressedCounter = 0;
50 0 : }
51 :
52 : void
53 58 : ers::ThrottleStream::throttle(IssueRecord& rec, const ers::Issue& issue)
54 : {
55 58 : std::time_t issueTime=issue.time_t();
56 58 : bool reported=false;
57 58 : if (issueTime - rec.m_lastOccurance > m_timeLimit) {
58 31 : if (rec.m_suppressedCounter>0) {
59 0 : reportSuppression(rec, issue);
60 0 : reported=true;
61 : }
62 31 : rec.reset();
63 : }
64 :
65 58 : if (rec.m_initialCounter<m_initialThreshold) {
66 58 : rec.m_initialCounter++;
67 58 : rec.m_lastReport=issueTime;
68 58 : if (!reported) {
69 58 : chained().write(issue);
70 : }
71 : }
72 0 : else if (rec.m_suppressedCounter>=rec.m_threshold) {
73 0 : rec.m_threshold=rec.m_threshold*10;
74 0 : reportSuppression(rec, issue);
75 : }
76 0 : else if (issueTime - rec.m_lastReport > m_timeLimit) {
77 0 : reportSuppression(rec, issue);
78 : }
79 : else {
80 0 : rec.m_suppressedCounter++;
81 : }
82 :
83 58 : rec.m_lastOccurance=issueTime;
84 58 : rec.m_lastOccuranceFormatted=issue.time<std::chrono::microseconds>();
85 58 : }
86 :
87 21 : ers::ThrottleStream::ThrottleStream( const std::string & criteria )
88 : {
89 21 : m_initialThreshold = 30;
90 21 : m_timeLimit = 30;
91 :
92 21 : std::vector<std::string> params;
93 21 : ers::tokenize( criteria, ",", params );
94 :
95 21 : if ( params.size() > 0 )
96 : {
97 21 : std::istringstream in( params[0] );
98 21 : in >> m_initialThreshold;
99 21 : }
100 :
101 21 : if ( params.size() > 1 )
102 : {
103 0 : std::istringstream in( params[1] );
104 0 : in >> m_timeLimit;
105 0 : }
106 21 : }
107 :
108 : /** Write method
109 : * basically calls \c throttle to check if the issue is accepted.
110 : * If this is the case, the \c write method on the chained stream is called with
111 : * \c issue.
112 : * \param issue issue to be sent.
113 : */
114 : void
115 58 : ers::ThrottleStream::write( const ers::Issue & issue )
116 : {
117 58 : const ers::Context& context = issue.context();
118 58 : std::string issueId = context.file_name() + boost::lexical_cast<std::string>(context.line_number());
119 :
120 58 : std::scoped_lock ml(m_mutex);
121 58 : throttle( m_issueMap[issueId], issue );
122 58 : }
|