Ice 3.7 C++11 API Reference
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>
17 #include <Ice/MetricsFunctional.h>
18 
19 #include <stdexcept>
20 
21 namespace IceMX
22 {
23 
25 template<typename T> class MetricsHelperT
26 {
27 public:
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 overriden in specialization to initialize state attributes
38  }
39 
40 protected:
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 
318 class Updater
319 #ifndef ICE_CPP11_MAPPING
320  : public virtual IceUtil::Shared
321 #endif
322 {
323 public:
324 
325  virtual void update() = 0;
326 };
327 ICE_DEFINE_PTR(UpdaterPtr, Updater);
328 
329 template<typename T> class UpdaterT ICE_FINAL : public Updater
330 {
331 public:
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 
348 private:
349 
350  const ICE_HANDLE<T> _updater;
351  void (T::*_fn)();
352 };
353 
354 #ifdef ICE_CPP11_MAPPING
355 template<typename T> UpdaterPtr
356 newUpdater(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
368 template<typename T> UpdaterPtr
369 newUpdater(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 
382 template<typename T> class ObserverT : public virtual ::Ice::Instrumentation::Observer
383 {
384 public:
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 
486  ICE_INTERNAL_HANDLE<ObserverImpl> obsv = ICE_MAKE_SHARED(ObserverImpl);
487  obsv->init(helper, metricsObjects);
488  return obsv;
489  }
490 
491 private:
492 
493  EntrySeqType _objects;
494  IceUtilInternal::StopWatch _watch;
495  IceUtil::Int64 _previousDelay;
496 };
497 
498 template<typename ObserverImplType>
499 class ObserverFactoryT : public Updater, private IceUtil::Mutex
500 {
501 public:
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 
651 private:
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 
664 typedef ObserverT<Metrics> ObserverI;
666 
667 }
668 
669 #endif
Instrumentation.h
Atomic.h
Ice::EndpointInfo::underlying
::std::shared_ptr<::Ice::EndpointInfo > underlying
The information of the underyling endpoint of null if there's no underlying endpoint.
Definition: Endpoint.h:176
ICE_DEFINE_PTR
#define ICE_DEFINE_PTR(TPtr, T)
Definition: Config.h:359
StopWatch.h
IceUtil::LockT
Definition: Lock.h:37
IceMX
Definition: Metrics.h:65
Ice::ConnectionInfo
Base class providing access to the connection details.
Definition: Connection.h:218
ICE_NULLPTR
#define ICE_NULLPTR
Definition: Config.h:362
Ice::EndpointInfo
Base class providing access to the endpoint details.
Definition: Endpoint.h:129
Metrics.h
Ice::Instrumentation::Observer
The object observer interface used by instrumented objects to notify the observer of their existence.
Definition: Instrumentation.h:160
Connection.h
ICE_FINAL
#define ICE_FINAL
Definition: Config.h:130
MetricsAdminI.h
MetricsFunctional.h
IceUtil::Mutex
Definition: Mutex.h:33
Ice::ConnectionInfo::underlying
::std::shared_ptr<::Ice::ConnectionInfo > underlying
The information of the underyling transport or null if there's no underlying transport.
Definition: Connection.h:249
Ice::Long
long long int Long
The mapping for the Slice long type.
Definition: Config.h:57
IceUtil::Handle
Definition: Handle.h:143
IceMX::MetricsMap
::std::vector<::std::shared_ptr< Metrics > > MetricsMap
A metrics map is a sequence of metrics.
Definition: Metrics.h:125
IceUtil::Int64
long long Int64
Definition: Config.h:342
ICE_MAKE_SHARED
#define ICE_MAKE_SHARED(T,...)
Definition: Config.h:358
IceUtil::Shared
Definition: Shared.h:78
Endpoint.h