scripts/mycroft/metrics/__init__.py
Go to the documentation of this file.
1 # Copyright 2017 Mycroft AI Inc.
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 import json
16 import threading
17 import time
18 
19 import requests
20 
21 from mycroft.api import DeviceApi, is_paired
22 from mycroft.configuration import Configuration
23 from mycroft.session import SessionManager
24 from mycroft.util.log import LOG
25 from mycroft.version import CORE_VERSION_STR
26 from copy import copy
27 
28 
29 def report_metric(name, data):
30  """
31  Report a general metric to the Mycroft servers
32 
33  Args:
34  name (str): Name of metric. Must use only letters and hyphens
35  data (dict): JSON dictionary to report. Must be valid JSON
36  """
37  try:
38  if is_paired() and Configuration().get()['opt_in']:
39  DeviceApi().report_metric(name, data)
40  except requests.RequestException as e:
41  LOG.error('Metric couldn\'t be uploaded, due to a network error ({})'
42  .format(e))
43 
44 
45 def report_timing(ident, system, timing, additional_data=None):
46  """
47  Create standardized message for reporting timing.
48 
49  ident (str): identifier of user interaction
50  system (str): system the that's generated the report
51  timing (stopwatch): Stopwatch object with recorded timing
52  additional_data (dict): dictionary with related data
53  """
54  additional_data = additional_data or {}
55  report = copy(additional_data)
56  report['id'] = ident
57  report['system'] = system
58  report['start_time'] = timing.timestamp
59  report['time'] = timing.time
60 
61  report_metric('timing', report)
62 
63 
64 class Stopwatch:
65  """
66  Simple time measuring class.
67  """
68  def __init__(self):
69  self.timestamp = None
70  self.time = None
71 
72  def start(self):
73  """
74  Start a time measurement
75  """
76  self.timestamp = time.time()
77 
78  def lap(self):
79  cur_time = time.time()
80  start_time = self.timestamp
81  self.timestamp = cur_time
82  return cur_time - start_time
83 
84  def stop(self):
85  """
86  Stop a running time measurement. returns the measured time
87  """
88  cur_time = time.time()
89  start_time = self.timestamp
90  self.time = cur_time - start_time
91  return self.time
92 
93  def __enter__(self):
94  """
95  Start stopwatch when entering with-block.
96  """
97  self.start()
98 
99  def __exit__(self, tpe, value, tb):
100  """
101  Stop stopwatch when exiting with-block.
102  """
103  self.stop()
104 
105  def __str__(self):
106  cur_time = time.time()
107  if self.timestamp:
108  return str(self.time or cur_time - self.timestamp)
109  else:
110  return 'Not started'
111 
112 
114  """
115  MetricsAggregator is not threadsafe, and multiple clients writing the
116  same metric "concurrently" may result in data loss.
117  """
118 
119  def __init__(self):
120  self._counters = {}
121  self._timers = {}
122  self._levels = {}
123  self._attributes = {}
124  self.attr("version", CORE_VERSION_STR)
125 
126  def increment(self, name, value=1):
127  cur = self._counters.get(name, 0)
128  self._counters[name] = cur + value
129 
130  def timer(self, name, value):
131  cur = self._timers.get(name)
132  if not cur:
133  self._timers[name] = []
134  cur = self._timers[name] = []
135  cur.append(value)
136 
137  def level(self, name, value):
138  self._levels[name] = value
139 
140  def clear(self):
141  self._counters = {}
142  self._timers = {}
143  self._levels = {}
144  self._attributes = {}
145  self.attr("version", CORE_VERSION_STR)
146 
147  def attr(self, name, value):
148  self._attributes[name] = value
149 
150  def flush(self):
151  publisher = MetricsPublisher()
152  payload = {
153  'counters': self._counters,
154  'timers': self._timers,
155  'levels': self._levels,
156  'attributes': self._attributes
157  }
158  self.clear()
159  count = (len(payload['counters']) + len(payload['timers']) +
160  len(payload['levels']))
161  if count > 0:
162  # LOG.debug(json.dumps(payload))
163 
164  def publish():
165  publisher.publish(payload)
166 
167  threading.Thread(target=publish).start()
168 
169 
171  def __init__(self, url=None, enabled=False):
172  conf = Configuration().get()['server']
173  self.url = url or conf['url']
174  self.enabled = enabled or conf['metrics']
175 
176  def publish(self, events):
177  if 'session_id' not in events:
178  session_id = SessionManager.get().session_id
179  events['session_id'] = session_id
180  if self.enabled:
181  requests.post(
182  self.url,
183  headers={'Content-Type': 'application/json'},
184  data=json.dumps(events), verify=False)
def report_timing(ident, system, timing, additional_data=None)
def is_paired(ignore_errors=True)
def __init__(self, url=None, enabled=False)
def get(phrase, lang=None, context=None)


mycroft_ros
Author(s):
autogenerated on Mon Apr 26 2021 02:35:40