Merge "Unify and fix `list_traces` function"
Zuul authored 6 years ago
Gerrit Code Review committed 6 years ago
167 | 167 | fields = ("base_id", "timestamp") |
168 | 168 | pretty_table = prettytable.PrettyTable(fields) |
169 | 169 | pretty_table.align = "l" |
170 | traces = engine.list_traces({}, fields) | |
170 | traces = engine.list_traces(fields) | |
171 | 171 | for trace in traces: |
172 | 172 | row = [trace[field] for field in fields] |
173 | 173 | pretty_table.add_row(row) |
52 | 52 | and implemented by any class derived from this class. |
53 | 53 | """ |
54 | 54 | |
55 | default_trace_fields = {"base_id", "timestamp"} | |
56 | ||
55 | 57 | def __init__(self, connection_str, project=None, service=None, host=None): |
56 | 58 | self.connection_str = connection_str |
57 | 59 | self.project = project |
100 | 102 | """Returns backend specific name for the driver.""" |
101 | 103 | return cls.__name__ |
102 | 104 | |
103 | def list_traces(self, query, fields): | |
104 | """Returns array of all base_id fields that match the given criteria | |
105 | ||
106 | :param query: dict that specifies the query criteria | |
107 | :param fields: iterable of strings that specifies the output fields | |
105 | def list_traces(self, fields=None): | |
106 | """Query all traces from the storage. | |
107 | ||
108 | :param fields: Set of trace fields to return. Defaults to 'base_id' | |
109 | and 'timestamp' | |
110 | :return List of traces, where each trace is a dictionary containing | |
111 | at least `base_id` and `timestamp`. | |
108 | 112 | """ |
109 | 113 | raise NotImplementedError("{0}: This method is either not supported " |
110 | 114 | "or has to be overridden".format( |
89 | 89 | |
90 | 90 | return result |
91 | 91 | |
92 | def list_traces(self, query={"match_all": {}}, fields=[]): | |
92 | def list_traces(self, fields=None): | |
93 | 93 | """Returns array of all base_id fields that match the given criteria |
94 | 94 | |
95 | 95 | :param query: dict that specifies the query criteria |
96 | 96 | :param fields: iterable of strings that specifies the output fields |
97 | 97 | """ |
98 | for base_field in ["base_id", "timestamp"]: | |
99 | if base_field not in fields: | |
100 | fields.append(base_field) | |
98 | query = {"match_all": {}} | |
99 | fields = set(fields or self.default_trace_fields) | |
101 | 100 | |
102 | 101 | response = self.client.search(index=self.index_name, |
103 | 102 | doc_type=self.conf.profiler.es_doc_type, |
59 | 59 | data["service"] = self.service |
60 | 60 | self.db.profiler.insert_one(data) |
61 | 61 | |
62 | def list_traces(self, query, fields=[]): | |
63 | """Returns array of all base_id fields that match the given criteria | |
62 | def list_traces(self, fields=None): | |
63 | """Query all traces from the storage. | |
64 | 64 | |
65 | :param query: dict that specifies the query criteria | |
66 | :param fields: iterable of strings that specifies the output fields | |
65 | :param fields: Set of trace fields to return. Defaults to 'base_id' | |
66 | and 'timestamp' | |
67 | :return List of traces, where each trace is a dictionary containing | |
68 | at least `base_id` and `timestamp`. | |
67 | 69 | """ |
68 | ids = self.db.profiler.find(query).distinct("base_id") | |
70 | fields = set(fields or self.default_trace_fields) | |
71 | ids = self.db.profiler.find("*").distinct("base_id") | |
69 | 72 | out_format = {"base_id": 1, "timestamp": 1, "_id": 0} |
70 | 73 | out_format.update({i: 1 for i in fields}) |
71 | 74 | return [self.db.profiler.find( |
69 | 69 | data["timestamp"] |
70 | 70 | self.db.set(key, jsonutils.dumps(data)) |
71 | 71 | |
72 | def list_traces(self, query="*", fields=[]): | |
73 | """Returns array of all base_id fields that match the given criteria | |
72 | def list_traces(self, fields=None): | |
73 | """Query all traces from the storage. | |
74 | 74 | |
75 | :param query: string that specifies the query criteria | |
76 | :param fields: iterable of strings that specifies the output fields | |
75 | :param fields: Set of trace fields to return. Defaults to 'base_id' | |
76 | and 'timestamp' | |
77 | :return List of traces, where each trace is a dictionary containing | |
78 | at least `base_id` and `timestamp`. | |
77 | 79 | """ |
78 | for base_field in ["base_id", "timestamp"]: | |
79 | if base_field not in fields: | |
80 | fields.append(base_field) | |
81 | ids = self.db.scan_iter(match=self.namespace + query) | |
80 | fields = set(fields or self.default_trace_fields) | |
81 | ||
82 | # With current schema every event is stored under its own unique key | |
83 | # To query all traces we first need to get all keys, then | |
84 | # get all events, sort them and pick up only the first one | |
85 | ids = self.db.scan_iter(match=self.namespace + "*") | |
82 | 86 | traces = [jsonutils.loads(self.db.get(i)) for i in ids] |
87 | traces.sort(key=lambda x: x["timestamp"]) | |
88 | seen_ids = set() | |
83 | 89 | result = [] |
84 | 90 | for trace in traces: |
85 | result.append({key: value for key, value in trace.iteritems() | |
86 | if key in fields}) | |
91 | if trace["base_id"] not in seen_ids: | |
92 | seen_ids.add(trace["base_id"]) | |
93 | result.append({key: value for key, value in trace.items() | |
94 | if key in fields}) | |
87 | 95 | return result |
88 | 96 | |
89 | 97 | def get_report(self, base_id): |
125 | 125 | enabled=True, |
126 | 126 | trace_sqlalchemy=False, |
127 | 127 | hmac_keys="SECRET_KEY") |
128 | ||
129 | def test_list_traces(self): | |
130 | # initialize profiler notifier (the same way as in services) | |
131 | initializer.init_from_conf( | |
132 | CONF, {}, self.PROJECT, self.SERVICE, "host") | |
133 | profiler.init("SECRET_KEY") | |
134 | ||
135 | # grab base_id | |
136 | base_id = profiler.get().get_base_id() | |
137 | ||
138 | # execute profiled code | |
139 | foo = Foo() | |
140 | foo.bar(1) | |
141 | ||
142 | # instantiate report engine (the same way as in osprofiler CLI) | |
143 | engine = base.get_driver(CONF.profiler.connection_string, | |
144 | project=self.PROJECT, | |
145 | service=self.SERVICE, | |
146 | host="host", | |
147 | conf=CONF) | |
148 | ||
149 | # generate the report | |
150 | traces = engine.list_traces() | |
151 | LOG.debug("Collected traces: %s", traces) | |
152 | ||
153 | # ensure trace with base_id is in the list of traces | |
154 | self.assertIn(base_id, [t["base_id"] for t in traces]) |