Jiri Simsa | d7616c9 | 2015-03-24 23:44:30 -0700 | [diff] [blame] | 1 | // Copyright 2015 The Vanadium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style |
| 3 | // license that can be found in the LICENSE file. |
| 4 | |
Todd Wang | 1ea8f19 | 2015-04-03 17:31:51 -0700 | [diff] [blame] | 5 | // Package statslib implements the Stats interface from |
Todd Wang | 94c9d0b | 2015-04-01 14:27:00 -0700 | [diff] [blame] | 6 | // v.io/v23/services/stats. |
Todd Wang | 1ea8f19 | 2015-04-03 17:31:51 -0700 | [diff] [blame] | 7 | package statslib |
Robin Thellend | 7a44243 | 2014-08-22 09:05:08 -0700 | [diff] [blame] | 8 | |
| 9 | import ( |
Todd Wang | b31da59 | 2015-02-20 12:50:39 -0800 | [diff] [blame] | 10 | "reflect" |
Robin Thellend | 7a44243 | 2014-08-22 09:05:08 -0700 | [diff] [blame] | 11 | "time" |
| 12 | |
Jiri Simsa | ffceefa | 2015-02-28 11:03:34 -0800 | [diff] [blame] | 13 | libstats "v.io/x/ref/lib/stats" |
Robin Thellend | 7a44243 | 2014-08-22 09:05:08 -0700 | [diff] [blame] | 14 | |
Jiri Simsa | 6ac9522 | 2015-02-23 16:11:49 -0800 | [diff] [blame] | 15 | "v.io/v23/naming" |
Matt Rosencrantz | 94502cf | 2015-03-18 09:43:44 -0700 | [diff] [blame] | 16 | "v.io/v23/rpc" |
Todd Wang | 94c9d0b | 2015-04-01 14:27:00 -0700 | [diff] [blame] | 17 | "v.io/v23/services/stats" |
Jiri Simsa | 6ac9522 | 2015-02-23 16:11:49 -0800 | [diff] [blame] | 18 | "v.io/v23/services/watch" |
Jiri Simsa | 6ac9522 | 2015-02-23 16:11:49 -0800 | [diff] [blame] | 19 | "v.io/v23/vdl" |
| 20 | "v.io/v23/verror" |
Jiri Simsa | 337af23 | 2015-02-27 14:36:46 -0800 | [diff] [blame] | 21 | "v.io/x/lib/vlog" |
Robin Thellend | 7a44243 | 2014-08-22 09:05:08 -0700 | [diff] [blame] | 22 | ) |
| 23 | |
Robin Thellend | 8a0f04f | 2014-11-17 10:40:24 -0800 | [diff] [blame] | 24 | type statsService struct { |
Robin Thellend | 7a44243 | 2014-08-22 09:05:08 -0700 | [diff] [blame] | 25 | suffix string |
| 26 | watchFreq time.Duration |
| 27 | } |
| 28 | |
Todd Wang | fb93903 | 2015-04-08 16:42:44 -0700 | [diff] [blame] | 29 | const pkgPath = "v.io/x/ref/services/internal/statslib" |
Mike Burrows | d65df96 | 2014-12-17 10:01:19 -0800 | [diff] [blame] | 30 | |
Robin Thellend | 7a44243 | 2014-08-22 09:05:08 -0700 | [diff] [blame] | 31 | var ( |
Mike Burrows | d65df96 | 2014-12-17 10:01:19 -0800 | [diff] [blame] | 32 | errOperationFailed = verror.Register(pkgPath+".errOperationFailed", verror.NoRetry, "{1:}{2:} operation failed{:_}") |
Robin Thellend | 7a44243 | 2014-08-22 09:05:08 -0700 | [diff] [blame] | 33 | ) |
| 34 | |
Robin Thellend | 8a0f04f | 2014-11-17 10:40:24 -0800 | [diff] [blame] | 35 | // NewStatsService returns a stats server implementation. The value of watchFreq |
Robin Thellend | e34761d | 2014-11-13 13:11:25 -0800 | [diff] [blame] | 36 | // is used to specify the time between WatchGlob updates. |
Robin Thellend | 8a0f04f | 2014-11-17 10:40:24 -0800 | [diff] [blame] | 37 | func NewStatsService(suffix string, watchFreq time.Duration) interface{} { |
Robin Thellend | bde278d | 2014-11-19 15:07:32 -0800 | [diff] [blame] | 38 | return stats.StatsServer(&statsService{suffix, watchFreq}) |
Robin Thellend | 7a44243 | 2014-08-22 09:05:08 -0700 | [diff] [blame] | 39 | } |
| 40 | |
Robin Thellend | 39ac323 | 2014-12-02 09:50:41 -0800 | [diff] [blame] | 41 | // Glob__ returns the name of all objects that match pattern. |
Matt Rosencrantz | 94502cf | 2015-03-18 09:43:44 -0700 | [diff] [blame] | 42 | func (i *statsService) Glob__(call rpc.ServerCall, pattern string) (<-chan naming.GlobReply, error) { |
Robin Thellend | 39ac323 | 2014-12-02 09:50:41 -0800 | [diff] [blame] | 43 | vlog.VI(1).Infof("%v.Glob__(%q)", i.suffix, pattern) |
Robin Thellend | 7a44243 | 2014-08-22 09:05:08 -0700 | [diff] [blame] | 44 | |
Todd Wang | 2331dd0 | 2015-03-17 15:38:39 -0700 | [diff] [blame] | 45 | ch := make(chan naming.GlobReply) |
Robin Thellend | 39ac323 | 2014-12-02 09:50:41 -0800 | [diff] [blame] | 46 | go func() { |
| 47 | defer close(ch) |
| 48 | it := libstats.Glob(i.suffix, pattern, time.Time{}, false) |
| 49 | for it.Advance() { |
Todd Wang | 2331dd0 | 2015-03-17 15:38:39 -0700 | [diff] [blame] | 50 | ch <- naming.GlobReplyEntry{naming.MountEntry{Name: it.Value().Key}} |
Robin Thellend | 7a44243 | 2014-08-22 09:05:08 -0700 | [diff] [blame] | 51 | } |
Robin Thellend | 39ac323 | 2014-12-02 09:50:41 -0800 | [diff] [blame] | 52 | if err := it.Err(); err != nil { |
| 53 | vlog.VI(1).Infof("libstats.Glob(%q, %q) failed: %v", i.suffix, pattern, err) |
| 54 | } |
| 55 | }() |
| 56 | return ch, nil |
Robin Thellend | 7a44243 | 2014-08-22 09:05:08 -0700 | [diff] [blame] | 57 | } |
| 58 | |
| 59 | // WatchGlob returns the name and value of the objects that match the request, |
| 60 | // followed by periodic updates when values change. |
Todd Wang | 8c1e4c8 | 2015-03-25 16:40:43 -0700 | [diff] [blame] | 61 | func (i *statsService) WatchGlob(call watch.GlobWatcherWatchGlobServerCall, req watch.GlobRequest) error { |
Robin Thellend | 7a44243 | 2014-08-22 09:05:08 -0700 | [diff] [blame] | 62 | vlog.VI(1).Infof("%v.WatchGlob(%+v)", i.suffix, req) |
| 63 | |
| 64 | var t time.Time |
| 65 | Loop: |
| 66 | for { |
| 67 | prevTime := t |
| 68 | t = time.Now() |
Robin Thellend | bde278d | 2014-11-19 15:07:32 -0800 | [diff] [blame] | 69 | it := libstats.Glob(i.suffix, req.Pattern, prevTime, true) |
Todd Wang | 8c1e4c8 | 2015-03-25 16:40:43 -0700 | [diff] [blame] | 70 | changes := []watch.Change{} |
Robin Thellend | 7a44243 | 2014-08-22 09:05:08 -0700 | [diff] [blame] | 71 | for it.Advance() { |
| 72 | v := it.Value() |
Todd Wang | 8c1e4c8 | 2015-03-25 16:40:43 -0700 | [diff] [blame] | 73 | c := watch.Change{ |
Robin Thellend | 7a44243 | 2014-08-22 09:05:08 -0700 | [diff] [blame] | 74 | Name: v.Key, |
Todd Wang | 8c1e4c8 | 2015-03-25 16:40:43 -0700 | [diff] [blame] | 75 | State: watch.Exists, |
Todd Wang | b31da59 | 2015-02-20 12:50:39 -0800 | [diff] [blame] | 76 | Value: vdl.ValueOf(v.Value), |
Robin Thellend | 7a44243 | 2014-08-22 09:05:08 -0700 | [diff] [blame] | 77 | } |
| 78 | changes = append(changes, c) |
| 79 | } |
| 80 | if err := it.Err(); err != nil { |
Mike Burrows | 2c98937 | 2015-03-31 18:06:39 -0700 | [diff] [blame] | 81 | if verror.ErrorID(err) == verror.ErrNoExist.ID { |
Suharsh Sivakumar | 31f4985 | 2015-03-03 16:13:20 -0800 | [diff] [blame] | 82 | return verror.New(verror.ErrNoExist, call.Context(), i.suffix) |
Robin Thellend | 7a44243 | 2014-08-22 09:05:08 -0700 | [diff] [blame] | 83 | } |
Suharsh Sivakumar | 31f4985 | 2015-03-03 16:13:20 -0800 | [diff] [blame] | 84 | return verror.New(errOperationFailed, call.Context(), i.suffix) |
Robin Thellend | 7a44243 | 2014-08-22 09:05:08 -0700 | [diff] [blame] | 85 | } |
Tilak Sharma | 8ef6026 | 2014-08-26 14:54:37 -0700 | [diff] [blame] | 86 | for _, change := range changes { |
Suharsh Sivakumar | 31f4985 | 2015-03-03 16:13:20 -0800 | [diff] [blame] | 87 | if err := call.SendStream().Send(change); err != nil { |
Tilak Sharma | 8ef6026 | 2014-08-26 14:54:37 -0700 | [diff] [blame] | 88 | return err |
| 89 | } |
Robin Thellend | 7a44243 | 2014-08-22 09:05:08 -0700 | [diff] [blame] | 90 | } |
| 91 | select { |
Suharsh Sivakumar | 31f4985 | 2015-03-03 16:13:20 -0800 | [diff] [blame] | 92 | case <-call.Context().Done(): |
Robin Thellend | 7a44243 | 2014-08-22 09:05:08 -0700 | [diff] [blame] | 93 | break Loop |
| 94 | case <-time.After(i.watchFreq): |
| 95 | } |
| 96 | } |
| 97 | return nil |
| 98 | } |
| 99 | |
| 100 | // Value returns the value of the receiver object. |
Matt Rosencrantz | 94502cf | 2015-03-18 09:43:44 -0700 | [diff] [blame] | 101 | func (i *statsService) Value(call rpc.ServerCall) (*vdl.Value, error) { |
Robin Thellend | 7a44243 | 2014-08-22 09:05:08 -0700 | [diff] [blame] | 102 | vlog.VI(1).Infof("%v.Value()", i.suffix) |
| 103 | |
Todd Wang | b31da59 | 2015-02-20 12:50:39 -0800 | [diff] [blame] | 104 | rv, err := libstats.Value(i.suffix) |
| 105 | switch { |
Mike Burrows | 2c98937 | 2015-03-31 18:06:39 -0700 | [diff] [blame] | 106 | case verror.ErrorID(err) == verror.ErrNoExist.ID: |
Matt Rosencrantz | 9dce9b2 | 2015-03-02 10:48:37 -0800 | [diff] [blame] | 107 | return nil, verror.New(verror.ErrNoExist, call.Context(), i.suffix) |
Mike Burrows | 2c98937 | 2015-03-31 18:06:39 -0700 | [diff] [blame] | 108 | case verror.ErrorID(err) == stats.ErrNoValue.ID: |
Matt Rosencrantz | 9dce9b2 | 2015-03-02 10:48:37 -0800 | [diff] [blame] | 109 | return nil, stats.NewErrNoValue(call.Context(), i.suffix) |
Todd Wang | b31da59 | 2015-02-20 12:50:39 -0800 | [diff] [blame] | 110 | case err != nil: |
Matt Rosencrantz | 9dce9b2 | 2015-03-02 10:48:37 -0800 | [diff] [blame] | 111 | return nil, verror.New(errOperationFailed, call.Context(), i.suffix) |
Robin Thellend | 7a44243 | 2014-08-22 09:05:08 -0700 | [diff] [blame] | 112 | } |
Todd Wang | b31da59 | 2015-02-20 12:50:39 -0800 | [diff] [blame] | 113 | vv, err := vdl.ValueFromReflect(reflect.ValueOf(rv)) |
| 114 | if err != nil { |
Matt Rosencrantz | 9dce9b2 | 2015-03-02 10:48:37 -0800 | [diff] [blame] | 115 | return nil, verror.New(verror.ErrInternal, call.Context(), i.suffix, err) |
Todd Wang | b31da59 | 2015-02-20 12:50:39 -0800 | [diff] [blame] | 116 | } |
| 117 | return vv, nil |
Robin Thellend | 7a44243 | 2014-08-22 09:05:08 -0700 | [diff] [blame] | 118 | } |