1//
2// NestedDiagnosticContext.h
3//
4// Library: Foundation
5// Package: Core
6// Module: NestedDiagnosticContext
7//
8// Definition of the NestedDiagnosticContext class.
9//
10// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
11// and Contributors.
12//
13// SPDX-License-Identifier: BSL-1.0
14//
15
16
17#ifndef Foundation_NestedDiagnosticContext_INCLUDED
18#define Foundation_NestedDiagnosticContext_INCLUDED
19
20
21#include "Poco/Foundation.h"
22#include <vector>
23#include <ostream>
24
25
26namespace Poco {
27
28
29class NDCScope;
30
31
32class Foundation_API NestedDiagnosticContext
33 /// This class implements a Nested Diagnostic Context (NDC),
34 /// as described in Neil Harrison's article "Patterns for Logging
35 /// Diagnostic Messages" in "Pattern Languages of Program Design 3"
36 /// (Addison-Wesley).
37 ///
38 /// A NDC maintains a stack of context information, consisting of
39 /// an informational string (e.g., a method name), as well as an
40 /// optional source code line number and file name.
41 /// NDCs are especially useful for tagging log messages with
42 /// context information which is very helpful in a multithreaded
43 /// server scenario.
44 /// Every thread has its own private NDC, which is automatically
45 /// created when needed and destroyed when the thread terminates.
46 ///
47 /// The NDCScope (or NDC::Scope) class can be used to automatically
48 /// push information at the beginning of a scope, and to pop it
49 /// at the end.
50 /// The poco_ndc(info) macro augments the information with a
51 /// source code line number and file name.
52{
53public:
54 typedef NDCScope Scope;
55
56 NestedDiagnosticContext();
57 /// Creates the NestedDiagnosticContext.
58
59 NestedDiagnosticContext(const NestedDiagnosticContext& ctx);
60 /// Copy constructor.
61
62 ~NestedDiagnosticContext();
63 /// Destroys the NestedDiagnosticContext.
64
65 NestedDiagnosticContext& operator = (const NestedDiagnosticContext& ctx);
66 /// Assignment operator.
67
68 void push(const std::string& info);
69 /// Pushes a context (without line number and filename) onto the stack.
70
71 void push(const std::string& info, int line, const char* filename);
72 /// Pushes a context (including line number and filename)
73 /// onto the stack. Filename must be a static string, such as the
74 /// one produced by the __FILE__ preprocessor macro.
75
76 void pop();
77 /// Pops the top-most context off the stack.
78
79 int depth() const;
80 /// Returns the depth (number of contexts) of the stack.
81
82 std::string toString() const;
83 /// Returns the stack as a string with entries
84 /// delimited by colons. The string does not contain
85 /// line numbers and filenames.
86
87 void dump(std::ostream& ostr) const;
88 /// Dumps the stack (including line number and filenames)
89 /// to the given stream. The entries are delimited by
90 /// a newline.
91
92 void dump(std::ostream& ostr, const std::string& delimiter) const;
93 /// Dumps the stack (including line number and filenames)
94 /// to the given stream.
95
96 void clear();
97 /// Clears the NDC stack.
98
99 static NestedDiagnosticContext& current();
100 /// Returns the current thread's NDC.
101
102private:
103 struct Context
104 {
105 std::string info;
106 const char* file;
107 int line;
108 };
109 typedef std::vector<Context> Stack;
110
111 Stack _stack;
112};
113
114
115typedef NestedDiagnosticContext NDC;
116
117
118class Foundation_API NDCScope
119 /// This class can be used to automatically push a context onto
120 /// the NDC stack at the beginning of a scope, and to pop
121 /// the context at the end of the scope.
122{
123public:
124 NDCScope(const std::string& info);
125 /// Pushes a context on the stack.
126
127 NDCScope(const std::string& info, int line, const char* filename);
128 /// Pushes a context on the stack.
129
130 ~NDCScope();
131 /// Pops the top-most context off the stack.
132};
133
134
135//
136// inlines
137//
138inline NDCScope::NDCScope(const std::string& info)
139{
140 NestedDiagnosticContext::current().push(info);
141}
142
143
144inline NDCScope::NDCScope(const std::string& info, int line, const char* filename)
145{
146 NestedDiagnosticContext::current().push(info, line, filename);
147}
148
149
150inline NDCScope::~NDCScope()
151{
152 try
153 {
154 NestedDiagnosticContext::current().pop();
155 }
156 catch (...)
157 {
158 poco_unexpected();
159 }
160}
161
162
163//
164// helper macros
165//
166#define poco_ndc(func) \
167 Poco::NDCScope _theNdcScope(#func, __LINE__, __FILE__)
168
169
170#if defined(_DEBUG)
171 #define poco_ndc_dbg(func) \
172 Poco::NDCScope _theNdcScope(#func, __LINE__, __FILE__)
173#else
174 #define poco_ndc_dbg(func)
175#endif
176
177
178} // namespace Poco
179
180
181#endif // Foundation_NestedDiagnosticContext_INCLUDED
182