bd7ed8fd3461218a353850704103a6339a95def7
[senf.git] / senf / Utils / Logger / SyslogUDPTarget.cc
1 // $Id$
2 //
3 // Copyright (C) 2008
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 //     Stefan Bund <g0dil@berlios.de>
7 //
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
23 /** \file
24     \brief SyslogUDPTarget non-inline non-template implementation */
25
26 #include "SyslogUDPTarget.hh"
27 //#include "SyslogUDPTarget.ih"
28
29 // Custom includes
30 #include <sstream>
31 #include <boost/algorithm/string/trim.hpp>
32 #include <boost/tokenizer.hpp>
33 #include <senf/Utils/Console/ParsedCommand.hh>
34 #include <senf/Utils/Console/Traits.hh>
35 #include <senf/Utils/Console/ScopedDirectory.hh>
36
37 //#include "SyslogUDPTarget.mpp"
38 #define prefix_
39 //-/////////////////////////////////////////////////////////////////////////////////////////////////
40
41 prefix_ void senf::log::SyslogUDPTarget::init()
42 {
43     namespace kw = senf::console::kw;
44     namespace fty = senf::console::factory;
45
46     consoleDir().remove("format");
47     consoleDir()
48         .add("format", fty::Command(&SyslogUDPTarget::consoleFormat, this)
49              .doc("Show the current log message format.") );
50     consoleDir()
51         .add("syslog", fty::Command(SENF_MEMBINDFNP(void, SyslogUDPTarget, syslog, (bool)))
52              .arg("flag","new syslog format state",
53                   kw::default_value=true)
54              .doc("Change the syslog format flag. By default, syslog formating is enabled. In this\n"
55                   "state, the udp target will send out minimal but valid syslog format messages.\n"
56                   "\n"
57                   "Disabling syslog format will remove the syslog prefix. Log messages will then be\n"
58                   "sent using plain UDP.") );
59 }
60
61 prefix_ void senf::log::SyslogUDPTarget::v_write(time_type timestamp, std::string const & stream,
62                                                  std::string const & area, unsigned level,
63                                                  std::string const & message)
64 {
65     std::string m (message);
66     boost::trim_right(m);
67     detail::quoteNonPrintable(m);
68
69     std::stringstream prfstream;
70     // The space after the '>' is there on purpose: It ensures, that the prefix (which may be empty)
71     // or message will not inadvertently be interpreted as date or hostname by a receiving syslog
72     // daemon or proxy
73     if (syslogFormat_)
74         prfstream << '<' << (facility_ | senf::log::SyslogTarget::LEVELMAP[level]) << "> ";
75     prfstream << prefix(timestamp, stream, area, level);
76     std::string const & prf (prfstream.str());
77
78     typedef boost::char_separator<char> Separator;
79     typedef boost::tokenizer<Separator> Tokenizer;
80     Separator separator ("\n");
81     Tokenizer tokenizer (m, separator);
82     Tokenizer::iterator i (tokenizer.begin());
83     Tokenizer::iterator const i_end (tokenizer.end());
84
85     std::string line;
86     unsigned sz (896-prf.size());
87     for (; i != i_end; ++i)
88         for (unsigned j (0); j < i->size(); j += sz) {
89             line = prf;
90             line += std::string(*i, j, sz);
91             handle_.write(line);
92         }
93 }
94
95 prefix_ void senf::log::SyslogUDPTarget::consoleFormat(std::ostream & os)
96 {
97     LogFormat::consoleFormat(os);
98     os << "syslog prefix " << (syslogFormat_ ? "enabled" : "disabled") << "\n";
99 }
100
101 namespace senf {
102 namespace log {
103
104     SENF_CONSOLE_REGISTER_ENUM_MEMBER(SyslogUDPTarget, LogFacility,
105                                       (AUTHPRIV)(CRON)(DAEMON)(FTP)(KERN)(LPR)(MAIL)(NEWS)(SYSLOG)
106                                       (USER)(UUCP)(LOCAL0)(LOCAL1)(LOCAL2)(LOCAL3)(LOCAL4)(LOCAL5)
107                                       (LOCAL6)(LOCAL7));
108
109 }}
110
111 prefix_ senf::log::SyslogUDPTarget::RegisterConsole::RegisterConsole()
112 {
113     namespace kw = senf::console::kw;
114     namespace fty = senf::console::factory;
115
116     detail::TargetRegistry::instance().consoleDir()
117         .add("udp-target",
118              fty::Command<senf::console::DirectoryNode::ptr (*)(INet4SocketAddress const &,
119                                                                 LogFacility)
120              >(&RegisterConsole::create)
121              .arg("address", "target address to send log messages to")
122              .arg("facility", "syslog facility to send messages to. One of\n"
123                   "                  AUTHPRIV CRON DAEMON FTP KERN LPR MAIL NEWS SYSLOG USER\n"
124                   "                  UUCP LOCAL0 LOCAL1 LOCAL2 LOCAL3 LOCAL4 LOCAL5 LOCAL6 LOCAL7",
125                   kw::default_value = USER)
126              .doc("Create new udp target. The {address} can be an IPv4 or IPv6 address. If the port\n"
127                   "number is omitted, it defaults to the default syslog port 514. Examples:\n"
128                   "\n"
129                   "Create new udp target sending messages to the syslog daemon running at localhost\n"
130                   "    $ udp-target localhost\n"
131                   "    <Directory '/sys/log/udp-127.0.0.1:514'>\n"
132                   "\n"
133                   "In a configuration file, create new udp target and set some parameters (If\n"
134                   "written on one line, this works at the console too:\n"
135                   "    /sys/log/udp-target localhost:2345 LOCAL2 {\n"
136                   "        route (IMPORTANT);             # route all important messages\n"
137                   "        timeFormat \"\";               # use non-formatted time format\n"
138                   "        showArea false;                # don't show log area\n"
139                   "        syslog false;                  # no syslog format, just plain udp\n"
140                   "    }\n") );
141     detail::TargetRegistry::instance().consoleDir()
142         .add("udp-target",
143              fty::Command<senf::console::DirectoryNode::ptr (*)(INet4Address const &,
144                                                                 LogFacility)
145              >(&RegisterConsole::create)
146              .arg("address")
147              .arg("facility", kw::default_value = USER) );
148     detail::TargetRegistry::instance().consoleDir()
149         .add("udp-target",
150              fty::Command<senf::console::DirectoryNode::ptr (*)(INet6SocketAddress const &,
151                                                                 LogFacility)
152              >(&RegisterConsole::create)
153              .arg("address")
154              .arg("facility", kw::default_value = USER) );
155     detail::TargetRegistry::instance().consoleDir()
156         .add("udp-target",
157              fty::Command<senf::console::DirectoryNode::ptr (*)(INet6Address const &,
158                                                                 LogFacility)
159              >(&RegisterConsole::create)
160              .arg("address")
161              .arg("facility", kw::default_value = USER) );
162 }
163
164 prefix_ boost::shared_ptr<senf::console::DirectoryNode>
165 senf::log::SyslogUDPTarget::RegisterConsole::create(senf::INet4SocketAddress const & target,
166                                                     LogFacility facility)
167 {
168     std::auto_ptr<Target> tp (new SyslogUDPTarget(target, facility));
169     Target & tg (*tp.get());
170     detail::TargetRegistry::instance().dynamicTarget(tp);
171     return tg.consoleDir().node().thisptr();
172 }
173
174 prefix_ boost::shared_ptr<senf::console::DirectoryNode>
175 senf::log::SyslogUDPTarget::RegisterConsole::create(senf::INet4Address const & target,
176                                                     LogFacility facility)
177 {
178     std::auto_ptr<Target> tp (new SyslogUDPTarget(target, facility));
179     Target & tg (*tp.get());
180     detail::TargetRegistry::instance().dynamicTarget(tp);
181     return tg.consoleDir().node().thisptr();
182 }
183
184 prefix_ boost::shared_ptr<senf::console::DirectoryNode>
185 senf::log::SyslogUDPTarget::RegisterConsole::create(senf::INet6SocketAddress const & target,
186                                                     LogFacility facility)
187 {
188     std::auto_ptr<Target> tp (new SyslogUDPTarget(target, facility));
189     Target & tg (*tp.get());
190     detail::TargetRegistry::instance().dynamicTarget(tp);
191     return tg.consoleDir().node().thisptr();
192 }
193
194 prefix_ boost::shared_ptr<senf::console::DirectoryNode>
195 senf::log::SyslogUDPTarget::RegisterConsole::create(senf::INet6Address const & target,
196                                                     LogFacility facility)
197 {
198     std::auto_ptr<Target> tp (new SyslogUDPTarget(target, facility));
199     Target & tg (*tp.get());
200     detail::TargetRegistry::instance().dynamicTarget(tp);
201     return tg.consoleDir().node().thisptr();
202 }
203
204 //-/////////////////////////////////////////////////////////////////////////////////////////////////
205 #undef prefix_
206 //#include "SyslogUDPTarget.mpp"
207
208 \f
209 // Local Variables:
210 // mode: c++
211 // fill-column: 100
212 // comment-column: 40
213 // c-file-style: "senf"
214 // indent-tabs-mode: nil
215 // ispell-local-dictionary: "american"
216 // compile-command: "scons -u test"
217 // End: