Ice 3.7 C++98 API Reference
Loading...
Searching...
No Matches
MetricsObserverI.h
Go to the documentation of this file.
1//
2// Copyright (c) ZeroC, Inc. All rights reserved.
3//
4
5#ifndef ICEMX_METRICSOBSERVER_I_H
6#define ICEMX_METRICSOBSERVER_I_H
7
8#include <IceUtil/StopWatch.h>
9#include <IceUtil/Atomic.h>
10
11#include <Ice/Instrumentation.h>
12#include <Ice/Endpoint.h>
13#include <Ice/Connection.h>
14
15#include <Ice/Metrics.h>
16#include <Ice/MetricsAdminI.h>
18
19#include <stdexcept>
20
21namespace IceMX
22{
23
25template<typename T> class MetricsHelperT
26{
27public:
28
29 virtual ~MetricsHelperT()
30 {
31 }
32
33 virtual std::string operator()(const std::string&) const = 0;
34
35 virtual void initMetrics(const ICE_INTERNAL_HANDLE<T>&) const
36 {
37 // To be overridden in specialization to initialize state attributes
38 }
39
40protected:
41
42 template<typename Helper> class AttributeResolverT
43 {
44 class Resolver
45 {
46 public:
47
48 Resolver(const std::string& name) : _name(name)
49 {
50 }
51
52 virtual ~Resolver()
53 {
54 }
55
56 virtual std::string operator()(const Helper* h) const = 0;
57
58 protected:
59
60 std::string _name;
61 };
62
63 public:
64
65 AttributeResolverT() : _default(0)
66 {
67 }
68
69 ~AttributeResolverT()
70 {
71 for(typename std::map<std::string, Resolver*>::iterator p = _attributes.begin(); p != _attributes.end();++p)
72 {
73 delete p->second;
74 }
75 }
76
77 std::string operator()(const Helper* helper, const std::string& attribute) const
78 {
79 typename std::map<std::string, Resolver*>::const_iterator p = _attributes.find(attribute);
80 if(p == _attributes.end())
81 {
82 if(attribute == "none")
83 {
84 return "";
85 }
86 if(_default)
87 {
88 return (helper->*_default)(attribute);
89 }
90 throw std::invalid_argument(attribute);
91 }
92 return (*p->second)(helper);
93 }
94
95 void
96 setDefault(std::string (Helper::*memberFn)(const std::string&) const)
97 {
98 _default = memberFn;
99 }
100
101 template<typename Y> void
102 add(const std::string& name, Y Helper::*member)
103 {
104 _attributes.insert(typename std::map<std::string,
105 Resolver*>::value_type(name, new HelperMemberResolver<Y>(name, member)));
106 }
107
108 template<typename Y> void
109 add(const std::string& name, Y (Helper::*memberFn)() const)
110 {
111 _attributes.insert(typename std::map<std::string,
112 Resolver*>::value_type(name, new HelperMemberFunctionResolver<Y>(name, memberFn)));
113 }
114
115 template<typename I, typename O, typename Y> void
116 add(const std::string& name, O (Helper::*getFn)() const, Y I::*member)
117 {
118 _attributes.insert(typename std::map<std::string,
119 Resolver*>::value_type(name, new MemberResolver<I, O, Y>(name, getFn, member)));
120 }
121
122 template<typename I, typename O, typename Y> void
123 add(const std::string& name, O (Helper::*getFn)() const, Y (I::*memberFn)() const)
124 {
125 _attributes.insert(typename std::map<std::string,
126 Resolver*>::value_type(name, new MemberFunctionResolver<I, O, Y>(name, getFn,
127 memberFn)));
128 }
129
130#if ICE_CPLUSPLUS >= 201703L
131 //
132 // Since C++17 the noexcept-specification is part of the function type and we need a separate
133 // overload to handle memberFn being noexcept
134 //
135 template<typename I, typename O, typename Y> void
136 add(const std::string& name, O (Helper::*getFn)() const, Y (I::*memberFn)() const noexcept)
137 {
138 _attributes.insert(typename std::map<std::string,
139 Resolver*>::value_type(name, new MemberFunctionResolver<I, O, Y>(name, getFn,
140 memberFn)));
141 }
142#endif
143
144 private:
145
146 template<typename Y> class HelperMemberResolver : public Resolver
147 {
148 public:
149
150 HelperMemberResolver(const std::string& name, Y Helper::*member) : Resolver(name), _member(member)
151 {
152 }
153
154 virtual std::string operator()(const Helper* r) const
155 {
156 return toString(r->*_member);
157 }
158
159 private:
160
161 Y Helper::*_member;
162 };
163
164 template<typename Y> class HelperMemberFunctionResolver : public Resolver
165 {
166 public:
167
168 HelperMemberFunctionResolver(const std::string& name, Y (Helper::*memberFn)() const) :
169 Resolver(name), _memberFn(memberFn)
170 {
171 }
172
173 virtual std::string operator()(const Helper* r) const
174 {
175 return toString((r->*_memberFn)());
176 }
177
178 private:
179
180 Y (Helper::*_memberFn)() const;
181 };
182
183 template<typename I, typename O, typename Y> class MemberResolver : public Resolver
184 {
185 public:
186
187 MemberResolver(const std::string& name, O (Helper::*getFn)() const, Y I::*member) :
188 Resolver(name), _getFn(getFn), _member(member)
189 {
190 }
191
192 virtual std::string operator()(const Helper* r) const
193 {
194 O o = (r->*_getFn)();
195 I* v = dynamicCast<I>(IceInternal::ReferenceWrapper<O>::get(o));
196 if(v)
197 {
198 return toString(v->*_member);
199 }
200 else
201 {
202 throw std::invalid_argument(Resolver::_name);
203 }
204 }
205
206 private:
207
208 O (Helper::*_getFn)() const;
209 Y I::*_member;
210 };
211
212 template<typename I, typename O, typename Y> class MemberFunctionResolver : public Resolver
213 {
214 public:
215
216 MemberFunctionResolver(const std::string& name, O (Helper::*getFn)() const, Y (I::*memberFn)() const) :
217 Resolver(name), _getFn(getFn), _memberFn(memberFn)
218 {
219 }
220
221 virtual std::string operator()(const Helper* r) const
222 {
223 O o = (r->*_getFn)();
224 I* v = dynamicCast<I>(IceInternal::ReferenceWrapper<O>::get(o));
225 if(v)
226 {
227 return toString((v->*_memberFn)());
228 }
229 else
230 {
231 throw std::invalid_argument(Resolver::_name);
232 }
233 }
234
235 private:
236
237 O (Helper::*_getFn)() const;
238 Y (I::*_memberFn)() const;
239 };
240
241 template<typename I, typename V> static I*
242 dynamicCast(V* v)
243 {
244 return dynamic_cast<I*>(v);
245 }
246
247 template<typename I> static I*
248 dynamicCast(Ice::EndpointInfo* v)
249 {
250 for(Ice::EndpointInfo* info = v; info; info = info->underlying.get())
251 {
252 I* i = dynamic_cast<I*>(info);
253 if(i)
254 {
255 return i;
256 }
257 }
258 return 0;
259 }
260
261 template<typename I> static I*
262 dynamicCast(Ice::ConnectionInfo* v)
263 {
264 for(Ice::ConnectionInfo* info = v; info; info = info->underlying.get())
265 {
266 I* i = dynamic_cast<I*>(info);
267 if(i)
268 {
269 return i;
270 }
271 }
272 return 0;
273 }
274
275 template<typename I> static std::string
276 toString(const I& v)
277 {
278 std::ostringstream os;
279 os << v;
280 return os.str();
281 }
282
283 static const std::string
284 toString(const Ice::ObjectPrxPtr& p)
285 {
286 return p->ice_toString();
287 }
288
289 static const std::string&
290 toString(const std::string& s)
291 {
292 return s;
293 }
294
295 static std::string
296 toString(const ::Ice::EndpointPtr& e)
297 {
298 return e->toString();
299 }
300
301 static std::string
302 toString(const ::Ice::ConnectionPtr& e)
303 {
304 return e->toString();
305 }
306
307 static std::string
308 toString(bool v)
309 {
310 return v ? "true" : "false";
311 }
312
313 std::map<std::string, Resolver*> _attributes;
314 std::string (Helper::*_default)(const std::string&) const;
315 };
316};
317
318class Updater
319#ifndef ICE_CPP11_MAPPING
320 : public virtual IceUtil::Shared
321#endif
322{
323public:
324
325 virtual void update() = 0;
326};
327ICE_DEFINE_PTR(UpdaterPtr, Updater);
328
329template<typename T> class UpdaterT ICE_FINAL : public Updater
330{
331public:
332
333#ifdef ICE_CPP11_MAPPING
334 UpdaterT(const std::shared_ptr<T>& updater, void (T::*fn)()) :
335#else
336 UpdaterT(T* updater, void (T::*fn)()) :
337#endif
338 _updater(updater),
339 _fn(fn)
340 {
341 }
342
343 virtual void update()
344 {
345 (_updater.get()->*_fn)();
346 }
347
348private:
349
350 const ICE_HANDLE<T> _updater;
351 void (T::*_fn)();
352};
353
354#ifdef ICE_CPP11_MAPPING
355template<typename T> UpdaterPtr
356newUpdater(const std::shared_ptr<T>& updater, void (T::*fn)())
357{
358 if(updater)
359 {
360 return std::make_shared<UpdaterT<T>>(updater, fn);
361 }
362 else
363 {
364 return nullptr;
365 }
366}
367#else
368template<typename T> UpdaterPtr
369newUpdater(const IceInternal::Handle<T>& updater, void (T::*fn)())
370{
371 if(updater)
372 {
373 return UpdaterPtr(new UpdaterT<T>(updater.get(), fn));
374 }
375 else
376 {
377 return 0;
378 }
379}
380#endif
381
382template<typename T> class ObserverT : public virtual ::Ice::Instrumentation::Observer
383{
384public:
385
386 typedef T MetricsType;
387 typedef typename IceInternal::MetricsMapT<MetricsType>::EntryTPtr EntryPtrType;
388 typedef std::vector<EntryPtrType> EntrySeqType;
389
390 ObserverT() : _previousDelay(0)
391 {
392 }
393
394 virtual void
395 attach()
396 {
397 if(!_watch.isStarted())
398 {
399 _watch.start();
400 }
401 }
402
403 virtual void
404 detach()
405 {
406 ::Ice::Long lifetime = _previousDelay + _watch.stop();
407 for(typename EntrySeqType::const_iterator p = _objects.begin(); p != _objects.end(); ++p)
408 {
409 (*p)->detach(lifetime);
410 }
411 }
412
413 virtual void
414 failed(const std::string& exceptionName)
415 {
416 for(typename EntrySeqType::const_iterator p = _objects.begin(); p != _objects.end(); ++p)
417 {
418 (*p)->failed(exceptionName);
419 }
420 }
421
422 template<typename Function> void
423 forEach(const Function& func)
424 {
425 for(typename EntrySeqType::const_iterator p = _objects.begin(); p != _objects.end(); ++p)
426 {
427 (*p)->execute(func);
428 }
429 }
430
431 void
432 init(const MetricsHelperT<MetricsType>& /*helper*/, EntrySeqType& objects, ObserverT* previous = 0)
433 {
434 _objects.swap(objects);
435
436 if(previous == 0)
437 {
438 return;
439 }
440
441 _previousDelay = previous->_previousDelay + previous->_watch.delay();
442 //
443 // Detach entries from previous observer which are no longer
444 // attached to this new observer.
445 //
446 for(typename EntrySeqType::const_iterator p = previous->_objects.begin(); p != previous->_objects.end(); ++p)
447 {
448 if(find(_objects.begin(), _objects.end(), *p) == _objects.end())
449 {
450 (*p)->detach(_previousDelay);
451 }
452 }
453 }
454
455 EntryPtrType
456 getEntry(IceInternal::MetricsMapT<MetricsType>* map)
457 {
458 for(typename EntrySeqType::const_iterator p = _objects.begin(); p != _objects.end(); ++p)
459 {
460 if((*p)->getMap() == map)
461 {
462 return *p;
463 }
464 }
465 return ICE_NULLPTR;
466 }
467
468 template<typename ObserverImpl, typename ObserverMetricsType> ICE_INTERNAL_HANDLE<ObserverImpl>
469 getObserver(const std::string& mapName, const MetricsHelperT<ObserverMetricsType>& helper)
470 {
471 std::vector<typename IceInternal::MetricsMapT<ObserverMetricsType>::EntryTPtr> metricsObjects;
472 for(typename EntrySeqType::const_iterator p = _objects.begin(); p != _objects.end(); ++p)
473 {
474 typename IceInternal::MetricsMapT<ObserverMetricsType>::EntryTPtr e = (*p)->getMatching(mapName, helper);
475 if(e)
476 {
477 metricsObjects.push_back(e);
478 }
479 }
480
481 if(metricsObjects.empty())
482 {
483 return ICE_NULLPTR;
484 }
485
487 obsv->init(helper, metricsObjects);
488 return obsv;
489 }
490
491private:
492
493 EntrySeqType _objects;
494 IceUtilInternal::StopWatch _watch;
495 IceUtil::Int64 _previousDelay;
496};
497
498template<typename ObserverImplType>
499class ObserverFactoryT : public Updater, private IceUtil::Mutex
500{
501public:
502
503#ifdef ICE_CPP11_MAPPING
504 using ObserverImplPtrType = ::std::shared_ptr<ObserverImplType>;
505 using MetricsType = typename ObserverImplType::MetricsType;
506 using MetricsMapSeqType = std::vector<::std::shared_ptr<IceInternal::MetricsMapT<MetricsType>>>;
507#else
508 typedef IceUtil::Handle<ObserverImplType> ObserverImplPtrType;
509 typedef typename ObserverImplType::MetricsType MetricsType;
510 typedef std::vector<IceUtil::Handle<IceInternal::MetricsMapT<MetricsType> > > MetricsMapSeqType;
511#endif
512
513 ObserverFactoryT(const IceInternal::MetricsAdminIPtr& metrics, const std::string& name) :
514 _metrics(metrics), _name(name), _enabled(0)
515 {
516 _metrics->registerMap<MetricsType>(name, this);
517 }
518
519 ~ObserverFactoryT()
520 {
521 if(_metrics)
522 {
523 _metrics->unregisterMap(_name);
524 }
525 }
526
527 ObserverImplPtrType
528 getObserver(const MetricsHelperT<MetricsType>& helper)
529 {
530 IceUtil::Mutex::Lock sync(*this);
531 if(!_metrics)
532 {
533 return ICE_NULLPTR;
534 }
535
536 typename ObserverImplType::EntrySeqType metricsObjects;
537 for(typename MetricsMapSeqType::const_iterator p = _maps.begin(); p != _maps.end(); ++p)
538 {
539 typename ObserverImplType::EntryPtrType entry = (*p)->getMatching(helper);
540 if(entry)
541 {
542 metricsObjects.push_back(entry);
543 }
544 }
545
546 if(metricsObjects.empty())
547 {
548 return ICE_NULLPTR;
549 }
550
551 ObserverImplPtrType obsv = ICE_MAKE_SHARED(ObserverImplType);
552 obsv->init(helper, metricsObjects);
553 return obsv;
554 }
555
556 template<typename ObserverPtrType> ObserverImplPtrType
557 getObserver(const MetricsHelperT<MetricsType>& helper, const ObserverPtrType& observer)
558 {
559#ifdef ICE_CPP11_MAPPING
560 ObserverImplPtrType old = std::dynamic_pointer_cast<ObserverImplType>(observer);
561#else
562 ObserverImplPtrType old = ObserverImplPtrType::dynamicCast(observer);
563#endif
564
565 if(!observer || !old)
566 {
567 return getObserver(helper);
568 }
569 IceUtil::Mutex::Lock sync(*this);
570 if(!_metrics)
571 {
572 return ICE_NULLPTR;
573 }
574
575 typename ObserverImplType::EntrySeqType metricsObjects;
576 for(typename MetricsMapSeqType::const_iterator p = _maps.begin(); p != _maps.end(); ++p)
577 {
578 typename ObserverImplType::EntryPtrType entry = (*p)->getMatching(helper, old->getEntry(p->get()));
579 if(entry)
580 {
581 metricsObjects.push_back(entry);
582 }
583 }
584 if(metricsObjects.empty())
585 {
586 old->detach();
587 return ICE_NULLPTR;
588 }
589
590 ObserverImplPtrType obsv = ICE_MAKE_SHARED(ObserverImplType);
591 obsv->init(helper, metricsObjects, old.get());
592 return obsv;
593 }
594
595 template<typename SubMapMetricsType> void
596 registerSubMap(const std::string& subMap, MetricsMap MetricsType::* member)
597 {
598 assert(_metrics);
599 _metrics->registerSubMap<SubMapMetricsType>(_name, subMap, member);
600 }
601
602 bool isEnabled() const
603 {
604 return _enabled != 0;
605 }
606
607 virtual void update()
608 {
609 UpdaterPtr updater;
610 {
611 IceUtil::Mutex::Lock sync(*this);
612 if(!_metrics)
613 {
614 return;
615 }
616
617 std::vector<IceInternal::MetricsMapIPtr> maps = _metrics->getMaps(_name);
618 _maps.clear();
619 for(std::vector<IceInternal::MetricsMapIPtr>::const_iterator p = maps.begin(); p != maps.end(); ++p)
620 {
621#ifdef ICE_CPP11_MAPPING
622 _maps.push_back(::std::dynamic_pointer_cast<IceInternal::MetricsMapT<MetricsType>>(*p));
623#else
624 _maps.push_back(IceUtil::Handle<IceInternal::MetricsMapT<MetricsType> >::dynamicCast(*p));
625#endif
626 assert(_maps.back());
627 }
628 _enabled.exchange(_maps.empty() ? 0 : 1);
629 updater = _updater;
630 }
631
632 if(updater)
633 {
634 updater->update();
635 }
636 }
637
638 void setUpdater(const UpdaterPtr& updater)
639 {
640 IceUtil::Mutex::Lock sync(*this);
641 _updater = updater;
642 }
643
644 void destroy()
645 {
646 IceUtil::Mutex::Lock sync(*this);
647 _metrics = 0;
648 _maps.clear();
649 }
650
651private:
652
653 IceInternal::MetricsAdminIPtr _metrics;
654 const std::string _name;
655 MetricsMapSeqType _maps;
656 //
657 // TODO: Replace by std::atomic<bool> when it becomes widely
658 // available.
659 //
660 IceUtilInternal::Atomic _enabled;
661 UpdaterPtr _updater;
662};
663
664typedef ObserverT<Metrics> ObserverI;
666
667}
668
669#endif
#define ICE_DEFINE_PTR(TPtr, T)
Definition Config.h:377
#define ICE_MAKE_SHARED(T,...)
Definition Config.h:376
#define ICE_HANDLE
Definition Config.h:373
#define ICE_NULLPTR
Definition Config.h:380
#define ICE_FINAL
Definition Config.h:130
#define ICE_INTERNAL_HANDLE
Definition Config.h:374
T * get() const
Definition Handle.h:25
LockT< Mutex > Lock
Definition Mutex.h:39
Definition Metrics.h:227
long long Int64
Definition Config.h:342
IceUtil::Int64 Long
The mapping for the Slice long type.
Definition Config.h:60
ObjectPrx ObjectPrxPtr
Definition ProxyF.h:48