HttpHandler::status_e RestAdminLogHandler::execute () {

  // .............................................................................
  // check the maximal log level to report
  // .............................................................................

  bool found1;
  string upto = StringUtils::tolower(_request->value("upto", found1));

  bool found2;
  string lvl = StringUtils::tolower(_request->value("level", found2));

  TRI_log_level_e ul = TRI_LOG_LEVEL_INFO;
  bool useUpto = true;
  string logLevel;
  
  // prefer level over upto
  if (found2) {
    logLevel = lvl;
    useUpto = false;
  }
  else if (found1) {
    logLevel = upto;
    useUpto = true;
  }

  if (found1 || found2) {
    if (logLevel == "fatal" || logLevel == "0") {
      ul = TRI_LOG_LEVEL_FATAL;
    }
    else if (logLevel == "error" || logLevel == "1") {
      ul = TRI_LOG_LEVEL_ERROR;
    }
    else if (logLevel == "warning" || logLevel == "2") {
      ul = TRI_LOG_LEVEL_WARNING;
    }
    else if (logLevel == "info" || logLevel == "3") {
      ul = TRI_LOG_LEVEL_INFO;
    }
    else if (logLevel == "debug" || logLevel == "4") {
      ul = TRI_LOG_LEVEL_DEBUG;
    }
    else if (logLevel == "trace" || logLevel == "5") {
      ul = TRI_LOG_LEVEL_TRACE;
    }
    else {
      generateError(HttpResponse::BAD, 
                    TRI_ERROR_HTTP_BAD_PARAMETER,
                    string("unknown '") + (found2 ? "level" : "upto") + "' log level: '" + logLevel + "'");
      return HANDLER_DONE;
    }
  }
  
  // .............................................................................
  // check the starting position
  // .............................................................................
  
  uint64_t start = 0;
  
  bool found;
  string s = _request->value("start", found);
  
  if (found) {
    start = StringUtils::uint64(s);
  }
  
  // .............................................................................
  // check the offset
  // .............................................................................
  
  uint64_t offset = 0;
  
  s = _request->value("offset", found);
  
  if (found) {
    offset = StringUtils::uint64(s);
  }
  
  // .............................................................................
  // check the size
  // .............................................................................
  
  uint64_t size = (uint64_t) -1;
  
  s = _request->value("size", found);
  
  if (found) {
    size = StringUtils::uint64(s);
  }
  
  // .............................................................................
  // check the sort direction
  // .............................................................................
  
  bool sortAscending = false;
  bool sortDescending = false;
  
  string sortdir = StringUtils::tolower(_request->value("sort", found));
  
  if (found) {
    if (sortdir == "asc") {
      sortAscending = true;
    }
    else if (sortdir == "desc") {
      sortDescending = true;
    }
    else {
      LOGGER_DEBUG << "unknown sort direction '" << sortdir << "'";
    }
  }
  
  // .............................................................................
  // check the search criteria
  // .............................................................................
  
  bool search = false;
  string searchString = StringUtils::tolower(_request->value("search", search));
  
  // .............................................................................
  // generate result
  // .............................................................................
  
  VariantArray* result = new VariantArray();
  
  VariantVector* lid = new VariantVector();
  result->add("lid", lid);
  
  VariantVector* level = new VariantVector();
  result->add("level", level);
  
  VariantVector* timestamp = new VariantVector();
  result->add("timestamp", timestamp);
  
  VariantVector* text = new VariantVector();
  result->add("text", text);
  
  TRI_vector_t * logs = TRI_BufferLogging(ul, start, useUpto);
  TRI_vector_t clean;
  
  TRI_InitVector(&clean, TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_log_buffer_t));
  
  for (size_t i = 0;  i < logs->_length;  ++i) {
    TRI_log_buffer_t* buf = (TRI_log_buffer_t*) TRI_AtVector(logs, i);
    
    if (search) {
      string text = StringUtils::tolower(buf->_text);
     
      if (text.find(searchString) == string::npos) {
        continue;
      }
    }
    
    TRI_PushBackVector(&clean, buf);
  }
  
  result->add("totalAmount", new VariantUInt64(clean._length));
  
  size_t length = clean._length;
  
  if (offset >= length) {
    length = 0;
    offset = 0;
  }
  else if (offset > 0) {
    length -= offset;
  }

  // restrict to at most <size> elements
  if (length > size) {
    length = size;
  }

  if (sortAscending) {
    qsort(((char*) TRI_BeginVector(&clean)) + offset * sizeof(TRI_log_buffer_t),
          length,
          sizeof(TRI_log_buffer_t),
          LidCompareAsc);
  }
  else if (sortDescending) {
    qsort(((char*) TRI_BeginVector(&clean)) + offset * sizeof(TRI_log_buffer_t),
          length,
          sizeof(TRI_log_buffer_t),
          LidCompareDesc);
  }
  
  for (size_t i = 0;  i < length;  ++i) {
    TRI_log_buffer_t* buf = (TRI_log_buffer_t*) TRI_AtVector(&clean, offset + i);
    uint32_t l = 0;
    
    switch (buf->_level) {
      case TRI_LOG_LEVEL_FATAL:  l = 0; break;
      case TRI_LOG_LEVEL_ERROR:  l = 1; break;
      case TRI_LOG_LEVEL_WARNING:  l = 2; break;
      case TRI_LOG_LEVEL_INFO:  l = 3; break;
      case TRI_LOG_LEVEL_DEBUG:  l = 4; break;
      case TRI_LOG_LEVEL_TRACE:  l = 5; break;
    }
    
    lid->add(new VariantUInt64(buf->_lid));
    level->add(new VariantUInt32(l));
    timestamp->add(new VariantUInt32(buf->_timestamp));
    text->add(new VariantString(buf->_text));
  }
  
  TRI_FreeBufferLogging(logs);
  TRI_DestroyVector(&clean);
  
  generateResult(result);
  return HANDLER_DONE;
}
예제 #2
0
VariantArray* TRI_StatisticsInfo (TRI_statistics_granularity_e granularity,
                                  size_t limit,
                                  bool showTotalTime,
                                  bool showQueueTime,
                                  bool showRequestTime,
                                  bool showBytesSent,
                                  bool showBytesReceived,
                                  bool showHttp) {
  vector<time_t> t;
  vector<StatisticsDesc> blocks;

  // .............................................................................
  // extract the statistics blocks for the given granularity
  // .............................................................................

  size_t resolution = 0;
  size_t total = 0;

  {
    MUTEX_LOCKER(Statistics._lock);

    switch (granularity) {
      case TRI_STATISTICS_SECONDS:
        // not used/implemented, yet
        break;

      case TRI_STATISTICS_MINUTES:
        resolution = Statistics._minute.getResolution();
        total = Statistics._minute.getLength();

        if (limit == (size_t) -1) {
          blocks = Statistics._minute.values(t);
        }
        else if (limit == 0) {
          blocks = Statistics._minute.values(t, 1);
        }
        else {
          blocks = Statistics._minute.values(t, limit);
        }

        break;

      case TRI_STATISTICS_HOURS:
        resolution = Statistics._hour.getResolution();
        total = Statistics._hour.getLength();
        
        if (limit == (size_t) -1) {
          blocks = Statistics._hour.values(t);
        }
        else if (limit == 0) {
          blocks = Statistics._hour.values(t, 1);
        }
        else {
          blocks = Statistics._hour.values(t, limit);
        }

        break;

      case TRI_STATISTICS_DAYS:
        resolution = Statistics._day.getResolution();
        total = Statistics._day.getLength();
        
        if (limit == (size_t) -1) {
          blocks = Statistics._day.values(t);
        }
        else if (limit == 0) {
          blocks = Statistics._day.values(t, 1);
        }
        else {
          blocks = Statistics._day.values(t, limit);
        }
        
        break;
    }
  }

  // .............................................................................
  // CASE 1: generate the current aka last block only
  // .............................................................................

  VariantArray* result = new VariantArray();

  result->add("resolution", new VariantUInt64(resolution));

  if (blocks.empty()) {
    return result;
  }

  if (limit == 0) {
    result->add("start", new VariantUInt32((uint32_t) t[0]));

    if (showTotalTime) {
      RRF_GenerateVariantDistribution<StatisticsDesc::totalAccessor>(result, blocks[0], "totalTime", true, false, false);
    }

    if (showQueueTime) {
      RRF_GenerateVariantDistribution<StatisticsDesc::queueAccessor>(result, blocks[0], "queueTime", true, false, false);
    }

    if (showRequestTime) {
      RRF_GenerateVariantDistribution<StatisticsDesc::requestAccessor>(result, blocks[0], "requestTime", true, false, false);
    }

    if (showBytesSent) {
      RRF_GenerateVariantDistribution<StatisticsDesc::bytesSentAccessor>(result, blocks[0], "bytesSent", true, false, false);
    }

    if (showBytesReceived) {
      RRF_GenerateVariantDistribution<StatisticsDesc::bytesReceivedAccessor>(result, blocks[0], "bytesReceived", true, false, false);
    }

    if (showHttp) {
      RRF_GenerateVariantCounter<StatisticsDesc::httpConnectionsAccessor>(result, blocks[0], "httpConnections", resolution);
      RRF_GenerateVariantDistribution<StatisticsDesc::httpDurationAccessor>(result, blocks[0], "httpDuration", true, false, false);
    }
  }

  // .............................................................................
  // CASE 2: generate all blocks upto limit
  // .............................................................................

  else {
    VariantVector* start = new VariantVector();
    result->add("start", start);

    size_t offset = 0;
    std::vector<time_t>::const_iterator k = t.begin();

    for (;  k != t.end();  ++k, ++offset) {
      if (*k != 0) {
        break;
      }
    }

    for (;  k != t.end();  ++k) {
      start->add(new VariantUInt64(*k));
    }

    if (0 < offset) {
      vector<StatisticsDesc> tmp;

      tmp.insert(tmp.begin(), blocks.begin() + offset, blocks.end());
      blocks.swap(tmp);
    }

    result->add("length", new VariantUInt64(blocks.size()));;
    result->add("totalLength", new VariantUInt64(total));

    if (showTotalTime) {
      RRF_GenerateVariantDistribution<StatisticsDesc::totalAccessor>(result, blocks, "totalTime", true, false, false);
    }

    if (showQueueTime) {
      RRF_GenerateVariantDistribution<StatisticsDesc::queueAccessor>(result, blocks, "queueTime", true, false, false);
    }

    if (showRequestTime) {
      RRF_GenerateVariantDistribution<StatisticsDesc::requestAccessor>(result, blocks, "requestTime", true, false, false);
    }

    if (showBytesSent) {
      RRF_GenerateVariantDistribution<StatisticsDesc::bytesSentAccessor>(result, blocks, "bytesSent", true, false, false);
    }

    if (showBytesReceived) {
      RRF_GenerateVariantDistribution<StatisticsDesc::bytesReceivedAccessor>(result, blocks, "bytesReceived", true, false, false);
    }

    if (showHttp) {
      RRF_GenerateVariantCounter<StatisticsDesc::httpConnectionsAccessor>(result, blocks, "httpConnections", resolution);
      RRF_GenerateVariantDistribution<StatisticsDesc::httpDurationAccessor>(result, blocks, "httpDuration", true, false, false);
    }
  }

  return result;
}