Skip to content

Commit 4ae3390

Browse files
authored
Merge pull request #1 from Tiaansu/fetch-log
Fetch logs, case sensitive support, automatic cleanup of logs result
2 parents 56c292d + 2bdb054 commit 4ae3390

File tree

14 files changed

+488
-2
lines changed

14 files changed

+488
-2
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,4 @@ You can check this [repository](https://github.com/Tiaansu/greet-component) for
5151
## Thanks to
5252
- [Amir's omp-node](https://github.com/AmyrAhmady/omp-node) (I copied it's `include` style so other components can use this component)
5353
- [maddinatOr's samp-log-core](https://github.com/maddinat0r/samp-log-core) (most of the code were from this project)
54+
- [Toiletduck / Eksqtr](https://github.com/eksqtr) (big thanks to this person. Many ideas were from him)

include/omp-logger.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ namespace OmpLogger
3535
}
3636

3737
struct IOmpLog;
38+
struct PaginatedResult;
3839

3940
static const UID OmpLoggerComponent_UID = UID(0xAB3BC9C4E583C8B4);
4041
class IOmpLoggerComponent : public IComponent
@@ -68,6 +69,8 @@ struct IOmpLog
6869

6970
virtual uint32_t getColor() const = 0;
7071

72+
virtual PaginatedResult fetchLogs(int linesPerPage, int pageStart, const std::string& searchTerm, bool caseSensitive) const = 0;
73+
7174
virtual bool log(AMX* amx, OmpLogger::ELogLevel level, StringView message) const = 0;
7275

7376
virtual bool log(OmpLogger::ELogLevel level, StringView message) const = 0;
@@ -103,4 +106,11 @@ class OmpLoggerManager
103106

104107
private:
105108
IOmpLoggerComponent* ompLogger_ = nullptr;
109+
};
110+
111+
struct PaginatedResult
112+
{
113+
std::vector<std::string> lines;
114+
int currentPage;
115+
int totalPages;
106116
};

omp-logger.inc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,17 @@ native bool:Logger_Info(Logger:id, const format[], OPEN_MP_TAGS:...);
3131
native bool:Logger_Warning(Logger:id, const format[], OPEN_MP_TAGS:...);
3232
native bool:Logger_Error(Logger:id, const format[], OPEN_MP_TAGS:...);
3333
native bool:Logger_Fatal(Logger:id, const format[], OPEN_MP_TAGS:...);
34+
35+
// Logs result
36+
native Logger_FetchLogs(playerid, Logger:logger, amount, pageStart, const callback[], const search[] = "", bool:caseSensitive = true);
37+
native Logger_GetResult(LogsResult:result, row, logs[], size = sizeof logs);
38+
native Logger_FreeResult(LogsResult:result);
39+
40+
// Cleanup results once they go out of scope
41+
stock operator~(const LogsResult:result[], len)
42+
{
43+
for (new i = 0; i < len; ++ i)
44+
{
45+
Logger_FreeResult(result[i]);
46+
}
47+
}

src/component.cpp

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <fmt/format.h>
44
#include "component.hpp"
55
#include "helpers/utils.hpp"
6+
#include "threaded-queue.hpp"
67

78
// API
89
IOmpLog* OmpLoggerComponent::createLogger(StringView name, int32_t color, OmpLogger::ELogLevel level, bool isPlugin)
@@ -26,7 +27,7 @@ IOmpLog* OmpLoggerComponent::createLogger(StringView name, int32_t color, OmpLog
2627
color = 0;
2728
}
2829

29-
std::FILE* file = ::fopen(filepath.c_str(), "a");
30+
std::FILE* file = ::fopen(filepath.c_str(), "a+");
3031
if (file == nullptr)
3132
{
3233
core_->logLn(LogLevel::Error, "Failed to open log file \"%s\".", filepath.c_str());
@@ -48,6 +49,24 @@ IOmpLog* OmpLoggerComponent::getLogger(int id)
4849
return pool_.get(id);
4950
}
5051

52+
// Fetch logs
53+
ILogsResult* OmpLoggerComponent::initLogsResult(std::vector<std::string> logs)
54+
{
55+
return logsResults_.emplace(logs);
56+
}
57+
58+
bool OmpLoggerComponent::deleteLogsResult(ILogsResult* result)
59+
{
60+
int id = static_cast<ILogsResult*>(result)->getID();
61+
logsResults_.release(id, false);
62+
return true;
63+
}
64+
65+
ILogsResult* OmpLoggerComponent::getLogsResult(int id)
66+
{
67+
return logsResults_.get(id);
68+
}
69+
5170
// Callbacks
5271
void OmpLoggerComponent::onLoad(ICore* c)
5372
{
@@ -68,6 +87,7 @@ void OmpLoggerComponent::onInit(IComponentList* components)
6887
setAmxFunctions(pawn_->getAmxFunctions());
6988
setAmxLookups(components);
7089
pawn_->getEventDispatcher().addEventHandler(this);
90+
core_->getEventDispatcher().addEventHandler(this);
7191

7292
IConfig& config = core_->getConfig();
7393
isLogLevelNameCapitalized_ = (config.getBool("logger.log_level_capitalized")) ? (*config.getBool("logger.log_level_capitalized")) : false;
@@ -193,6 +213,8 @@ void OmpLoggerComponent::free()
193213
serverLoggerFile_ = nullptr;
194214
}
195215

216+
ThreadedQueue::Get()->Destroy();
217+
196218
delete this;
197219
core_->printLn("[omp-logger] Logger released.");
198220
}
@@ -210,7 +232,13 @@ void OmpLoggerComponent::onAmxLoad(IPawnScript& script)
210232

211233
void OmpLoggerComponent::onAmxUnload(IPawnScript& script)
212234
{
213-
debugEraseAMX(script.GetAMX());
235+
AMX* amx = script.GetAMX();
236+
debugEraseAMX(amx);
237+
}
238+
239+
void OmpLoggerComponent::onTick(Microseconds elapsed, TimePoint now)
240+
{
241+
ThreadedQueue::Get()->Process();
214242
}
215243

216244
OmpLoggerComponent::~OmpLoggerComponent()
@@ -219,6 +247,10 @@ OmpLoggerComponent::~OmpLoggerComponent()
219247
{
220248
pawn_->getEventDispatcher().removeEventHandler(this);
221249
}
250+
if (core_)
251+
{
252+
core_->getEventDispatcher().removeEventHandler(this);
253+
}
222254
}
223255

224256
// API - Config

src/component.hpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@
1111
#include "omp-logger.hpp"
1212
#include "omp-log.hpp"
1313
#include "debug-manager.hpp"
14+
#include "logs-result.hpp"
1415

1516
class OmpLoggerComponent final
1617
: public IOmpLoggerComponent
1718
, public PawnEventHandler
19+
, public CoreEventHandler
1820
{
1921
private:
2022
ICore* core_ = nullptr;
@@ -23,6 +25,8 @@ class OmpLoggerComponent final
2325

2426
MarkedPoolStorage<OmpLog, IOmpLog, 1, 1000> pool_;
2527

28+
MarkedPoolStorage<LogsResult, ILogsResult, 1, 5000> logsResults_;
29+
2630
inline static OmpLoggerComponent* instance_ = nullptr;
2731

2832
// configs
@@ -44,6 +48,13 @@ class OmpLoggerComponent final
4448

4549
IOmpLog* getLogger(int id) override;
4650

51+
// Fetch logs
52+
ILogsResult* initLogsResult(std::vector<std::string> logs);
53+
54+
bool deleteLogsResult(ILogsResult* result);
55+
56+
ILogsResult* getLogsResult(int id);
57+
4758
// Component
4859
StringView componentName() const override
4960
{
@@ -54,6 +65,8 @@ class OmpLoggerComponent final
5465
{
5566
return SemanticVersion(0, 0, 1, 0);
5667
}
68+
69+
void onTick(Microseconds elapsed, TimePoint now) override;
5770

5871
void onLoad(ICore* c) override;
5972

src/logs-result.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#include "logs-result.hpp"
2+
#include "component.hpp"
3+
4+
using namespace Impl;
5+
6+
int LogsResult::getID() const
7+
{
8+
return poolID;
9+
}
10+
11+
std::string LogsResult::getLog(int row) const
12+
{
13+
return logs_.at(row);
14+
}
15+
16+
LogsResult::LogsResult(std::vector<std::string> logs)
17+
: logs_(std::move(logs))
18+
{
19+
}

src/logs-result.hpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#pragma once
2+
3+
#include <sdk.hpp>
4+
#include <Impl/pool_impl.hpp>
5+
6+
using namespace Impl;
7+
8+
struct ILogsResult
9+
{
10+
virtual int getID() const = 0;
11+
12+
virtual std::string getLog(int row) const = 0;
13+
};
14+
15+
class LogsResult final
16+
: public ILogsResult
17+
, public PoolIDProvider
18+
, public NoCopy
19+
{
20+
private:
21+
std::vector<std::string> logs_;
22+
23+
public:
24+
int getID() const override;
25+
26+
std::string getLog(int row) const override;
27+
28+
LogsResult(std::vector<std::string> logs);
29+
};

src/natives.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
#include <algorithm>
22
#include <string>
3+
#include <vector>
4+
#include <thread>
35

46
#include <sdk.hpp>
57
#include <Server/Components/Pawn/Impl/pawn_natives.hpp>
68

79
#include "component.hpp"
810
#include "natives.hpp"
911
#include "omp-logger.hpp"
12+
#include "threaded-queue.hpp"
1013
#include "helpers/format.hpp"
1114

1215
SCRIPT_API(Logger_Create, int(std::string const& name, int32_t color, OmpLogger::ELogLevel level))
@@ -56,4 +59,39 @@ SCRIPT_API(Logger_Fatal, bool(IOmpLog& logger, cell const* format))
5659
{
5760
AMX* amx = GetAMX();
5861
return logger.log(amx, OmpLogger::ELogLevel::Fatal, AmxStringFormatter(format, amx, GetParams(), 2));
62+
}
63+
64+
SCRIPT_API(Logger_FetchLogs, bool(IPlayer& player, IOmpLog& logger, int linesPerPage, int pageStart, std::string const& callback, std::string const& searchTerm, bool caseSensitive))
65+
{
66+
AMX* amx = GetAMX();
67+
68+
auto func = [&player, &logger, amx, callback, searchTerm, linesPerPage, pageStart, caseSensitive]() {
69+
70+
int funcIDX = 0;
71+
if (!amx_FindPublic(amx, callback.c_str(), &funcIDX))
72+
{
73+
PaginatedResult result = logger.fetchLogs(linesPerPage, pageStart, searchTerm, caseSensitive);
74+
ILogsResult* logsResult = OmpLoggerComponent::Get()->initLogsResult(result.lines);
75+
amx_Push(amx, result.totalPages);
76+
amx_Push(amx, result.currentPage);
77+
amx_Push(amx, (int)result.lines.size());
78+
amx_Push(amx, logsResult->getID());
79+
amx_Push(amx, logger.getID());
80+
amx_Push(amx, player.getID());
81+
amx_Exec(amx, NULL, funcIDX);
82+
}
83+
};
84+
ThreadedQueue::Get()->Dispatch(func);
85+
return 1;
86+
}
87+
88+
SCRIPT_API(Logger_GetResult, int(ILogsResult& result, int row, OutputOnlyString& logs))
89+
{
90+
logs = result.getLog(row);
91+
return std::get<StringView>(logs).length();
92+
}
93+
94+
SCRIPT_API(Logger_FreeResult, bool(ILogsResult& result))
95+
{
96+
return OmpLoggerComponent::Get()->deleteLogsResult(&result);
5997
}

src/natives.hpp

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,4 +104,104 @@ namespace pawn_natives
104104
ParamCast(AMX*, cell*, int) = delete;
105105
ParamCast() = delete;
106106
};
107+
108+
// Logs result
109+
template <>
110+
struct ParamLookup<ILogsResult>
111+
{
112+
static ILogsResult* Val(cell ref) noexcept
113+
{
114+
if (auto pool = OmpLoggerComponent::Get())
115+
{
116+
return pool->getLogsResult(ref);
117+
}
118+
return nullptr;
119+
}
120+
};
121+
122+
template <>
123+
class ParamCast<ILogsResult*>
124+
{
125+
public:
126+
ParamCast(AMX* amx, cell* params, int idx) noexcept
127+
{
128+
value_ = ParamLookup<ILogsResult>::Val(params[idx]);
129+
}
130+
131+
~ParamCast()
132+
{
133+
}
134+
135+
ParamCast(ParamCast<ILogsResult*> const&) = delete;
136+
ParamCast(ParamCast<ILogsResult*>&&) = delete;
137+
138+
operator ILogsResult*()
139+
{
140+
return value_;
141+
}
142+
143+
bool Error() const
144+
{
145+
return false;
146+
}
147+
148+
static constexpr int Size = 1;
149+
150+
private:
151+
ILogsResult* value_;
152+
};
153+
154+
template <>
155+
class ParamCast<ILogsResult&>
156+
{
157+
public:
158+
ParamCast(AMX* amx, cell* params, int idx)
159+
{
160+
value_ = ParamLookup<ILogsResult>::Val(params[idx]);
161+
if (value_ == nullptr)
162+
{
163+
AmxFuncCallInfo dest;
164+
if (!DebugManager::Get()->GetFunctionCall(amx, amx->cip, dest))
165+
{
166+
OmpLoggerComponent::Get()->getCore()->logLn(LogLevel::Warning, "Invalid logs result id %i", static_cast<int>(params[idx]));
167+
}
168+
else
169+
{
170+
OmpLoggerComponent::Get()->getCore()->logLn(LogLevel::Warning, "Invalid logs result id %i (%s:%i)", static_cast<int>(params[idx]), dest.file, static_cast<int>(dest.line));
171+
}
172+
error_ = true;
173+
}
174+
}
175+
176+
~ParamCast()
177+
{
178+
}
179+
180+
ParamCast(ParamCast<ILogsResult&> const&) = delete;
181+
ParamCast(ParamCast<ILogsResult&>&&) = delete;
182+
183+
operator ILogsResult&()
184+
{
185+
return *value_;
186+
}
187+
188+
bool Error() const
189+
{
190+
return error_;
191+
}
192+
193+
static constexpr int Size = 1;
194+
195+
private:
196+
ILogsResult* value_;
197+
bool error_ = false;
198+
};
199+
200+
template <>
201+
class ParamCast<const ILogsResult&>
202+
{
203+
public:
204+
ParamCast(AMX*, cell*, int) = delete;
205+
ParamCast() = delete;
206+
};
107207
}

0 commit comments

Comments
 (0)