2

I am new to game server design,now assigned to a task to refactory our log server. I create a class Log for communication between Game server and Log server.

class Log
{
    public:
        void    encode(Encoder& encoder) const;
        int     decode(Decoder& decoder);
    private:
        std::string sql_cmd;
}

On the game server, there is a class for send log request to log server.

class LogHelper
{
public:
        static void LogItemChange(const GameShare::GameItem& item, const PackageChangeDetails& pcd);
        {
                Log log(get_item_change_sql(item,pcd);
                send_to_log_server();
        }


private:
        static std::string get_item_change_sql(const GameShare::GameItem& item, const PackageChangeDetails& pcd);
}

The question is:

  1. Should I generate sql text on game server? If generate sql text on game server, does it have bad effect for performance of game server?

  2. If not generate sql text on game server, then should genrate sql text on log server. I should send GameItem and PackageChangeDetails instance data to log server, it will complicated the log server, does anybody has good ided?

cspolton
  • 4,495
  • 4
  • 26
  • 34
ark
  • 23
  • 3
  • If the log server controls the database for the logs, then it should control the SQL language for it as well. If done right, the rest of the code shouldn't even care--let alone be aware--of the implementation behind your logger. Logging can have a huge impact on performance and because of your admitted inexperience, you must ask the rest of your team for assistance with this, and make sure that you use prepared statements to avoid SQL injection (look this up for your database of choice in C++ if you don't know what this means). – pickypg Sep 04 '12 at 04:08
  • Thanks for your replay. The log server controls the database for the log and it will execute the sql command. the problem is the choice between generate sql on Game server then send the sql string to log server or send log data to log server and generate sql with the data server? For the sql injection part, since the log module has no direct interaction with player, there is no need to worry about it. – ark Sep 04 '12 at 05:23
  • the problem is the choice between generate sql on Game server then send the sql string to log server or send log data to log server and generate sql with the data [server]-this word should be deleted,don't know how to edit it,so replay again. – ark Sep 04 '12 at 05:46

2 Answers2

2

If the log's SQL is generated by the Game Server, then there is almost no need for there to be any Log Server code as it becomes a passthru to the database manager piece, which the Game Server almost certainly already knows about (although I imagine they could potentially be different databases), or could easily interact with.

The Log Server should be a separate component that logs in whatever format is most convenient for you (performance, verbosity, size, etc), and as long as the API is flexible enough, it could be written such that the underlying implementation could be replaced without the Game Server knowing.

By coupling complete knowledge of the underlying implementation with the Game Server code, you not only prevent such a future undertaking, but you are also putting potentially a lot of work into the Game Server's code that could be done by a separate thread on the Log Server. Not to mention, by opening up the API to SQL, you are putting potential bugs all over the Game Server code that would otherwise be centralized.

The forward looking, replacement-driven approach is ideal when designing Object Oriented systems. If you can avoid coupling to anything except an API, then you can always replace whatever is beneath the API without effecting the outside code (ignoring bugs), but this demands thought being put into the API to ensure that it has enough flexibility for the future.

On that note, I strongly suggest that you implement the Logging API as a pure virtual interface, and then write an implementation on top of it that talks to the database, possibly with a separate implementation that logs to a text file (for convenient, local testing without a database accessible, if that's ever an issue) as well as a do-nothing implementation. With the first two in mind, it should help to guide you to a better design, and away from coupling.

This also might lead to some basic interface that your other classes implement (e.g., public: std::string to_log_string() const;), which can then be used by the Logger to bring in any implementing object and quickly convert it into a logged message.

All of this is to say, put the logging related SQL into the Log Server and not in the Game Server. The Game Server shouldn't care what the Log Server does beyond generically "logging."

pickypg
  • 22,034
  • 5
  • 72
  • 84
0

Do not generate SQL text on the game server. Don't do it on the log server either. SQL in hindsight should only have prepared statements. Generating queries at runtime is about as insane as generating indexes at runtime. So, leave the generation of the final SQL text to the database.

Therefore the API between the game server and the log server should only contain the variables you want logged, not the code to do so.

The fact that this utterly avoids SQL injection is a side benefit. But it still is a real benefit. If you'd log as much as a username, you must already consider SQL injection.

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • Thanks for your answer. Our project use mysqlpp and colleague filter character in input(e.g. username) like '%','=',etc. I've no idea how to do sql prepaired statements, could you give me some hint? – ark Sep 05 '12 at 05:59
  • Apparently, for mysqlpp they're called [template queries](http://tangentsoft.net/mysql++/doc/html/userman/tquery.html) – MSalters Sep 06 '12 at 08:13