Branch data Line data Source code
1 : : // Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
2 : : //
3 : : // Permission to use, copy, modify, and/or distribute this software for any
4 : : // purpose with or without fee is hereby granted, provided that the above
5 : : // copyright notice and this permission notice appear in all copies.
6 : : //
7 : : // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
8 : : // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
9 : : // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
10 : : // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
11 : : // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
12 : : // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
13 : : // PERFORMANCE OF THIS SOFTWARE.
14 : :
15 : : #include <auth/statistics.h>
16 : : #include <auth/auth_log.h>
17 : :
18 : : #include <dns/opcode.h>
19 : :
20 : : #include <cc/data.h>
21 : : #include <cc/session.h>
22 : :
23 : : #include <statistics/counter.h>
24 : : #include <statistics/counter_dict.h>
25 : :
26 : : #include <algorithm>
27 : : #include <cctype>
28 : : #include <cassert>
29 : : #include <string>
30 : : #include <sstream>
31 : : #include <iostream>
32 : :
33 : : #include <boost/noncopyable.hpp>
34 : :
35 : : using namespace isc::dns;
36 : : using namespace isc::auth;
37 : : using namespace isc::statistics;
38 : :
39 : : // TODO: We need a namespace ("auth_server"?) to hold
40 : : // AuthSrv and AuthCounters.
41 : :
42 : : // TODO: Make use of wrappers like isc::dns::Opcode
43 : : // for counter item type.
44 : :
45 : : class AuthCountersImpl : boost::noncopyable {
46 : : public:
47 : : AuthCountersImpl();
48 : : ~AuthCountersImpl();
49 : : void inc(const AuthCounters::ServerCounterType type);
50 : : void inc(const Opcode opcode) {
51 : 265 : opcode_counter_.inc(opcode.getCode());
52 : : }
53 : : void inc(const Rcode rcode) {
54 : 281 : rcode_counter_.inc(rcode.getCode());
55 : : }
56 : : void inc(const std::string& zone,
57 : : const AuthCounters::PerZoneCounterType type);
58 : : bool submitStatistics() const;
59 : : void setStatisticsSession(isc::cc::AbstractSession* statistics_session);
60 : : void registerStatisticsValidator
61 : : (AuthCounters::validator_type validator);
62 : : // Currently for testing purpose only
63 : : uint64_t getCounter(const AuthCounters::ServerCounterType type) const;
64 : : uint64_t getCounter(const Opcode opcode) const {
65 : 67 : return (opcode_counter_.get(opcode.getCode()));
66 : : }
67 : : uint64_t getCounter(const Rcode rcode) const {
68 : 323 : return (rcode_counter_.get(rcode.getCode()));
69 : : }
70 : : private:
71 : : Counter server_counter_;
72 : : Counter opcode_counter_;
73 : : static const size_t NUM_OPCODES = 16;
74 : : Counter rcode_counter_;
75 : : static const size_t NUM_RCODES = 17;
76 : : CounterDictionary per_zone_counter_;
77 : : isc::cc::AbstractSession* statistics_session_;
78 : : AuthCounters::validator_type validator_;
79 : : };
80 : :
81 : 107 : AuthCountersImpl::AuthCountersImpl() :
82 : : // initialize counter
83 : : // size of server_counter_: AuthCounters::SERVER_COUNTER_TYPES
84 : : // size of per_zone_counter_: AuthCounters::PER_ZONE_COUNTER_TYPES
85 : : server_counter_(AuthCounters::SERVER_COUNTER_TYPES),
86 : : opcode_counter_(NUM_OPCODES), rcode_counter_(NUM_RCODES),
87 : : per_zone_counter_(AuthCounters::PER_ZONE_COUNTER_TYPES),
88 [ + - ][ + - ]: 107 : statistics_session_(NULL)
[ + - ]
89 : : {
90 [ + - ][ + - ]: 107 : per_zone_counter_.addElement("_SERVER_");
91 : 107 : }
92 : :
93 [ + - ][ + - ]: 107 : AuthCountersImpl::~AuthCountersImpl()
[ + - ]
94 : 107 : {}
95 : :
96 : : void
97 : 48 : AuthCountersImpl::inc(const AuthCounters::ServerCounterType type) {
98 : 48 : server_counter_.inc(type);
99 : 47 : }
100 : :
101 : : void
102 : 0 : AuthCountersImpl::inc(const std::string& zone,
103 : : const AuthCounters::PerZoneCounterType type)
104 : : {
105 : 0 : per_zone_counter_[zone].inc(type);
106 : 0 : }
107 : :
108 : : bool
109 : 11 : AuthCountersImpl::submitStatistics() const {
110 [ + + ]: 11 : if (statistics_session_ == NULL) {
111 [ + - ]: 1 : LOG_ERROR(auth_logger, AUTH_NO_STATS_SESSION);
112 : : return (false);
113 : : }
114 : 21 : std::stringstream statistics_string;
115 : : // add pid in order for stats to identify which auth sends
116 : : // statistics in the situation that multiple auth instances are
117 : : // working
118 [ + - ]: 10 : statistics_string << "{\"command\": [\"set\","
119 [ + - ]: 10 : << "{ \"owner\": \"Auth\","
120 [ + - ][ + - ]: 20 : << " \"pid\":" << getpid()
121 [ + - ]: 10 : << ", \"data\":"
122 [ + - ]: 10 : << "{ \"queries.udp\": "
123 [ + - ]: 10 : << server_counter_.get(AuthCounters::SERVER_UDP_QUERY)
124 [ + - ]: 10 : << ", \"queries.tcp\": "
125 : : << server_counter_.get(
126 [ + - ]: 10 : AuthCounters::SERVER_TCP_QUERY);
127 : : // Insert non 0 Opcode counters.
128 [ + + ]: 170 : for (int i = 0; i < NUM_OPCODES; ++i) {
129 [ + - ]: 160 : const Counter::Type counter = opcode_counter_.get(i);
130 [ + + ]: 160 : if (counter != 0) {
131 : : // The counter item name should be derived lower-cased textual
132 : : // representation of the code.
133 [ + - ][ + - ]: 74 : std::string opcode_txt = Opcode(i).toText();
134 : : std::transform(opcode_txt.begin(), opcode_txt.end(),
135 [ + - ]: 37 : opcode_txt.begin(), ::tolower);
136 [ + - ][ + - ]: 37 : statistics_string << ", \"opcode." << opcode_txt << "\": "
[ + - ]
137 : : << counter;
138 : : }
139 : : }
140 : : // Insert non 0 Rcode counters.
141 [ + + ]: 180 : for (int i = 0; i < NUM_RCODES; ++i) {
142 [ + - ]: 170 : const Counter::Type counter = rcode_counter_.get(i);
143 [ + + ]: 170 : if (counter != 0) {
144 : : // The counter item name should be derived lower-cased textual
145 : : // representation of the code.
146 [ + - ][ + - ]: 22 : std::string rcode_txt = Rcode(i).toText();
147 : : std::transform(rcode_txt.begin(), rcode_txt.end(),
148 [ + - ]: 11 : rcode_txt.begin(), ::tolower);
149 [ + - ][ + - ]: 11 : statistics_string << ", \"rcode." << rcode_txt << "\": "
[ + - ]
150 : : << counter;
151 : : }
152 : : }
153 [ + - ]: 10 : statistics_string << " }"
154 [ + - ]: 10 : << "}"
155 [ + - ]: 10 : << "]}";
156 : : isc::data::ConstElementPtr statistics_element =
157 [ + - ]: 10 : isc::data::Element::fromJSON(statistics_string);
158 : : // validate the statistics data before send
159 [ + + ]: 10 : if (validator_) {
160 [ + + ]: 2 : if (!validator_(
161 [ + - ][ + - ]: 6 : statistics_element->get("command")->get(1)->get("data"))) {
[ + - ][ + - ]
[ + - ]
162 [ + - ][ + - ]: 1 : LOG_ERROR(auth_logger, AUTH_INVALID_STATISTICS_DATA);
[ + - ][ + - ]
163 : : return (false);
164 : : }
165 : : }
166 : : try {
167 : : // group_{send,recv}msg() can throw an exception when encountering
168 : : // an error, and group_recvmsg() will throw an exception on timeout.
169 : : // We don't want to kill the main server just due to this, so we
170 : : // handle them here.
171 : : const int seq =
172 [ + - ][ + - ]: 27 : statistics_session_->group_sendmsg(statistics_element, "Stats");
[ + - ][ + + ]
173 : : isc::data::ConstElementPtr env, answer;
174 : : // TODO: parse and check response from statistics module
175 : : // currently it just returns empty message
176 [ + + ]: 8 : statistics_session_->group_recvmsg(env, answer, false, seq);
177 [ + - ]: 2 : } catch (const isc::cc::SessionError& ex) {
178 [ - + ][ + - ]: 1 : LOG_ERROR(auth_logger, AUTH_STATS_COMMS).arg(ex.what());
[ - + ][ - + ]
[ - + ]
179 : : return (false);
180 [ - + + ]: 3 : } catch (const isc::cc::SessionTimeout& ex) {
[ + - ]
181 [ - + ][ + - ]: 1 : LOG_ERROR(auth_logger, AUTH_STATS_TIMEOUT).arg(ex.what());
[ - + ][ - + ]
[ - + ]
182 : : return (false);
183 : : }
184 : : return (true);
185 : : }
186 : :
187 : : void
188 : 83 : AuthCountersImpl::setStatisticsSession
189 : : (isc::cc::AbstractSession* statistics_session)
190 : : {
191 : 83 : statistics_session_ = statistics_session;
192 : 83 : }
193 : :
194 : : void
195 : 3 : AuthCountersImpl::registerStatisticsValidator
196 : : (AuthCounters::validator_type validator)
197 : : {
198 : 3 : validator_ = validator;
199 : 3 : }
200 : :
201 : : // Currently for testing purpose only
202 : : uint64_t
203 : 16 : AuthCountersImpl::getCounter(const AuthCounters::ServerCounterType type) const {
204 : 16 : return (server_counter_.get(type));
205 : : }
206 : :
207 [ + - ]: 107 : AuthCounters::AuthCounters() : impl_(new AuthCountersImpl())
208 : 107 : {}
209 : :
210 : 107 : AuthCounters::~AuthCounters() {}
211 : :
212 : : void
213 : 48 : AuthCounters::inc(const AuthCounters::ServerCounterType type) {
214 : 48 : impl_->inc(type);
215 : 47 : }
216 : :
217 : : void
218 : 265 : AuthCounters::inc(const Opcode opcode) {
219 : 265 : impl_->inc(opcode);
220 : 265 : }
221 : :
222 : : void
223 : 281 : AuthCounters::inc(const Rcode rcode) {
224 : 281 : impl_->inc(rcode);
225 : 281 : }
226 : :
227 : : bool
228 : 11 : AuthCounters::submitStatistics() const {
229 : 11 : return (impl_->submitStatistics());
230 : : }
231 : :
232 : : void
233 : 83 : AuthCounters::setStatisticsSession
234 : : (isc::cc::AbstractSession* statistics_session)
235 : : {
236 : 83 : impl_->setStatisticsSession(statistics_session);
237 : 83 : }
238 : :
239 : : uint64_t
240 : 16 : AuthCounters::getCounter(const AuthCounters::ServerCounterType type) const {
241 : 16 : return (impl_->getCounter(type));
242 : : }
243 : :
244 : : uint64_t
245 : 67 : AuthCounters::getCounter(const Opcode opcode) const {
246 : 134 : return (impl_->getCounter(opcode));
247 : : }
248 : :
249 : : uint64_t
250 : 323 : AuthCounters::getCounter(const Rcode rcode) const {
251 : 646 : return (impl_->getCounter(rcode));
252 : : }
253 : :
254 : : void
255 : 3 : AuthCounters::registerStatisticsValidator
256 : : (AuthCounters::validator_type validator) const
257 : : {
258 [ + - ]: 6 : return (impl_->registerStatisticsValidator(validator));
259 : 49 : }
|