First commit
[anna.git] / include / anna / core / tracing / TraceLevelChecker.hpp
1 // ANNA - Anna is Not 'N' Anymore
2 //
3 // (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
4 //
5 // https://bitbucket.org/testillano/anna
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
9 // are met:
10 //
11 //     * Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 //     * Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following disclaimer
15 // in the documentation and/or other materials provided with the
16 // distribution.
17 //     * Neither the name of Google Inc. nor the names of its
18 // contributors may be used to endorse or promote products derived from
19 // this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 //
33 // Authors: eduardo.ramos.testillano@gmail.com
34 //          cisco.tierra@gmail.com
35
36
37 #ifndef anna_core_tracing_TraceLevelChecker_hpp
38 #define anna_core_tracing_TraceLevelChecker_hpp
39
40
41
42 #include <anna/core/tracing/Logger.hpp>
43
44 // STL
45 #include <string>
46
47
48
49 namespace anna {
50
51 namespace tracing {
52
53
54
55 /**
56 * Helper class used for selective tracing
57 */
58 class TraceLevelChecker {
59
60
61   anna::Logger::Level a_previousLevel; // backup level to be restored at destructor
62   std::string a_contextData;
63
64 public:
65
66
67   /**
68   * Constructs one class instance providing the context data to be compared with current configuration
69   * trigger references. Depending on changeLevelCondition(), certain trace level will be assigned. Trace level is
70   * preconfigured on global Configuration class for each trigger item, but changeLevelCondition() re-implementation
71   * could modify this behaviour (i.e. fix to debug level for all situations).
72   * That easy... just like that: build instance wherever you want to check context to decide a trace level change.
73   *
74   * Is possible to detect several concepts with a little imagination. For example, if you want to change
75   * trace level when MSISDN is 609555555 and ServiceId is greater than 3, you could do something like this:
76   *
77   * <pre>
78   *    1) Set the trigger (usually this is done at general configuration, oam commands, etc):
79   *    (Configuration::instantiate()).activateTraceTrigger("609555555#3"); // only one trigger item (more didactic)
80   *
81   *    Triggers are strings, then multi-concept contexts requires token management or something similar.
82   *
83   *    2) Create the child class with specific condition method:
84   *    2.1) MyTraceLevelChecker_WithMsisdnAndserviceIdLessThanValue inherit from TraceLevelChecker
85   *    2.2) MyTraceLevelChecker_WithMsisdnAndserviceIdLessThanValue::changeLevelCondition() reimplementation:
86   *          Tokenize ('#' separator) both context data and reference trigger item:
87   *          a) extract 'contextMSISDN' from 'contextData'
88   *          b) extract 'contextSERVICEID' from 'contextData'
89   *          c) extract 'MSISDNreference' (see Configuration::getTraceTriggerMap())
90   *          d) extract 'SERVICEIDreference' (idem)
91   *          e) Return condition: (contextMSISDN == MSISDNreference) && (atoi(contextSERVICEID) > atoi(SERVICEIDreference))
92   *
93   *    3) Plan selective trace on application handler (data receive, context expiration, etc.):
94   *    std::string contextChain = msisdn; contextChain += "#"; contextChain += anna::functions::asString(serviceId);
95   *    MyTraceLevelChecker_WithMsisdnAndserviceIdLessThanValue tlc (contextChain);
96   *
97   *    Normally, only one concept like MSISDN is compared, and the list of triggers references has only one item.
98   * </pre>
99   *
100   * @param contextData String to be compared. If NULL provided, no checkings will be done now (use load() instead)
101   * and empty string will be prepared for future load() calls without context data specification.
102   *
103   * @see load()
104   */
105   TraceLevelChecker(const char * contextData = NULL) {
106     a_previousLevel = anna::Logger::getLevel(); // protection (si por error no se usara el load() nunca, el destructor podria alterar el nivel de traceo del proceso)
107     a_contextData = contextData ? contextData : "";
108
109     if(contextData) load(contextData);
110   }
111
112
113   /**
114   * Destructor restores initial context trace level
115   *
116   * This apply when application finish the execution scope or when exceptions are launched anywhere.
117   *
118   * @see restore()
119   */
120   ~TraceLevelChecker() { restore(); }
121
122
123   /**
124   * Defines the condition between the context information and global Configuration class trigger references.
125   * Target trace level when condition is true, is preconfigured for each trigger reference, but this method
126   * could be reimplemented to fix to debug level ignoring global Configuration class trigger preferences.
127   *
128   * Default implementation check incoming context data to be the same as any of the global Configuration
129   * class trigger references registered. Specific implementation could check that context data contains
130   * any of the trigger reference, or perhaps use regular expressions to be more flexible.
131   *
132   * @param contextData String to be compared
133   * @param targetLevel Desired target level configured for each trigger item at global Configuration class
134   */
135   virtual bool changeLevelCondition(const std::string & contextData, anna::Logger::Level & targetLevel) const throw();
136
137
138   /**
139   * Performs trace level checkings for context data provided.
140   * Gives higher control over the funtionality: using with restore(), application can fix tracing
141   * zones, but in most cases constructor & destructor are enough for normal behaviour (more simply and secure).
142   *
143   * Multiple calls to this method could provide OR operation regarding trace level changes with context data
144   * strings loaded, but this is unusual because implies assume same nature for different context indicators.
145   * Then, be careful if data passed is not sure to be the same when application manage different tracing zones
146   * with restore().
147   *
148   * @param contextData String to be compared. If NULL provided (default-missing parameter call), last valid
149   * assignment (within constructor or former load() call) will be used.
150   *
151   * @return Boolean about trace level change because of condition result
152   */
153   bool load(const char * contextData = NULL) throw();
154
155
156   /**
157   * Do the same than destructor.
158   * Gives higher control over the funtionality: using with load(), application can fix tracing
159   * zones, but in most cases constructor & destructor are enough for normal behaviour.
160   *
161   * @return Boolean about Trace level change because restore proceed
162   */
163   bool restore(void) throw();
164 };
165
166 }
167 }
168
169 #endif