Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
TraceMngPolicy.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* TraceMngPolicy.cc (C) 2000-2019 */
9/* */
10/* Policy for configuring trace managers. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arccore/base/ReferenceCounter.h"
15
16#include "arcane/utils/ITraceMng.h"
17#include "arcane/utils/StringBuilder.h"
18#include "arcane/utils/Iostream.h"
19#include "arcane/utils/ScopedPtr.h"
20#include "arcane/utils/PlatformUtils.h"
21#include "arcane/utils/String.h"
22#include "arcane/utils/TraceClassConfig.h"
23#include "arcane/utils/Array.h"
24#include "arcane/utils/ValueConvert.h"
25#include "arcane/utils/Iterator.h"
26#include "arcane/utils/ITraceMngPolicy.h"
27
28#include "arcane/core/XmlNode.h"
29#include "arcane/core/XmlNodeList.h"
30#include "arcane/core/IApplication.h"
31#include "arcane/core/IXmlDocumentHolder.h"
32
33#include <map>
34#include <mutex>
35#include <algorithm>
36
37/*---------------------------------------------------------------------------*/
38/*---------------------------------------------------------------------------*/
39
40namespace Arcane
41{
42
43/*---------------------------------------------------------------------------*/
44/*---------------------------------------------------------------------------*/
45
53class TraceMngPolicy
54: public ITraceMngPolicy
55{
56 public:
57
58 TraceMngPolicy(IApplication* app)
59 : m_application(app)
60 , m_is_parallel(false)
61 , m_is_debug(false)
62 , m_is_master_has_output_file(false)
63 , m_stdout_verbosity_level(Trace::UNSPECIFIED_VERBOSITY_LEVEL)
64 , m_verbosity_level(Trace::UNSPECIFIED_VERBOSITY_LEVEL)
65 , m_is_parallel_output(false)
66 {
67 m_default_config_doc = IXmlDocumentHolder::createNull();
68 m_output_file_prefix = platform::getEnvironmentVariable("ARCANE_PARALLEL_OUTPUT_PREFIX");
69 }
70
71 ~TraceMngPolicy()
72 {
73 }
74
75 void build() override {}
76 void initializeTraceMng(ITraceMng* trace, Int32 rank) override;
77 void initializeTraceMng(ITraceMng* trace, ITraceMng* parent_trace, const String& file_suffix) override;
78 void setClassConfigFromXmlBuffer(ITraceMng* trace, ByteConstArrayView bytes) override;
79 void setIsParallel(bool v) override { m_is_parallel = v; }
80 bool isParallel() const override { return m_is_parallel; }
81 void setIsDebug(bool v) override { m_is_debug = v; }
82 bool isDebug() const override { return m_is_debug; }
83 void setIsParallelOutput(bool v) override { m_is_parallel_output = v; }
84 bool isParallelOutput() const override { return m_is_parallel_output; }
85 void setStandardOutputVerbosityLevel(Int32 level) override { m_stdout_verbosity_level = level; }
86 Int32 standardOutputVerbosityLevel() const override { return m_stdout_verbosity_level; }
87 void setVerbosityLevel(Int32 level) override { m_verbosity_level = level; }
88 Int32 verbosityLevel() const override { return m_verbosity_level; }
89 void setIsMasterHasOutputFile(bool active) override { m_is_master_has_output_file = active; }
90 bool isMasterHasOutputFile() const override { return m_is_master_has_output_file; }
91 void setDefaultVerboseLevel(ITraceMng* trace, Int32 minimal_level) override;
92 void setDefaultClassConfigXmlBuffer(ByteConstSpan bytes) override;
93
94 private:
95
96 IApplication* m_application;
97 bool m_is_parallel;
98 bool m_is_debug;
99 bool m_is_master_has_output_file;
100 Int32 m_stdout_verbosity_level;
101 Int32 m_verbosity_level;
102 std::map<String, Arccore::ReferenceCounter<ITraceStream>> m_output_files;
103 String m_output_file_prefix;
104 bool m_is_parallel_output;
105 ScopedPtrT<IXmlDocumentHolder> m_default_config_doc;
106 std::mutex m_init_mutex;
107 std::mutex m_getfile_mutex;
108
109 private:
110
111 ITraceStream* _getFile(const String& rank);
112 void _initializeTraceClasses(ITraceMng* trace);
113 void _setAllTraceClassConfig(ITraceMng* trace, ByteConstArrayView bytes, bool do_log);
114 void _setAllTraceClassConfig(ITraceMng* trace, XmlNode root_element, bool do_log);
115 void _setAllTraceClassConfig(ITraceMng* trace, IXmlDocumentHolder* doc, bool do_log);
116 void _initializeTraceMng(ITraceMng* trace, bool is_master, const String& rank_str);
117};
118
119/*---------------------------------------------------------------------------*/
120/*---------------------------------------------------------------------------*/
121
122extern "C++" ARCANE_IMPL_EXPORT ITraceMngPolicy*
123arcaneCreateTraceMngPolicy(IApplication* app)
124{
125 ITraceMngPolicy* itmp = new TraceMngPolicy(app);
126 itmp->build();
127 return itmp;
128}
129
130/*---------------------------------------------------------------------------*/
131/*---------------------------------------------------------------------------*/
132
135{
136 _initializeTraceMng(trace, rank == 0, String::fromNumber(rank));
137}
138
139/*---------------------------------------------------------------------------*/
140/*---------------------------------------------------------------------------*/
141
142void TraceMngPolicy::
143_initializeTraceMng(ITraceMng* trace, bool is_master, const String& rank_str)
144{
145 bool is_output_file = false;
146 {
147 StringBuilder trace_id;
148 trace_id += rank_str;
149 trace_id += ",";
150 trace_id += platform::getHostName();
151 trace->setTraceId(trace_id.toString());
152 }
153 // By default, if nothing is specified, only the master process outputs the info.
154 bool is_info_disabled = !is_master;
155 if (m_is_parallel_output) {
156 is_info_disabled = false;
157 is_output_file = true;
158 }
159 if (is_master && m_is_master_has_output_file)
160 is_output_file = true;
161
162 trace->setInfoActivated(!is_info_disabled);
163
164 if (is_output_file) {
165 ITraceStream* ofile = _getFile(rank_str);
166 trace->setRedirectStream(ofile);
167 }
168
169 _initializeTraceClasses(trace);
170 trace->setMaster(is_master);
171 trace->finishInitialize();
172}
173
174/*---------------------------------------------------------------------------*/
175/*---------------------------------------------------------------------------*/
176
178initializeTraceMng(ITraceMng* trace, ITraceMng* parent_trace, const String& file_suffix)
179{
180 _initializeTraceMng(trace, false, file_suffix);
181 if (parent_trace) {
182 trace->setVerbosityLevel(parent_trace->verbosityLevel());
184 }
185}
186
187/*---------------------------------------------------------------------------*/
188/*---------------------------------------------------------------------------*/
189
191setDefaultVerboseLevel(ITraceMng* trace, Int32 minimal_level)
192{
193 if (m_verbosity_level != Trace::UNSPECIFIED_VERBOSITY_LEVEL) {
194 Int32 level = m_verbosity_level;
195 if (minimal_level != Trace::UNSPECIFIED_VERBOSITY_LEVEL)
196 level = std::max(level, minimal_level);
197 trace->setVerbosityLevel(level);
198 }
199 if (m_stdout_verbosity_level != Trace::UNSPECIFIED_VERBOSITY_LEVEL) {
200 Int32 level = m_stdout_verbosity_level;
201 if (minimal_level != Trace::UNSPECIFIED_VERBOSITY_LEVEL)
202 level = std::max(level, minimal_level);
204 }
205}
206
207/*---------------------------------------------------------------------------*/
208/*---------------------------------------------------------------------------*/
209
212{
213 _setAllTraceClassConfig(trace, bytes, false);
214}
215
216/*---------------------------------------------------------------------------*/
217/*---------------------------------------------------------------------------*/
218
219void TraceMngPolicy::
220setDefaultClassConfigXmlBuffer(ByteConstSpan bytes)
221{
222 if (bytes.empty()) {
223 m_default_config_doc = IXmlDocumentHolder::createNull();
224 return;
225 }
226
227 ITraceMng* tm = m_application->traceMng();
228 m_default_config_doc = IXmlDocumentHolder::loadFromBuffer(bytes, String(), tm);
229}
230
231/*---------------------------------------------------------------------------*/
232/*---------------------------------------------------------------------------*/
233
234ITraceStream* TraceMngPolicy::
235_getFile(const String& rank)
236{
237 std::lock_guard<std::mutex> guard(m_getfile_mutex);
238
239 auto i = m_output_files.find(rank);
240 if (i != m_output_files.end())
241 return i->second.get();
242
243 StringBuilder buf(m_output_file_prefix);
244 if (!m_output_file_prefix.null()) {
245 buf += "/";
246 }
247 buf += "output";
248 buf += rank;
249 String bufstr = buf.toString();
250
251 ReferenceCounter<ITraceStream> stream(ITraceStream::createFileStream(bufstr));
252 m_output_files.insert(std::make_pair(rank, stream));
253 return stream.get();
254}
255
256/*---------------------------------------------------------------------------*/
257/*---------------------------------------------------------------------------*/
258
259void TraceMngPolicy::
260_initializeTraceClasses(ITraceMng* trace)
261{
262 _setAllTraceClassConfig(trace, m_default_config_doc.get(), true);
263}
264
265/*---------------------------------------------------------------------------*/
266/*---------------------------------------------------------------------------*/
267
268void TraceMngPolicy::
269_setAllTraceClassConfig(ITraceMng* trace, ByteConstArrayView bytes, bool do_log)
270{
271 ScopedPtrT<IXmlDocumentHolder> config_doc;
272 if (!bytes.empty()) {
273 // Trace to display information during reading.
274 // Do not confuse with \a trace passed as argument
275 ITraceMng* print_tm = m_application->traceMng();
276 config_doc = IXmlDocumentHolder::loadFromBuffer(bytes, String(), print_tm);
277 }
278 _setAllTraceClassConfig(trace, config_doc.get(), do_log);
279}
280
281/*---------------------------------------------------------------------------*/
282/*---------------------------------------------------------------------------*/
283
284void TraceMngPolicy::
285_setAllTraceClassConfig(ITraceMng* trace, IXmlDocumentHolder* doc, bool do_log)
286{
287 // We must always call _setAllTraceClassConfig even if we don't have
288 // a root element, otherwise the default initialization is incorrect.
289 XmlNode root_element;
290 if (doc) {
291 XmlNode document_node = m_default_config_doc->documentNode();
292 if (!document_node.null())
293 root_element = document_node.documentElement();
294 }
295 _setAllTraceClassConfig(trace, root_element, do_log);
296}
297
298/*---------------------------------------------------------------------------*/
299/*---------------------------------------------------------------------------*/
300
301void TraceMngPolicy::
302_setAllTraceClassConfig(ITraceMng* trace, XmlNode root_element, bool do_log)
303{
304 if (do_log)
305 trace->logdate() << "Reading trace classes";
306
307 trace->removeAllClassConfig();
308 bool is_info_activated = trace->isInfoActivated();
309 Trace::eDebugLevel debug_level = Trace::Medium;
310 // Deactivates debug info if we are not outputting to a file
311 // and if the info is deactivated. This prevents all PEs from writing
312 // debug info to standard output.
313 if (!is_info_activated && !m_is_parallel_output)
314 debug_level = Trace::None;
315 TraceClassConfig medium_cc(is_info_activated, true, debug_level);
316 trace->setClassConfig("*", medium_cc);
317 if (root_element.null()) {
318 if (do_log)
319 trace->log() << "No user configuration";
320 return;
321 }
322
323 XmlNodeList children = root_element.child("traces").children("trace-class");
324 String ustr_name("name");
325 String ustr_info("info");
326 String ustr_pinfo("parallel-info");
327 String ustr_debug("debug");
328 String ustr_true("true");
329 String ustr_none("none");
330 String ustr_lowest("lowest");
331 String ustr_low("low");
332 String ustr_medium("medium");
333 String ustr_high("high");
334 String ustr_highest("highest");
335 String ustr_star("*");
336 String ustr_print_class_name("print-class-name");
337 String ustr_print_elapsed_time("print-elapsed-time");
338
339 for (const auto& xnode : children) {
340 String module_name = xnode.attrValue(ustr_name);
341 String activate_str = xnode.attrValue(ustr_info);
342 String parallel_activate_str = xnode.attrValue(ustr_pinfo);
343 String dbg_lvl_str = xnode.attrValue(ustr_debug);
344 String print_class_name_str = xnode.attrValue(ustr_print_class_name);
345 String print_elapsed_time_str = xnode.attrValue(ustr_print_elapsed_time);
346 if (module_name.null())
347 continue;
348 TraceClassConfig def_config = trace->classConfig("*");
349 bool is_activate = def_config.isActivated();
350 builtInGetValue(is_activate, activate_str);
351 bool is_parallel_activate = is_activate;
352 // If \a disable_info is true, deactivate info messages unless
353 // \e parallel-info is \a true
354 if (!is_info_activated) {
355 is_activate = false;
356 if (parallel_activate_str == ustr_true)
357 is_activate = true;
358 }
359
360 Trace::eDebugLevel dbg_lvl = def_config.debugLevel();
361 {
362 if (dbg_lvl_str == ustr_none)
363 dbg_lvl = Trace::None;
364 if (dbg_lvl_str == ustr_lowest)
365 dbg_lvl = Trace::Lowest;
366 if (dbg_lvl_str == ustr_low)
367 dbg_lvl = Trace::Low;
368 if (dbg_lvl_str == ustr_medium)
369 dbg_lvl = Trace::Medium;
370 if (dbg_lvl_str == ustr_high)
371 dbg_lvl = Trace::High;
372 if (dbg_lvl_str == ustr_highest)
373 dbg_lvl = Trace::Highest;
374 }
375
376 bool is_print_class_name = true;
377 builtInGetValue(is_print_class_name, print_class_name_str);
378 bool is_print_elapsed_time = false;
379 builtInGetValue(is_print_elapsed_time, print_elapsed_time_str);
380 int flags = Trace::PF_Default;
381 if (!is_print_class_name)
382 flags |= Trace::PF_NoClassName;
383 if (is_print_elapsed_time)
384 flags |= Trace::PF_ElapsedTime;
385
386 TraceClassConfig mc(is_activate, is_parallel_activate, dbg_lvl, flags);
387 if (do_log)
388 trace->log() << "Config " << mc.isActivated() << ' '
389 << mc.isParallelActivated() << ' ' << module_name;
390 trace->setClassConfig(module_name, mc);
391 if (do_log)
392 trace->log() << "Config module class"
393 << " name=" << module_name
394 << " activated=" << is_activate
395 << " dbglvl=" << (int)dbg_lvl;
396 }
397}
398
399/*---------------------------------------------------------------------------*/
400/*---------------------------------------------------------------------------*/
401
402} // End namespace Arcane
403
404/*---------------------------------------------------------------------------*/
405/*---------------------------------------------------------------------------*/
Application interface.
virtual ITraceMng * traceMng() const =0
Trace manager.
Interface for the configuration manager of a trace manager.
virtual bool setInfoActivated(bool v)=0
Modifies the activation state of info messages.
virtual void setMaster(bool is_master)=0
Sets the 'master' state of the instance.
virtual ARCCORE_DEPRECATED_2018 void setRedirectStream(std::ostream *o)=0
Redirects all messages to the stream o.
virtual void setStandardOutputVerbosityLevel(Int32 level)=0
Sets the verbosity level of outputs on std::cout.
virtual Int32 standardOutputVerbosityLevel() const =0
Message verbosity level on std::cout.
virtual void finishInitialize()=0
Finishes initialization.
virtual void setTraceId(const String &id)=0
Sets the manager identifier.
virtual Int32 verbosityLevel() const =0
Message verbosity level.
virtual void setVerbosityLevel(Int32 level)=0
Sets the verbosity level of the outputs.
Manager of a DOM document.
static IXmlDocumentHolder * createNull()
Creates and returns a null document.
static IXmlDocumentHolder * loadFromBuffer(Span< const Byte > buffer, const String &name, ITraceMng *tm)
Loads an XML document.
Definition DomUtils.cc:425
Unicode character string constructor.
String toString() const
Returns the constructed character string.
Management of trace behavior.
void setStandardOutputVerbosityLevel(Int32 level) override
Verbosity level for the standard output stream (stdout).
void setIsParallelOutput(bool v) override
Indicates if all ranks output traces to a file in parallel.
void setClassConfigFromXmlBuffer(ITraceMng *trace, ByteConstArrayView bytes) override
Sets the values of the TraceClassConfig of trace via the data contained in bytes.
void setIsDebug(bool v) override
Indicates if debug outputs are active.
void setIsParallel(bool v) override
Indicates if parallelism is active.
void setIsMasterHasOutputFile(bool active) override
Indicates if a master ITraceMng outputs traces to a file in addition to standard output.
void initializeTraceMng(ITraceMng *trace, Int32 rank) override
Initializes trace.
void setDefaultVerboseLevel(ITraceMng *trace, Int32 minimal_level) override
void setVerbosityLevel(Int32 level) override
Verbosity level.
void build() override
Constructs the instance.
Node of a DOM tree.
Definition XmlNode.h:51
@ Medium
Medium level (default).
@ PF_ElapsedTime
Display of elapsed time.
@ PF_NoClassName
Display or not the message class.
String getHostName()
Name of the machine running the process.
String getEnvironmentVariable(const String &name)
Environment variable named name.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Span< const std::byte > ByteConstSpan
Read-only view of a 1D array of characters.
Definition UtilsTypes.h:548
ConstArrayView< Byte > ByteConstArrayView
C equivalent of a 1D array of characters.
Definition UtilsTypes.h:476
std::int32_t Int32
Signed integer type of 32 bits.