Commit 1e99958b authored by Pavel Vainerman's avatar Pavel Vainerman

(LogDB): добавил для /logs возможность задать параметры

from=YYYY-MM-DD to=YYYY-MM-DD last=XX[m|h|d|M] - Логи за последние m-минуты, h-часы, d-дни, M - месяцы
parent 1c4a19d4
......@@ -23,6 +23,7 @@
#include "unisetstd.h"
#include <Poco/Net/NetException.h>
#include "ujson.h"
#include "LogDB.h"
#include "Configuration.h"
#include "Debug.h"
......@@ -105,14 +106,6 @@ LogDB::LogDB( const string& name , const string& prefix ):
throw uniset::SystemError(err.str());
}
// if( l->cmd.empty() )
// {
// ostringstream err;
// err << name << "(init): Unknown 'cmd' for '" << l->name << "'..";
// dbcrit << err.str() << endl;
// throw uniset::SystemError(err.str());
// }
// l->tcp = make_shared<UTCPStream>();
l->dblog = dblog;
l->signal_on_read().connect(sigc::mem_fun(this, &LogDB::addLog));
......@@ -562,12 +555,22 @@ void LogDB::handleRequest( Poco::Net::HTTPServerRequest& req, Poco::Net::HTTPSer
if( cmd == "help" )
{
out << "{ \"help\": ["
"{\"help\": {\"desc\": \"this help\"}},"
"{\"list\": {\"desc\": \"list of logs\"}},"
"{\"read?logname&offset=N&limit=M\": {\"desc\": \"read logs\"}},"
"{\"apidocs\": {\"desc\": \"https://github.com/Etersoft/uniset2\"}}"
"]}";
using uniset::json::help::item;
uniset::json::help::object myhelp("help");
myhelp.emplace(item("help", "this help"));
myhelp.emplace(item("list", "list of logs"));
myhelp.emplace(item("count?logname", "count of logs for logname"));
item l("logs", "read logs");
l.param("from='YYYY-MM-DD'", "From date");
l.param("to='YYYY-MM-DD'", "To date");
l.param("last=XX[m|h|d|M]", "Last records (m - minute, h - hour, d - day, M - month)");
l.param("offset=N", "offset");
l.param("limit=M", "limit records for response");
myhelp.add(l);
myhelp.emplace(item("apidocs", "https://github.com/Etersoft/uniset2"));
myhelp.get()->stringify(out);
}
else
{
......@@ -676,24 +679,32 @@ Poco::JSON::Object::Ptr LogDB::httpGetLogs( const Poco::URI::QueryParameters& pa
{
Poco::JSON::Object::Ptr jdata = new Poco::JSON::Object();
std::string logname = params[0].first;
if( logname.empty() )
if( params.empty() || params[0].first.empty() )
{
ostringstream err;
err << "BAD REQUEST: unknown logname";
throw uniset::SystemError(err.str());
}
std::string logname = params[0].first;
size_t offset = 0;
size_t limit = 0;
vector<std::string> q_where;
for( const auto& p : params )
{
if( p.first == "offset" )
offset = uni_atoi(p.second);
else if( p.first == "limit" )
limit = uni_atoi(p.second);
else if( p.first == "from" )
q_where.push_back("tms>='" + p.second + "'");
else if( p.first == "to" )
q_where.push_back("tms<='" + p.second + "'");
else if( p.first == "last" )
q_where.push_back(qLast(p.second));
}
Poco::JSON::Array::Ptr jlist = uniset::json::make_child_array(jdata, "logs");
......@@ -705,6 +716,12 @@ Poco::JSON::Object::Ptr LogDB::httpGetLogs( const Poco::URI::QueryParameters& pa
<< " strftime('%H:%M:%S',datetime(tms,'unixepoch')) as time,"
<< " usec, text FROM logs WHERE name='" << logname << "'";
if( !q_where.empty() )
{
for( const auto& w : q_where )
q << " AND " << w;
}
if( limit > 0 )
q << " ORDER BY tms ASC LIMIT " << offset << "," << limit;
......@@ -760,5 +777,45 @@ Poco::JSON::Object::Ptr LogDB::httpGetCount( const Poco::URI::QueryParameters& p
return jdata;
}
// -----------------------------------------------------------------------------
string LogDB::qLast( const string& p )
{
if( p.empty() )
return "";
char unit = p[p.size() - 1];
std::string sval = p.substr(0, p.size() - 1);
if( unit == 'h' || unit == 'H' )
{
size_t h = uni_atoi(sval);
ostringstream q;
q << "tms >= strftime('%s',datetime('now')) - " << h << "*60*60";
return q.str();
}
else if( unit == 'd' || unit == 'D' )
{
size_t d = uni_atoi(sval);
ostringstream q;
q << "tms >= strftime('%s',datetime('now')) - " << d << "*24*60*60";
return q.str();
}
else if( unit == 'M' )
{
size_t m = uni_atoi(sval);
ostringstream q;
q << "tms >= strftime('%s',datetime('now')) - " << m << "*30*24*60*60";
return q.str();
}
else // по умолчанию минут
{
size_t m = (unit == 'm') ? uni_atoi(sval) : uni_atoi(p);
ostringstream q;
q << "tms >= strftime('%s',datetime('now')) - " << m << "*60";
return q.str();
}
return "";
}
// -----------------------------------------------------------------------------
#endif
// -----------------------------------------------------------------------------
......@@ -73,25 +73,29 @@ namespace uniset
http-сервер. Параметры запуска можно указать при помощи:
--prefix-httpserver-host и --prefix-httpserver-port.
Запросы принимаются по: api/version/logdb/...
Запросы обрабатываются по пути: api/version/logdb/...
/help - Получение списка доступных команд
/list - список доступных логов
/logs?logname&offset=N&limit=M - получение логов 'logname'
Не обязательные параметры:
offset - начиная с,
limit - количество в ответе.
/logs?logname&..parameters.. - получение логов 'logname'
Не обязательные параметры:
offset=N - начиная с N-ой записи,
limit=M - количество в ответе.
from='YYYY-MM-DD' - 'с' указанной даты
to='YYYY-MM-DD' - 'по' указанную дату
last=XX[m|h|d|M] - за последние XX m-минут, h-часов, d-дней, M-месяцев
По умолчанию: минут
/count?logname - Получить текущее количество записей
\todo Добавить настройки таймаутов, размера буфера, размера для резервирования под строку, количество потоков для http и т.п.
\todo Добавить ротацию БД
\todo REST API: продумать команды и реализовать
\todo Сделать настройку, для формата даты и времени при выгрузке из БД (при формировании json).
\todo Возможно в /logs стоит в ответе сразу возвращать и общее количество в БД (это один лишний запрос, каждый раз).
\todo Продумать поддержку websocket
\todo Встроить поддержку websocket
\todo Возможно в последствии оптимизировать таблицы (нормализовать) если будет тормозить. Сейчас пока прототип.
\todo Пока не очень эффективная работа с датой и временем (заодно подумать всё-таки в чём хранить)
*/
class LogDB:
public EventLoopServer
......@@ -136,6 +140,10 @@ namespace uniset
Poco::JSON::Object::Ptr httpGetList( const Poco::URI::QueryParameters& p );
Poco::JSON::Object::Ptr httpGetLogs( const Poco::URI::QueryParameters& p );
Poco::JSON::Object::Ptr httpGetCount( const Poco::URI::QueryParameters& p );
// формирование условия where для строки XX[m|h|d|M]
// XX m - минут, h-часов, d-дней, M - месяцев
static std::string qLast( const std::string& p );
#endif
std::string myname;
std::unique_ptr<SQLiteInterface> db;
......
......@@ -57,6 +57,7 @@ namespace uniset
object( const std::string& name, Poco::JSON::Object::Ptr ptr );
void add( item& i );
void emplace( item&& i );
Poco::JSON::Object::Ptr get();
......
......@@ -92,11 +92,16 @@ namespace uniset
}
}
// --------------------------------------------------------------------------
void json::help::object::add(json::help::item& i)
void json::help::object::add( json::help::item& i)
{
cmdlist->add(i);
}
// --------------------------------------------------------------------------
void json::help::object::emplace( json::help::item&& i )
{
cmdlist->add( std::move(i) );
}
// --------------------------------------------------------------------------
Poco::JSON::Object::Ptr json::help::object::get()
{
return root;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment