blob: ad82498ebae133d1499172a3a0670d3ee7013a56 [file] [log] [blame]
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001/*
2 *
Craig Tiller2e190362016-03-25 14:33:26 -07003 * Copyright 2015-2016, Google Inc.
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08004 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
Hongyu Chen1ef06e62015-02-04 10:36:04 -080034#include "src/core/statistics/census_tracing.h"
Craig Tillerf40df232016-03-25 13:38:14 -070035#include "src/core/statistics/census_interface.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080036
hongyu24200d32015-01-08 15:13:49 -080037#include <stdio.h>
38#include <string.h>
39
hongyu24200d32015-01-08 15:13:49 -080040#include <grpc/support/alloc.h>
41#include <grpc/support/log.h>
42#include <grpc/support/port_platform.h>
hongyu24200d32015-01-08 15:13:49 -080043#include <grpc/support/sync.h>
Craig Tillerf40df232016-03-25 13:38:14 -070044#include "src/core/statistics/hash_table.h"
45#include "src/core/support/string.h"
hongyu24200d32015-01-08 15:13:49 -080046
Craig Tillera82950e2015-09-22 12:33:20 -070047void census_trace_obj_destroy(census_trace_obj *obj) {
Craig Tiller45724b32015-09-22 10:42:19 -070048 census_trace_annotation *p = obj->annotations;
Craig Tillera82950e2015-09-22 12:33:20 -070049 while (p != NULL) {
50 census_trace_annotation *next = p->next;
51 gpr_free(p);
52 p = next;
53 }
54 gpr_free(obj->method);
55 gpr_free(obj);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080056}
57
Craig Tillera82950e2015-09-22 12:33:20 -070058static void delete_trace_obj(void *obj) {
59 census_trace_obj_destroy((census_trace_obj *)obj);
Hongyu Chen2bfbfe82015-02-05 16:12:26 -080060}
hongyu24200d32015-01-08 15:13:49 -080061
62static const census_ht_option ht_opt = {
Craig Tillerf40df232016-03-25 13:38:14 -070063 CENSUS_HT_UINT64 /* key type */,
64 571 /* n_of_buckets */,
65 NULL /* hash */,
66 NULL /* compare_keys */,
67 delete_trace_obj /* delete data */,
Craig Tillera82950e2015-09-22 12:33:20 -070068 NULL /* delete key */
Craig Tillerecd49342015-01-18 14:36:47 -080069};
hongyu24200d32015-01-08 15:13:49 -080070
71static gpr_once g_init_mutex_once = GPR_ONCE_INIT;
Craig Tillera82950e2015-09-22 12:33:20 -070072static gpr_mu g_mu; /* Guards following two static variables. */
Craig Tiller45724b32015-09-22 10:42:19 -070073static census_ht *g_trace_store = NULL;
Craig Tiller7536af02015-12-22 13:49:30 -080074static uint64_t g_id = 0;
hongyu24200d32015-01-08 15:13:49 -080075
Craig Tillera82950e2015-09-22 12:33:20 -070076static census_ht_key op_id_as_key(census_op_id *id) {
77 return *(census_ht_key *)id;
hongyu24200d32015-01-08 15:13:49 -080078}
79
Craig Tiller7536af02015-12-22 13:49:30 -080080static uint64_t op_id_2_uint64(census_op_id *id) {
81 uint64_t ret;
Craig Tillera82950e2015-09-22 12:33:20 -070082 memcpy(&ret, id, sizeof(census_op_id));
hongyu24200d32015-01-08 15:13:49 -080083 return ret;
84}
85
Craig Tillera82950e2015-09-22 12:33:20 -070086static void init_mutex(void) { gpr_mu_init(&g_mu); }
87
88static void init_mutex_once(void) {
89 gpr_once_init(&g_init_mutex_once, init_mutex);
Craig Tiller3eef2c42015-01-15 11:37:54 -080090}
hongyu24200d32015-01-08 15:13:49 -080091
Craig Tillera82950e2015-09-22 12:33:20 -070092census_op_id census_tracing_start_op(void) {
93 gpr_mu_lock(&g_mu);
hongyu24200d32015-01-08 15:13:49 -080094 {
Craig Tillera82950e2015-09-22 12:33:20 -070095 census_trace_obj *ret = gpr_malloc(sizeof(census_trace_obj));
96 memset(ret, 0, sizeof(census_trace_obj));
hongyu24200d32015-01-08 15:13:49 -080097 g_id++;
Craig Tillera82950e2015-09-22 12:33:20 -070098 memcpy(&ret->id, &g_id, sizeof(census_op_id));
hongyu24200d32015-01-08 15:13:49 -080099 ret->rpc_stats.cnt = 1;
Craig Tillera82950e2015-09-22 12:33:20 -0700100 ret->ts = gpr_now(GPR_CLOCK_REALTIME);
101 census_ht_insert(g_trace_store, op_id_as_key(&ret->id), (void *)ret);
102 gpr_log(GPR_DEBUG, "Start tracing for id %lu", g_id);
103 gpr_mu_unlock(&g_mu);
hongyu24200d32015-01-08 15:13:49 -0800104 return ret->id;
105 }
106}
107
Craig Tillera82950e2015-09-22 12:33:20 -0700108int census_add_method_tag(census_op_id op_id, const char *method) {
hongyu24200d32015-01-08 15:13:49 -0800109 int ret = 0;
Craig Tiller45724b32015-09-22 10:42:19 -0700110 census_trace_obj *trace = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700111 gpr_mu_lock(&g_mu);
112 trace = census_ht_find(g_trace_store, op_id_as_key(&op_id));
113 if (trace == NULL) {
114 ret = 1;
115 } else {
116 trace->method = gpr_strdup(method);
117 }
118 gpr_mu_unlock(&g_mu);
hongyu24200d32015-01-08 15:13:49 -0800119 return ret;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800120}
121
Craig Tillera82950e2015-09-22 12:33:20 -0700122void census_tracing_print(census_op_id op_id, const char *anno_txt) {
Craig Tiller45724b32015-09-22 10:42:19 -0700123 census_trace_obj *trace = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700124 gpr_mu_lock(&g_mu);
125 trace = census_ht_find(g_trace_store, op_id_as_key(&op_id));
126 if (trace != NULL) {
127 census_trace_annotation *anno = gpr_malloc(sizeof(census_trace_annotation));
128 anno->ts = gpr_now(GPR_CLOCK_REALTIME);
hongyu440d3d82015-01-09 12:39:36 -0800129 {
Craig Tillera82950e2015-09-22 12:33:20 -0700130 char *d = anno->txt;
131 const char *s = anno_txt;
132 int n = 0;
133 for (; n < CENSUS_MAX_ANNOTATION_LENGTH && *s != '\0'; ++n) {
134 *d++ = *s++;
hongyu440d3d82015-01-09 12:39:36 -0800135 }
Craig Tillera82950e2015-09-22 12:33:20 -0700136 *d = '\0';
hongyu440d3d82015-01-09 12:39:36 -0800137 }
Craig Tillera82950e2015-09-22 12:33:20 -0700138 anno->next = trace->annotations;
139 trace->annotations = anno;
140 }
141 gpr_mu_unlock(&g_mu);
hongyu440d3d82015-01-09 12:39:36 -0800142}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800143
Craig Tillera82950e2015-09-22 12:33:20 -0700144void census_tracing_end_op(census_op_id op_id) {
Craig Tiller45724b32015-09-22 10:42:19 -0700145 census_trace_obj *trace = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700146 gpr_mu_lock(&g_mu);
147 trace = census_ht_find(g_trace_store, op_id_as_key(&op_id));
148 if (trace != NULL) {
149 trace->rpc_stats.elapsed_time_ms = gpr_timespec_to_micros(
150 gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), trace->ts));
151 gpr_log(GPR_DEBUG, "End tracing for id %lu, method %s, latency %f us",
152 op_id_2_uint64(&op_id), trace->method,
153 trace->rpc_stats.elapsed_time_ms);
154 census_ht_erase(g_trace_store, op_id_as_key(&op_id));
155 }
156 gpr_mu_unlock(&g_mu);
hongyu24200d32015-01-08 15:13:49 -0800157}
158
Craig Tillera82950e2015-09-22 12:33:20 -0700159void census_tracing_init(void) {
160 init_mutex_once();
161 gpr_mu_lock(&g_mu);
162 if (g_trace_store == NULL) {
163 g_id = 1;
164 g_trace_store = census_ht_create(&ht_opt);
165 } else {
166 gpr_log(GPR_ERROR, "Census trace store already initialized.");
167 }
168 gpr_mu_unlock(&g_mu);
hongyu24200d32015-01-08 15:13:49 -0800169}
170
Craig Tillera82950e2015-09-22 12:33:20 -0700171void census_tracing_shutdown(void) {
172 gpr_mu_lock(&g_mu);
173 if (g_trace_store != NULL) {
174 census_ht_destroy(g_trace_store);
175 g_trace_store = NULL;
176 } else {
177 gpr_log(GPR_ERROR, "Census trace store is not initialized.");
178 }
179 gpr_mu_unlock(&g_mu);
hongyu24200d32015-01-08 15:13:49 -0800180}
181
Craig Tillera82950e2015-09-22 12:33:20 -0700182void census_internal_lock_trace_store(void) { gpr_mu_lock(&g_mu); }
183
184void census_internal_unlock_trace_store(void) { gpr_mu_unlock(&g_mu); }
185
186census_trace_obj *census_get_trace_obj_locked(census_op_id op_id) {
187 if (g_trace_store == NULL) {
188 gpr_log(GPR_ERROR, "Census trace store is not initialized.");
189 return NULL;
190 }
191 return (census_trace_obj *)census_ht_find(g_trace_store,
192 op_id_as_key(&op_id));
hongyu24200d32015-01-08 15:13:49 -0800193}
194
Craig Tillera82950e2015-09-22 12:33:20 -0700195const char *census_get_trace_method_name(const census_trace_obj *trace) {
Hongyu Chenb5674542015-02-05 12:18:05 -0800196 return trace->method;
hongyu24200d32015-01-08 15:13:49 -0800197}
Hongyu Chen1ef06e62015-02-04 10:36:04 -0800198
Craig Tillera82950e2015-09-22 12:33:20 -0700199static census_trace_annotation *dup_annotation_chain(
200 census_trace_annotation *from) {
Craig Tiller45724b32015-09-22 10:42:19 -0700201 census_trace_annotation *ret = NULL;
202 census_trace_annotation **to = &ret;
Craig Tillera82950e2015-09-22 12:33:20 -0700203 for (; from != NULL; from = from->next) {
204 *to = gpr_malloc(sizeof(census_trace_annotation));
205 memcpy(*to, from, sizeof(census_trace_annotation));
206 to = &(*to)->next;
207 }
Hongyu Chen1ed726c2015-02-05 15:49:09 -0800208 return ret;
Hongyu Chen1ef06e62015-02-04 10:36:04 -0800209}
210
Craig Tillera82950e2015-09-22 12:33:20 -0700211static census_trace_obj *trace_obj_dup(census_trace_obj *from) {
Craig Tiller45724b32015-09-22 10:42:19 -0700212 census_trace_obj *to = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700213 GPR_ASSERT(from != NULL);
214 to = gpr_malloc(sizeof(census_trace_obj));
Hongyu Chen1ef06e62015-02-04 10:36:04 -0800215 to->id = from->id;
216 to->ts = from->ts;
217 to->rpc_stats = from->rpc_stats;
Craig Tillera82950e2015-09-22 12:33:20 -0700218 to->method = gpr_strdup(from->method);
219 to->annotations = dup_annotation_chain(from->annotations);
Hongyu Chen1ef06e62015-02-04 10:36:04 -0800220 return to;
221}
222
Craig Tillera82950e2015-09-22 12:33:20 -0700223census_trace_obj **census_get_active_ops(int *num_active_ops) {
Craig Tiller45724b32015-09-22 10:42:19 -0700224 census_trace_obj **ret = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700225 gpr_mu_lock(&g_mu);
226 if (g_trace_store != NULL) {
227 size_t n = 0;
228 census_ht_kv *all_kvs = census_ht_get_all_elements(g_trace_store, &n);
229 *num_active_ops = (int)n;
230 if (n != 0) {
231 size_t i = 0;
232 ret = gpr_malloc(sizeof(census_trace_obj *) * n);
233 for (i = 0; i < n; i++) {
234 ret[i] = trace_obj_dup((census_trace_obj *)all_kvs[i].v);
235 }
Hongyu Chen1ef06e62015-02-04 10:36:04 -0800236 }
Craig Tillera82950e2015-09-22 12:33:20 -0700237 gpr_free(all_kvs);
238 }
239 gpr_mu_unlock(&g_mu);
Hongyu Chen1ef06e62015-02-04 10:36:04 -0800240 return ret;
Craig Tiller190d3602015-02-18 09:23:38 -0800241}