Пример #1
0
void w_perf_log(w_perf_t *perf) {
  json_t *info;
  char *dumped = NULL;

  if (!perf->will_log) {
    return;
  }

  // Assemble a perf blob
  info = json_pack("{s:u, s:O, s:i, s:u}",           //
                   "description", perf->description, //
                   "meta", perf->meta_data,          //
                   "pid", getpid(),                  //
                   "version", PACKAGE_VERSION        //
                   );

#ifdef WATCHMAN_BUILD_INFO
  set_unicode_prop(info, "buildinfo", WATCHMAN_BUILD_INFO);
#endif

#define ADDTV(name, tv)                                                        \
  set_prop(info, name, json_real(w_timeval_abs_seconds(tv)))
  ADDTV("elapsed_time", perf->duration);
  ADDTV("start_time", perf->time_begin);
#ifdef HAVE_SYS_RESOURCE_H
  ADDTV("user_time", perf->usage.ru_utime);
  ADDTV("system_time", perf->usage.ru_stime);
#define ADDU(n) set_prop(info, #n, json_integer(perf->usage.n))
  ADDU(ru_maxrss);
  ADDU(ru_ixrss);
  ADDU(ru_idrss);
  ADDU(ru_minflt);
  ADDU(ru_majflt);
  ADDU(ru_nswap);
  ADDU(ru_inblock);
  ADDU(ru_oublock);
  ADDU(ru_msgsnd);
  ADDU(ru_msgrcv);
  ADDU(ru_nsignals);
  ADDU(ru_nvcsw);
  ADDU(ru_nivcsw);
#endif // HAVE_SYS_RESOURCE_H
#undef ADDU
#undef ADDTV

  // Log to the log file
  dumped = json_dumps(info, 0);
  w_log(W_LOG_ERR, "PERF: %s\n", dumped);
  free(dumped);

  if (!cfg_get_json(NULL, "perf_logger_command")) {
    json_decref(info);
    return;
  }

  // Send this to our logging thread for async processing

  pthread_mutex_lock(&perf_log_lock);
  if (!perf_log_thread_started) {
    pthread_cond_init(&perf_log_cond, NULL);
    pthread_create(&perf_log_thr, NULL, perf_log_thread, NULL);
    perf_log_thread_started = true;
  }

  if (!perf_log_samples) {
    perf_log_samples = json_array();
  }
  json_array_append_new(perf_log_samples, info);
  pthread_mutex_unlock(&perf_log_lock);

  pthread_cond_signal(&perf_log_cond);
}
Пример #2
0
void watchman_perf_sample::log() {
  char *dumped = NULL;

  if (!will_log) {
    return;
  }

  // Assemble a perf blob
  auto info = json_object(
      {{"description", typed_string_to_json(description)},
       {"meta", meta_data},
       {"pid", json_integer(getpid())},
       {"version", typed_string_to_json(PACKAGE_VERSION, W_STRING_UNICODE)}});

#ifdef WATCHMAN_BUILD_INFO
  info.set(
      "buildinfo", typed_string_to_json(WATCHMAN_BUILD_INFO, W_STRING_UNICODE));
#endif

#define ADDTV(name, tv) info.set(name, json_real(w_timeval_abs_seconds(tv)))
  ADDTV("elapsed_time", duration);
  ADDTV("start_time", time_begin);
#ifdef HAVE_SYS_RESOURCE_H
  ADDTV("user_time", usage.ru_utime);
  ADDTV("system_time", usage.ru_stime);
#define ADDU(n) info.set(#n, json_integer(usage.n))
  ADDU(ru_maxrss);
  ADDU(ru_ixrss);
  ADDU(ru_idrss);
  ADDU(ru_minflt);
  ADDU(ru_majflt);
  ADDU(ru_nswap);
  ADDU(ru_inblock);
  ADDU(ru_oublock);
  ADDU(ru_msgsnd);
  ADDU(ru_msgrcv);
  ADDU(ru_nsignals);
  ADDU(ru_nvcsw);
  ADDU(ru_nivcsw);
#endif // HAVE_SYS_RESOURCE_H
#undef ADDU
#undef ADDTV

  // Log to the log file
  dumped = json_dumps(info, 0);
  w_log(W_LOG_ERR, "PERF: %s\n", dumped);
  free(dumped);

  if (!cfg_get_json("perf_logger_command")) {
    return;
  }

  // Send this to our logging thread for async processing

  {
    // The common case is that we already set up the logging
    // thread and that we can just log through it.
    auto rlock = perfThread.rlock();
    if (rlock->get()) {
      (*rlock)->addSample(std::move(info));
      return;
    }
  }

  // If it wasn't set, then we need an exclusive lock to
  // make sure that we don't spawn multiple instances.
  {
    auto wlock = perfThread.wlock();

    if (!wlock->get()) {
      *wlock = watchman::make_unique<PerfLogThread>();
    }

    (*wlock)->addSample(std::move(info));
  }
}