Kea  1.9.9-git
log_parser.cc
Go to the documentation of this file.
1 // Copyright (C) 2014-2019 Internet Systems Consortium, Inc. ("ISC")
2 //
3 // This Source Code Form is subject to the terms of the Mozilla Public
4 // License, v. 2.0. If a copy of the MPL was not distributed with this
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 
7 #include <config.h>
8 #include <cc/data.h>
9 #include <process/log_parser.h>
10 #include <boost/foreach.hpp>
11 #include <boost/lexical_cast.hpp>
13 #include <log/logger_support.h>
14 #include <log/logger_manager.h>
15 #include <log/logger_name.h>
16 
17 using namespace isc::data;
18 using namespace isc::log;
19 
20 namespace isc {
21 namespace process {
22 
23 LogConfigParser::LogConfigParser(const ConfigPtr& storage)
24  :config_(storage), verbose_(false) {
25  if (!storage) {
26  isc_throw(BadValue, "LogConfigParser needs a pointer to the "
27  "configuration, so parsed data can be stored there");
28  }
29 }
30 
32  bool verbose) {
33  verbose_ = verbose;
34 
35  // Iterate over all entries in "Server/loggers" list
36  BOOST_FOREACH(ConstElementPtr logger, loggers->listValue()) {
37  parseConfigEntry(logger);
38  }
39 }
40 
41 void LogConfigParser::parseConfigEntry(isc::data::ConstElementPtr entry) {
42  if (!entry) {
43  // This should not happen, but let's be on the safe side and check
44  return;
45  }
46 
47  if (!config_) {
48  isc_throw(BadValue, "configuration storage not set, can't parse logger config.");
49  }
50 
51  LoggingInfo info;
52  // Remove default destinations as we are going to replace them.
53  info.clearDestinations();
54 
55  // Get user context
56  isc::data::ConstElementPtr user_context = entry->get("user-context");
57  if (user_context) {
58  info.setContext(user_context);
59  }
60 
61  // Get a name
62  isc::data::ConstElementPtr name_ptr = entry->get("name");
63  if (!name_ptr) {
64  isc_throw(BadValue, "loggers entry does not have a mandatory 'name' "
65  "element (" << entry->getPosition() << ")");
66  }
67  info.name_ = name_ptr->stringValue();
68 
69  // Get severity
70  isc::data::ConstElementPtr severity_ptr = entry->get("severity");
71  if (!severity_ptr) {
72  isc_throw(BadValue, "loggers entry does not have a mandatory "
73  "'severity' element (" << entry->getPosition() << ")");
74  }
75  try {
76  info.severity_ = isc::log::getSeverity(severity_ptr->stringValue().c_str());
77  } catch (const std::exception&) {
78  isc_throw(BadValue, "Unsupported severity value '"
79  << severity_ptr->stringValue() << "' ("
80  << severity_ptr->getPosition() << ")");
81  }
82 
83  // Get debug logging level
84  info.debuglevel_ = 0;
85  isc::data::ConstElementPtr debuglevel_ptr = entry->get("debuglevel");
86 
87  // It's ok to not have debuglevel, we'll just assume its least verbose
88  // (0) level.
89  if (debuglevel_ptr) {
90  try {
91  info.debuglevel_ = boost::lexical_cast<int>(debuglevel_ptr->str());
92  if ( (info.debuglevel_ < 0) || (info.debuglevel_ > 99) ) {
93  // Comment doesn't matter, it is caught several lines below
94  isc_throw(BadValue, "");
95  }
96  } catch (...) {
97  isc_throw(BadValue, "Unsupported debuglevel value '"
98  << debuglevel_ptr->stringValue()
99  << "', expected 0-99 ("
100  << debuglevel_ptr->getPosition() << ")");
101  }
102  }
103 
104  // We want to follow the normal path, so it could catch parsing errors even
105  // when verbose mode is enabled. If it is, just override whatever was parsed
106  // in the config file.
107  if (verbose_) {
108  info.severity_ = isc::log::DEBUG;
109  info.debuglevel_ = 99;
110  }
111 
112  isc::data::ConstElementPtr output_options = entry->get("output_options");
113 
114  if (output_options) {
115  parseOutputOptions(info.destinations_, output_options);
116  }
117 
118  config_->addLoggingInfo(info);
119 }
120 
121 void LogConfigParser::parseOutputOptions(std::vector<LoggingDestination>& destination,
122  isc::data::ConstElementPtr output_options) {
123  if (!output_options) {
124  isc_throw(BadValue, "Missing 'output_options' structure in 'loggers'");
125  }
126 
127  BOOST_FOREACH(ConstElementPtr output_option, output_options->listValue()) {
128 
129  LoggingDestination dest;
130 
131  isc::data::ConstElementPtr output = output_option->get("output");
132  if (!output) {
133  isc_throw(BadValue, "output_options entry does not have a mandatory 'output' "
134  "element (" << output_option->getPosition() << ")");
135  }
136  dest.output_ = output->stringValue();
137 
138  isc::data::ConstElementPtr maxver_ptr = output_option->get("maxver");
139  if (maxver_ptr) {
140  dest.maxver_ = boost::lexical_cast<int>(maxver_ptr->str());
141  }
142 
143  isc::data::ConstElementPtr maxsize_ptr = output_option->get("maxsize");
144  if (maxsize_ptr) {
145  dest.maxsize_ = boost::lexical_cast<uint64_t>(maxsize_ptr->str());
146  }
147 
148  isc::data::ConstElementPtr flush_ptr = output_option->get("flush");
149  if (flush_ptr) {
150  dest.flush_ = flush_ptr->boolValue();
151  }
152 
153  isc::data::ConstElementPtr pattern = output_option->get("pattern");
154  if (pattern) {
155  dest.pattern_ = pattern->stringValue();
156  }
157 
158  destination.push_back(dest);
159  }
160 }
161 
162 } // namespace isc::dhcp
163 } // namespace isc
isc::log::Severity getSeverity(const std::string &sev_str)
Returns the isc::log::Severity value represented by the given string.
Definition: logger_level.cc:20
void parseConfiguration(const isc::data::ConstElementPtr &log_config, bool verbose=false)
Parses specified configuration.
Definition: log_parser.cc:31
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:23
Defines the logger used by the top-level component of kea-dhcp-ddns.
isc::log::Logger logger("asiodns")
Use the ASIO logger.
Logging initialization functions.
boost::shared_ptr< ConfigBase > ConfigPtr
Non-const pointer to the ConfigBase.
Definition: config_base.h:176