"Fossies" - the Fresh Open Source Software Archive

Member "sysdig-0.26.1/userspace/libsinsp/eventformatter.cpp" (24 May 2019, 7831 Bytes) of package /linux/misc/sysdig-0.26.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "eventformatter.cpp" see the Fossies "Dox" file reference documentation.

    1 /*
    2 Copyright (C) 2013-2018 Draios Inc dba Sysdig.
    3 
    4 This file is part of sysdig.
    5 
    6 Licensed under the Apache License, Version 2.0 (the "License");
    7 you may not use this file except in compliance with the License.
    8 You may obtain a copy of the License at
    9 
   10     http://www.apache.org/licenses/LICENSE-2.0
   11 
   12 Unless required by applicable law or agreed to in writing, software
   13 distributed under the License is distributed on an "AS IS" BASIS,
   14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   15 See the License for the specific language governing permissions and
   16 limitations under the License.
   17 
   18 */
   19 
   20 #include "sinsp.h"
   21 #include "sinsp_int.h"
   22 #include "filter.h"
   23 #include "filterchecks.h"
   24 #include "eventformatter.h"
   25 
   26 ///////////////////////////////////////////////////////////////////////////////
   27 // rawstring_check implementation
   28 ///////////////////////////////////////////////////////////////////////////////
   29 #ifdef HAS_FILTERING
   30 extern sinsp_filter_check_list g_filterlist;
   31 
   32 sinsp_evt_formatter::sinsp_evt_formatter(sinsp* inspector, const string& fmt)
   33 {
   34     m_inspector = inspector;
   35     set_format(fmt);
   36 }
   37 
   38 sinsp_evt_formatter::~sinsp_evt_formatter()
   39 {
   40     uint32_t j;
   41 
   42     for(j = 0; j < m_chks_to_free.size(); j++)
   43     {
   44         delete m_chks_to_free[j];
   45     }
   46 }
   47 
   48 void sinsp_evt_formatter::set_format(const string& fmt)
   49 {
   50     uint32_t j;
   51     uint32_t last_nontoken_str_start = 0;
   52     string lfmt(fmt);
   53 
   54     if(lfmt == "")
   55     {
   56         throw sinsp_exception("empty formatting token");
   57     }
   58 
   59     //
   60     // If the string starts with a *, it means that we are ok with printing
   61     // the string even when not all the values it specifies are set.
   62     //
   63     if(lfmt[0] == '*')
   64     {
   65         m_require_all_values = false;
   66         lfmt.erase(0, 1);
   67     }
   68     else
   69     {
   70         m_require_all_values = true;
   71     }
   72 
   73     //
   74     // Parse the string and extract the tokens
   75     //
   76     const char* cfmt = lfmt.c_str();
   77 
   78     m_tokens.clear();
   79     uint32_t lfmtlen = (uint32_t)lfmt.length();
   80 
   81     for(j = 0; j < lfmtlen; j++)
   82     {
   83         if(cfmt[j] == '%')
   84         {
   85             int toklen = 0;
   86 
   87             if(last_nontoken_str_start != j)
   88             {
   89                 rawstring_check* newtkn = new rawstring_check(lfmt.substr(last_nontoken_str_start, j - last_nontoken_str_start));
   90                 m_tokens.emplace_back(make_pair("", newtkn));
   91                 m_tokenlens.push_back(0);
   92                 m_chks_to_free.push_back(newtkn);
   93             }
   94 
   95             if(j == lfmtlen - 1)
   96             {
   97                 throw sinsp_exception("invalid formatting syntax: formatting cannot end with a %");
   98             }
   99 
  100             //
  101             // If the field specifier starts with a number, it means that we have a length modifier
  102             //
  103             if(isdigit(cfmt[j + 1]))
  104             {
  105                 //
  106                 // Parse the token length
  107                 //
  108                 sscanf(cfmt+ j + 1, "%d", &toklen);
  109 
  110                 //
  111                 // Advance until the beginning of the field name
  112                 //
  113                 while(true)
  114                 {
  115                     if(j == lfmtlen - 1)
  116                     {
  117                         throw sinsp_exception("invalid formatting syntax: formatting cannot end with a number");
  118                     }
  119                     else if(isdigit(cfmt[j + 1]))
  120                     {
  121                         j++;
  122                         continue;
  123                     }
  124                     else
  125                     {
  126                         break;
  127                     }
  128                 }
  129             }
  130 
  131             sinsp_filter_check* chk = g_filterlist.new_filter_check_from_fldname(string(cfmt + j + 1),
  132                 m_inspector,
  133                 false);
  134 
  135             if(chk == NULL)
  136             {
  137                 throw sinsp_exception("invalid formatting token " + string(cfmt + j + 1));
  138             }
  139 
  140             m_chks_to_free.push_back(chk);
  141 
  142             const char * fstart = cfmt + j + 1;
  143             uint32_t fsize = chk->parse_field_name(fstart, true, false);
  144 
  145             j += fsize;
  146             ASSERT(j <= lfmt.length());
  147 
  148             m_tokens.emplace_back(make_pair(string(fstart, fsize), chk));
  149             m_tokenlens.push_back(toklen);
  150 
  151             last_nontoken_str_start = j + 1;
  152         }
  153     }
  154 
  155     if(last_nontoken_str_start != j)
  156     {
  157         sinsp_filter_check * chk = new rawstring_check(lfmt.substr(last_nontoken_str_start, j - last_nontoken_str_start));
  158         m_tokens.emplace_back(make_pair("", chk));
  159         m_chks_to_free.push_back(chk);
  160         m_tokenlens.push_back(0);
  161     }
  162 }
  163 
  164 bool sinsp_evt_formatter::on_capture_end(OUT string* res)
  165 {
  166     res->clear();
  167     return res->size() > 0;
  168 }
  169 
  170 bool sinsp_evt_formatter::resolve_tokens(sinsp_evt *evt, map<string,string>& values)
  171 {
  172     bool retval = true;
  173     const filtercheck_field_info* fi;
  174     uint32_t j = 0;
  175 
  176     ASSERT(m_tokenlens.size() == m_tokens.size());
  177 
  178     for(j = 0; j < m_tokens.size(); j++)
  179     {
  180         char* str = m_tokens[j].second->tostring(evt);
  181 
  182         if(str == NULL)
  183         {
  184             if(m_require_all_values)
  185             {
  186                 retval = false;
  187                 break;
  188             }
  189             else
  190             {
  191                 str = (char*)"<NA>";
  192             }
  193         }
  194 
  195         fi = m_tokens[j].second->get_field_info();
  196         if(fi)
  197         {
  198             values[m_tokens[j].first] = string(str);
  199         }
  200     }
  201 
  202     return retval;
  203 }
  204 
  205 
  206 bool sinsp_evt_formatter::tostring(sinsp_evt* evt, OUT string* res)
  207 {
  208     bool retval = true;
  209     const filtercheck_field_info* fi;
  210 
  211     uint32_t j = 0;
  212     vector<sinsp_filter_check*>::iterator it;
  213     res->clear();
  214 
  215     ASSERT(m_tokenlens.size() == m_tokens.size());
  216 
  217     for(j = 0; j < m_tokens.size(); j++)
  218     {
  219         if(m_inspector->get_buffer_format() == sinsp_evt::PF_JSON
  220            || m_inspector->get_buffer_format() == sinsp_evt::PF_JSONEOLS
  221            || m_inspector->get_buffer_format() == sinsp_evt::PF_JSONHEX
  222            || m_inspector->get_buffer_format() == sinsp_evt::PF_JSONHEXASCII
  223            || m_inspector->get_buffer_format() == sinsp_evt::PF_JSONBASE64)
  224         {
  225             Json::Value json_value = m_tokens[j].second->tojson(evt);
  226 
  227             if(retval == false)
  228             {
  229                 continue;
  230             }
  231 
  232             if(json_value == Json::nullValue && m_require_all_values)
  233             {
  234                 retval = false;
  235                 continue;
  236             }
  237 
  238             fi = m_tokens[j].second->get_field_info();
  239 
  240             if(fi)
  241             {
  242                 m_root[m_tokens[j].first] = m_tokens[j].second->tojson(evt);
  243             }
  244         }
  245         else
  246         {
  247             char* str = m_tokens[j].second->tostring(evt);
  248 
  249             if(retval == false)
  250             {
  251                 continue;
  252             }
  253 
  254             if(str == NULL)
  255             {
  256                 if(m_require_all_values)
  257                 {
  258                     retval = false;
  259                     continue;
  260                 }
  261                 else
  262                 {
  263                     str = (char*)"<NA>";
  264                 }
  265             }
  266 
  267             uint32_t tks = m_tokenlens[j];
  268 
  269             if(tks != 0)
  270             {
  271                 string sstr(str);
  272                 sstr.resize(tks, ' ');
  273                 (*res) += sstr;
  274             }
  275             else
  276             {
  277                 (*res) += str;
  278             }
  279         }
  280     }
  281 
  282     if(m_inspector->get_buffer_format() == sinsp_evt::PF_JSON
  283        || m_inspector->get_buffer_format() == sinsp_evt::PF_JSONEOLS
  284        || m_inspector->get_buffer_format() == sinsp_evt::PF_JSONHEX
  285        || m_inspector->get_buffer_format() == sinsp_evt::PF_JSONHEXASCII
  286        || m_inspector->get_buffer_format() == sinsp_evt::PF_JSONBASE64)
  287     {
  288         (*res) = m_writer.write(m_root);
  289         (*res) = res->substr(0, res->size() - 1);
  290     }
  291 
  292     return retval;
  293 }
  294 
  295 #else  // HAS_FILTERING
  296 
  297 sinsp_evt_formatter::sinsp_evt_formatter(sinsp* inspector, const string& fmt)
  298 {
  299 }
  300 
  301 void sinsp_evt_formatter::set_format(const string& fmt)
  302 {
  303     throw sinsp_exception("sinsp_evt_formatter unvavailable because it was not compiled in the library");
  304 }
  305 
  306 bool sinsp_evt_formatter::resolve_tokens(sinsp_evt *evt, map<string,string>& values)
  307 {
  308     throw sinsp_exception("sinsp_evt_formatter unvavailable because it was not compiled in the library");
  309 }
  310 
  311 bool sinsp_evt_formatter::tostring(sinsp_evt* evt, OUT string* res)
  312 {
  313     throw sinsp_exception("sinsp_evt_formatter unvavailable because it was not compiled in the library");
  314 }
  315 #endif // HAS_FILTERING
  316 
  317 sinsp_evt_formatter_cache::sinsp_evt_formatter_cache(sinsp *inspector)
  318     : m_inspector(inspector)
  319 {
  320 }
  321 
  322 sinsp_evt_formatter_cache::~sinsp_evt_formatter_cache()
  323 {
  324 }
  325 
  326 std::shared_ptr<sinsp_evt_formatter>& sinsp_evt_formatter_cache::get_cached_formatter(string &format)
  327 {
  328     auto it = m_formatter_cache.lower_bound(format);
  329 
  330     if(it == m_formatter_cache.end() ||
  331        it->first != format)
  332     {
  333         it = m_formatter_cache.emplace_hint(it,
  334                             std::make_pair(format, make_shared<sinsp_evt_formatter>(m_inspector, format)));
  335     }
  336 
  337     return it->second;
  338 }
  339 
  340 bool sinsp_evt_formatter_cache::resolve_tokens(sinsp_evt *evt, string &format, map<string,string>& values)
  341 {
  342     return get_cached_formatter(format)->resolve_tokens(evt, values);
  343 }
  344 
  345 bool sinsp_evt_formatter_cache::tostring(sinsp_evt *evt, string &format, OUT string *res)
  346 {
  347     return get_cached_formatter(format)->tostring(evt, res);
  348 }