You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

worker_commands.go 4.2 kB

4 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. // Copyright 2017, OpenCensus Authors
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. //
  15. package view
  16. import (
  17. "errors"
  18. "fmt"
  19. "strings"
  20. "time"
  21. "go.opencensus.io/stats"
  22. "go.opencensus.io/stats/internal"
  23. "go.opencensus.io/tag"
  24. )
  25. type command interface {
  26. handleCommand(w *worker)
  27. }
  28. // getViewByNameReq is the command to get a view given its name.
  29. type getViewByNameReq struct {
  30. name string
  31. c chan *getViewByNameResp
  32. }
  33. type getViewByNameResp struct {
  34. v *View
  35. }
  36. func (cmd *getViewByNameReq) handleCommand(w *worker) {
  37. v := w.views[cmd.name]
  38. if v == nil {
  39. cmd.c <- &getViewByNameResp{nil}
  40. return
  41. }
  42. cmd.c <- &getViewByNameResp{v.view}
  43. }
  44. // registerViewReq is the command to register a view.
  45. type registerViewReq struct {
  46. views []*View
  47. err chan error
  48. }
  49. func (cmd *registerViewReq) handleCommand(w *worker) {
  50. for _, v := range cmd.views {
  51. if err := v.canonicalize(); err != nil {
  52. cmd.err <- err
  53. return
  54. }
  55. }
  56. var errstr []string
  57. for _, view := range cmd.views {
  58. vi, err := w.tryRegisterView(view)
  59. if err != nil {
  60. errstr = append(errstr, fmt.Sprintf("%s: %v", view.Name, err))
  61. continue
  62. }
  63. internal.SubscriptionReporter(view.Measure.Name())
  64. vi.subscribe()
  65. }
  66. if len(errstr) > 0 {
  67. cmd.err <- errors.New(strings.Join(errstr, "\n"))
  68. } else {
  69. cmd.err <- nil
  70. }
  71. }
  72. // unregisterFromViewReq is the command to unregister to a view. Has no
  73. // impact on the data collection for client that are pulling data from the
  74. // library.
  75. type unregisterFromViewReq struct {
  76. views []string
  77. done chan struct{}
  78. }
  79. func (cmd *unregisterFromViewReq) handleCommand(w *worker) {
  80. for _, name := range cmd.views {
  81. vi, ok := w.views[name]
  82. if !ok {
  83. continue
  84. }
  85. // Report pending data for this view before removing it.
  86. w.reportView(vi, time.Now())
  87. vi.unsubscribe()
  88. if !vi.isSubscribed() {
  89. // this was the last subscription and view is not collecting anymore.
  90. // The collected data can be cleared.
  91. vi.clearRows()
  92. }
  93. w.unregisterView(name)
  94. }
  95. cmd.done <- struct{}{}
  96. }
  97. // retrieveDataReq is the command to retrieve data for a view.
  98. type retrieveDataReq struct {
  99. now time.Time
  100. v string
  101. c chan *retrieveDataResp
  102. }
  103. type retrieveDataResp struct {
  104. rows []*Row
  105. err error
  106. }
  107. func (cmd *retrieveDataReq) handleCommand(w *worker) {
  108. w.mu.Lock()
  109. defer w.mu.Unlock()
  110. vi, ok := w.views[cmd.v]
  111. if !ok {
  112. cmd.c <- &retrieveDataResp{
  113. nil,
  114. fmt.Errorf("cannot retrieve data; view %q is not registered", cmd.v),
  115. }
  116. return
  117. }
  118. if !vi.isSubscribed() {
  119. cmd.c <- &retrieveDataResp{
  120. nil,
  121. fmt.Errorf("cannot retrieve data; view %q has no subscriptions or collection is not forcibly started", cmd.v),
  122. }
  123. return
  124. }
  125. cmd.c <- &retrieveDataResp{
  126. vi.collectedRows(),
  127. nil,
  128. }
  129. }
  130. // recordReq is the command to record data related to multiple measures
  131. // at once.
  132. type recordReq struct {
  133. tm *tag.Map
  134. ms []stats.Measurement
  135. attachments map[string]interface{}
  136. t time.Time
  137. }
  138. func (cmd *recordReq) handleCommand(w *worker) {
  139. w.mu.Lock()
  140. defer w.mu.Unlock()
  141. for _, m := range cmd.ms {
  142. if (m == stats.Measurement{}) { // not registered
  143. continue
  144. }
  145. ref := w.getMeasureRef(m.Measure().Name())
  146. for v := range ref.views {
  147. v.addSample(cmd.tm, m.Value(), cmd.attachments, time.Now())
  148. }
  149. }
  150. }
  151. // setReportingPeriodReq is the command to modify the duration between
  152. // reporting the collected data to the registered clients.
  153. type setReportingPeriodReq struct {
  154. d time.Duration
  155. c chan bool
  156. }
  157. func (cmd *setReportingPeriodReq) handleCommand(w *worker) {
  158. w.timer.Stop()
  159. if cmd.d <= 0 {
  160. w.timer = time.NewTicker(defaultReportingDuration)
  161. } else {
  162. w.timer = time.NewTicker(cmd.d)
  163. }
  164. cmd.c <- true
  165. }