게임 운영 Part 3: 플레이어 행동 로그

게임 서버에서 남기는 로그의 종류를 크게 다음 두 가지로 구분할 수 있습니다.

  1. 디버깅 로그: 서버 로직을 디버깅하기 위한 로그.

  2. 플레이어 행동 로그: 고객 지원을 위해 남기는 사용자 행동 로그.

디버깅 로그 는 특정 시점의 서버의 동작을 파악하기 위해 로그의 양이 많고 로그 형식이 정형화 되어 있지 않은 반면, 플레이어 행동 로그 는 로그 형식을 정형화해서 검색이나 통계를 뽑아낼 수 있도록 설계합니다.

아이펀 엔진에서는 디버깅 로그플레이어 행동 로그 두가지를 모두 지원합니다.

이 챕터에서는 플레이어가 획득한 아이템 에 대한 로그를 남기는 예제를 통해서 플레이어 행동 로그 (이하 행동 로그) 를 남기는 방법에 대해서 설명합니다.

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 loggerDB 저장 기능은 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.jsonMongoDbBase 항목을 추가해야 합니다. 아래 예시를 참고하시기 바랍니다.

    "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

행동 로그 설정 항목