diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..c7cd3915 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,30 @@ +cmake_minimum_required(VERSION 2.6) + +project(digwatch) + +set(DRAIOS_DEBUG_FLAGS "-D_DEBUG") +#set(DRAIOS_FEATURE_FLAGS "-DPPM_ENABLE_SENTINEL") + +set(CMAKE_C_FLAGS "-Wall -ggdb ${DRAIOS_FEATURE_FLAGS}") +set(CMAKE_CXX_FLAGS "-Wall -ggdb --std=c++0x ${DRAIOS_FEATURE_FLAGS}") +set(CMAKE_C_FLAGS_DEBUG "${DRAIOS_DEBUG_FLAGS}") +set(CMAKE_CXX_FLAGS_DEBUG "${DRAIOS_DEBUG_FLAGS}") +# Add "-fno-inline -fno-omit-frame-pointer" for perf +set(CMAKE_C_FLAGS_RELEASE "-O3 -fno-strict-aliasing -DNDEBUG") +set(CMAKE_CXX_FLAGS_RELEASE "-O3 -fno-strict-aliasing -DNDEBUG") + +add_definitions(-DPLATFORM_NAME="${CMAKE_SYSTEM_NAME}") +add_definitions(-DHAS_CAPTURE) + +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + set(KBUILD_FLAGS "${DRAIOS_DEBUG_FLAGS} ${DRAIOS_FEATURE_FLAGS}") +else() + set(KBUILD_FLAGS "${DRAIOS_FEATURE_FLAGS}") +endif() + +set(PACKAGE_NAME "draios-digwatch") + +add_subdirectory(${PROJECT_SOURCE_DIR}/../sysdig ${PROJECT_BINARY_DIR}/sysdig) + +add_subdirectory(userspace/digwatch) + diff --git a/userspace/digwatch/CMakeLists.txt b/userspace/digwatch/CMakeLists.txt new file mode 100644 index 00000000..a6c8420e --- /dev/null +++ b/userspace/digwatch/CMakeLists.txt @@ -0,0 +1,10 @@ +include_directories(${PROJECT_SOURCE_DIR}/../sysdig/userspace/libsinsp/third-party/jsoncpp) + +include_directories(${PROJECT_SOURCE_DIR}/../sysdig/userspace/libscap) +include_directories(${PROJECT_SOURCE_DIR}/../sysdig/userspace/libsinsp) + +add_executable(digwatch digwatch.cpp) + +target_link_libraries(digwatch sinsp) + + diff --git a/userspace/digwatch/digwatch.cpp b/userspace/digwatch/digwatch.cpp new file mode 100644 index 00000000..49d7f02c --- /dev/null +++ b/userspace/digwatch/digwatch.cpp @@ -0,0 +1,288 @@ +#define __STDC_FORMAT_MACROS + +#include +#include +#include +#include +#include +#include + +#include +#include "lua_parser.h" +#include "digwatch.h" +#include "utils.h" + +#include +#include + +lua_parser* g_lua_parser; + +static void usage(); + +// +// Program help +// +static void usage() +{ + printf( + "Usage: digwatch [options] [-p ] [filter]\n\n" + "Options:\n" + " -h, --help Print this page\n" + " -M Stop collecting after reached.\n" + " -N Don't convert port numbers to names.\n" + " -n , --numevents=\n" + " Stop capturing after events\n" + " -u , --user-parser \n" + " Name of lua file containing parser\n" + " -r , --read=\n" + " Read the events from .\n" + " --unbuffered Turn off output buffering. This causes every single line\n" + " emitted by digwatch to be flushed, which generates higher CPU\n" + " usage but is useful when piping digwatch's output into another\n" + " process or into a script.\n" + "\n" + ); +} + + +// +// Event processing loop +// +captureinfo do_inspect(sinsp* inspector, + uint64_t cnt, + int duration_to_tot, + sinsp_evt_formatter* formatter) +{ + captureinfo retval; + int32_t res; + sinsp_evt* ev; + string line; + int duration_start = 0; + + // + // Loop through the events + // + duration_start = ((double)clock()) / CLOCKS_PER_SEC; + while(1) + { + if(duration_to_tot > 0) + { + int duration_tot = ((double)clock()) / CLOCKS_PER_SEC - duration_start; + if(duration_tot >= duration_to_tot) + { + break; + } + } + if(retval.m_nevts == cnt) + { + // + // End of capture, either because the user stopped it, or because + // we reached the event count specified with -n. + // + break; + } + + res = inspector->next(&ev); + + if(res == SCAP_TIMEOUT) + { + continue; + } + else if(res == SCAP_EOF) + { + break; + } + else if(res != SCAP_SUCCESS) + { + // + // Event read error. + // Notify the chisels that we're exiting, and then die with an error. + // + cerr << "res = " << res << endl; + throw sinsp_exception(inspector->getlasterr().c_str()); + } + + retval.m_nevts++; + + if(!inspector->is_debug_enabled() && + ev->get_category() & EC_INTERNAL) + { + continue; + } + if(formatter->tostring(ev, &line)) + { + cout << line; + cout << endl; + } + + } + + return retval; +} + +// +// ARGUMENT PARSING AND PROGRAM SETUP +// +digwatch_init_res digwatch_init(int argc, char **argv) +{ + digwatch_init_res res; + sinsp* inspector = NULL; + int op; + uint64_t cnt = -1; + sinsp_evt::param_fmt event_buffer_format = sinsp_evt::PF_NORMAL; + int duration_to_tot = 0; + captureinfo cinfo; + string output_format; + int long_index = 0; + string user_parser; + + static struct option long_options[] = + { + {"help", no_argument, 0, 'h' }, + {"numevents", required_argument, 0, 'n' }, + {"user-parser", required_argument, 0, 'u' }, + {"readfile", required_argument, 0, 'r' }, + {"unbuffered", no_argument, 0, 0 }, + {0, 0, 0, 0} + }; + + output_format = "*%evt.num %evt.outputtime %evt.cpu %proc.name (%thread.tid) %evt.dir %evt.type %evt.info"; + + try + { + inspector = new sinsp(); + + + // + // Parse the args + // + while((op = getopt_long(argc, argv, + "hM:Nn:r:u:", + long_options, &long_index)) != -1) + { + switch(op) + { + case 'h': + usage(); + delete inspector; + return digwatch_init_res(EXIT_SUCCESS); + case 'M': + duration_to_tot = atoi(optarg); + if(duration_to_tot <= 0) + { + throw sinsp_exception(string("invalid duration") + optarg); + res.m_res = EXIT_FAILURE; + goto exit; + } + break; + case 'N': + inspector->set_hostname_and_port_resolution_mode(false); + break; + case 'n': + try + { + cnt = sinsp_numparser::parseu64(optarg); + } + catch(...) + { + throw sinsp_exception("can't parse the -n argument, make sure it's a number"); + } + + if(cnt <= 0) + { + throw sinsp_exception(string("invalid event count ") + optarg); + res.m_res = EXIT_FAILURE; + goto exit; + } + break; + case 'u': + user_parser = optarg; + break; + case '?': + delete inspector; + return digwatch_init_res(EXIT_FAILURE); + break; + default: + break; + } + + } + + inspector->set_buffer_format(event_buffer_format); + + string filter; + + // + // the filter is at the end of the command line + // + if(optind < argc) + { +#ifdef HAS_FILTERING + for(int32_t j = optind ; j < argc; j++) + { + filter += argv[j]; + if(j < argc - 1) + { + filter += " "; + } + } + +#else + fprintf(stderr, "filtering not compiled.\n"); + res.m_res = EXIT_FAILURE; + goto exit; +#endif + } + + // + // Create the event formatter + // + sinsp_evt_formatter formatter(inspector, output_format); + + g_lua_parser = new lua_parser(inspector, user_parser); + + if(filter.size()) + { + inspector->set_filter(filter); + } + inspector->open(""); + + cinfo = do_inspect(inspector, + cnt, + duration_to_tot, + &formatter); + + inspector->close(); + } + catch(sinsp_exception& e) + { + cerr << e.what() << endl; + res.m_res = EXIT_FAILURE; + } + catch(...) + { + printf("Exeception\n"); + res.m_res = EXIT_FAILURE; + } + +exit: + + if(inspector) + { + delete inspector; + } + + return res; +} + +// +// MAIN +// +int main(int argc, char **argv) +{ + digwatch_init_res res; + + res = digwatch_init(argc, argv); + + return res.m_res; +} diff --git a/userspace/digwatch/digwatch.h b/userspace/digwatch/digwatch.h new file mode 100644 index 00000000..cdea9fb1 --- /dev/null +++ b/userspace/digwatch/digwatch.h @@ -0,0 +1,60 @@ +/* +Copyright (C) 2013-2014 Draios inc. + +This file is part of sysdig. + +sysdig is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License version 2 as +published by the Free Software Foundation. + +sysdig is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with sysdig. If not, see . +*/ + +#pragma once + +#ifdef HAS_CAPTURE +#include "../../driver/driver_config.h" +#endif // HAS_CAPTURE + + +// +// Capture results +// +class digwatch_init_res +{ +public: + digwatch_init_res() + { + m_res = EXIT_SUCCESS; + } + + digwatch_init_res(int res) + { + m_res = res; + } + + int m_res; + vector m_next_run_args; +}; + +// +// Capture results +// +class captureinfo +{ +public: + captureinfo() + { + m_nevts = 0; + m_time = 0; + } + + uint64_t m_nevts; + uint64_t m_time; +};