コード例 #1
0
ファイル: statsd.c プロジェクト: JonasKunze/reconnoiter
static int noit_statsd_onload(mtev_image_t *self) {
  if(!nlerr) nlerr = mtev_log_stream_find("error/statsd");
  if(!nldeb) nldeb = mtev_log_stream_find("debug/statsd");
  if(!nlerr) nlerr = noit_error;
  if(!nldeb) nldeb = noit_debug;
  return 0;
}
コード例 #2
0
ファイル: httptrap.c プロジェクト: edwardt/reconnoiter
static int mtev_httptrap_onload(mtev_image_t *self) {
  if(!nlerr) nlerr = mtev_log_stream_find("error/httptrap");
  if(!nldeb) nldeb = mtev_log_stream_find("debug/httptrap");
  if(!nlerr) nlerr = noit_error;
  if(!nldeb) nldeb = noit_debug;
  return 0;
}
コード例 #3
0
ファイル: mysql.c プロジェクト: aidancully/reconnoiter
static int mysql_onload(mtev_image_t *self) {
  nlerr = mtev_log_stream_find("error/mysql");
  nldeb = mtev_log_stream_find("debug/mysql");
  if(!nlerr) nlerr = noit_stderr;
  if(!nldeb) nldeb = noit_debug;

  eventer_name_callback("mysql/mysql_drive_session", mysql_drive_session);
  return 0;
}
コード例 #4
0
ファイル: test_abort.c プロジェクト: aidancully/reconnoiter
static int test_abort_onload(mtev_image_t *self) {
  nlerr = mtev_log_stream_find("error/test_abort");
  nldeb = mtev_log_stream_find("debug/test_abort");
  if(!nlerr) nlerr = noit_stderr;
  if(!nldeb) nldeb = noit_debug;

  eventer_name_callback("http/test_abort_drive_session", test_abort_drive_session);
  return 0;
}
コード例 #5
0
ファイル: check_test.c プロジェクト: aidancully/reconnoiter
static int
check_test_onload(mtev_image_t *self) {
  nlerr = mtev_log_stream_find("error/checktest");
  nldeb = mtev_log_stream_find("debug/checktest");
  if(!nlerr) nlerr = noit_stderr;
  if(!nldeb) nldeb = noit_debug;
  mtev_skiplist_init(&in_progress);
  mtev_skiplist_set_compare(&in_progress, check_complete_heap,
                            check_complete_heap_key);
  return 0;
}
コード例 #6
0
ファイル: lua_general.c プロジェクト: postwait/libmtev
static int
mtev_lua_general_onload(mtev_image_t *self) {
  nlerr = mtev_log_stream_find("error/lua");
  nldeb = mtev_log_stream_find("debug/lua");
  if(!nlerr) nlerr = mtev_stderr;
  if(!nldeb) nldeb = mtev_debug;
  mtev_lua_context_describe(LUA_GENERAL_INFO_MAGIC,
                            describe_lua_general_context);
  mtev_lua_context_describe_json(LUA_GENERAL_INFO_MAGIC,
                                 describe_lua_general_context_json);
  mtev_lua_general_register_console_commands(self);
  return 0;
}
コード例 #7
0
ファイル: noit_check_log.c プロジェクト: sean/reconnoiter
static void
handle_extra_feeds(noit_check_t *check,
                   int (*log_f)(mtev_log_stream_t ls, noit_check_t *check)) {
    mtev_log_stream_t ls;
    mtev_skiplist_node *curr, *next;
    const char *feed_name;

    if(!check->feeds) return;
    curr = next = mtev_skiplist_getlist(check->feeds);
    while(curr) {
        /* We advance next here (before we try to use curr).
         * We may need to remove the node we're looking at and that would
         * disturb the iterator, so advance in advance. */
        mtev_skiplist_next(check->feeds, &next);
        feed_name = (char *)curr->data;
        ls = mtev_log_stream_find(feed_name);
        if(!ls || log_f(ls, check)) {
            noit_check_transient_remove_feed(check, feed_name);
            /* mtev_skiplisti_remove(check->feeds, curr, free); */
        }
        curr = next;
    }
    /* We're done... we may have destroyed the last feed.
     * that combined with transience means we should kill the check */
    /* noit_check_transient_remove_feed(check, NULL); */
}
コード例 #8
0
void
stratcon_datastore_core_init() {
  static int initialized = 0;
  if(initialized) return;
  initialized = 1;
  ds_err = mtev_log_stream_find("error/datastore");
  ds_deb = mtev_log_stream_find("debug/datastore");
  ds_pool_deb = mtev_log_stream_find("debug/datastore_pool");
  ingest_err = mtev_log_stream_find("error/ingest");
  if(!ds_err) ds_err = noit_error;
  if(!ingest_err) ingest_err = noit_error;
  if(!mtev_conf_get_string(NULL, "//database/journal/path",
                           &basejpath)) {
    mtevL(noit_error, "//database/journal/path is unspecified\n");
    exit(-1);
  }
}
コード例 #9
0
ファイル: fq_driver.c プロジェクト: pamaddox/reconnoiter
static int noit_fq_driver_init(mtev_dso_generic_t *self) {
  if(!nlerr) nlerr = mtev_log_stream_find("error/fq_driver");
  if(!nlerr) nlerr = mtev_error;
  mtev_hash_init(&filtered_checks_hash);
  stratcon_iep_mq_driver_register("fq", &mq_driver_fq);
  register_console_fq_commands();
  eventer_add_in_s_us(fq_status_checker, NULL, 0, 0);
  return 0;
}
コード例 #10
0
ファイル: zipkin_fq.c プロジェクト: esproul/libmtev
static int
zipkin_fq_driver_init(mtev_dso_generic_t *img) {
  debugls = mtev_log_stream_find("debug/zipkin_fq");
  fq_client_init(&zc_client, 0, debug_logger);
  fq_client_creds(zc_client, zc_host, zc_port, zc_user, zc_pass);
  fq_client_heartbeat(zc_client, zc_heartbeat);
  fq_client_set_backlog(zc_client, zc_backlog, 100);
  fq_client_set_nonblock(zc_client, true);
  fq_client_connect(zc_client);
  zipkin_publish_hook_register("fq", zipkin_fq_publish, NULL);
  return 0;
}
コード例 #11
0
static int rest_show_feed(mtev_http_rest_closure_t *restc,
                          int npats, char **pats) {
  mtev_http_session_ctx *ctx = restc->http_ctx;
  const char *err = "unknown error";
  const char *jpath_with_sub;
  char jlogpath[PATH_MAX], *cp, **subs = NULL;
  int nsubs, i;
  mtev_log_stream_t feed;
  jlog_ctx *jctx = NULL;
  xmlDocPtr doc = NULL;
  xmlNodePtr root = NULL, subnodes;

  feed = mtev_log_stream_find("feed");
  if(!feed) { err = "cannot find feed"; goto error; }

  jpath_with_sub = mtev_log_stream_get_path(feed);
  strlcpy(jlogpath, jpath_with_sub, sizeof(jlogpath));
  cp = strchr(jlogpath, '(');
  if(cp) *cp = '\0';

  jctx = jlog_new(jlogpath);
  if((nsubs = jlog_ctx_list_subscribers(jctx, &subs)) == -1) {
    err = jlog_ctx_err_string(jctx);
    goto error;
  }

  doc = xmlNewDoc((xmlChar *)"1.0");
  root = xmlNewDocNode(doc, NULL, (xmlChar *)"feed", NULL);
  xmlDocSetRootElement(doc, root);

  subnodes = xmlNewNode(NULL, (xmlChar *)"subscribers");
  for(i=0; i<nsubs; i++) {
    xmlNewChild(subnodes, NULL, (xmlChar *)"subscriber", (xmlChar *)subs[i]);
  }
  xmlAddChild(root, subnodes);

  mtev_http_response_ok(restc->http_ctx, "text/xml");
  mtev_http_response_xml(restc->http_ctx, doc);
  mtev_http_response_end(restc->http_ctx);
  if(subs) jlog_ctx_list_subscribers_dispose(jctx, subs);
  xmlFreeDoc(doc);
  jlog_ctx_close(jctx);
  return 0;

 error:
  if(doc) xmlFreeDoc(doc);
  if(subs) jlog_ctx_list_subscribers_dispose(jctx, subs);
  mtev_http_response_server_error(ctx, "text/plain");
  mtev_http_response_append(ctx, err, strlen(err));
  mtev_http_response_end(ctx);
  if(jctx) jlog_ctx_close(jctx);
  return 0;
}
コード例 #12
0
ファイル: mtev_main.c プロジェクト: JonasKunze/libmtev
void cli_log_switches() {
    int i;
    mtev_log_stream_t ls;
    for(i=0; i<enable_logs_cnt; i++) {
        ls = mtev_log_stream_find(enable_logs[i]);
        if(!ls) ls = mtev_baked_log(enable_logs[i]);
        if(!ls) mtevL(mtev_error, "No such log: '%s'\n", enable_logs[i]);
        if(ls && !N_L_S_ON(ls)) {
            mtevL(mtev_notice, "Enabling %s\n", enable_logs[i]);
            mtev_log_stream_set_flags(ls, mtev_log_stream_get_flags(ls) | MTEV_LOG_STREAM_ENABLED);
        }
    }
    for(i=0; i<disable_logs_cnt; i++) {
        ls = mtev_log_stream_find(disable_logs[i]);
        if(!ls) ls = mtev_baked_log(disable_logs[i]);
        if(!ls) mtevL(mtev_error, "No such log: '%s'\n", enable_logs[i]);
        if(ls && N_L_S_ON(ls)) {
            mtevL(mtev_notice, "Disabling %s\n", disable_logs[i]);
            mtev_log_stream_set_flags(ls, mtev_log_stream_get_flags(ls) & ~MTEV_LOG_STREAM_ENABLED);
        }
    }
}
コード例 #13
0
ファイル: mtev_events_rest.c プロジェクト: adriancole/libmtev
int
mtev_rest_eventer_logs(mtev_http_rest_closure_t *restc, int n, char **p) {
  char *endptr = NULL;
  const char *since_s, *last_s;
  const char *jsonstr;
  char errbuf[128];
  unsigned long long since;
  int last = 0;
  struct json_object *doc;
  mtev_log_stream_t ls;
  mtev_http_request *req = mtev_http_session_request(restc->http_ctx);
  since_s = mtev_http_request_querystring(req, "since");
  if(since_s) since = strtoull(since_s, &endptr, 10);
  last_s = mtev_http_request_querystring(req, "last");
  if(last_s) last = atoi(last_s);

  assert(n==1);
  ls = mtev_log_stream_find(p[0]);
  if(!ls || strcmp(mtev_log_stream_get_type(ls),"memory"))
    goto not_found;

  doc = json_object_new_array();
  if(endptr != since_s)
    mtev_log_memory_lines_since(ls, since, json_spit_log, doc);
  else
    mtev_log_memory_lines(ls, last, json_spit_log, doc);

  mtev_http_response_ok(restc->http_ctx, "application/json");
  jsonstr = json_object_to_json_string(doc);
  mtev_http_response_append(restc->http_ctx, jsonstr, strlen(jsonstr));
  mtev_http_response_append(restc->http_ctx, "\n", 1);
  json_object_put(doc);
  mtev_http_response_end(restc->http_ctx);
  return 0;
 not_found:
  doc = json_object_new_object();
  snprintf(errbuf, sizeof(errbuf), "log '%s' not found", p[0]);
  json_object_object_add(doc, "error", json_object_new_string(errbuf));
  jsonstr = json_object_to_json_string(doc);
  mtev_http_response_not_found(restc->http_ctx, "application/json");
  mtev_http_response_append(restc->http_ctx, jsonstr, strlen(jsonstr));
  mtev_http_response_append(restc->http_ctx, "\n", 1);
  json_object_put(doc);
  mtev_http_response_end(restc->http_ctx);
  return 0;
}
コード例 #14
0
static int rest_delete_feed(mtev_http_rest_closure_t *restc,
                            int npats, char **pats) {
  mtev_http_session_ctx *ctx = restc->http_ctx;
  const char *err = "unknown error";
  const char *jpath_with_sub;
  char jlogpath[PATH_MAX], *cp;
  int rv;
  mtev_log_stream_t feed;
  jlog_ctx *jctx;

  feed = mtev_log_stream_find("feed");
  if(!feed) { err = "cannot find feed"; goto error; }

  jpath_with_sub = mtev_log_stream_get_path(feed);
  strlcpy(jlogpath, jpath_with_sub, sizeof(jlogpath));
  cp = strchr(jlogpath, '(');
  if(cp) *cp = '\0';

  jctx = jlog_new(jlogpath);
  rv = jlog_ctx_remove_subscriber(jctx, pats[0]);
  jlog_ctx_close(jctx);
  if(rv < 0) {
    err = jlog_ctx_err_string(jctx);
    goto error;
  }

  /* removed or note, we should do a sweeping cleanup */
  jlog_clean(jlogpath);

  if(rv == 0) {
    mtev_http_response_not_found(ctx, "text/plain");
    mtev_http_response_end(ctx);
    return 0;
  }

  mtev_http_response_standard(ctx, 204, "OK", "text/plain");
  mtev_http_response_end(ctx);
  return 0;

 error:
  mtev_http_response_server_error(ctx, "text/plain");
  mtev_http_response_append(ctx, err, strlen(err));
  mtev_http_response_end(ctx);
  return 0;
}
コード例 #15
0
int
noit_jlog_handler(eventer_t e, int mask, void *closure,
                     struct timeval *now) {
  eventer_t newe;
  pthread_t tid;
  pthread_attr_t tattr;
  int newmask = EVENTER_READ | EVENTER_EXCEPTION;
  acceptor_closure_t *ac = closure;
  noit_jlog_closure_t *jcl = ac->service_ctx;
  char errbuff[256];
  const char *errstr = "unknown error";

  if(mask & EVENTER_EXCEPTION || (jcl && jcl->wants_shutdown)) {
    int len, nlen;
socket_error:
    /* Exceptions cause us to simply snip the connection */
    len = strlen(errstr);
    nlen = htonl(0 - len);
    e->opset->write(e->fd, &nlen, sizeof(nlen), &newmask, e);
    e->opset->write(e->fd, errstr, strlen(errstr), &newmask, e);
    eventer_remove_fd(e->fd);
    e->opset->close(e->fd, &newmask, e);
    if(jcl) noit_jlog_closure_free(jcl);
    acceptor_closure_free(ac);
    return 0;
  }

  if(!ac->service_ctx) {
    mtev_log_stream_t ls;
    const char *logname, *type;
    int first_attempt = 1;
    char path[PATH_MAX], subscriber[256], *sub;
    jcl = ac->service_ctx = noit_jlog_closure_alloc();
    if(!mtev_hash_retr_str(ac->config,
                           "log_transit_feed_name",
                           strlen("log_transit_feed_name"),
                           &logname)) {
      errstr = "No 'log_transit_feed_name' specified in log_transit.";
      mtevL(noit_error, "%s\n", errstr);
      goto socket_error;
    }
    ls = mtev_log_stream_find(logname);
    if(!ls) {
      snprintf(errbuff, sizeof(errbuff),
               "Could not find log '%s' for log_transit.", logname);
      errstr = errbuff;
      mtevL(noit_error, "%s\n", errstr);
      goto socket_error;
    }
    type = mtev_log_stream_get_type(ls);
    if(!type || strcmp(type, "jlog")) {
      snprintf(errbuff, sizeof(errbuff),
               "Log '%s' for log_transit is not a jlog.", logname);
      errstr = errbuff;
      mtevL(noit_error, "%s\n", errstr);
      goto socket_error;
    }
    if(ac->cmd == NOIT_JLOG_DATA_FEED) {
      if(!ac->remote_cn) {
        errstr = "jlog transit started to unidentified party.";
        mtevL(noit_error, "%s\n", errstr);
        goto socket_error;
      }
      strlcpy(subscriber, ac->remote_cn, sizeof(subscriber));
      jcl->feed_stats = noit_jlog_feed_stats(subscriber);
    }
    else {
      jcl->feed_stats = noit_jlog_feed_stats("~");
      snprintf(subscriber, sizeof(subscriber),
               "~%07d", mtev_atomic_inc32(&tmpfeedcounter));
    }
    jcl->subscriber = strdup(subscriber);

    strlcpy(path, mtev_log_stream_get_path(ls), sizeof(path));
    sub = strchr(path, '(');
    if(sub) {
      char *esub = strchr(sub, ')');
      if(esub) {
        *esub = '\0';
        *sub++ = '\0';
      }
    }

    jcl->jlog = jlog_new(path);
    if(ac->cmd == NOIT_JLOG_DATA_TEMP_FEED) {
 add_sub:
      if(jlog_ctx_add_subscriber(jcl->jlog, jcl->subscriber, JLOG_END) == -1) {
        snprintf(errbuff, sizeof(errbuff),
                 "jlog reader[%s] error: %s", jcl->subscriber,
                 jlog_ctx_err_string(jcl->jlog));
        errstr = errbuff;
        mtevL(noit_error, "%s\n", errstr);
      }
    }
    if(jlog_ctx_open_reader(jcl->jlog, jcl->subscriber) == -1) {
      if(sub && !strcmp(sub, "*")) {
        if(first_attempt) {
          jlog_ctx_close(jcl->jlog);
          jcl->jlog = jlog_new(path);
          first_attempt = 0;
          goto add_sub;
        }
      }
      snprintf(errbuff, sizeof(errbuff),
               "jlog reader[%s] error: %s", jcl->subscriber,
               jlog_ctx_err_string(jcl->jlog));
      errstr = errbuff;
      mtevL(noit_error, "%s\n", errstr);
      goto socket_error;
    }
  }

  /* The jlog stuff is disk I/O and can block us.
   * We'll create a new thread to just handle this connection.
   */
  eventer_remove_fd(e->fd);
  newe = eventer_alloc();
  memcpy(newe, e, sizeof(*e));
  pthread_attr_init(&tattr);
  pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
  mtev_gettimeofday(&jcl->feed_stats->last_connection, NULL);
  mtev_atomic_inc32(&jcl->feed_stats->connections);
  if(pthread_create(&tid, &tattr, noit_jlog_thread_main, newe) == 0) {
    return 0;
  }

  /* Undo our dup */
  eventer_free(newe);
  /* Creating the thread failed, close it down and deschedule. */
  e->opset->close(e->fd, &newmask, e);
  return 0;
}
コード例 #16
0
ファイル: example.c プロジェクト: JonasKunze/reconnoiter
static int example_onload(mtev_image_t *self) {
  if(NULL == (nlerr=mtev_log_stream_find("error/example"))) nlerr = mtev_error;
  if(NULL == (nldeb=mtev_log_stream_find("debug/example"))) nldeb = mtev_debug;
  return 0;
}
コード例 #17
0
static int rest_add_feed(mtev_http_rest_closure_t *restc,
                         int npats, char **pats) {
  mtev_http_session_ctx *ctx = restc->http_ctx;
  xmlXPathObjectPtr pobj = NULL;
  xmlDocPtr doc = NULL, indoc = NULL;
  xmlNodePtr node, root;
  acceptor_closure_t *ac = restc->ac;
  int error_code = 500, complete = 0, mask = 0, rv;
  const char *error = "internal error", *logname;
  char *name, *copy_from;
  mtev_log_stream_t feed;
  const char *jpath_with_sub;
  char jlogpath[PATH_MAX], *cp;
  jlog_ctx *jctx = NULL;
  jlog_id chkpt;

  if(npats != 0) goto error;

  indoc = rest_get_xml_upload(restc, &mask, &complete);
  if(!complete) return mask;
  if(indoc == NULL) {
    error = "xml parse error";
    goto error;
  }
  if(!mtev_hash_retr_str(ac->config,
                         "log_transit_feed_name",
                         strlen("log_transit_feed_name"),
                         &logname)) {
    goto error;

  }
  feed = mtev_log_stream_find("feed");
  if(!feed) { 
    error = "couldn't find feed";
    goto error; 
  }

  jpath_with_sub = mtev_log_stream_get_path(feed);
  strlcpy(jlogpath, jpath_with_sub, sizeof(jlogpath));
  cp = strchr(jlogpath, '(');
  if(cp) *cp = '\0';

  node = xmlDocGetRootElement(indoc);
  name = (char*)xmlGetProp(node, (xmlChar*)"name");
  copy_from = (char*)xmlGetProp(node, (xmlChar*)"checkpoint_copy");

  jctx = jlog_new(jlogpath);
  if (!jctx) {
    error = "couldn't open logpath";
    goto error;
  }

  if (!jlog_get_checkpoint(jctx, name, &chkpt)) {
    error = "subscriber already exists, can't add";
    goto error;
  }

  if (copy_from) {
    rv = jlog_ctx_add_subscriber_copy_checkpoint(jctx, name, copy_from);
  }
  else {
    rv = jlog_ctx_add_subscriber(jctx, name, JLOG_END);
  }
  if (rv == -1) {
    error = "couldn't add subscriber";
    goto error;
  }

  mtev_http_response_ok(restc->http_ctx, "text/xml");
  mtev_http_response_end(restc->http_ctx);
  goto cleanup;

 error:
  mtev_http_response_standard(ctx, error_code, "ERROR", "text/xml");
  doc = xmlNewDoc((xmlChar *)"1.0");
  root = xmlNewDocNode(doc, NULL, (xmlChar *)"error", NULL);
  xmlDocSetRootElement(doc, root);
  xmlNodeAddContent(root, (xmlChar *)error);
  mtev_http_response_xml(ctx, doc);
  mtev_http_response_end(ctx);

 cleanup:
  if (jctx) {
    jlog_ctx_close(jctx);
  }
  if(pobj) xmlXPathFreeObject(pobj);
  if(doc) xmlFreeDoc(doc);
  return 0;
}
コード例 #18
0
ファイル: histogram.c プロジェクト: aidancully/reconnoiter
static void
log_histo(struct histogram_config *conf,
          noit_check_t *check, u_int64_t whence_s,
          const char *metric_name, histogram_t *h,
          mtev_boolean live_feed) {
  mtev_boolean extended_id = mtev_false;
  char uuid_str[256*3+37];
  const char *v;
  char *hist_serial = NULL;
  char *hist_encode = NULL;
  struct timeval whence;
  ssize_t est, enc_est;
  whence.tv_sec = whence_s;
  whence.tv_usec = 0;

  if(!conf->histogram) return;

  SETUP_LOG(metrics, );
  if(metrics_log) {
    v = mtev_log_stream_get_property(metrics_log, "extended_id");
    if(v && !strcmp(v, "on")) extended_id = mtev_true;
  }
  uuid_str[0] = '\0';
  if(extended_id) {
    strlcat(uuid_str, check->target, sizeof(uuid_str)-37);
    strlcat(uuid_str, "`", sizeof(uuid_str)-37);
    strlcat(uuid_str, check->module, sizeof(uuid_str)-37);
    strlcat(uuid_str, "`", sizeof(uuid_str)-37);
    strlcat(uuid_str, check->name, sizeof(uuid_str)-37);
    strlcat(uuid_str, "`", sizeof(uuid_str)-37);
  }
  uuid_unparse_lower(check->checkid, uuid_str + strlen(uuid_str));

#define SECPART(a) ((unsigned long)(a)->tv_sec)
#define MSECPART(a) ((unsigned long)((a)->tv_usec / 1000))

  est = hist_serialize_estimate(h);
  hist_serial = malloc(est);
  if(!hist_serial) {
    mtevL(noit_error, "malloc(%d) failed\n", (int)est);
    goto cleanup;
  }
  enc_est = ((est + 2)/3)*4;
  hist_encode = malloc(enc_est);
  if(!hist_encode) {
    mtevL(noit_error, "malloc(%d) failed\n", (int)enc_est);
    goto cleanup;
  }
  if(hist_serialize(h, hist_serial, est) != est) {
    mtevL(noit_error, "histogram serialization failure\n");
    goto cleanup;
  }
  enc_est = mtev_b64_encode((unsigned char *)hist_serial, est,
                            hist_encode, enc_est);
  if(enc_est < 0) {
    mtevL(noit_error, "base64 histogram encoding failure\n");
    goto cleanup;
  }

  if(live_feed && check->feeds) {
    mtev_skiplist_node *curr, *next;
    curr = next = mtev_skiplist_getlist(check->feeds);
    while(curr) {
      const char *feed_name = (char *)curr->data;
      mtev_log_stream_t ls = mtev_log_stream_find(feed_name);
      mtev_skiplist_next(check->feeds, &next);
      if(!ls ||
         mtev_log(ls, &whence, __FILE__, __LINE__,
           "H1\t%lu.%03lu\t%s\t%s\t%.*s\n",
           SECPART(&whence), MSECPART(&whence),
           uuid_str, metric_name, (int)enc_est, hist_encode))
        noit_check_transient_remove_feed(check, feed_name);
      curr = next;
    }
  }

  if(!live_feed) {
    SETUP_LOG(metrics, goto cleanup);
    mtev_log(metrics_log, &whence, __FILE__, __LINE__,
             "H1\t%lu.%03lu\t%s\t%s\t%.*s\n",
             SECPART(&whence), MSECPART(&whence),
             uuid_str, metric_name, (int)enc_est, hist_encode);
  }