게임 운영 Part 3: 플레이어 행동 로그¶
게임 서버에서 남기는 로그의 종류를 크게 다음 두 가지로 구분할 수 있습니다.
디버깅 로그: 서버 로직을 디버깅하기 위한 로그.
플레이어 행동 로그: 고객 지원을 위해 남기는 사용자 행동 로그.
디버깅 로그 는 특정 시점의 서버의 동작을 파악하기 위해 로그의 양이 많고 로그 형식이 정형화 되어 있지 않은 반면, 플레이어 행동 로그 는 로그 형식을 정형화해서 검색이나 통계를 뽑아낼 수 있도록 설계합니다.
아이펀 엔진에서는 디버깅 로그 와 플레이어 행동 로그 두가지를 모두 지원합니다.
이 챕터에서는 플레이어가 획득한 아이템 에 대한 로그를 남기는 예제를 통해서 플레이어 행동 로그 (이하 행동 로그) 를 남기는 방법에 대해서 설명합니다.
Tip
디버깅 로그 에 대해서는 프로그래밍 Part1: 디버그용 로그 을 참고하시기 바랍니다.
개요¶
게임마다 정의하고자 하는 플레이어의 행동이 다르기 때문에 아이펀 엔진은 서버 컴파일 과정에서 행동 로그 형식을 정의한 JSON 파일로부터 게임 서버 코드에서 사용할 수 있는 Logger 함수를 생성합니다.
여러분은 이렇게 생성된 Logger 함수를 이용해서 플레이어 행동 로그 를 남길 수 있습니다.
행동 로그 는 정형화된 로그를 잘 활용할 수 있도록 표준 입출력, 다른 logger 서비스, 파일 그리고, DB 처럼 다양한 위치로 출력 할 수 있습니다.
Warning
디버깅 로그 와는 용도가 다르기 때문에 기본적으로는 따로 출력되지만 설정을 통해서 통합 할 수도 있습니다.
자세한 내용은 다른 로깅 서비스로 출력 을 참고하시기 바랍니다.
행동 로그 형식 정의하기¶
아이펀 엔진 프로젝트를 생성하면 src
디렉터리에 {프로젝트명}_loggers.json
이라는 이름의 행동 로그를 정의하는 JSON 파일이 함께 생성되며, 이 파일에는
행동 로그 형식의 예시가 기본 정의되어 있습니다.
예를들어 my_project 라는 이름의 프로젝트를 생성했다면, 플레이어 행동로그를 정의하는 JSON 파일의 경로는 my_project-source/src/my_project_loggers.json 입니다.
새로운 행동 로그 를 정의하기 원하시면 다음과 같이 원하는 행동 로그를 정의할 수 있습니다.
{
"LogType1": {
"Argument1": "Type1"
},
"LogType2": {
"Argument1": "Type1",
"Argument2": "Type2"
}
}
그럼, 앞서 설명했던 것처럼 플레이어가 획득한 아이템 에 대한 로그를 추가 해 보겠습니다.
{
"SessionOpened": {
"session_id": "string",
"when": "datetime2"
},
"SessionClosed": {
"session_id": "string",
"when": "datetime2"
},
"PlayerLoggedIn": {
"session_id": "string",
"account_id": "string",
"when": "datetime2"
},
"PlayerItemAcquired": {
"player_name": "string",
"item_name": "string"
}
}
사용 가능한 인자의 데이터 타입¶
아래 표는 행동 로그 정의에서 사용할 수 있는 데이터 타입과 각 언어 별로 대응하는 기본 데이터 타입에 대해서 설명합니다.
Logger type |
Description |
C++ type |
C# type |
---|---|---|---|
bool |
참/거짓 |
bool |
bool |
double |
실수형 |
double |
double |
integer |
정수형 |
int64_t |
long |
string |
문자열 |
string & |
string |
datetime |
날짜 (time_t 형식) |
time_t |
System.DateTime |
datetime2 |
날짜 (WallClock::Value 형식) |
const WallClock::Value & |
System.DateTime |
Logger 함수 생성하기¶
행동 로그 형식 정의하기 의 내용과 같이 행동 로그 를 추가했다면, 컴파일 수행해서 C++ 과 C# 프로젝트 각각의 환경에 맞게 Logger 함수를 자동으로 생성합니다.
// file: my_project-source/src/my_project_loggers.h
namespace logger {
void SessionOpened(const string &session_id, const WallClock::Value &when);
void SessionClosed(const string &session_id, const WallClock::Value &when);
void PlayerLoggedIn(const string &session_id, const string &account_id, const WallClock::Value &when);
void PlayerItemAcquired(const string &player_name, const string &item_name);
} // namespace logger
// my_project-source/mono/ActivityLog/my_project_loggers.cs
class ActivityLog {
public void SessionOpened(string arg_session_id, System.DateTime arg_when);
public void SessionClosed(string arg_session_id, System.DateTime arg_when);
public void PlayerLoggedIn(string arg_session_id, string arg_account_id, System.DateTime arg_when);
public void PlayerItemAcquired(string arg_player_name, string arg_item_name);
}
이제, 서버 코드에서 플레이어가 아이템을 획득할 때마다 PlayerItemAcquired()
함수를 호출해서 로그를 남길 수 있습니다.
행동 로그 출력 위치¶
앞에서도 언급했듯이 아이펀 엔진은 행동 로그 를 여러가지 방법으로 확용할 수 있도록 다양한 출력 방법을 지원합니다.
행동 로그 를 출력하는 위치는 MANIFEST.json 에서 설정할 수 있습니다.
Logging -> activity_log_output 항목에 파일, DB 또는 Syslog 등 원하는 저장 위치를 설정하는 것으로 플레이어 행동 로그를 다양한 매체에 저장할 수 있습니다.
"Logging": {
"activity_log_output": "json://activity_log/test"
}
설정할 수 있는 종류는 다음과 같습니다.
표준 출력 장치로 출력¶
stdout: 표준 출력(Standard Out) 으로 행동 로그를 출력합니다.
stderr: 표준 에러(Standard Error) 으로 행동 로그를 출력합니다.
다음과 같은 형식로 화면에 출력되며, 기본적으로 행동 로그의 종류(PlayerItemAcquired) 와 로그가 출력된 시각(158…, Unix Time Stamp) 을 함께 출력합니다.
PlayerItemAcquired:1584604021: (player_name,item_name) = ("player1","super rare item")
다른 로깅 서비스로 출력¶
glog: 디버깅 로그 를 출력하는 glog 에 같이 섞여서 출력합니다.
표준 출력의 경우와 마찬가지로 행동 로그의 종류(PlayerItemAcquired) 와 로그가 출력된 시각(158…, Unix Time Stamp) 을 함께 출력합니다.
I0319 17:02:02.226044 18048 logging.cc:265] PlayerItemAcquired:1584604922: (player_name,item_name) = ("player1","super rare item")
syslog://procname: Linux 의 표준 메시지 로깅 서비스(syslog) 로 행동 로그를 출력합니다. (이 기능은 Linux 에서만 동작합니다)
아래에 보이는 것처럼 procname 태그를 붙이고, INFO 레벨로 출력합니다.
Mar 19 17:04:08 server-bionic procname[18647]: { "_type": "PlayerItemAcquired", "_ts": 1584605048, "_game": "ActLog", "_node": "", "player_name": "player1", "item_name": "super rare item"}
기본적으로 함께 출력되는 파라미터는 다음과 같습니다.
_type: 행동 로그 타입.
_ts: 행동 로그가 남겨신 시각. (Unix Time Stamp)
_game: 행동 로그를 출력한 서버의 이름입니다.
_node: 분산 서비스를 사용할 경우 RpcPeer 정보입니다.
파일로 출력¶
file://path/to/filename: 서버의 실행 파라미터 인자 중
log_root_dir
이 가리키는 위치에path/to/날짜
라는 디렉토리를 생성하고, 그 안에 filename.시간 형식의 파일에 아래와 같은 형식으로 행동 로그를 저장합니다.PlayerItemAcquired:1584607656: (player_name,item_name) = ("player1","super rare item")
json://path/to/filename: 위의
file
타입의 경우와 로그를 남기는 파일의 경로는 동일하지만, 아래와 같은 형식으로 행동 로그를 저장합니다.{"_type": "PlayerItemAcquired", "_ts": 1584614264, "_game": "ActLog", "_node": "10.10.2.115:8015", "player_name": "player1", "item_name": "super rare item"}
Note
log_root_dir
은 서버 컴파일 단계에서 서버의 실행 스크립트에 기본값이 정의되는데,
{프로젝트명}-local 파일과 {프로젝트명}-launcher 파일에서 다르게 정의합니다.
{프로젝트}-local: build 디렉터리 아래 logs 디렉터리.
{프로젝트}-launcher: /var/log/funapi/{{ project_name }} 디렉터리.
MongoDB 에 출력¶
먼저, 리눅스의 경우 행동 로그 를 MongoDB 에 저장하기 위해서는 아이펀 엔진에서 제공하는 libfunapi1-mongodblogger 패키지를 추가로 설치해야 합니다.
Note
윈도우즈의 경우 추가 설치 작업이 따로 필요 없습니다.
Ubuntu:
sudo apt-get install libfunapi1-mongodblogger
CentOS:
sudo yum install funapi1-mongodblogger
Important
2020년 2월을 기준으로 Activity logger 의 DB 저장 기능은 MongoDB v3.0 이상 v4.0 이하의 버전을 지원합니다.
만약, MongoDB 를 직접 설치해야 하는 경우, MongoDB 공식 매뉴얼의 CE 설치 매뉴얼(영문) 를 참고하시기 바랍니다.
mongodb://user:passwd@host:port/database: MongoDB 의 특정 database 에 로그를 생성합니다. user, password, port 등의 정보는 여러분의 환경에 맞는 설정을 입력하시면 됩니다.
예를 들어 매뉴얼의 테스트 환경에서는
mongodb://localhost:27017/my_activity_log
와 같이 설정했습니다.Replica set 지정등을 위한 보다 자세한 URI 형식에 대해서는 MongoDB 공식 매뉴얼의 접속 URI 형식(영문) 항목을 참고해주세요.
또한,
MANIFEST.json
에MongoDbBase
항목을 추가해야 합니다. 아래 예시를 참고하시기 바랍니다."Logging": { "activity_log_output": "mongodb://localhost:27017/activity_log", ... }, "MongoDbBase": { "mongodb_logger_enable_ssl": false }
Note
SSL/TLS 연결이 필요한 경우
mongodb_logger_enable_ssl
옵션을 true 로 변경해야 합니다.
MySQL 호환 DB 에 출력¶
mysql://user:passwd@host:port/database: MySQL 혹은 호환 DB 의 특정 database 에 로그를 생성합니다. user, password, port 등의 정보는 여러분의 환경에 맞는 설정을 입력하시면 됩니다.
예를 들어 매뉴얼의 테스트 환경에서는
mysql://localhost/my_activity_loggers
와 같이 설정했습니다."Logging": { "activity_log_output": "mysql://localhost/my_activity_loggers", ... },
Note
SQL 문의 예약어 (reserved keywords) 와의 충돌을 막기 위해서 activity log 내 사용자 지정 column 이름에는 col_
이 접두어(prefix)로 붙게 됩니다. 예를 들면 행동 로그 형식 정의하기 에서 when
이라는 것을 정의한 경우 이는 col_when
으로 변경됩니다.
Tip
MANIFST.json 에 activity_log_write_schema
를 true 로 설정하면 게임 서버가 뜰 때 해당 DB 나 table 이 존재하지 않을 때 자동으로 schema 를 생성합니다.
Schema 를 생성할 때는 같은 이름의 log table 이 존재할 경우 세부 column 내용이 같은지까지는 확인하지 않습니다. 따라서 activity log 정의가 바뀐 경우 기존의 DB 에 변경된 column 내용을 반영해주시지 않으면 실행 시간에 DB 에 데이터를 저장하는데 문제가 발생했다는 오류 메시지가 발생하게 됩니다.
Tip
MANIFST.json 에 export_activity_log_schema
를 true 로 설정하면 activity log 로 쓰게될 DB 의 schema 파일을 생성합니다. 생성되는 파일의 정확한 위치는 프로그램 실행 로그에 다음과 같이 남게 됩니다. 아래 예제는 /tmp/hello_schema
에 파일이 생성된 경우입니다.
I0410 11:08:46.773728 10640 logging.cc:774] The activity log db schema file has been generated: /tmp/hello_schema/hello_schema.20200410.activity_log.sql