Java SDK 主要用于服务端 Java 应用,对于 Android App,请使用 Android SDK。示例代码均对应 Java SDK 最新版本,版本信息点击查看 Java SDK 更新日志

1. 集成神策分析 SDK

在服务端 Java 应用中集成 Java SDK,使用神策分析采集并分析用户行为。

我们推荐使用 Maven 管理 Java 项目,请在 pom.xml 文件中,添加以下依赖信息,Maven 将自动获取神策分析 SDK 并更新项目配置。

<dependencies>
	// ...
	<dependency>
	<groupId>com.sensorsdata.analytics.javasdk</groupId>
	<artifactId>SensorsAnalyticsSDK</artifactId>
	<version>3.2.0</version>
	</dependency>
</dependencies>
CODE


若出现依赖冲突的问题(例如运行时找不到类),可以使用 standalone 版本:将上面的 version 替换为 3.2.0-standalone。

如果不使用 Maven,也可以用下面任意一种方式集成:

  • 直接从 GitHub 下载 Java SDK 的源代码,并将其作为模块添加进项目中使用;

最新版本的神策 Java SDK 支持的 JDK 最低版本为 JDK 1.6。

2. 初始化神策分析 SDK

2.1. 获取配置信息

首先从神策分析的主页中,获取数据接收的 URL 和 Token(Cloud 版)。

如果使用神策分析 Cloud 服务,需获取的配置信息为:

如果用户使用单机版私有部署的神策分析,默认的配置信息为:

  • 数据接收地址: http://{$host_name}:8106/sa?project={$project_name}
    (注:神策分析 1.7 及之前的版本,单机版私有部署默认端口号为 8006)

如果用户使用集群版私有部署的神策分析,默认的配置信息为:

  • 数据接收地址: http://{$host_name}:8106/sa?project={$project_name}

其中 {$host_name} 可以是集群中任意一台机器。

如果私有部署的过程中修改了 Nginx 的默认配置,或通过 CDN 等访问神策分析,则请咨询相关人员获得配置信息。

2.2. 在普通 Java 程序中初始化 SDK

在选择 ConcurrentLoggingConsumer 模式的时候,请注意初始化方式!!!每实例化一个 SDK 对象,都会创建一个与之对应的内存缓存队列。所以请谨慎创建 SDK 实例对象,推荐在应用程序启动时全局初始化一次,然后进行全局调用。

非Spring 容器环境下,建议使用单例模式创建 SDK 实例对象;Spring 容器环境下,建议按照下列步骤创建 SDK 实例对象。

如果应用程序需求,需要创建多个实例对象,请谨慎操作。一定要避免在埋点方法内部调用初始化 SDK 方法,这样操作的后果就会导致业务每触发一次埋点,都会创建一个 SDK 实例对象!!!一定要避免这样的操作,不然会导致内存占用率过高。


在程序启动时(如 public static void main(String[] args) 方法中),调用构造函数 new SensorsAnalytics(Consumer) 初始化 Java SDK 实例(需要全局初始化一次即可)。

// 使用 ConcurrentLoggingConsumer 初始化 SensorsAnalytics
final SensorsAnalytics sa = new SensorsAnalytics(new ConcurrentLoggingConsumer("您的日志文件路径"));

// 用户的 Distinct ID
String distinctId = "ABCDEF123456789";

// 记录用户登录事件
EventRecord loginRecord = EventRecord.builder().setDistinctId(distinctId).isLoginId(Boolean.TRUE)
                              .setEventName("UserLogin")
                              .build();
sa.track(loginRecord);

// 使用神策分析记录用户行为数据
// ...
JAVA

在生产环境中使用 ConcurrentLoggingConsumer,并结合 LogAgent 工具完成数据采集,程序调试时可以使用 DebugConsumer,具体信息请参考文档中 设置 Java SDK 第七节 。

至此,我们已经可以正常使用神策分析 SDK 采集用户数据了。在开发多线程程序时,开发者可以在线程间复用神策分析实例用于记录数据。

请注意:Debug 模式是为方便开发者调试而设置的模式,该模式会逐条校验数据并在校验失败时抛出异常,性能远低于正常模式。
线上环境使用 Debug 模式会严重影响性能并存在崩溃风险,产品上线前请务必替换掉/关闭 Debug 模式。

2.3. 在 Spring 框架里面初始化 SDK

在 Spring 相关框架里面集成 SDK 之后,需要在全局初始化 SDK 唯一实例,推荐将初始化操作装配成 Bean,交给 Spring 容器来管理。在使用的类中注入即可使用。

2.3.1. 使用 xml 配置文件创建 Bean 对象

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">

    <!-- 本地日志模式(此模式会在指定路径生成相应的日志文件) -->
    <bean id="loggingConsumer" class="com.sensorsdata.analytics.javasdk.consumer.ConcurrentLoggingConsumer">
        <constructor-arg name="filenamePrefix" value="您的日志文件路径"/>
    </bean>

    <!-- debug 模式(此模式只适用于测试集成 SDK 功能,千万不要使用到生产环境!!!) -->
    <!--<bean id="debugConsumer" class="com.sensorsdata.analytics.javasdk.consumer.DebugConsumer">
        <constructor-arg name="serverUrl" value="数据接收地址"/>
        <constructor-arg name="writeData" value="true"/>
    </bean>-->

    <!-- 网络批量发送模式(此模式在容器关闭的时候,如果存在数据还没有发送完毕,就会丢失未发送的数据!!!)-->
    <!--<bean id="batchConsumer" class="com.sensorsdata.analytics.javasdk.consumer.BatchConsumer">
        <constructor-arg name="serverUrl" value="数据接收地址"/>
    </bean>-->

    <!-- 此处选择合适的模式进行数据采集操作(此处选择本地日志模式) -->
    <bean id="sensorsAnalytics" class="com.sensorsdata.analytics.javasdk.SensorsAnalytics" destroy-method="shutdown">
        <constructor-arg name="consumer" ref="loggingConsumer"/>
    </bean>

</beans>
JAVA

2.3.2. 使用注解创建 Bean 对象

@Configuration
public class SensorsConfig {

    @Bean(destroyMethod = "shutdown")
    public ISensorsAnalytics init() throws IOException {
        //本地日志模式(此模式会在指定路径生成相应的日志文件)
        return new SensorsAnalytics(new ConcurrentLoggingConsumer("您的日志文件路径"));
        //debug 模式(此模式只适用于测试集成 SDK 功能,千万不要使用到生产环境!!!)
        //return new SensorsAnalytics(new DebugConsumer("数据接收地址", true));
        //网络批量发送模式(此模式在容器关闭的时候,如果存在数据还没有发送完毕,就会丢失未发送的数据!!!)
        //return new SensorsAnalytics(new BatchConsumer("数据接收地址"));
    }

}
JAVA

2.3.3. 在业务代码中调用创建的 Bean 对象

@Service
public class TestServiceImpl implements ITestService {

    //注入神策实例化对象
    @Autowired
    ISensorsAnalytics sa;

    public String hello(String userId) throws InvalidArgumentException {
        //相关业务处理逻辑代码
		...
        //调用神策 SDK 记录事件
        EventRecord eventRecord = EventRecord.builder().setDistinctId(userId).isLoginId(Boolean.TRUE)
                                      .setEventName("track")
                                      .addProperty("$time", Calendar.getInstance().getTime())
                                      .build();
        sa.track(eventRecord);
        return "success";
    }
}
JAVA


3. 用户识别

在服务端应用中,神策分析也要求为每个事件设置用户的 Distinct ID,这有助于神策分析提供更准确的留存率等数据。

对于注册用户,推荐使用客户业务系统中的用户 ID 作为 Distinct ID,不建议使用用户名、Email、手机号码等可以被修改的信息作为 Distinct ID;

对于未注册的匿名用户,获取用户匿名 ID 的方法如下:

  1. 后端获取前端 JavaScript SDK 生成的匿名 ID 的方式:
    可以在 Cookie 里面找到 key 为 sensorsdata2015jssdkcross 的 value 值然后进行 decodeURIComponent 解码,最后通过 JSON.parse 方法得到一个对象,对象里面的 distinct_id 的值即为所需要的 ID
    (注意,如果前端已经调用过 login 方法,那么此时 distinct_id 为登录 ID,所以需要先获取 first_id 字段的值,如果获取不到,就去获取 distinct_id 的值)。
  2. 如果 App 中嵌入了  Login 方法,需要客户端使用神策提供的获取匿名 ID 接口,将匿名 ID 传给服务端,服务端使用客户端传过来的匿名 ID 作为 Distinct ID。

所有的 trackprofile 系列方法都必须同时指定用户 ID(distinctId)和用户 ID 是否为登录 ID (isLoginId) 这两个参数,以便明确告知神策分析用户 ID 的类型。

3.1. 用户注册/登录

通过 trackSignUp() 将匿名 ID 和登录 ID 关联,以保证用户分析的准确性。例如:

// 前端的匿名 ID,获取匿名 ID 的方式参考上文
String anonymousId = "9771C579-71F0-4650-8EE8-8999FA717761";

String registerId = "0012345678";
// 用户注册/登录时,将用户登录 ID 与匿名 ID 关联
sa.trackSignUp(registerId, anonymousId);
JAVA

注意以下问题:

  • trackSignUp() 建议在用户注册/登录时调用。如果客户端也有采集任意事件,在注册/登录时,也需要在客户端调用一次关联方法 login() 将匿名 ID 和登录 ID 关联。 注册/登录时,客户端和服务端都各自调用一次关联方法的原因如下:
    • 一对一关联机制下,避免出现用户注册/登录时,客户端的关联信息 $SignUp 事件没有发送成功/延迟发送到神策系统,而服务端触发的事件( $is_login_id=true )先发送到神策系统中,导致登录 ID 自关联,从而导致登录 ID 无法再和匿名 ID 关联,客户端匿名行为和登录后的行为识别两个用户的行为。
    • 客户端调用一次关联方法 login() 的作用,除了将匿名 ID 和 登录 ID 关联之外,还会会将客户端标记用户的 distinctId 值从匿名 ID 切换为登录 ID。这样查看用户行为序列时,可以很好的根据 distinctId 的值判断用户行为是登录后的行为还是匿名行为。因此强烈建议用户登录/注册时,在客户端调用一次 login() 的同时,在服务端也调用一次 trackSignUp() 。
  • 如果服务端只在用户登录成功之后,才会采集相关事件或者设置用户属性,要保证 track 事件/profileSet 设置用户属性($is_login_id 设置为 true)的代码在 trackSignUp() 方法之后调用,从而可以保证先将匿名 ID 和登录 ID 关联之后,再采集登录用户的行为事件/设置用户属性。
  • 在神策分析 1.13 版本之前,多次调用 trackSignUp() /login()时,只有第一次关联行为是有效的。神策分析 1.13 版本之后提供了多设备 ID 关联的方法。更详细的说明请参考 标识用户,并在必要时联系我们的技术支持人员。

4. 追踪事件

第一次接入神策分析时,建议先追踪 3~5 个关键的事件,只需要几行代码,便能体验神策分析的分析功能。例如:

  • 图片社交产品,可以追踪用户浏览图片和评论事件
  • 电商产品,可以追踪用户注册、浏览商品和下订单等事件

神策分析 SDK 初始化成功后,可以通过 track() 记录事件,必须包含用户 ID(distinctId)、用户 ID 是否为登录 ID (isLoginId)、事件名(eventName)这三个参数,同时可以传入一个 EventRecord 对象,为事件添加自定义事件属性。以电商产品为例,可以这样追踪一次购物行为:

// 使用 ConcurrentLoggingConsumer 初始化 SensorsAnalytics
final SensorsAnalytics sa = new SensorsAnalytics(new SensorsAnalytics.ConcurrentLoggingConsumer("您的日志文件路径"));

// 用户的 Distinct ID
String distinctId = "ABCDEF123456789";

// 用户浏览商品
{
     EventRecord lookRecord = EventRecord.builder().setDistinctId(distinctId).isLoginId(Boolean.FALSE)
           .setEventName("ViewProduct")
           .addProperty("$time", new Date())  // '$time' 属性是系统预置属性,表示事件发生的时间,如果不填入该属性,则默认使用系统当前时间
           // '$ip' 属性是系统预置属性,如果服务端中能获取用户 IP 地址,并填入该属性,神策分析会自动根据 IP 地址解析用户的省份、城市信息
          .addProperty("$ip", "123.123.123.123")
          .addProperty("ProductId", "123456")
          .build();
    // 记录用户浏览商品事件
    sa.track(lookRecord);
}

// 用户订单付款
{
	// 订单中的商品 ID 列表
    List<String> productIdList = new ArrayList<String>();
    productIdList.add("123456");
    productIdList.add("234567");
    productIdList.add("345678");
    EventRecord lookRecord = EventRecord.builder().setDistinctId(distinctId).isLoginId(Boolean.FALSE)
           .setEventName("PaidOrder")
           // '$ip' 属性是系统预置属性,如果服务端中能获取用户 IP 地址,并填入该属性,神策分析会自动根据 IP 地址解析用户的省份、城市信息
           .addProperty("$ip", "123.123.123.123")
           .addProperty("OrderId", "123456")
           .addProperty("ProductIdList", productIdList)
           .build();
    // 记录用户订单付款事件
    sa.track(lookRecord);
}
JAVA

通过 调试模式 ,可以校验追踪的事件及属性是否正确。正常模式下,数据导入后,在神策分析中稍等片刻,便能看到追踪结果。

4.1. 事件属性

如前文中的样例,追踪的事件可以设置自定义的事件属性,例如浏览商品事件中,将商品 ID、商品分类等信息作为事件属性。在后续的分析工作中,事件属性可以作为统计过滤条件使用,也可以作为维度进行多维分析。对于事件属性,神策分析有一些约束:

  • 事件属性是一个 EventRecord 对象;
  • EventRecord 中每个元素描述一个属性,Key 为属性名称,必需是 String 类型;
  • EventRecord 中,每个元素的 Value 是属性的值,支持 StringBooleanNumberList<String>Date。

对于神策分析中事件属性的更多约束,请参考 数据格式在开发多线程程序时,开发者不能在线程间复用传入的属性对象

4.1.1. 系统预置属性

如前文中样例,事件属性中以 '$' 开头的属性为系统预置属性,在自定义事件属性中填入对应 '$' 开头的属性值可以覆盖这些预置属性:

  • $ip - 填入该属性,神策分析会自动根据 IP 地址解析用户的省份、城市信息,该属性值为 String 类型;
  • $time - 填入该属性,神策分析将事件时间设置为属性值的时间,该属性值必须为 Date 类型。请注意,神策分析默认会过滤忽略 2 年前或 1 小时后的数据,如需修改请联系我们;
  • $project - 填入该属性,神策分析某些导入工具例如 LogAgent (LogAgent 的配置中未指定 project 参数时)会将数据导入指定项目。

关于其他更多预置属性,请参考  数据格式 中 '预置属性' 一节。

4.1.2. 事件公共属性

特别地,如果某个事件的属性,在所有事件中都会出现,可以通过 registerSuperProperties() 将该属性设置为事件公共属性。例如将服务器的应用版本及机房地址设置为事件的公共属性,设置方法如下:

//设置公共属性,以后上传的每一个事件都附带该属性
SuperPropertiesRecord propertiesRecord = SuperPropertiesRecord.builder()
        .addProperty("ServerVersion", "1.2")
        .addProperty("Location", "Beijing")
        .build();
sa.registerSuperProperties(propertiesRecord);
JAVA

成功设置事件公共属性后,再通过 track() 追踪事件时,事件公共属性会被添加进每个事件中,例如:

String distinctId = "ABCDEF123456789";
EventRecord loginRecord = EventRecord.builder().setDistinctId(distinctId).isLoginId(Boolean.FALSE)
        .setEventName("UserLogin")
        .addProperty("$ip", "123.123.123.123")
        .build();
// 追踪用户登录事件
sa.track(loginRecord);
JAVA

在设置事件公共属性后,实际发送的事件中会被加入 ServerVersionLocation 属性,等价于

String distinctId = "ABCDEF123456789";
EventRecord loginRecord = EventRecord.builder().setDistinctId(distinctId).isLoginId(Boolean.FALSE)
        .setEventName("UserLogin")
        .addProperty("$ip", "123.123.123.123")
        .addProperty("ServerVersion", "1.2")
        .addProperty("Location", "Beijing")
        .build();
// 追踪用户登录事件
sa.track(loginRecord);
JAVA

使用 clearSuperProperties() 会删除所有已设置的事件公共属性。

当事件公共属性和事件属性的 Key 冲突时,事件属性优先级最高,它会覆盖事件公共属性。

5. 设置用户属性

为了更准确地提供针对人群的分析服务,神策分析 SDK 可以设置用户属性,如年龄、性别等。用户可以在留存分析、分布分析等功能中,使用用户属性作为过滤条件或以用户属性作为维度进行多维分析。

使用 profileSet() 设置用户属性:

String distinctId = "ABCDEF123456789";
UserRecord userRecord = UserRecord.builder().setDistinctId(distinctId).isLoginId(Boolean.TRUE)
        .addProperty("Sex", "Male") // 设置用户性别属性(Sex)为男性
        .build();
sa.profileSet(userRecord);

userRecord = UserRecord.builder().setDistinctId(distinctId).isLoginId(Boolean.TRUE)
        .addProperty("UserLv", "Elite VIP") // 设置用户等级属性(Level)为 VIP
        .build();
sa.profileSet(userRecord);
JAVA


对于不再需要的用户属性,可以通过 profileUnset() 接口将属性删除。

用户属性中,属性名称与属性值的约束条件与事件属性相同,详细说明请参考 数据格式

5.1. 记录初次设定的属性

对于只在首次设置时有效的属性,我们可以使用 profileSetOnce() 记录这些属性。与 profileSet() 接口不同的是,如果被设置的用户属性已存在,则这条记录会被忽略而不会覆盖已有数据,如果属性不存在则会自动创建。因此,profileSetOnce() 比较适用于为用户设置首次激活时间、首次注册时间等属性。例如:

String distinctId = "ABCDEF123456789";
UserRecord firstVisitRecord = UserRecord.builder().setDistinctId(distinctId).isLoginId(Boolean.TRUE)
        .addProperty("AdSource", "App Store")
        .build();
sa.profileSetOnce(firstVisitRecord);
JAVA

5.2. 数值类型的属性

对于数值型的用户属性,可以使用 profileIncrement() 对属性值进行累加。常用于记录用户付费次数、付费额度、积分等属性。例如:

String distinctId = "ABCDEF123456789";

UserRecord incrementRecord = UserRecord.builder().setDistinctId(distinctId).isLoginId(Boolean.TRUE)
        .addProperty("GamePlayed", 1)   // 设置用户游戏次数属性(GamePlayed),将次数累加1次
        .build();
sa.profileIncrement(incrementRecord);
JAVA

5.3. 列表类型的属性

对于用户喜爱的电影、用户点评过的餐厅等属性,可以记录列表型属性。需要注意的是,列表型属性中的元素必须为 String 类型,且元素的值会自动去重。关于列表类型限制请见 数据格式 1.7.4 属性长度限制。

String distinctId = "ABCDEF123456789";

// 电影列表
List<String> movies = new ArrayList<String>();
movies.add("Sicario");
movies.add("Love Letter");

// 游戏列表
List<String> games = new ArrayList<String>();
games.add("Call of Duty");
games.add("Halo");

// 用户属性
Map<String, Object> properties = new HashMap<String, Object>();
properties.put("movies", movies);
properties.put("games", games);

// 传入properties,设置用户喜欢的电影属性(movies)和喜欢的游戏属性(games)
// 设置成功后,"movies" 属性值为 ["Sicario", "Love Letter"];"games" 属性值为 ["Call of Duty", "Halo"]
UserRecord appendRecord = UserRecord.builder().setDistinctId(distinctId).isLoginId(Boolean.TRUE)
        .addProperty("movies", movies)
        .addProperty("games", games)
        .build();
sa.profileAppend(appendRecord);

// 传入属性名称和需要插入属性的值,设置用户喜欢的电影属性(movies)
// 设置成功后 "movies" 属性值为 ["Sicario", "Love Letter", "Dead Poets Society"]
UserRecord appendRecord = UserRecord.builder().setDistinctId(distinctId).isLoginId(Boolean.TRUE)
        .addProperty("movies", "Dead Poets Society")
        .build();
sa.profileAppend(appendRecord);
JAVA

6. 物品元数据上报

在神策推荐项目中,客户需要将物品元数据上报,以开展后续推荐业务的开发与维护。神策分析 SDK 提供了设置与删除物品元数据的方法。

item_id(物品 ID )item_type (物品所属类型)共同组成了一个物品的唯一标识。所有的 item 系列方法都必须同时指定物品 ID 及物品所属类型这两个参数,来完成对物品的操作。

6.1. 设置物品

直接设置一个物品,如果已存在则覆盖。除物品 ID 与物品所属类型外,其他物品属性需在 properties 中定义。

物品属性中,属性名称与属性值的约束条件与事件属性相同,详细说明请参考 数据格式

public void itemSet(String itemType, String itemId, Map<String, Object> properties);

// 例如
Map<String, Object> properties = new LinkedHashMap<>();
properties.put("name", "C++ Primer");
properties.put("price", 31.54);
sensorsAnalytics.itemSet("book", "0321714113", properties);
JAVA

6.2. 删除一个物品

如果物品不可被推荐需要下线,删除该物品即可,如不存在则忽略。

除物品 ID 与 物品所属类型外,不解析其他物品属性。

public void itemDelete(String itemType, String itemId, Map<String, Object> properties);

// 例如
ItemRecord deleteRecord = ItemRecord.builder().setItemId("0321714113").setItemType("book")
        .build();
sensorsAnalytics.itemDelete(deleteRecord);
JAVA

7. 立刻上报缓存数据

如果想要事件数据、用户数据或者物品数据立刻上报,可以调用 flush() 方法:

// 立刻上报缓存数据
sa.flush();
CODE

8. 设置神策分析 SDK

以下内容说明如何更精细地控制神策分析 SDK 的行为。

8.1. 数据采集

Java SDK 主要由以下两个组件构成:

  • SensorsAnalytics: 用于发送数据的接口对象,构造函数需要传入一个 Consumer 实例
  • Consumer: Consumer 会进行实际的数据发送

为了让开发者更灵活的接入数据,神策分析 SDK 实现了以下 Consumer。

8.1.1. DebugConsumer

用于校验数据导入是否正确,关于调试模式的详细信息,请进入相关页面查看。

请注意:Debug 模式是为方便开发者调试而设置的模式,该模式会逐条校验数据并在校验失败时抛出异常,性能远低于正常模式。

线上环境使用 Debug 模式会严重影响性能并存在崩溃风险,产品上线前请务必替换掉/关闭 Debug 模式。

// 从神策分析获取的数据接收的 URL
final String SA_SERVER_URL = "YOUR_SERVER_URL";
// 使用 Debug 模式,并且导入 Debug 模式下所发送的数据
final boolean SA_WRITE_DATA = true;

// 使用 DebugConsumer 初始化 SensorsAnalytics
final SensorsAnalytics sa = new SensorsAnalytics(new DebugConsumer(SA_SERVER_URL, SA_WRITE_DATA));

// 使用神策分析记录用户行为数据
// ...
JAVA

8.1.2. ConcurrentLoggingConsumer

用于将数据输出到指定目录并按天切割生成日志,并使用 LogAgent 等工具导入,该工具能保证导入不重复、不遗漏。推荐在生产环境中使用 ConcurrentLoggingConsumer 导入数据。支持多个进程写同一个目录(目录不能是 nas、nfs 类文件系统),生成的文件始终是带日期后缀的,每天一个。

  • ConcurrentLoggingConsumer 内部有一个  8k 的缓存队列,当缓存队列写满时落盘写入磁盘日志文件中(如果测试的数据量较少,达不到缓存上限,则数据不会落盘到日志)。缓存队列的长度可在构造函数中设置,也可以调用 flush() 方法强制落盘。
  • LogAgent 配置文件中一定要注释掉 real_time_file_name 参数,否则无法正常导入数据。
// 使用 ConcurrentLoggingConsumer 初始化 SensorsAnalytics
// 将数据输出到 /data/sa 下的 access.log.2017-01-11 文件中,每天一个文件;对应目录需要自己创建,日志文件会自动生成
final SensorsAnalytics sa = new SensorsAnalytics(new ConcurrentLoggingConsumer("/data/sa/access.log"));

// !! 注意 !! 如果是在 Windows 环境下使用 ConcurrentLoggingConsumer 并使用 LogAgent 发送数据,
// 需要额外通过构造函数的第二个参数指定一个文件地址用于文件锁,例如:
// SensorsAnalytics sa = new SensorsAnalytics(new ConcurrentLoggingConsumer("D:\\data\\service", "D:\\var\\sa.lock"));
// 若该文件与数据文件同目录,配置 LogAgent 的 pattern 时请不要匹配到这个文件。

// 使用神策分析记录用户行为数据
// ...
JAVA

8.1.3. LoggingConsumer

已不推荐在生产环境中使用,因为在多进程下文件切分可能有问题。已使用 LoggingConsumer 的客户建议按照如下步骤切换到 ConcurrentLoggingConsumer

第 1 步 停掉 LogAgent,并注释掉 LogAgent 配置中的 real_time_file_name 参数。

第 2 步 将日志目录下的 real_time_file_name 的文件加上当前时间的后缀。

第 3 步 后端程序升级切换到 ConcurrentLoggingConsumer

第 4 步 重新启动 LogAgent。

关于 LogAgent 操作请参见 LogAgent

8.1.4. BatchConsumer

批量发送数据的 Consumer,当数据达到指定的量时(默认50条,最多可指定1000条),才将数据进行发送。也可以调用 flush() 方法去强制发送。注意:BatchConsumer 默认不会抛出异常,如果网络出现异常,导致数据发送失败,会造成数据丢失。如果你想获取对应的异常信息,需要通过初始化函数  BatchConsumer(final String serverUrl, final int bulkSize, final boolean throwException) 指定 throwException 参数为 true。

通常用于导入小规模历史数据,或者离线 / 旁路导入数据的场景。由于是网络直接发送数据,如果网络出现异常可能会导致数据重发或丢失,因此不要用在任何线上服务中。

// 从神策分析获取的数据接收的 URL
final String SA_SERVER_URL = "YOUR_SERVER_URL";
// 当缓存的数据量达到50条时,批量发送数据
final int SA_BULK_SIZE = 50;
// 数据同步失败不抛出异常
final boolean THROW_EXCEPTION = false;
// 内存中数据最大缓存条数,如此值大于0,代表缓存的数据会有条数限制,最小 3000 条,最大 6000 条。否则无条数限制。
final int MAX_CACHE_SIZE = 0;
// 使用 BatchConsumer 初始化 SensorsAnalytics
// 不要在任何线上的服务中使用此 Consumer
final SensorsAnalytics sa = new SensorsAnalytics(new BatchConsumer(SA_SERVER_URL, SA_BULK_SIZE, MAX_CACHE_SIZE, THROW_EXCEPTION));

// 使用神策分析记录用户行为数据
// ...
JAVA

8.1.5. ConsoleConsumer

用于将数据输出到特定 Writer,一般用于在生产环境的 Java 程序中处理历史数据,生成日志文件并使用 BatchImporter 等工具导入

// 将数据输出到标准输出
final Writer writer = new PrintWriter(System.out);

// 使用 ConsoleConsumer 初始化 SensorsAnalytics
final SensorsAnalytics sa = new SensorsAnalytics(new ConsoleConsumer(writer));

// 使用神策分析记录用户行为数据
// ...

// Flush the writer
writer.flush();
JAVA

8.2. 关闭 SDK

如果您想要主动关闭 SDK,可以参考以下使用方式:

// 关闭神策分析 SDK 所有服务并销毁实例
sa.shutdown();
JAVA

8.3. 其它设置

导入历史数据:默认情况下,神策会过滤发生时间比较久远数据(例如 10 天之前,具体取决于服务端设置),如果想导入历史数据,可以通过开启 Time Free 选项来绕过这个限制。

// 初始化 SensorsAnalytics
final SensorsAnalytics sa = new SensorsAnalytics(...);
// 开启 Time Free 以便导入历史数据
sa.setEnableTimeFree(true);
JAVA