Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions src/main/java/io/growing/sdk/java/GrowingAPI.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import io.growing.sdk.java.exception.GIOSendBeRejectedException;
import io.growing.sdk.java.logger.GioLogger;
import io.growing.sdk.java.sender.FixThreadPoolSender;
import io.growing.sdk.java.sender.SendResult;
import io.growing.sdk.java.sender.SyncSender;
import io.growing.sdk.java.store.StoreStrategy;
import io.growing.sdk.java.store.StoreStrategyClient;
import io.growing.sdk.java.utils.ConfigUtils;
Expand Down Expand Up @@ -59,6 +61,19 @@ public void send(GIOMessage msg) {
}
}

private static final SyncSender SYNC_SENDER = new SyncSender();

public SendResult sendSync(GIOMessage msg) {
try {
if (validDefaultConfig && businessVerification(msg)) {
return SYNC_SENDER.sendMsg(msg);
}
} catch (Exception e) {
GioLogger.error("failed to send msg, " + e.toString());
}
return new SendResult(SendResult.State.UNKNOWN_ERROR, "unknown error");
}

/**
* 添加埋点事件,当队列满时,可以抛出拒绝异常.
*
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/io/growing/sdk/java/dto/GIOMessage.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,6 @@ public String getProjectKey() {
public boolean isIllegal() {
return false;
}

public abstract Class<?> getMessageClass();
}
5 changes: 5 additions & 0 deletions src/main/java/io/growing/sdk/java/dto/GioCdpEventMessage.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ public EventV3Dto getMessage() {
return event.toBuilder().setProjectKey(projectKey).setDataSourceId(dataSourceId).build();
}

@Override
public Class<?> getMessageClass() {
return GioCdpEventMessage.class;
}

@Override
public boolean isIllegal() {
if (StringUtils.isBlank(event.getEventName())) {
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/io/growing/sdk/java/dto/GioCdpItemMessage.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ public ItemDto getMessage() {
return event.toBuilder().setProjectKey(projectKey).setDataSourceId(dataSourceId).build();
}

@Override
public Class<?> getMessageClass() {
return GioCdpItemMessage.class;
}

@Override
public boolean isIllegal() {
if (event.getId().isEmpty() || event.getKey().isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ public UserMappingDto getMessage() {
return event.toBuilder().setProjectKey(projectKey).setDataSourceId(dataSourceId).build();
}

@Override
public Class<?> getMessageClass() {
return GioCdpUserMappingMessage.class;
}

@Override
public boolean isIllegal() {
if (event.getIdentifiesMap().isEmpty()) {
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/io/growing/sdk/java/dto/GioCdpUserMessage.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ public EventV3Dto getMessage() {
return user.toBuilder().setProjectKey(projectKey).setDataSourceId(dataSourceId).build();
}

@Override
public Class<?> getMessageClass() {
return GioCdpUserMessage.class;
}

@Override
public boolean isIllegal() {
if (user.getAttributesMap().isEmpty()) {
Expand Down
138 changes: 138 additions & 0 deletions src/main/java/io/growing/sdk/java/logger/FileWriter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
package io.growing.sdk.java.logger;

import io.growing.sdk.java.utils.ConfigUtils;

import java.io.File;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.text.SimpleDateFormat;
import java.util.Date;

public class FileWriter {
private static final String loggerFilePath;
private static final int loggerFileMaxSize;
private static final int loggerFileMaxDays;

static {
loggerFilePath = ConfigUtils.getStringValue("logger.file.path", "/logs").trim();
loggerFileMaxSize = ConfigUtils.getIntValue("logger.file.max_size", 10);
loggerFileMaxDays = ConfigUtils.getIntValue("logger.file.max_days", -1);
}

private FileWriter() {
}

private static class SingleInstance {
private static final FileWriter INSTANCE = new FileWriter();
}

public static FileWriter getInstance() {
return FileWriter.SingleInstance.INSTANCE;
}

private FileChannel fileChannel;
private Date lastDate;
private static final SimpleDateFormat fileDateFormat = new SimpleDateFormat("yyyy-MM-dd");
private static final SimpleDateFormat logDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

public synchronized void log(String message) {
try {
if (lastDate == null || intervalDays(lastDate.getTime(), new Date().getTime()) > 0) {
createFileIfNotExist();
}

if (fileChannel != null && fileChannel.isOpen()) {
// 超过单个文件大小限制后直接关闭channel,不再写入日志
if (fileChannel.size() > ((long) loggerFileMaxSize * 1024L * 1024L)) {
if (fileChannel != null) {
fileChannel.close();
fileChannel = null;
}
return;
}

ByteBuffer buffer = ByteBuffer.wrap((logDateFormat.format(new Date()) + ": " + message + "\n").getBytes());
fileChannel.write(buffer);
}
} catch (Exception e) {
e.printStackTrace();
}
}

private void createFileIfNotExist() {
try {
String currentDate = fileDateFormat.format(new Date());
lastDate = fileDateFormat.parse(currentDate);
String filePath = loggerFilePath + File.separator + currentDate + ".log";
File file = new File(filePath);
if (!createMissingParentDirectories(file)) {
return;
}
if (file.createNewFile()) {
// 每次创建新的文件时,关闭上一个fileChannel,并且删除过期的日志文件
if (fileChannel != null) {
fileChannel.close();
fileChannel = null;
}
deleteExpiredFiles();
}

RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rwd");
randomAccessFile.seek(randomAccessFile.length());
fileChannel = randomAccessFile.getChannel();
} catch (Exception e) {
e.printStackTrace();
}
}

private void deleteExpiredFiles() {
try {
if (loggerFileMaxDays > 0) {
File logsDir = new File(loggerFilePath);
File[] logFiles = logsDir.listFiles();
if (logFiles == null || logFiles.length == 0) {
return;
}
for (File logFile : logFiles) {
String fileName = logFile.getName();
if (logFile.isFile() && fileName.endsWith(".log") && isExpiredFile(fileName)) {
logFile.delete();
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}

private Boolean isExpiredFile(String fileName) {
try {
String fileTime = fileName.substring(0, fileName.lastIndexOf("."));
Date fileDate = fileDateFormat.parse(fileTime);
Date currentDate = new Date();
long days = intervalDays(fileDate.getTime(), currentDate.getTime());
if (days > loggerFileMaxDays) {
return true;
}
} catch (Exception e) {
e.printStackTrace();
}

return false;
}

private long intervalDays(long lastTime, long currentTime) {
return (currentTime - lastTime) / (1000 * 60 * 60 * 24);
}

private boolean createMissingParentDirectories(File file) {
File parent = file.getParentFile();
if (parent == null) {
return true;
}

parent.mkdirs();
return parent.exists();
}
}
8 changes: 8 additions & 0 deletions src/main/java/io/growing/sdk/java/logger/GioLogger.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@
public class GioLogger {
private static GioLoggerInterface logger;
private static final String loggerLevel;
private static final Boolean loggerFileEnabled;

static {
String loggerImplName = ConfigUtils.getStringValue("logger.implementation", "io.growing.sdk.java.logger.GioLoggerImpl");

loggerFileEnabled = ConfigUtils.getBooleanValue("logger.file.enabled", false);
loggerLevel = ConfigUtils.getStringValue("logger.level", "error");

try {
Expand Down Expand Up @@ -44,4 +46,10 @@ public static void debug(String msg) {
public static void error(String msg) {
logger.error(msg);
}

public static void file(String msg) {
if (loggerFileEnabled) {
FileWriter.getInstance().log(msg);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ public static Collection<MessageProcessor> getProcessors(){
return processors.values();
}

public static MessageProcessor getProcessor(Class<?> clazz){
return processors.get(clazz);
}

public static MessageProcessor getApiInstance(GIOMessage msg) {
return processors.get(msg.getClass());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,13 @@
public class FixThreadPoolSender implements MessageSender {
private static final ExecutorService sendThread = Executors.newFixedThreadPool(ConfigUtils.getIntValue("send.msg.thread", 3), new GioThreadNamedFactory("gio-sender"));

private static final NetProviderAbstract netProvider = new HttpUrlProvider();

@Override
public void sendMsg(final String projectKey, final List<GIOMessage> msg) {
doSend(projectKey, msg);
}

public static NetProviderAbstract getNetProvider() {
return netProvider;
return HttpUrlProvider.getInstance();
}

public void doSend(final String projectKey, final List<GIOMessage> msgList) {
Expand Down
33 changes: 33 additions & 0 deletions src/main/java/io/growing/sdk/java/sender/SendResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package io.growing.sdk.java.sender;

public class SendResult {
public enum State {
SUCCESS,
NETWORK_FAILURE,
EXCEPTION_FAILURE,
UNKNOWN_ERROR
}
private State state;
private String msg;

public SendResult(State state, String msg) {
this.state = state;
this.msg = msg;
}

public State getState() {
return state;
}

public String getMsg() {
return msg;
}

@Override
public String toString() {
return "SendResult{" +
"state=" + state +
", msg='" + msg + '\'' +
'}';
}
}
42 changes: 42 additions & 0 deletions src/main/java/io/growing/sdk/java/sender/SyncSender.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package io.growing.sdk.java.sender;

import io.growing.sdk.java.com.googlecode.protobuf.format.JsonFormat;
import io.growing.sdk.java.dto.GIOMessage;
import io.growing.sdk.java.dto.GioCDPMessage;
import io.growing.sdk.java.logger.GioLogger;
import io.growing.sdk.java.process.EventProcessorClient;
import io.growing.sdk.java.process.MessageProcessor;
import io.growing.sdk.java.sender.net.HttpUrlProvider;

import java.util.Arrays;

public class SyncSender {

private static final JsonFormat JSON_FORMAT = new JsonFormat();

public SendResult sendMsg(final GIOMessage msg) {
String projectKey = msg.getProjectKey();

MessageProcessor processor = EventProcessorClient.getProcessor(msg.getMessageClass());
byte[] processed = processor.process(Arrays.asList(msg));

if (processed != null && processed.length > 0) {
RequestDto requestDto = new RequestDto.Builder()
.setUrl(processor.apiHost(projectKey))
.setContentType(processor.contentType())
.setBytes(processed)
.setHeaders(processor.headers())
.build();

SendResult result = HttpUrlProvider.getInstance().toSendSync(requestDto);
if (result.getState() != SendResult.State.SUCCESS) {
if (msg instanceof GioCDPMessage) {
GioLogger.file("send failed, result: " + result + ", data: " + JSON_FORMAT.printToString(((GioCDPMessage<?>) msg).getMessage()));
}
}
return result;
}

return new SendResult(SendResult.State.UNKNOWN_ERROR, "unknown error");
}
}
Loading