mirror of
https://github.com/tstack/lnav
synced 2024-11-03 23:15:38 +00:00
[papertrail] use the curl_looper
This commit is contained in:
parent
9555ad911a
commit
e9a96caf09
@ -57,7 +57,7 @@ public:
|
||||
|
||||
template<typename F>
|
||||
auto_mem(F free_func)
|
||||
: am_ptr(NULL), am_free_func((void(*) (void *))free_func) { };
|
||||
: am_ptr(NULL), am_free_func((free_func_t)free_func) { };
|
||||
|
||||
~auto_mem()
|
||||
{
|
||||
@ -102,7 +102,7 @@ public:
|
||||
{
|
||||
if (this->am_ptr != ptr) {
|
||||
if (this->am_ptr != NULL) {
|
||||
this->am_free_func(this->am_ptr);
|
||||
this->am_free_func((void *)this->am_ptr);
|
||||
}
|
||||
this->am_ptr = ptr;
|
||||
}
|
||||
|
14
src/lnav.cc
14
src/lnav.cc
@ -2679,13 +2679,15 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
if (!lnav_data.ld_pt_search.empty()) {
|
||||
lnav_data.ld_pt_proc.reset(new papertrail_proc(lnav_data.ld_pt_search.substr(3)));
|
||||
if (!lnav_data.ld_pt_proc->start()) {
|
||||
fprintf(stderr, "error:%s\n", lnav_data.ld_pt_proc->ptp_error.c_str());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
#ifdef HAVE_LIBCURL
|
||||
auto_ptr<papertrail_proc> pt(new papertrail_proc(lnav_data.ld_pt_search.substr(3)));
|
||||
lnav_data.ld_file_names.insert(
|
||||
make_pair(lnav_data.ld_pt_search, lnav_data.ld_pt_proc->ptp_fd.release()));
|
||||
make_pair(lnav_data.ld_pt_search, pt->copy_fd().release()));
|
||||
lnav_data.ld_curl_looper.add_request(pt.release());
|
||||
#else
|
||||
fprintf(stderr, "error: lnav not compiled with libcurl\n");
|
||||
retval = EXIT_FAILURE;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (lnav_data.ld_file_names.empty() && !(lnav_data.ld_flags & LNF_HELP)) {
|
||||
|
@ -237,7 +237,6 @@ struct _lnav_data {
|
||||
|
||||
std::list<pid_t> ld_children;
|
||||
std::list<piper_proc *> ld_pipers;
|
||||
std::auto_ptr<papertrail_proc> ld_pt_proc;
|
||||
xterm_mouse ld_mouse;
|
||||
term_extra ld_term_extra;
|
||||
|
||||
|
@ -1135,6 +1135,7 @@ static string com_open(string cmdline, vector<string> &args)
|
||||
string fn = wordmem->we_wordv[lpc];
|
||||
|
||||
if (startswith(fn, "pt:")) {
|
||||
#ifdef HAVE_LIBCURL
|
||||
for (list<logfile *>::iterator iter = lnav_data.ld_files.begin();
|
||||
iter != lnav_data.ld_files.end();
|
||||
++iter) {
|
||||
@ -1145,18 +1146,19 @@ static string com_open(string cmdline, vector<string> &args)
|
||||
}
|
||||
}
|
||||
|
||||
lnav_data.ld_curl_looper.close_request("papertrailapp.com");
|
||||
auto_ptr<papertrail_proc> pt(new papertrail_proc(fn.substr(3)));
|
||||
lnav_data.ld_pt_search = fn;
|
||||
lnav_data.ld_pt_proc.reset(new papertrail_proc(lnav_data.ld_pt_search.substr(3)));
|
||||
if (!lnav_data.ld_pt_proc->start()) {
|
||||
retval = "error:" + lnav_data.ld_pt_proc->ptp_error;
|
||||
break;
|
||||
}
|
||||
lnav_data.ld_file_names.insert(
|
||||
make_pair(lnav_data.ld_pt_search, lnav_data.ld_pt_proc->ptp_fd.release()));
|
||||
make_pair(lnav_data.ld_pt_search, pt->copy_fd().release()));
|
||||
lnav_data.ld_curl_looper.add_request(pt.release());
|
||||
|
||||
ensure_view(&lnav_data.ld_views[LNV_LOG]);
|
||||
|
||||
retval = "info: opened papertrail query";
|
||||
#else
|
||||
retval = "error: lnav not compiled with libcurl";
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -33,13 +33,12 @@
|
||||
|
||||
#ifdef HAVE_LIBCURL
|
||||
#include <curl/curl.h>
|
||||
#endif
|
||||
|
||||
#include "papertrail_proc.hh"
|
||||
#include "yajl/api/yajl_parse.h"
|
||||
|
||||
static const int POLL_DELAY = 2;
|
||||
static const char *PT_SEARCH_URL = "https://papertrailapp.com/api/v1/events/search.json?min_id=%s&q=%s";
|
||||
const char *papertrail_proc::PT_SEARCH_URL =
|
||||
"https://papertrailapp.com/api/v1/events/search.json?min_id=%s&q=%s";
|
||||
|
||||
static int read_max_id(yajlpp_parse_context *ypc, const unsigned char *str, size_t len)
|
||||
{
|
||||
@ -80,7 +79,7 @@ static int read_event_field(yajlpp_parse_context *ypc, const unsigned char *str,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int json_map_start(void *ctx)
|
||||
int papertrail_proc::json_map_start(void *ctx)
|
||||
{
|
||||
yajlpp_parse_context *ypc = (yajlpp_parse_context *)ctx;
|
||||
papertrail_proc *ptp = (papertrail_proc *) ypc->ypc_userdata;
|
||||
@ -92,7 +91,7 @@ static int json_map_start(void *ctx)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int json_map_end(void *ctx)
|
||||
int papertrail_proc::json_map_end(void *ctx)
|
||||
{
|
||||
yajlpp_parse_context *ypc = (yajlpp_parse_context *)ctx;
|
||||
papertrail_proc *ptp = (papertrail_proc *) ypc->ypc_userdata;
|
||||
@ -136,112 +135,17 @@ void papertrail_proc::yajl_writer(void *context, const char *str, size_t len)
|
||||
write(ptp->ptp_fd, str, len);
|
||||
}
|
||||
|
||||
bool papertrail_proc::start(void)
|
||||
long papertrail_proc::complete(CURLcode result)
|
||||
{
|
||||
#ifndef HAVE_LIBCURL
|
||||
return false;
|
||||
#else
|
||||
this->ptp_api_key = getenv("PAPERTRAIL_API_TOKEN");
|
||||
yajl_reset(this->ptp_jhandle.in());
|
||||
|
||||
if (this->ptp_api_key == NULL) {
|
||||
this->ptp_error = "papertrail search requested, but PAPERTRAIL_API_TOKEN is not set";
|
||||
return false;
|
||||
if (result != CURLE_OK) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
char piper_tmpname[PATH_MAX];
|
||||
const char *tmpdir;
|
||||
this->set_url();
|
||||
|
||||
if ((tmpdir = getenv("TMPDIR")) == NULL) {
|
||||
tmpdir = _PATH_VARTMP;
|
||||
}
|
||||
snprintf(piper_tmpname, sizeof(piper_tmpname),
|
||||
"%s/lnav.papertrail.XXXXXX",
|
||||
tmpdir);
|
||||
if ((this->ptp_fd = mkstemp(piper_tmpname)) == -1) {
|
||||
this->ptp_error = "Unable to make temporary file for papertrail";
|
||||
return false;
|
||||
}
|
||||
|
||||
unlink(piper_tmpname);
|
||||
|
||||
fcntl(this->ptp_fd.get(), F_SETFD, FD_CLOEXEC);
|
||||
|
||||
if ((this->ptp_child = fork()) < 0) {
|
||||
this->ptp_error = "Unable to fork papertrail child";
|
||||
return false;
|
||||
}
|
||||
|
||||
signal(SIGTERM, SIG_DFL);
|
||||
signal(SIGINT, SIG_DFL);
|
||||
|
||||
if (this->ptp_child != 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
this->child_body();
|
||||
} catch (...) {
|
||||
fprintf(stderr, "papertrail child failed");
|
||||
}
|
||||
|
||||
_exit(0);
|
||||
#endif
|
||||
};
|
||||
|
||||
void papertrail_proc::child_body()
|
||||
{
|
||||
#ifdef HAVE_LIBCURL
|
||||
int nullfd;
|
||||
|
||||
nullfd = open("/dev/null", O_RDWR);
|
||||
dup2(nullfd, STDIN_FILENO);
|
||||
dup2(nullfd, STDOUT_FILENO);
|
||||
|
||||
auto_mem<CURL> handle(curl_easy_cleanup);
|
||||
yajlpp_parse_context ypc("papertrailapp.com", FORMAT_HANDLERS);
|
||||
ypc.ypc_alt_callbacks.yajl_start_map = json_map_start;
|
||||
ypc.ypc_alt_callbacks.yajl_end_map = json_map_end;
|
||||
yajl_handle jhandle = yajl_alloc(&ypc.ypc_callbacks, NULL, &ypc);
|
||||
auto_mem<yajl_gen_t> gen(yajl_gen_free);
|
||||
this->ptp_gen = gen = yajl_gen_alloc(NULL);
|
||||
|
||||
ypc.ypc_userdata = this;
|
||||
yajl_gen_config(gen, yajl_gen_print_callback, yajl_writer, this);
|
||||
|
||||
const char *quoted_search = curl_easy_escape(
|
||||
handle, this->ptp_search.c_str(), this->ptp_search.size());
|
||||
|
||||
bool looping = true;
|
||||
|
||||
while (looping) {
|
||||
auto_mem<char> url;
|
||||
handle = curl_easy_init();
|
||||
|
||||
asprintf(url.out(), PT_SEARCH_URL, this->ptp_last_max_id.c_str(),
|
||||
quoted_search);
|
||||
if (!url.in()) {
|
||||
break;
|
||||
}
|
||||
curl_easy_setopt(handle, CURLOPT_URL, url.in());
|
||||
curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, write_cb);
|
||||
curl_easy_setopt(handle, CURLOPT_WRITEDATA, jhandle);
|
||||
|
||||
auto_mem<struct curl_slist> chunk(curl_slist_free_all);
|
||||
auto_mem<char> token_header;
|
||||
|
||||
asprintf(token_header.out(), "X-Papertrail-Token: %s", this->ptp_api_key);
|
||||
if (!token_header.in()) {
|
||||
break;
|
||||
}
|
||||
chunk = curl_slist_append(chunk, token_header.in());
|
||||
|
||||
curl_easy_setopt(handle, CURLOPT_HTTPHEADER, chunk.in());
|
||||
|
||||
curl_easy_perform(handle);
|
||||
|
||||
yajl_reset(jhandle);
|
||||
|
||||
sleep(POLL_DELAY);
|
||||
}
|
||||
#endif
|
||||
return 3000;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -32,6 +32,8 @@
|
||||
#ifndef LNAV_PAPERTRAIL_PROC_HH
|
||||
#define LNAV_PAPERTRAIL_PROC_HH
|
||||
|
||||
#ifdef HAVE_LIBCURL
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <paths.h>
|
||||
#include <signal.h>
|
||||
@ -44,45 +46,108 @@
|
||||
#include "auto_fd.hh"
|
||||
#include "auto_mem.hh"
|
||||
#include "yajlpp.hh"
|
||||
#include "curl_looper.hh"
|
||||
#include "line_buffer.hh"
|
||||
|
||||
class papertrail_proc {
|
||||
class papertrail_proc : public curl_request {
|
||||
|
||||
public:
|
||||
papertrail_proc(const std::string &search)
|
||||
: ptp_search(search), ptp_child(-1) {
|
||||
: curl_request("papertrailapp.com"),
|
||||
ptp_jcontext(this->cr_name, FORMAT_HANDLERS),
|
||||
ptp_jhandle(yajl_free),
|
||||
ptp_gen(yajl_gen_free),
|
||||
ptp_search(search),
|
||||
ptp_quoted_search(curl_free),
|
||||
ptp_header_list(curl_slist_free_all) {
|
||||
char piper_tmpname[PATH_MAX];
|
||||
const char *tmpdir;
|
||||
|
||||
if ((tmpdir = getenv("TMPDIR")) == NULL) {
|
||||
tmpdir = _PATH_VARTMP;
|
||||
}
|
||||
snprintf(piper_tmpname, sizeof(piper_tmpname),
|
||||
"%s/lnav.pt.XXXXXX",
|
||||
tmpdir);
|
||||
if ((this->ptp_fd = mkstemp(piper_tmpname)) == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
unlink(piper_tmpname);
|
||||
|
||||
this->ptp_jcontext.ypc_alt_callbacks.yajl_start_map = json_map_start;
|
||||
this->ptp_jcontext.ypc_alt_callbacks.yajl_end_map = json_map_end;
|
||||
this->ptp_jcontext.ypc_userdata = this;
|
||||
this->ptp_jhandle = yajl_alloc(&this->ptp_jcontext.ypc_callbacks, NULL, &this->ptp_jcontext);
|
||||
|
||||
this->ptp_gen = yajl_gen_alloc(NULL);
|
||||
yajl_gen_config(this->ptp_gen, yajl_gen_print_callback, yajl_writer, this);
|
||||
|
||||
curl_easy_setopt(this->cr_handle, CURLOPT_WRITEFUNCTION, write_cb);
|
||||
curl_easy_setopt(this->cr_handle, CURLOPT_WRITEDATA, this->ptp_jhandle.in());
|
||||
curl_easy_setopt(this->cr_handle, CURLOPT_FAILONERROR, 1L);
|
||||
|
||||
this->ptp_api_key = getenv("PAPERTRAIL_API_TOKEN");
|
||||
|
||||
if (this->ptp_api_key == NULL) {
|
||||
this->ptp_error = "papertrail search requested, but PAPERTRAIL_API_TOKEN is not set";
|
||||
}
|
||||
|
||||
this->ptp_quoted_search = curl_easy_escape(this->cr_handle,
|
||||
this->ptp_search.c_str(),
|
||||
this->ptp_search.size());
|
||||
|
||||
asprintf(this->ptp_token_header.out(),
|
||||
"X-Papertrail-Token: %s",
|
||||
this->ptp_api_key);
|
||||
this->ptp_header_list = curl_slist_append(this->ptp_header_list,
|
||||
this->ptp_token_header.in());
|
||||
|
||||
curl_easy_setopt(this->cr_handle, CURLOPT_HTTPHEADER, this->ptp_header_list.in());
|
||||
|
||||
this->set_url();
|
||||
};
|
||||
|
||||
~papertrail_proc() {
|
||||
// TODO: refactor this with piper_proc
|
||||
if (this->ptp_child > 0) {
|
||||
int status;
|
||||
|
||||
kill(this->ptp_child, SIGTERM);
|
||||
while (waitpid(this->ptp_child, &status, 0) < 0 && (errno == EINTR)) {
|
||||
;
|
||||
}
|
||||
|
||||
this->ptp_child = -1;
|
||||
}
|
||||
}
|
||||
|
||||
bool start(void);
|
||||
void child_body(void);
|
||||
auto_fd copy_fd() const {
|
||||
return this->ptp_fd;
|
||||
};
|
||||
|
||||
long complete(CURLcode result);
|
||||
|
||||
void set_url() {
|
||||
asprintf(this->ptp_url.out(),
|
||||
PT_SEARCH_URL,
|
||||
this->ptp_last_max_id.c_str(),
|
||||
this->ptp_quoted_search.in());
|
||||
curl_easy_setopt(this->cr_handle, CURLOPT_URL, this->ptp_url.in());
|
||||
};
|
||||
|
||||
static size_t write_cb(void *contents, size_t size, size_t nmemb, void *userp);
|
||||
|
||||
static int json_map_start(void *ctx);
|
||||
static int json_map_end(void *ctx);
|
||||
|
||||
static void yajl_writer(void *context, const char *str, size_t len);
|
||||
static struct json_path_handler FORMAT_HANDLERS[];
|
||||
static const char *PT_SEARCH_URL;
|
||||
|
||||
yajlpp_parse_context ptp_jcontext;
|
||||
auto_mem<yajl_handle_t> ptp_jhandle;
|
||||
auto_mem<yajl_gen_t> ptp_gen;
|
||||
const char *ptp_api_key;
|
||||
const std::string ptp_search;
|
||||
auto_mem<const char> ptp_quoted_search;
|
||||
auto_mem<char> ptp_url;
|
||||
auto_mem<char> ptp_token_header;
|
||||
auto_mem<struct curl_slist> ptp_header_list;
|
||||
auto_fd ptp_fd;
|
||||
pid_t ptp_child;
|
||||
line_buffer ptp_line_buffer;
|
||||
yajl_gen ptp_gen;
|
||||
std::string ptp_last_max_id;
|
||||
std::string ptp_error;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif //LNAV_PAPERTRAIL_PROC_HH
|
||||
|
Loading…
Reference in New Issue
Block a user