# LogMessage [LogMessage.java](../../oblogclient-common/src/main/java/com/oceanbase/oms/logmessage/LogMessage.java) defines `LogMessage` as the structure of the log records. During the running of the program, the client will convert the received log data into LogMessage objects, and users can use them to customize their own processing logic. ## Struct When we fetch log data from OceanBase, the data will firstly be serialized using [oblogmsg](https://github.com/oceanbase/oblogmsg), and eventually be converted into LogMessage struct in the client. For specific field information, please refer to oblogmsg. There are the common fields of LogMessage:
Field Getter Type Description
byteBuf getRawData byte[] The original log data in byte array format.
srcType getDbType DbTypeEnum Type of datasource, OceanBase versions before 1.0 correspond to OB_05, versions 1.0 and later correspond to OB_MYSQL and OB_ORACLE.
op getOpt DataMessage.Record.Type The type of log data, OceanBase mainly involves BEGIN, COMMIT, INSERT, UPDATE, DELETE, DDL, HEARTBEAT.
timestamp getTimestamp String The timestamp of data change execution time.
dbName getDbName String Database name of log data. Note that this value contains the tenant name in the format of tenant_name.db_name.
tableName getTableName String Table name of log data.
The field list of DML and DDL can be obtained through the `getFieldList` method. The following are commonly used fields in the Field struct:
Field Getter Type Description
primaryKey isPrimary boolean Flag of whether this field is a primary key of not null unique key.
name getFieldname String Field name.
type getType DataMessage.Record.Field.Type Field type.
encoding getEncoding String Field encoding.
value getValue ByteString Field value in ByteString type.
prev isPrev boolean Flag of whether it is a old value. It is true if this field is the value before the change, and false if it is the value after the change.
## Usage Please refer to [LogProxyClientTest.java](../../oblogclient-logproxy/src/test/java/com/oceanbase/clogproxy/client/LogProxyClientTest.java). ### Safe Checkpoint LogMessage provides `safeTimestamp` to indicate the safe checkpoint for data reception, that is to say, LogMessage committed earlier than this timestamp has been received by the client. When a application consumes data, it generally maintains a safe checkpoint for data processing. For LogMessage, we should use HEARTBEAT `timestamp` as the safe checkpoint. LogMessage contains two kinds of timestamp: - HEARTBEAT type: the value of the `timestamp` field is the timestamp corresponding to the safe checkpoint. - Other types: the value of the `timestamp` field is the execution time of the data change, and the `fileNameOffset` field corresponds to the latest HEARTBEAT timestamp. Since `libobcdc` does not guarantee that the fetched data changes are in timestamp order, so for DDL and DML types of LogMessage, `fileNameOffset` should be used as safe checkpoint instead of `timestamp`. The following code can be used to obtain the safe checkpoint corresponding to the current data: ```java long checkpoint; if (DataMessage.Record.Type.HEARTBEAT.equals(message.getOpt())) { checkpoint = Long.parseLong(message.getTimestamp()); } else { checkpoint = message.getFileNameOffset(); } ```