summaryrefslogtreecommitdiff
path: root/boost/log/sinks/syslog_backend.hpp
blob: 74249311895aee203b050405f9a1d6fe978390cc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
/*
 *          Copyright Andrey Semashev 2007 - 2015.
 * Distributed under the Boost Software License, Version 1.0.
 *    (See accompanying file LICENSE_1_0.txt or copy at
 *          http://www.boost.org/LICENSE_1_0.txt)
 */
/*!
 * \file   syslog_backend.hpp
 * \author Andrey Semashev
 * \date   08.01.2008
 *
 * The header contains implementation of a Syslog sink backend along with its setup facilities.
 */

#ifndef BOOST_LOG_SINKS_SYSLOG_BACKEND_HPP_INCLUDED_
#define BOOST_LOG_SINKS_SYSLOG_BACKEND_HPP_INCLUDED_

#include <boost/log/detail/config.hpp>

#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif

#ifndef BOOST_LOG_WITHOUT_SYSLOG

#include <string>
#include <boost/log/detail/asio_fwd.hpp>
#include <boost/log/detail/light_function.hpp>
#include <boost/log/detail/parameter_tools.hpp>
#include <boost/log/sinks/basic_sink_backend.hpp>
#include <boost/log/sinks/syslog_constants.hpp>
#include <boost/log/sinks/attribute_mapping.hpp>
#include <boost/log/attributes/attribute_value_set.hpp>
#include <boost/log/keywords/facility.hpp>
#include <boost/log/keywords/use_impl.hpp>
#include <boost/log/keywords/ident.hpp>
#include <boost/log/keywords/ip_version.hpp>
#include <boost/log/detail/header.hpp>

namespace boost {

BOOST_LOG_OPEN_NAMESPACE

namespace sinks {

//! Supported IP protocol versions
enum ip_versions
{
    v4,
    v6
};

namespace syslog {

    //! The enumeration defined the possible implementation types for the syslog backend
    enum impl_types
    {
#ifdef BOOST_LOG_USE_NATIVE_SYSLOG
        native = 0                  //!< Use native syslog API
#ifndef BOOST_LOG_NO_ASIO
        ,
#endif
#endif
#ifndef BOOST_LOG_NO_ASIO
        udp_socket_based = 1        //!< Use UDP sockets, according to RFC3164
#endif
    };

    /*!
     * \brief Straightforward severity level mapping
     *
     * This type of mapping assumes that attribute with a particular name always
     * provides values that map directly onto the Syslog levels. The mapping
     * simply returns the extracted attribute value converted to the Syslog severity level.
     */
    template< typename AttributeValueT = int >
    class direct_severity_mapping :
        public basic_direct_mapping< level, AttributeValueT >
    {
        //! Base type
        typedef basic_direct_mapping< level, AttributeValueT > base_type;

    public:
        /*!
         * Constructor
         *
         * \param name Attribute name
         */
        explicit direct_severity_mapping(attribute_name const& name) :
            base_type(name, info)
        {
        }
    };

    /*!
     * \brief Customizable severity level mapping
     *
     * The class allows to setup a custom mapping between an attribute and Syslog severity levels.
     * The mapping should be initialized similarly to the standard \c map container, by using
     * indexing operator and assignment.
     */
    template< typename AttributeValueT = int >
    class custom_severity_mapping :
        public basic_custom_mapping< level, AttributeValueT >
    {
        //! Base type
        typedef basic_custom_mapping< level, AttributeValueT > base_type;

    public:
        /*!
         * Constructor
         *
         * \param name Attribute name
         */
        explicit custom_severity_mapping(attribute_name const& name) :
            base_type(name, info)
        {
        }
    };

} // namespace syslog

/*!
 * \brief An implementation of a syslog sink backend
 *
 * The backend provides support for the syslog protocol, defined in RFC3164.
 * The backend sends log records to a remote host via UDP. The host name can
 * be specified by calling the \c set_target_address method. By default log
 * records will be sent to localhost:514. The local address can be specified
 * as well, by calling the \c set_local_address method. By default syslog
 * packets will be sent from any local address available.
 *
 * It is safe to create several sink backends with the same local addresses -
 * the backends within the process will share the same socket. The same applies
 * to different processes that use the syslog backends to send records from
 * the same socket. However, it is not guaranteed to work if some third party
 * facility is using the socket.
 *
 * On systems with native syslog implementation it may be preferable to utilize
 * the POSIX syslog API instead of direct socket management in order to bypass
 * possible security limitations that may be in action. To do so one has to pass
 * the <tt>use_impl = native</tt> to the backend constructor. Note, however,
 * that in that case you will only have one chance to specify syslog facility and
 * process identification string - on the first native syslog backend construction.
 * Other native syslog backends will ignore these parameters.
 * Obviously, the \c set_local_address and \c set_target_address
 * methods have no effect for native backends. Using <tt>use_impl = native</tt>
 * on platforms with no native support for POSIX syslog API will have no effect.
 */
class syslog_backend :
    public basic_formatted_sink_backend< char >
{
    //! Base type
    typedef basic_formatted_sink_backend< char > base_type;
    //! Implementation type
    struct implementation;

public:
    //! Character type
    typedef base_type::char_type char_type;
    //! String type that is used to pass message test
    typedef base_type::string_type string_type;

    //! Syslog severity level mapper type
    typedef boost::log::aux::light_function< syslog::level (record_view const&) > severity_mapper_type;

private:
    //! Pointer to the implementation
    implementation* m_pImpl;

public:
    /*!
     * Constructor. Creates a UDP socket-based backend with <tt>syslog::user</tt> facility code.
     * IPv4 protocol will be used.
     */
    BOOST_LOG_API syslog_backend();
    /*!
     * Constructor. Creates a sink backend with the specified named parameters.
     * The following named parameters are supported:
     *
     * \li \c facility - Specifies the facility code. If not specified, <tt>syslog::user</tt> will be used.
     * \li \c use_impl - Specifies the backend implementation. Can be one of:
     *                   \li \c native - Use the native syslog API, if available. If no native API
     *                                   is available, it is equivalent to \c udp_socket_based.
     *                   \li \c udp_socket_based - Use the UDP socket-based implementation, conforming to
     *                                             RFC3164 protocol specification. This is the default.
     * \li \c ip_version - Specifies IP protocol version to use, in case if socket-based implementation
     *                     is used. Can be either \c v4 (the default one) or \c v6.
     * \li \c ident - Process identification string. This parameter is only supported by native syslog implementation.
     */
#ifndef BOOST_LOG_DOXYGEN_PASS
    BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_CALL(syslog_backend, construct)
#else
    template< typename... ArgsT >
    explicit syslog_backend(ArgsT... const& args);
#endif

    /*!
     * Destructor
     */
    BOOST_LOG_API ~syslog_backend();

    /*!
     * The method installs the function object that maps application severity levels to syslog levels
     */
    BOOST_LOG_API void set_severity_mapper(severity_mapper_type const& mapper);

#if !defined(BOOST_LOG_NO_ASIO)

    /*!
     * The method sets the local host name which log records will be sent from. The host name
     * is resolved to obtain the final IP address.
     *
     * \note Does not have effect if the backend was constructed to use native syslog API
     *
     * \param addr The local address
     * \param port The local port number
     */
    BOOST_LOG_API void set_local_address(std::string const& addr, unsigned short port = 514);
    /*!
     * The method sets the local address which log records will be sent from.
     *
     * \note Does not have effect if the backend was constructed to use native syslog API
     *
     * \param addr The local address
     * \param port The local port number
     */
    BOOST_LOG_API void set_local_address(boost::asio::ip::address const& addr, unsigned short port = 514);

    /*!
     * The method sets the remote host name where log records will be sent to. The host name
     * is resolved to obtain the final IP address.
     *
     * \note Does not have effect if the backend was constructed to use native syslog API
     *
     * \param addr The remote host address
     * \param port The port number on the remote host
     */
    BOOST_LOG_API void set_target_address(std::string const& addr, unsigned short port = 514);
    /*!
     * The method sets the address of the remote host where log records will be sent to.
     *
     * \note Does not have effect if the backend was constructed to use native syslog API
     *
     * \param addr The remote host address
     * \param port The port number on the remote host
     */
    BOOST_LOG_API void set_target_address(boost::asio::ip::address const& addr, unsigned short port = 514);

#endif // !defined(BOOST_LOG_NO_ASIO)

    /*!
     * The method passes the formatted message to the syslog API or sends to a syslog server
     */
    BOOST_LOG_API void consume(record_view const& rec, string_type const& formatted_message);

private:
#ifndef BOOST_LOG_DOXYGEN_PASS
    //! The method creates the backend implementation
    template< typename ArgsT >
    void construct(ArgsT const& args)
    {
        construct(
            args[keywords::facility | syslog::user],
#if !defined(BOOST_LOG_NO_ASIO)
            args[keywords::use_impl | syslog::udp_socket_based],
#else
            args[keywords::use_impl | syslog::native],
#endif
            args[keywords::ip_version | v4],
            args[keywords::ident | std::string()]);
    }
    BOOST_LOG_API void construct(
        syslog::facility facility, syslog::impl_types use_impl, ip_versions ip_version, std::string const& ident);
#endif // BOOST_LOG_DOXYGEN_PASS
};

} // namespace sinks

BOOST_LOG_CLOSE_NAMESPACE // namespace log

} // namespace boost

#include <boost/log/detail/footer.hpp>

#endif // BOOST_LOG_WITHOUT_SYSLOG

#endif // BOOST_LOG_SINKS_SYSLOG_BACKEND_HPP_INCLUDED_