/* * * Copyright 2015 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "src/core/lib/debug/trace.h" #include #include #include #include #include "src/core/lib/support/env.h" int grpc_tracer_set_enabled(const char* name, int enabled); typedef struct tracer { grpc_tracer_flag* flag; struct tracer* next; } tracer; static tracer* tracers; #ifdef GRPC_THREADSAFE_TRACER #define TRACER_SET(flag, on) gpr_atm_no_barrier_store(&(flag).value, (on)) #else #define TRACER_SET(flag, on) (flag).value = (on) #endif void grpc_register_tracer(grpc_tracer_flag* flag) { tracer* t = (tracer*)gpr_malloc(sizeof(*t)); t->flag = flag; t->next = tracers; TRACER_SET(*flag, false); tracers = t; } static void add(const char* beg, const char* end, char*** ss, size_t* ns) { size_t n = *ns; size_t np = n + 1; char* s; size_t len; GPR_ASSERT(end >= beg); len = (size_t)(end - beg); s = (char*)gpr_malloc(len + 1); memcpy(s, beg, len); s[len] = 0; *ss = (char**)gpr_realloc(*ss, sizeof(char**) * np); (*ss)[n] = s; *ns = np; } static void split(const char* s, char*** ss, size_t* ns) { const char* c = strchr(s, ','); if (c == NULL) { add(s, s + strlen(s), ss, ns); } else { add(s, c, ss, ns); split(c + 1, ss, ns); } } static void parse(const char* s) { char** strings = NULL; size_t nstrings = 0; size_t i; split(s, &strings, &nstrings); for (i = 0; i < nstrings; i++) { if (strings[i][0] == '-') { grpc_tracer_set_enabled(strings[i] + 1, 0); } else { grpc_tracer_set_enabled(strings[i], 1); } } for (i = 0; i < nstrings; i++) { gpr_free(strings[i]); } gpr_free(strings); } static void list_tracers() { gpr_log(GPR_DEBUG, "available tracers:"); tracer* t; for (t = tracers; t; t = t->next) { gpr_log(GPR_DEBUG, "\t%s", t->flag->name); } } void grpc_tracer_init(const char* env_var) { char* e = gpr_getenv(env_var); if (e != NULL) { parse(e); gpr_free(e); } } void grpc_tracer_shutdown(void) { while (tracers) { tracer* t = tracers; tracers = t->next; gpr_free(t); } } int grpc_tracer_set_enabled(const char* name, int enabled) { tracer* t; if (0 == strcmp(name, "all")) { for (t = tracers; t; t = t->next) { TRACER_SET(*t->flag, enabled); } } else if (0 == strcmp(name, "list_tracers")) { list_tracers(); } else if (0 == strcmp(name, "refcount")) { for (t = tracers; t; t = t->next) { if (strstr(t->flag->name, "refcount") != NULL) { TRACER_SET(*t->flag, enabled); } } } else { int found = 0; for (t = tracers; t; t = t->next) { if (0 == strcmp(name, t->flag->name)) { TRACER_SET(*t->flag, enabled); found = 1; } } if (!found) { gpr_log(GPR_ERROR, "Unknown trace var: '%s'", name); return 0; /* early return */ } } return 1; }