Commit 8bfb6751 authored by Pavel Vainerman's avatar Pavel Vainerman

(LogDB): предварительно реализовал обработку запроса /logs?logname..

Собственно основной запрос на получение логов.
parent de9ac27b
...@@ -40,8 +40,8 @@ ...@@ -40,8 +40,8 @@
<LogServer name="smplus" port="3333" host="localhost" /> <LogServer name="smplus" port="3333" host="localhost" />
<LogDB name="LogDB"> <LogDB name="LogDB">
<logserver name="logserver1" ip="localhost" port="3333" cmd="-s level1"/> <logserver name="logserver1" ip="localhost" port="3333" cmd="-s level1" description="SES log"/>
<logserver name="logserver2" ip="localhost" port="3333" cmd=""/> <logserver name="logserver2" ip="localhost" port="3333" cmd="" description="GEU log"/>
</LogDB> </LogDB>
<settings> <settings>
......
...@@ -79,6 +79,7 @@ LogDB::LogDB( const string& name , const string& prefix ): ...@@ -79,6 +79,7 @@ LogDB::LogDB( const string& name , const string& prefix ):
l->ip = sit.getProp("ip"); l->ip = sit.getProp("ip");
l->port = sit.getIntProp("port"); l->port = sit.getIntProp("port");
l->cmd = sit.getProp("cmd"); l->cmd = sit.getProp("cmd");
l->description = sit.getProp("description");
if( l->name.empty() ) if( l->name.empty() )
{ {
...@@ -526,7 +527,7 @@ void LogDB::handleRequest( Poco::Net::HTTPServerRequest& req, Poco::Net::HTTPSer ...@@ -526,7 +527,7 @@ void LogDB::handleRequest( Poco::Net::HTTPServerRequest& req, Poco::Net::HTTPSer
// В этой версии API поддерживается только GET // В этой версии API поддерживается только GET
if( req.getMethod() != "GET" ) if( req.getMethod() != "GET" )
{ {
auto jdata = respError(resp, HTTPResponse::HTTP_BAD_REQUEST,"method must be 'GET'"); auto jdata = respError(resp, HTTPResponse::HTTP_BAD_REQUEST, "method must be 'GET'");
jdata->stringify(out); jdata->stringify(out);
out.flush(); out.flush();
return; return;
...@@ -548,7 +549,7 @@ void LogDB::handleRequest( Poco::Net::HTTPServerRequest& req, Poco::Net::HTTPSer ...@@ -548,7 +549,7 @@ void LogDB::handleRequest( Poco::Net::HTTPServerRequest& req, Poco::Net::HTTPSer
{ {
ostringstream err; ostringstream err;
err << "Bad request structure. Must be /api/" << uniset::UHttp::UHTTP_API_VERSION << "/logdb/xxx"; err << "Bad request structure. Must be /api/" << uniset::UHttp::UHTTP_API_VERSION << "/logdb/xxx";
auto jdata = respError(resp, HTTPResponse::HTTP_BAD_REQUEST,err.str()); auto jdata = respError(resp, HTTPResponse::HTTP_BAD_REQUEST, err.str());
jdata->stringify(out); jdata->stringify(out);
out.flush(); out.flush();
return; return;
...@@ -576,7 +577,7 @@ void LogDB::handleRequest( Poco::Net::HTTPServerRequest& req, Poco::Net::HTTPSer ...@@ -576,7 +577,7 @@ void LogDB::handleRequest( Poco::Net::HTTPServerRequest& req, Poco::Net::HTTPSer
} }
catch( std::exception& ex ) catch( std::exception& ex )
{ {
auto jdata = respError(resp, HTTPResponse::HTTP_INTERNAL_SERVER_ERROR,ex.what()); auto jdata = respError(resp, HTTPResponse::HTTP_INTERNAL_SERVER_ERROR, ex.what());
jdata->stringify(out); jdata->stringify(out);
} }
...@@ -601,6 +602,9 @@ Poco::JSON::Object::Ptr LogDB::httpGetRequest( const string& cmd, const Poco::UR ...@@ -601,6 +602,9 @@ Poco::JSON::Object::Ptr LogDB::httpGetRequest( const string& cmd, const Poco::UR
if( cmd == "list" ) if( cmd == "list" )
return httpGetList(p); return httpGetList(p);
if( cmd == "logs" )
return httpGetLogs(p);
ostringstream err; ostringstream err;
err << "Unknown command '" << cmd << "'"; err << "Unknown command '" << cmd << "'";
throw uniset::SystemError(err.str()); throw uniset::SystemError(err.str());
...@@ -629,15 +633,17 @@ Poco::JSON::Object::Ptr LogDB::httpGetList( const Poco::URI::QueryParameters& p ...@@ -629,15 +633,17 @@ Poco::JSON::Object::Ptr LogDB::httpGetList( const Poco::URI::QueryParameters& p
q << "SELECT COUNT(*), name FROM logs GROUP BY name"; q << "SELECT COUNT(*), name FROM logs GROUP BY name";
DBResult ret = db->query(q.str()); DBResult ret = db->query(q.str());
if( !ret ) if( !ret )
return jdata; return jdata;
for( auto it = ret.begin(); it!=ret.end(); ++it ) for( auto it = ret.begin(); it != ret.end(); ++it )
{ {
Poco::JSON::Object::Ptr j = new Poco::JSON::Object(); Poco::JSON::Object::Ptr j = new Poco::JSON::Object();
j->set("name", it.as_string("name")); j->set("name", it.as_string("name"));
jlist->add(j); jlist->add(j);
} }
#else #else
// Получение из конфигурации // Получение из конфигурации
// хорошо тем, что если логов ещё не было // хорошо тем, что если логов ещё не было
...@@ -650,16 +656,73 @@ Poco::JSON::Object::Ptr LogDB::httpGetList( const Poco::URI::QueryParameters& p ...@@ -650,16 +656,73 @@ Poco::JSON::Object::Ptr LogDB::httpGetList( const Poco::URI::QueryParameters& p
* если вдруг в REST API будет возможность добавлять логи.. нужно защищаться * если вдруг в REST API будет возможность добавлять логи.. нужно защищаться
* либо переделывать обработку * либо переделывать обработку
*/ */
for( const auto& s: logservers ) for( const auto& s : logservers )
{ {
Poco::JSON::Object::Ptr j = new Poco::JSON::Object(); Poco::JSON::Object::Ptr j = new Poco::JSON::Object();
j->set("name", s->name); j->set("name", s->name);
j->set("description", s->description);
jlist->add(j); jlist->add(j);
} }
#endif #endif
return jdata; return jdata;
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
Poco::JSON::Object::Ptr LogDB::httpGetLogs( const Poco::URI::QueryParameters& params )
{
Poco::JSON::Object::Ptr jdata = new Poco::JSON::Object();
std::string logname = params[0].first;
if( logname.empty() )
{
ostringstream err;
err << "BAD REQUEST: unknown logname";
throw uniset::SystemError(err.str());
}
size_t offset = 0;
size_t limit = 0;
for( const auto& p : params )
{
if( p.first == "offset" )
offset = uni_atoi(p.second);
else if( p.first == "limit" )
limit = uni_atoi(p.second);
}
Poco::JSON::Array::Ptr jlist = uniset::json::make_child_array(jdata, "logs");
ostringstream q;
q << "SELECT tms,"
<< " strftime('%d-%m-%Y',datetime(tms,'unixepoch')) as date,"
<< " strftime('%H:%M:%S',datetime(tms,'unixepoch')) as time,"
<< " usec, text FROM logs WHERE name='" << logname << "'";
if( limit > 0 )
q << " ORDER BY tms ASC LIMIT " << offset << "," << limit;
DBResult ret = db->query(q.str());
if( !ret )
return jdata;
for( auto it = ret.begin(); it != ret.end(); ++it )
{
Poco::JSON::Object::Ptr j = new Poco::JSON::Object();
j->set("tms", it.as_string("tms"));
j->set("date", it.as_string("date"));
j->set("time", it.as_string("time"));
j->set("usec", it.as_string("usec"));
j->set("text", it.as_string("text"));
jlist->add(j);
}
return jdata;
}
// -----------------------------------------------------------------------------
#endif #endif
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
...@@ -55,11 +55,15 @@ namespace uniset ...@@ -55,11 +55,15 @@ namespace uniset
и сохранении их в БД (sqlite). Помимо этого LogDB выступает в качестве и сохранении их в БД (sqlite). Помимо этого LogDB выступает в качестве
REST сервиса, позволяющего получать логи за указанный период в виде json. REST сервиса, позволяющего получать логи за указанный период в виде json.
Реализация намеренно простая, т.к. пока неясно нужно ли это и в каком виде.
Ожидается что контролируемых логов будет не очень много (максимум несколько десятков)
и каждый лог будет генерировать не более 2-5 мегабайт записей. Поэтому sqlite должно хватить.
\section sec_LogDB_Conf Конфигурирвание LogDB \section sec_LogDB_Conf Конфигурирвание LogDB
<LogDB name="LogDB" ...> <LogDB name="LogDB" ...>
<logserver name="" ip=".." port=".." cmd=".."/> <logserver name="" ip=".." port=".." cmd=".." description=".."/>
<logserver name="" ip=".." port=".." cmd=".."/> <logserver name="" ip=".." port=".." cmd=".." description=".."/>
<logserver name="" ip=".." port=".." cmd=".."/> <logserver name="" ip=".." port=".." cmd=".."/>
</LogDB> </LogDB>
...@@ -73,7 +77,7 @@ namespace uniset ...@@ -73,7 +77,7 @@ namespace uniset
/help - Получение списка доступных команд /help - Получение списка доступных команд
/list - список доступных логов /list - список доступных логов
/read?logname&offset=N&limit=M - получение логов 'logname' /logs?logname&offset=N&limit=M - получение логов 'logname'
Не обязательные параметры: Не обязательные параметры:
offset - начиная с, offset - начиная с,
limit - количество в ответе. limit - количество в ответе.
...@@ -83,6 +87,7 @@ namespace uniset ...@@ -83,6 +87,7 @@ namespace uniset
\todo Добавить настройки таймаутов, размера буфера, размера для резервирования под строку, количество потоков для http и т.п. \todo Добавить настройки таймаутов, размера буфера, размера для резервирования под строку, количество потоков для http и т.п.
\todo Добавить ротацию БД \todo Добавить ротацию БД
\todo REST API: продумать команды и реализовать \todo REST API: продумать команды и реализовать
\todo Сделать настройку, для формата даты и времени при выгрузке из БД (при формировании json).
\todo Продумать поддержку websocket \todo Продумать поддержку websocket
\todo Возможно в последствии оптимизировать таблицы (нормализовать) если будет тормозить. Сейчас пока прототип. \todo Возможно в последствии оптимизировать таблицы (нормализовать) если будет тормозить. Сейчас пока прототип.
*/ */
...@@ -127,6 +132,7 @@ namespace uniset ...@@ -127,6 +132,7 @@ namespace uniset
Poco::JSON::Object::Ptr respError( Poco::Net::HTTPServerResponse& resp, Poco::Net::HTTPResponse::HTTPStatus s, const std::string& message ); Poco::JSON::Object::Ptr respError( Poco::Net::HTTPServerResponse& resp, Poco::Net::HTTPResponse::HTTPStatus s, const std::string& message );
Poco::JSON::Object::Ptr httpGetRequest( const std::string& cmd, const Poco::URI::QueryParameters& p ); Poco::JSON::Object::Ptr httpGetRequest( const std::string& cmd, const Poco::URI::QueryParameters& p );
Poco::JSON::Object::Ptr httpGetList( const Poco::URI::QueryParameters& p ); Poco::JSON::Object::Ptr httpGetList( const Poco::URI::QueryParameters& p );
Poco::JSON::Object::Ptr httpGetLogs( const Poco::URI::QueryParameters& p );
#endif #endif
std::string myname; std::string myname;
std::unique_ptr<SQLiteInterface> db; std::unique_ptr<SQLiteInterface> db;
...@@ -147,6 +153,7 @@ namespace uniset ...@@ -147,6 +153,7 @@ namespace uniset
int port = { 0 }; int port = { 0 };
std::string cmd; std::string cmd;
std::string peername; std::string peername;
std::string description;
std::shared_ptr<DebugStream> dblog; std::shared_ptr<DebugStream> dblog;
......
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