日志接入流程大致分为四个步骤:
1.客户端技术调用JSSDK提供的接口来获取ServiceCode;
2.服务端日志接入负责人根据日志接入流程文档,调用日志接口,完成几个基础日志的记录;
3.掌趣科技数据中心对服务端接入的日志进行格式和字段内容检查;
4.服务端日志接入开发负责人与掌趣技术人员通过日志接入测试用例后,日志接入工作正式完成。
功能说明
1.参考《H5游戏接入说明》中 “4.6 初始化回调接口 readyCallback” 章节,此章节中会有获取ServiceCode的方法。
2.游戏研发人员 获取ServiceCode后,联系 掌趣服务器端同学 联调服务端日志,获取ServiceCode接入工作正式完成。
服务端日志接口,用于采集诸如玩家注册、登录,玩家虚拟物品变更、属性变更,玩家游戏内的任务、关卡场景等用户行为,为产品运营,数据分析,推广营销等工作提供数据支持。
在调用日志接口时,需要为日志接口提供客户端配置信息,设备信息,用户信息,角色信息,日志内容等参数,最终组装成为一个json数组,作为http请求的content body发送到数据中心日志接口
Log对象属性如下
字段名 | 字段类型 | 字段样例 | 字段含义 |
---|---|---|---|
id | String | 10006 | 日志id |
serviceCode | String | 封装设备信息的字符串 | |
uid | String | 0100010000000000000000000000000090019780 | 用户中心UID |
clientIp | String | 1.202.218.162 | 游戏客户端ip地址 |
server | String | 1 | 逻辑服 |
roleId | String | 671092810 | 角色ID |
roleName | String | 马克.吐温 | 角色名 |
roleLevel | String | 10 | 角色等级 |
roleVipLevel | String | 1 | 角色VIP等级 |
customId | String | lz_rolelogin | 自定义日志id(如果该日志不是自定义日志,则该字段为空) |
roleSpecAttr | Map | 用于封装角色特殊属性的一个Map | |
logInfo | Map | 用于封装具体日志信息的一个Map | |
createLogTime | long | 记录游戏日志生成的时间戳,因为游戏采用异步进程的方式发送日志,日志发送的时间,不一定为日志生成的时间,所以要记录日志生成的时间 |
编码:当传入中文字符串时,务必确保该中文字符串使用的是utf8编码。例如,商品名称。
配置一致性:有的产品人员和开发人员自行设定的字段信息,也必须由相应的负责人确保内容的一致性。 例如同一个逻辑服下,如果在用户登录注册时调用日志接口传递的逻辑服标识是1001,那么在调用计费中心的充值计费接口时逻辑服标识也应该是同样的1001,而不应该是其他的值。
ID一致性:同样的,如果A用户在购买一个极品武器时记录的物品id是001weapon,那么另外一个用户在拍卖同样一个极品武器时物品id也应该是001weapon。
接入日志类型的要求:目前UC平台的游戏都需要接入10006注册日志、10007登录日志和10010角色变更日志,其它的日志类型请根据游戏各自需要接入。
需要导入的jar包:lib中的第三方jar包请根据项目需要导入。
插件运行日志:如果需要运行日志,通过调用PalmLogSender.startRunLog(“/opt/ourpalm/log”);来开启调试模式,传入参数即为生成运行日志的目录。
使用PalmLogSender.sendLog(log)接口仍然能发送单个日志,使用日志接入详解的方式进行单个日志的组装即可。
通常情况下,使用我们提供的prism-client.jar就足够完成日志发送工作,如果研发人员认为有必要自行实现日志发送功能,请先与我们取得联系,避免沟通不到位引发接入过程中的各种问题。
掌趣平台会对游戏服的IP进行鉴权,请游戏提供游戏服的IP添加至日志接收服的IP白名单,未添加白名单会导致服务端日志发送不成功。
为了便于研发人员接入服务端日志接口,我们把所有用到的类声明都放到了logsender.h这个头文件中,只需要#include 这一个文件即可,这个文件的命名空间为OurpalmLog
通常情况下,使用我们提供的OurpalmLog::{Log,LogRolePropUpdate,PalmLogSender}类就足够完成日志发送工作,如果研发人员认为有必要自行实现日志发送功能,请先与我们取得联系,避免沟通不到位引发接入过程中的各种问题。
下面给出示例:
#include "logsender.h"
using namespace std;
using OurpalmLog::Log;
using OurpalmLog::LogRolePropUpdate;
using OurpalmLog::PalmLogSender;
在logsender.h同目录下的config.ini文件里有一些配置项需要研发人员根据实际情况手动修改,一般不许变动此文件的配置信息,我们将配置项对应的意义列举如下
属性名 | 属性值说明 |
---|---|
log.sendurl | 日志发送地址 示例: 大陆节点 http://bicenter.gamebean.net/bicenter/prismClient/sendLogV1.do 香港节点 http://bicenterhk.gamesbean.net/bicenter/prismClient/sendLogV1.do 韩国节点 http://bicenter.fingertips.kr/bicenter/prismClient/sendLogV1.do 欧美节点 http://bicenter-us.gamesbean.net/bicenter/prismClient/sendLogV1.do |
log.errorlogpath | 发送失败的日志保存目录,请确保这个目录有写入权限 示例:/opt/ourpalm/logs/prismClient/fail |
log.size | 单次批量发送日志的最大数量 示例:log.size=300 |
目前日志接口支持以下日志的接入
日志ID | 日志名 | GSC平台日志名称 |
---|---|---|
10006 | 服务端玩家注册日志 | 玩家注册 |
10007 | 服务端玩家登录日志 | 玩家登录 |
10071 | 服务端玩家登出日志 | 玩家登出 |
10008 | 服务端玩家充值日志(仅接入统计SDK时需要) | —— |
10091 | 服务端玩家货币变更日志 | 货币变更 |
10009 | 服务端玩家物品变更日志 | 物品变更 |
10010 | 服务端玩家属性变更日志 | 玩家属性变更 |
10013 | 服务端玩家商品属性变更日志 | 商品属性变更 |
10014 | 服务端玩家卡牌属性变更日志 | 卡牌属性变更 |
11000 | 服务端完全自定义日志 | —— |
11101 | 服务端玩家任务日志 | 游戏任务 |
11102 | 服务端玩家副本关卡场景日志 | 游戏关卡 |
11103 | 服务端玩家其他事件日志 | 其他事件 |
12001 | 服务端玩家自定义交互日志 | 交互日志 |
当玩家注册一个游戏内的新角色时,记录一条角色注册日志,角色注册日志没有特别要传入的日志字段,只需填入用户id和角色基本信息即可。
日志格式示例:
try{
string serviceCode = “从SDKAPI中获取的serviceCode”;
std::map<string, string> map;
Log log;
log.setId("10006");
log.putServer("1");
log.putRoleId("11111111");
log.putRoleName("马克.吐温");
log.putRoleLevel("1");
log.putRoleVipLevel("0");
log.setServiceCode(serviceCode);
log.putUserId("0100010000000000000000000000000090019780");
log.setClientIp("111.111.111.111");
log.setCreateLogTime(time(NULL) * 1000);
log.setLogInfo(map);
vector<Log> logArr;
logArr.push_back(log);
PalmLogSender::sendLogList(logArr);
} catch(exception &e) {
cout << "catch exception:" << e.what() << endl;
}
}
该记录表示玩家马克吐温已经在逻辑服1注册完成了
当玩家的角色登录游戏时,记录一条角色登录日志,角色登录日志没有特别要传入的日志字段,只需填入用户id和角色基本信息即可。
日志格式示例:
try{
string serviceCode = “从SDKAPI中获取的serviceCode”;
std::map<string, string> map;
Log log;
log.setId("10007");
log.putServer("1");
log.putRoleId("11111111");
log.putRoleName("马克.吐温");
log.putRoleLevel("1");
log.putRoleVipLevel("0");
log.setServiceCode(serviceCode);
log.putUserId("0100010000000000000000000000000090019780");
log.setClientIp("111.111.111.111");
log.setCreateLogTime(time(NULL) * 1000);
log.setLogInfo(map);
vector<Log> logArr;
logArr.push_back(log);
PalmLogSender::sendLogList(logArr);
}catch(exception &e){
cout << "catch exception:" << e.what() << endl;
}
}
该记录表示玩家马克吐温已经登录逻辑服1了
当玩家的角色登出游戏时,记录一条角色登出日志,角色登出日志没有特别要传入的日志字段,只需填入用户id和角色基本信息即可。
日志格式示例:
try{
string serviceCode = “从SDKAPI中获取的serviceCode”;
std::map<string, string> map;
Log log;
log.setId("10071");
log.putServer("1");
log.putRoleId("11111111");
log.putRoleName("马克.吐温");
log.putRoleLevel("1");
log.putRoleVipLevel("0");
log.setServiceCode(serviceCode);
log.putUserId("0100010000000000000000000000000090019780");
log.setClientIp("111.111.111.111");
log.setCreateLogTime(time(NULL) * 1000);
log.setLogInfo(map);
vector<Log> logArr;
logArr.push_back(log);
PalmLogSender::sendLogList(logArr);
}catch(exception &e){
cout << "catch exception:" << e.what() << endl;
}
}
该记录表示玩家马克吐温已经登出逻辑服1了
这个日志是为只接入了统计SDK的游戏准备的,没有使用掌趣的计费中心但又希望能够看到常规的收入统计报表数据。接入的时候请严格按照下面的示例来接入,尤其是货币类型和支付金额,货币类型可以参考附录的对应关系,支付金额需要按照货币类型的最小货币单位传入,比如 人民币的最小单位是 分,泰铢的最小单位是 萨当
LogId | 日志名称 | LogKey |
---|---|---|
10008 | 玩家充值日志 | server-role-credit |
字段名 | 字段类型 | 字段说明 | 备注 |
---|---|---|---|
payChannelId | String | 支付方式 | 只能填写英文和数字,非必需 |
orderNo | String | 订单号 | 必需 |
currencyType | String | 货币类型 | (参照附2.1货币规范)必需 |
currencyAmount | Integer | 订单金额 | 单位:对应货币类型的最小货币单位,必需 |
itemId | String | 商品ID | 游戏中商品或者道具ID,必需 |
itemName | String | 商品名称 | 便于运营人员识别商品,一般传入中文,必需 |
itemCount | Integer | 商品个数 | 必需 |
日志格式示例:
try{
string serviceCode = “从SDKAPI中获取的serviceCode”;
std::map<string, string> map;
map.insert(pair<string, string>("payChannelId", "3100052033100012"));
map.insert(pair<string, string>("orderNo", "0012014090110143611500"));
map.insert(pair<string, string>("currencyType", "1"));
map.insert(pair<string, string>("currencyAmount", "100"));
map.insert(pair<string, string>("itemId", "diamond"));
map.insert(pair<string, string>("itemName", "钻石"));
map.insert(pair<string, string>("itemCount", "100"));
Log log;
log.setId("10008");
log.putServer("1");
log.putRoleId("11111111");
log.putRoleName("马克.吐温");
log.putRoleLevel("1");
log.putRoleVipLevel("0");
log.setServiceCode(serviceCode);
log.putUserId("0100010000000000000000000000000090019780");
log.setClientIp("111.111.111.111");
log.setCreateLogTime(time(NULL) * 1000);
log.setLogInfo(map);
vector<Log> logArr;
logArr.push_back(log);
PalmLogSender::sendLogList(logArr);
} catch(exception &e) {
cout << "catch exception:" << e.what() << endl;
}
该记录表示当前登录的角色马克.吐温充值100分人民币购买游戏内100钻石
当用户在游戏内,因为种种原因产生虚拟货币的增加和消耗时,需要记录一条对应的虚拟货币变更日志。如果玩家的一次用户行为导致多种虚拟货币变更,比如完成一次充值同时获得1000钻石20000铜币,则需要记录相应的两条虚拟货币变更日志。
LogId | 日志名称 | LogKey |
---|---|---|
10091 | 玩家虚拟货币变更日志 | role-income-update |
字段名 | 字段类型 | 字段说明 | 备注 |
---|---|---|---|
updateType | String | 变更类型 | 1:新增 0:消耗 |
itemId | String | 货币ID | |
itemName | String | 货币名称 | 便于运营人员识别商品,一般传入中文 |
isPrecious | String | 是否为珍贵物品 | 1:是 0:否 |
itemCount | Integer | 货币个数 | 必须是一个大于0的整数 |
remains | Integer | 变化后货币数量 | 必须是一个大于等于0的整数 |
custom | String | 变更描述 | 描述变更的原因或途径 |
变更类型:用于标识本次变更是新增了虚拟货币还是消耗了虚拟货币,新增记录1,消耗记录0。
货币ID:用于记录本次引发虚拟货币变更的货币ID。
货币名称:用于记录本次引发虚拟货币变更的货币名称。
是否为珍贵物品:用于区分珍贵物品,一般情况下直接充值获得的即为珍贵物品,例如 钻石和铜币, 钻石可视为珍贵物品,铜币可视为非珍贵物品。
货币个数:用于记录用户本次消费行为涉及多少个货币,如果用户本次消费行为与具体货币无关,则该字段置空即可。
变化后货币数量:用于记录用户本次消费完成后用户总的货币剩余量
变更描述:用于标识用户因为什么原因或途径变更虚拟货币。
日志格式示例:
try{
string serviceCode = “从SDKAPI中获取的serviceCode”;
std::map<string, string> map;
map.insert(pair<string, string>("updateType", "0"));
map.insert(pair<string, string>("itemId", "diamond"));
map.insert(pair<string, string>("itemName", "钻石"));
map.insert(pair<string, string>("isPrecious", "1"));
map.insert(pair<string, string>("itemCount", "100"));
map.insert(pair<string, string>("remains", "200"));
map.insert(pair<string, string>("custom", "购买道具"));
Log log;
log.setId("10091");
log.putServer("1");
log.putRoleId("11111111");
log.putRoleName("马克.吐温");
log.putRoleLevel("1");
log.putRoleVipLevel("0");
log.setServiceCode(serviceCode);
log.putUserId("0100010000000000000000000000000090019780");
log.setClientIp("111.111.111.111");
log.setCreateLogTime(time(NULL) * 1000);
log.setLogInfo(map);
vector<Log> logArr;
logArr.push_back(log);
PalmLogSender::sendLogList(logArr);
} catch(exception &e) {
cout << "catch exception:" << e.what() << endl;
}
上面日志表示当前登录的角色为了购买道具花费了100钻石,剩余钻石200。
当用户在游戏内,因为种种原因产生虚拟物品的增加和消耗时,需要记录一条对应的虚拟物品变更日志。如果玩家的一次用户行为导致多种虚拟物品变更,比如完成一次史诗副本同时获得1000珍珠20000石币,则需要记录相应的两条虚拟物品变更日志。
LogId | 日志名称 | LogKey |
---|---|---|
10009 | 玩家虚拟物品变更日志 | role-item-update |
字段名 | 字段类型 | 字段说明 | 备注 |
---|---|---|---|
updateType | String | 变更类型 | 1:新增 0:消耗 |
itemId | String | 商品ID | |
itemName | String | 商品名称 | 便于运营人员识别商品,一般传入中文 |
itemCount | Integer | 商品个数 | 必须是一个大于0的整数 |
remains | Integer | 商品剩余个数 | 必须是一个大于等于0的整数 |
custom | String | 变更描述 | 描述变更的原因或途径 |
变更类型:用于标识本次变更是新增了虚拟物品还是消耗了虚拟物品,新增记录1,消耗记录0。
商品ID:用于记录用户本次是因为哪一个游戏内的商品引发的虚拟物品变更,例如购买游戏内的装备、经验、头衔、坐骑等。商品名称由游戏策划人员自行定义,比如 0001对应装备图纸,0002对应黄金翅膀,0003对应经验丹,0004对应体力等等。传入0001,0002,0003……这些ID即可
商品名称:用于记录用户本次是因为哪一个游戏内的商品引发的虚拟物品变更,例如购买游戏内的装备、经验、头衔、坐骑等。商品名称由游戏策划人员自行定义,比如 0001装备图纸,0002黄金翅膀,0003经验丹,0004体力等等。统计结果也会直接将日志中的商品名称展示出来,如果用户本次变更行为与具体商品道具无关,则该字段置空即可。
商品个数:用于记录用户本次消费行为涉及多少个商品,如果用户本次消费行为与具体商品无关,则该字段置空即可。
商品剩余个数:用于记录本次商品获得或者消耗后,当前剩余的个数。
变更描述:用于标识用户因为什么原因或途径变更虚拟物品(虚拟货币),如任务获得,怪物掉落,系统赠送,副本奖励,世界喊话,家族奉献,婚姻喜宴等等。
日志格式示例:
try{
string serviceCode = “从SDKAPI中获取的serviceCode”;
std::map<string, string> map;
map.insert(pair<string, string>("updateType", "1"));
map.insert(pair<string, string>("itemId", "hammer"));
map.insert(pair<string, string>("itemName", "铁锤"));
map.insert(pair<string, string>("itemCount", "1"));
map.insert(pair<string, string>("remains", "2"));
map.insert(pair<string, string>("custom", "购买道具"));
Log log;
log.setId("10009");
log.putServer("1");
log.putRoleId("11111111");
log.putRoleName("马克.吐温");
log.putRoleLevel("1");
log.putRoleVipLevel("0");
log.setServiceCode(serviceCode);
log.putUserId("0100010000000000000000000000000090019780");
log.setClientIp("111.111.111.111");
log.setCreateLogTime(time(NULL) * 1000);
log.setLogInfo(map);
vector<Log> logArr;
logArr.push_back(log);
PalmLogSender::sendLogList(logArr);
} catch(exception &e) {
cout << "catch exception:" << e.what() << endl;
}
上面两条日志表示当前登录的角色马克.吐温为了购买id为玛格汉铁锤的武器花了100钻石,剩余255钻石,拥有了2把玛格汉铁锤。
当用户的角色,发生一些属性上的变化时,记录相应的角色属性变更日志。例如等级提升,军衔提升,VIP等级提升,属性点重配,种族天赋变更等等。
LogId | 日志名称 | LogKey |
---|---|---|
10010 | 玩家属性变更日志 | role-prop-update |
字段名 | 字段类型 | 字段说明 | 备注 |
---|---|---|---|
propKey | String | 属性标识 | |
propValue | String | 新属性值 | |
rangeability | String | 变更值 | |
custom | String | 变更描述 | 描述变更的原因或途径 |
属性标识:角色变更了哪种属性,其中等级标识为level,VIP等级标识为vipLevel,其余属性标识由游戏产品和开发人员自行设定。请注意标识大小写。
新属性值:角色完成属性变更之后,该属性的值变成了什么。
变更值:如果该属性值是一个数字,比如等级level,那么本次用户的等级变更了多少,例如购买大礼包level连升三级,则变更值为3。
变更描述:用于记录属性变化的原因或途径
日志格式示例:
try{
string serviceCode = “从SDKAPI中获取的serviceCode”;
std::map<string, string> map;
map.insert(pair<string, string>("propKey", "level"));
map.insert(pair<string, string>("propValue", "1"));
map.insert(pair<string, string>("rangeability", "1"));
map.insert(pair<string, string>("custom", "奖励升级"));
Log log;
log.setId("10010");
log.putServer("1");
log.putRoleId("11111111");
log.putRoleName("马克.吐温");
log.putRoleLevel("1");
log.putRoleVipLevel("0");
log.setServiceCode(serviceCode);
log.putUserId("0100010000000000000000000000000090019780");
log.setClientIp("111.111.111.111");
log.setCreateLogTime(time(NULL) * 1000);
log.setLogInfo(map);
vector<Log> logArr;
logArr.push_back(log);
PalmLogSender::sendLogList(logArr);
} catch(exception &e) {
cout << "catch exception:" << e.what() << endl;
}
这两条日志表示当前角色马克.吐温连升了两级,目前等级为3。他的vip等级升了一级,目前vip等级为1。
当用户的角色,发生一些属性上的变化时,记录相应的角色属性变更日志。例如等级提升,军衔提升,VIP等级提升,属性点重配,种族天赋变更等等。
为了满足同一个玩家同时有多个属性变化的游戏场景,我们提供第二种玩家属性变更日志的接入方式,同时传入玩家变更前和变更后的属性Map,由数据中心判断玩家有哪些属性发生了变化
LogId | 日志名称 | LogKey |
---|---|---|
10010 | 玩家属性变更日志 | role-prop-update |
字段名 | 字段类型 | 字段说明 | 备注 |
---|---|---|---|
propMapOld | Map | 旧属性集合 | |
propMapNew | Map | 新属性集合 |
旧属性集合:玩家的角色在变更之前有哪些属性值,用Map
新属性集合:玩家的角色在变更之前有哪些属性值,用Map
注意,只有数值类型的属性,才应该通过这个方法来发送属性变更日志,如果是一些文本类型的属性,比如玩家更改了角色名称,服务器id,种族天赋类型等,则不应该使用这个方法来保存
日志格式示例:
try{
string serviceCode = “从SDKAPI中获取的serviceCode”;
std::map<string, string> propMapOld;
propMapOld.insert(pair<string, string>("level", "3"));
propMapOld.insert(pair<string, string>("vipLevel", "1"));
propMapOld.insert(pair<string, string>("hp", "1000"));
propMapOld.insert(pair<string, string>("mp", "1000"));
std::map<string, string> propMapNew;
propMapNew.insert(pair<string, string>("level", "4"));
propMapNew.insert(pair<string, string>("vipLevel", "1"));
propMapNew.insert(pair<string, string>("hp", "1500"));
propMapNew.insert(pair<string, string>("mp", "1500"));
LogRolePropUpdate log;
log.setId("10010");
log.putServer("1");
log.putRoleId("11111111");
log.putRoleName("马克.吐温");
log.putRoleLevel("1");
log.putRoleVipLevel("0");
log.setServiceCode(serviceCode);
log.putUserId("0100010000000000000000000000000090019780");
log.setClientIp("112.23.22.22");
log.setCreateLogTime(time(NULL) * 1000);
log.setPropMapOld(propMapOld);
log.setPropMapNew(propMapNew);
vector<LogRolePropUpdate> logArr;
logArr.push_back(log);
string logjson = PalmLogSender::constructLogJson(logArr);
//获取到logjson后再调用amqp协议api发送日志
} catch(exception &e) {
cout << "catch exception:" << e.what() << endl;
}
这条日志表示当前角色马克.吐温等级升了1级,目前等级为4。他的hp从1000增加到了1500,mp也从1000增加到了1500。三个属性发生了变化,vip等级不变
某些游戏的游戏内商品也有各种属性,比如射击类有戏的枪械会因为改装增加各种新功能,赛车游戏的赛车可以更改引擎、喷漆、轮胎,rpg游戏的玩家会饲养和升级宠物,升级随从的等级和装备等等,因此我们提供了一个游戏内商品属性变更日志,用于记录游戏内各种物品,道具,宠物,随从,武器的等级、技能等属性变更情况。
LogId | 日志名称 | LogKey |
---|---|---|
10013 | 玩家商品属性变更日志 | role-item-prop-update |
字段名 | 字段类型 | 字段说明 | 备注 |
---|---|---|---|
itemId | String | 商品ID | 必需 |
itemName | String | 商品名称 | 便于运营人员识别商品,一般传入中文,必需 |
propKey | String | 属性标识 | 必需 |
propValue | String | 新属性值 | 必需 |
rangeability | String | 变更值 | 必需 |
custom | String | 变更描述 | 描述变更的原因或途径 |
玩家商品属性变更日志的格式与玩家属性变更日志的区别在于,商品属性变更日志中多了两个用于描述商品的itemId和itemName字段。
日志格式示例:
try{
string serviceCode = “从SDKAPI中获取的serviceCode”;
std::map<string, string> map;
map.insert(pair<string, string>("itemId", "MGH_Weapon_001"));
map.insert(pair<string, string>("itemName", "玛格汉铁锤"));
map.insert(pair<string, string>("propKey", "level"));
map.insert(pair<string, string>("propValue", "2"));
map.insert(pair<string, string>("rangeability", "1"));
map.insert(pair<string, string>("custom", "强化装备"));
Log log;
log.setId("10013");
log.putServer("1");
log.putRoleId("11111111");
log.putRoleName("马克.吐温");
log.putRoleLevel("1");
log.putRoleVipLevel("0");
log.setServiceCode(serviceCode);
log.putUserId("0100010000000000000000000000000090019780");
log.setClientIp("111.111.111.111");
log.setCreateLogTime(time(NULL) * 1000);
log.setLogInfo(map);
vector<Log> logArr;
logArr.push_back(log);
PalmLogSender::sendLogList(logArr);
} catch(exception &e) {
cout << "catch exception:" << e.what() << endl;
}
该条日志记录,玩家的玛格汉铁锤等级提升1级,现在的等级为2级
对于卡牌类游戏而言,卡牌的收集和升级一直是游戏重点,比如卡牌的稀有程度,等级变化,技能等级等等,因此我们提供了一个游戏内卡牌属性变更日志,用于记录游戏内对应英雄、侠客、随扈等等卡牌的属性变更情况。
LogId | 日志名称 | LogKey |
---|---|---|
10014 | 玩家卡牌属性变更日志 | role-card-prop-update |
字段名 | 字段类型 | 字段说明 | 备注 |
---|---|---|---|
cardId | String | 卡牌ID | 必需 |
cardName | String | 卡牌名称 | 便于运营人员识别商品,一般传入中文,必需 |
propKey | String | 属性标识 | 必需 |
newValue | String | 新属性值 | 必需 |
oldValue | String | 旧属性值 | 必需 |
custom | String | 变更描述 | 描述变更的原因或途径 |
玩家卡牌属性变更日志的格式与玩家商品属性变更日志的区别在于,商品属性变更日志中记录的是游戏内商品道具的属性变更,比如武器装备升级之类,而卡牌属性变更则适用于卡牌类游戏。
日志格式示例:
try{
string serviceCode = “从SDKAPI中获取的serviceCode”;
std::map<string, string> map;
map.insert(pair<string, string>("cardId", "blr_man_001"));
map.insert(pair<string, string>("cardName", "李星云"));
map.insert(pair<string, string>("propKey", "level"));
map.insert(pair<string, string>("newValue", "蓝+1"));
map.insert(pair<string, string>("oldValue", "绿"));
map.insert(pair<string, string>("custom", "强化装备"));
Log log;
log.setId("10014");
log.putServer("1");
log.putRoleId("11111111");
log.putRoleName("马克.吐温");
log.putRoleLevel("1");
log.putRoleVipLevel("0");
log.setServiceCode(serviceCode);
log.putUserId("0100010000000000000000000000000090019780");
log.setClientIp("111.111.111.111");
log.setCreateLogTime(time(NULL) * 1000);
log.setLogInfo(map);
vector<Log> logArr;
logArr.push_back(log);
PalmLogSender::sendLogList(logArr);
} catch(exception &e) {
cout << "catch exception:" << e.what() << endl;
}
该条日志记录,玩家的侠客——李星云,进阶从绿变成了蓝+1。
当运营人员需要对游戏内的任务完成情况,关卡完成情况进行记录时,即可记录一条游戏自定义事件。在记录日志之前,游戏运营人员有必要向掌趣科技统计后台提供一份任务,关卡,以及其他自定义事件的id和名称对照表,并在掌趣科技统计后台描述任务,关卡,道具之间的关系。
任务,副本关卡日志的格式均为stageId,stageName,detail三个字段,三个字段的值完全由游戏研发人员和运营人员自行指定,例如新手引导任务可以用 newbieguide标识stageId,也可以用task001或其他字符串标识来表示stageId,任务完成,既可以用 SUCC表示,也可以用complete表示,还可以根据任务的中断,放弃,失败等多种状况,为同一个任务记录多条日志。对于同一种事件结果,建议使用同样的detail内容来描述。尽量做到同一个detail的含义一致,同一个事件结果的detail一致。
需要注意的地方:
无论是任务,关卡还是其他自定义事件日志,taskId/stageId/actId字段都必须是相对于该日志的logId唯一,不能够与其他任务,关卡或道具的id字段重复。
尽管任务,副本/场景,以及游戏自定义事件三个日志的字段数量和格式相同,但是我们希望研发人员能够按照预设的不同logid和logkey分别记录这三类日志,这样一来,便于将相对重要的日志同其它日志区分出来,也便于我们对任务和场景副本日志采用预设的特定算法来进行统计运算。
我们要求用以下的默认字段来记录事件日志的detail,以便统计后台可以用默认的配置来对游戏自定义事件进行计算成功率,通过率等进一步指标。
如果列表中的detail无法满足游戏的日志记录要求,也允许各个游戏使用自己定义的detail来记录日志。
LogId | 日志名称 | key |
---|---|---|
11101 | 任务 | role-task |
字段名 | 字段类型 | 字段说明 |
---|---|---|
taskId | String | 任务编码,英文或数字 |
taskName | String | 人物名称,最好传中文 |
detail | String | 相关信息,全为英文 |
其中detail字段建议取值如下所示:
detail | 含义 |
---|---|
accept | 接任务 |
fail | 任务失败 |
cancel | 放弃任务 |
succ | 达成任务条件 |
complete | 任务完成 |
日志格式示例:
try{
string serviceCode = “从SDKAPI中获取的serviceCode”;
std::map<string, string> map1;
map1.insert(pair<string, string>("taskId", "guide1"));
map1.insert(pair<string, string>("taskName", "引导流程1"));
map1.insert(pair<string, string>("detail", "accept"));
std::map<string, string> map2;
map2.insert(pair<string, string>("taskId", "guide1"));
map2.insert(pair<string, string>("taskName", "引导流程"));
map2.insert(pair<string, string>("detail", "complete"));
Log log;
log.setId("11101");
log.putServer("1");
log.putRoleId("11111111");
log.putRoleName("马克.吐温");
log.putRoleLevel("1");
log.putRoleVipLevel("0");
log.setServiceCode(serviceCode);
log.putUserId("0100010000000000000000000000000090019780");
log.setClientIp("112.23.22.22");
log.setCreateLogTime(time(NULL) * 1000);
log.setLogInfo(map1);
Log log2;
log2.setId("11101");
log2.putServer("1");
log2.putRoleId("11111111");
log2.putRoleName("马克.吐温");
log2.putRoleLevel("1");
log2.putRoleVipLevel("0");
log2.setServiceCode(serviceCode);
log2.putUserId("0100010000000000000000000000000090019780");
log2.setClientIp("112.23.22.22");
log2.setCreateLogTime(time(NULL) * 1000);
log2.setLogInfo(map2);
vector<Log> logArr;
logArr.push_back(log);
logArr.push_back(log2);
PalmLogSender::sendLogList(logArr);
} catch(exception &e) {
cout << "catch exception:" << e.what() << endl;
}
这两条日志表示,当前角色马克.吐温接受并且完成了新手流程任务1.
LogId | 日志名称 | key |
---|---|---|
11102 | 副本场景日志 | role-stage |
字段名 | 字段类型 | 字段说明 |
---|---|---|
stageId | String | 副本场景标识,英文或数字 |
stageName | String | 副本场景名称,最好传中文 |
detail | String | 相关信息,全为英文 |
其中detail字段建议取值如下所示:
detail | 含义 |
---|---|
begin | 场景开始 |
fail | 场景失败 |
cancel | 场景取消 |
end | 场景结束 |
日志格式示例:
try{
string serviceCode = “从SDKAPI中获取的serviceCode”;
std::map<string, string> map1;
map1.insert(pair<string, string>("stageId", "deadMine"));
map1.insert(pair<string, string>("stageName", "副本-死亡矿井"));
map1.insert(pair<string, string>("detail", "begin"));
std::map<string, string> map2;
map2.insert(pair<string, string>("stageId", "deadMine"));
map2.insert(pair<string, string>("stageName", "副本-死亡矿井"));
map2.insert(pair<string, string>("detail", "end"));
Log log;
log.setId("11102");
log.putServer("1");
log.putRoleId("11111111");
log.putRoleName("马克.吐温");
log.putRoleLevel("1");
log.putRoleVipLevel("0");
log.setServiceCode(serviceCode);
log.putUserId("0100010000000000000000000000000090019780");
log.setClientIp("112.23.22.22");
log.setCreateLogTime(time(NULL) * 1000);
log.setLogInfo(map1);
Log log2;
log2.setId("11102");
log2.putServer("1");
log2.putRoleId("11111111");
log2.putRoleName("马克.吐温");
log2.putRoleLevel("1");
log2.putRoleVipLevel("0");
log2.setServiceCode(serviceCode);
log2.putUserId("0100010000000000000000000000000090019780");
log2.setClientIp("112.23.22.22");
log2.setCreateLogTime(time(NULL) * 1000);
log2.setLogInfo(map2);
vector<Log> logArr;
logArr.push_back(log);
logArr.push_back(log2);
PalmLogSender::sendLogList(logArr);
} catch(exception &e) {
cout << "catch exception:" << e.what() << endl;
}
这两条日志表示,当前角色开始并且完成了场景死亡矿井副本.
LogId | 日志名称 | key |
---|---|---|
11103 | 玩家其他事件 | role-act |
字段名 | 字段类型 | 字段说明 |
---|---|---|
actId | String | 事件标识,英文或数字 |
actName | String | 事件名称,最好传中文 |
detail | String | 相关信息,全为英文 |
日志格式示例:
try{
string serviceCode = “从SDKAPI中获取的serviceCode”;
std::map<string, string> map;
map.insert(pair<string, string>("actId", "fight-0001"));
map.insert(pair<string, string>("actName", "进入战斗-克尔苏加德"));
map.insert(pair<string, string>("detail", "begin"));
Log log;
log.setId("11103");
log.putServer("1");
log.putRoleId("11111111");
log.putRoleName("马克.吐温");
log.putRoleLevel("1");
log.putRoleVipLevel("0");
log.setServiceCode(serviceCode);
log.putUserId("0100010000000000000000000000000090019780");
log.setClientIp("111.111.111.111");
log.setCreateLogTime(time(NULL) * 1000);
log.setLogInfo(map);
vector<Log> logArr;
logArr.push_back(log);
PalmLogSender::sendLogList(logArr);
} catch(exception &e) {
cout << "catch exception:" << e.what() << endl;
}
这条日志表示,当前角色开始了一场战斗
游戏中除了角色与系统间发生的事件之外,还会有玩家之间的交互事件,这类事件使用交互事件日志来记录。
LogId | 日志名称 | LogKey |
---|---|---|
12001 | 交互行为日志 | role-interact |
字段名 | 字段类型 | 字段说明 |
---|---|---|
interactId | String | 自定义事件编码,数字或字母 |
interactName | String | 自定义事件名称,建议写中文 |
targetType | String | 目标类型,0:系统,1:玩家,2:自定义类型 |
targetCode | String | 目标,若目标类型为玩家则为对方角色ID |
targetInfo | String | 目标详细信息,若目标类型为玩家,则为对方逻辑服ID |
detail | String | 相关信息,全为英文 |
与游戏自定义事件相比,交互事件多了一个交互对象的概念,targetType字段用于描述本次交互的对象是哪一类对象,0、系统交互,1、玩家之间互动,2、游戏自定义交互。
系统交互事件应该尽量使用游戏自定义事件来记录,除非交互对象较为重要需要额外记录。
targetCode用于描述当前玩家与具体哪一个对象进行了交互,当targetType为2时,targetCode必须为对方角色id,targetInfo必须为对方逻辑服标识。
日志格式示例:
try{
string serviceCode = “从SDKAPI中获取的serviceCode”;
std::map<string, string> map;
map.insert(pair<string, string>("interactId", "addfriend"));
map.insert(pair<string, string>("interactName", "添加好友"));
map.insert(pair<string, string>("targetType", "1"));
map.insert(pair<string, string>("targetCode", "0010000067543"));
map.insert(pair<string, string>("targetInfo", "珍妮.爱荷华"));
map.insert(pair<string, string>("detail", "SUCC"));
Log log;
log.setId("12001");
log.putServer("1");
log.putRoleId("11111111");
log.putRoleName("马克.吐温");
log.putRoleLevel("1");
log.putRoleVipLevel("0");
log.setServiceCode(serviceCode);
log.putUserId("0100010000000000000000000000000090019780");
log.setClientIp("111.111.111.111");
log.setCreateLogTime(time(NULL) * 1000);
log.setLogInfo(map);
vector<Log> logArr;
logArr.push_back(log);
PalmLogSender::sendLogList(logArr);
} catch(exception &e) {
cout << "catch exception:" << e.what() << endl;
}
这条日志表示当前玩家马克吐温添加了玩家珍妮佛为好友
由于游戏行业的产品类型丰富,各种新的玩法和子系统层出不穷,用固定格式固定字段的日志无法满足不同产品的日志记录和查询需求。我们在固定格式的日志之外,提供了一个非固定格式自定义日志的发送接口,大概是调用我们的LogUtils.sendCustomLog 方法,传入一个日志类型id和一个保存日志全部字段的map即可
LogId | 日志名称 | LogKey |
---|---|---|
11000 | 完全自定义日志 | server-custom |
字段名 | 字段类型 | 字段说明 |
---|---|---|
customId | String | 日志标识,仅限字母,数字,下划线 |
logInfo | Map | 封装日志内容的一个Map |
id | String | 注:自定义日志的id,现为必填项,填入11000 |
日志标识:用来唯一确定一类日志,同一类日志必须传入同一标识,标识只能由英文字母,数字,下划线构成,不允许传入特殊字符
日志内容:key-val方式(Map
日志格式示例:
try{
string serviceCode = “从SDKAPI中获取的serviceCode”;
std::map<string, string> map;
map.insert(pair<string, string>("Time", "2016-05-31 12:01:00"));
map.insert(pair<string, string>("roleid", "123000"));
map.insert(pair<string, string>("rolename", "艾亚诺"));
map.insert(pair<string, string>("occupation", "战士"));
map.insert(pair<string, string>("lev", "10"));
map.insert(pair<string, string>("fightvalue", "5"));
map.insert(pair<string, string>("logintime", "2016-05-31 11:01:00"));
map.insert(pair<string, string>("Vip", "1"));
map.insert(pair<string, string>("Coin", "50000"));
map.insert(pair<string, string>("Diamond", "10"));
map.insert(pair<string, string>("Gold", "200"));
map.insert(pair<string, string>("Itemsn", "79001"));
map.insert(pair<string, string>("Price", "300"));
map.insert(pair<string, string>("Tax", "45"));
Log log;
log.setCustomId("tbl_moneyflow");
log.setId("11000");
log.setServiceCode(serviceCode);
log.setClientIp("112.32.112.22");
log.setCreateLogTime(time(NULL) * 1000);
log.setLogInfo(map);
vector<Log> logArr;
logArr.push_back(log);
PalmLogSender::sendLogList(logArr);
} catch(exception &e) {
cout << "catch exception:" << e.what() << endl;
}
该条日志记录了一次交易所物品上架