로그인 로그
유저 가 로그인할 때 생성하는 로그입니다. 새롭게 출시한 게임에서나, 마케팅을 진행 중인 게임에 유입되는 유저의 현황을 확인할 수 있습니다.
카테고리¶
- Scribe 방식
| 상용 서버 | login_log | 
|---|---|
| 개발 서버 | test_login_log | 
- FTP 방식
| 파일명 규칙 | login_[날짜]_[서버]_[중복방지용id].json | 예. login_20180705_111500_GLOBAL-4.json | 
- fluentd 방식 (로그 정의 템플릿)
| 서버 (2대 로드밸런싱) | analytics-hivelog-03.withhive.com analytics-hivelog-04.withhive.com | |
|---|---|---|
| TAG명 규칙 | ha2union.game.[게임명약칭].login_log | 예. ha2union.game.samplegame.login_log | 
| category 필드 값 | [게임명약칭]_login_log | 예. {"category":"samplegame_login_log","aaa":1} | 
- http 방식 (로그 정의 템플릿)
| 서버 | https://analytics-log.withhive.com | |
|---|---|---|
| category 필드 값 | [게임명약칭]_login_log | 예. {"category":"samplegame_login_log","aaa":1} | 
로그 스펙¶
Note
스네이크 케이스(예: server_id) 형태의 필드는 최종 저장소(BigQuery)에 저장될 때 카멜 케이스(예: serverId) 형태로 변환되며, serverid 같은 스펙에 명시되지 않은 형태로 전송된 로그는 해당 컬럼에 저장되지 않습니다.
| 필드명 | 설명 | 타입 | 필수여부 | 
|---|---|---|---|
| date | 로그 발생 시각 형식: 년-월-일 시:분:초. 한국시간 (KST) 예. 2012-01-19 16:24:00 Scribe/FTP 전송 시 필수, Fluentd 전송 시 선택 | string | N | 
| dateTime | 로그 발생 시각 형식: 년-월-일 시:분:초. 한국시간 (KST) 예. 2012-01-19 16:24:00 | string | Y | 
| category | [게임 브랜드명]_[로그명] 게임 브랜드명은 app_id의 세 번째 항목 예. "derbyday_login_log" | string | Y | 
| timezone | 로그에 입력하는 시간 파라미터 값의 UTC offset 값 
 | string | Y | 
| channel | 로그인 채널 C2S: HIVE KAK: 카카오 LIN: 라인 WEI: 웨이보 GVL: 게임빌라이브 STE: 스팀 | string(3) | Y | 
| user_id | channel 필드로 설정된 채널에서 사용하는 유저 식별자 C2S: vid KAK: 앱 센터에서 발급하는 유저 식별자 LIN: 앱 센터에서 발급하는 유저 식별자 WEI: 웨이보 | bigint | Y | 
| app_id | HIVE에서 사용하는 AppID 예. 'com.com2us.derbyday.kakao.freefull.google.global.android.common' | string(200) | Y | 
| did | HIVE에서 사용하는 단말기 식별자(did) 값 (did가 변경될시에는 변경된 did로 보내줘야함) | bigint | Y | 
| level | 게임 내 유저 레벨 (캐릭터가 다수면 최고 레벨) | int | Y | 
| client_ip | 클라이언트의 IP, 이 값으로 GeoIP를 이용하여 country값 추출 | string(32) | Y | 
| server_ip | 서버의 IP | string(32) | N | 
| device_name | 유저의 단말기 모델명 예. iPhone, iPad, SM-G935, LGM-G600S | string(32) | Y | 
| company | 로그의 대상이 되는 게임 제작 회사 예. "C2S": 컴투스, "GVI": 컴투스홀딩스 | string(3) | Y | 
| server_id | 서버 구분 코드 서버코드표 참조하여 '서버 코드 (JSON 입력 코드)'를 입력 | string | Y | 
| server_uid | 게임 서버에서 발급하는 유저 식별자. | bigint | Y | 
| last_login_date | 이전 기준 마지막 로그인 일시 유저가 금일 가입한 신규 유저라면, 본 필드는 유저의 로그인 시간과 동일하게 설정 형식: yyyy-mm-dd hh 예. 2017-02-28 14:33:00 | string | 필수는 아니지만 권장 | 
| country | client_ip 를 못받아오는 경우 국가값을 직접 입력 HIVE 식별자 정책 참고 예. KR | string(2) | N | 
| os_version | OS의 버전 정보 예. 9.2.1 | string(10) | 필수는 아니지만 권장 | 
| game_language | 소문자 두 자로 구성된 게임 언어 HIVE 식별자 정책 참고 예. ko | varchar | 필수는 아니지만 권장 | 
| is_emulator | 블루스택 등 PC용 에뮬레이터로 접속했으면 1, 아니면 0 PC버전으로 접속 시 2 | int | 필수는 아니지만 권장 | 
| guid | 매 로그마다 발생하는 고유 키 값 uuid와 같은 랜덤 문자열 형태를 권장 | varchar(64) | N | 
로그 예제¶
{
"dateTime":"2021-10-11 11:27:15",
"category":"[게임명]_login_log",
"timezone":"UTC+09:00",
"channel":"HIVE",
"user_id":10053833008,
"app_id":"com.com2us.hivesdk.android.google.global.normal",
"did":5102491016,
"level":0,
"client_ip":"172.XX.XXX.XX",
"device_name":"TINNO U319AA",
"company":"C2S",
"server_id":"GLOBAL-2",
"server_uid":256489411,
"last_login_date":"2021-10-10 08:33:11",
"os_version":"11",
"is_emulator":0,
"game_language":"en"
}
수집 DB 테이블 스키마(reduced)¶
CREATE TABLE `LOGIN_LOG_20131031` (
    `log_id` BIGINT(20) NOT NULL AUTO_INCREMENT,
    `login_date` DATE NOT NULL,
    `last_login_date` DATETIME NULL,
    `app_id` VARCHAR(200) NOT NULL,
    `channel` VARCHAR(3) NOT NULL,
    `user_id` BIGINT(20) NOT NULL,
    `device_name` VARCHAR(128) NOT NULL DEFAULT 'unknown',
    `level` INT(11) NOT NULL,
    `country` CHAR(2) NULL DEFAULT NULL,
    `count` INT(11) NOT NULL,
    `add_date` DATETIME NOT NULL,
    `mod_date` DATETIME NOT NULL,
    `db_date` DATETIME NOT NULL,
    PRIMARY KEY (`log_id`),
    UNIQUE INDEX `ix_unique` (`login_date`, `app_id`, `channel`, `user_id`, `device_name`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
scribe 방식¶
<?php
$GLOBALS['THRIFT_ROOT'] = '/dev/scribe-php'; // 해당경로는 절대적인 것이 아님. 환경에 맞게 수정하기 바람.
include_once $GLOBALS['THRIFT_ROOT'].'/scribe.php';
include_once $GLOBALS['THRIFT_ROOT'].'/transport/TSocket.php';
include_once $GLOBALS['THRIFT_ROOT'].'/transport/TFramedTransport.php';
include_once $GLOBALS['THRIFT_ROOT'].'/protocol/TBinaryProtocol.php';
…
public function writeLoginLog($app_id, $channel, $user_id) // 함수또한 예제임. 각자에 맞게 수정요함.(단 category는 반드시 ‘login_log’로 맞춰야함.)
{
        $msg['category'] = 'login_log';
        $msg['message'] = array();
        $msg['message']['date'] = date('Y-m-d H:i:s', time());
        $msg['message']['last_login_date'] = date('Y-m-d H:i:s', time());
        $msg['message']['app_id'] = $app_id;
        $msg['message']['channel'] = $channel;
        $msg['message']['user_id'] = $user_id;
        $msg['message']['level'] = $level;
        $msg['message']['client_ip'] = $client_ip;
        $msg['message']['server_ip'] = $server_ip;
        $msg['message'] = json_encode($msg['message']);
        $entry = new LogEntry($msg);
        $messages = array($entry);
        //var_dump($messages);
        $socket = new TSocket('localhost', 1463, TRUE); // log를 전송할 목적지 host(포트고정)
        $transport = new TFramedTransport($socket);
        $protocol = new TBinaryProtocol($transport, FALSE, FALSE);
        $scribe_client = new scribeClient($protocol, $protocol);
        $transport->open();
        $scribe_client->Log($messages);
        $transport->close();  
}
?>
활용 예시¶
- 서버에 쌓이는 로그를 1시간마다 오픈 쿼리로 가지고 와서 실시간 유저 현황을 제공합니다.
- 신규 출시 게임, 마케팅을 집행한 게임 등 유저 유입 현황을 즉시 확인할 목적으로 활용합니다.
- HIVE 로그에서는 server_id(서버구분)를 알 수 없으므로 Login_log 테이블을 활용하여 보여줍니다.
- server_id = 1(한국)/2(일본)/3(중국)/4(글로벌)로 구분되며 게임마다 다릅니다.

