SUPLogRecord API

Every package has a LogRecordImpl table in its own database. The Unwired Server can send import messages with LogRecordImpl records as part of its response to replay requests (success or failure). LogRecord stores two types of logs.

The Unwired Server can embed a "log" JSON array into the header of a server message; the array is written to the LogRecordImpl table by the client. The client application can also write its own records. Each entity has a method called newLogRecord, which allows the entity to write its own log record. The LogRecordImpl table has "component" and "entityKey" columns that associate the log record entry with a particular MBO and primary key value.

SUPObjectList *salesorders = [SUP101Sales_order findAll];
  if([salesorders size] > 0)
  {
    SUP101Sales_order * so = [salesorders item:0];
    SUP101LogRecordImpl *lr = [SUP101LogRecordImpl getInstance];
    lr.message = :@"testing record"]; 
    lr.level = [SUPLogLevel INFO];
    [lr save]; 

    // submitting log records
    [SUP101SUP101DB submitLogRecords];
    // synchronize with server
    [SUP101SUP101DB synchronize:@"system"];
  } 
}

You can use the getLogRecords method to return log records from the table.

SUPQuery *query = [SUPQuery getInstance];
  	 SUPObjectList *loglist = [SUP101SUP101DB getLogRecords:query];
	for(id o in loglist)
	{
		LogRecordImpl *log = (LogRecordImpl*)o;
		MBOLogError(@"Log Record %llu: Operation = %@, Timestamp = %@,  
                                 
MBO = %@, key= %@,message=%@",log.messageId,log.operation,
  [SUPDateTimeUtil toString:log.timestamp],log.component,log.entityKey,log.message);
}

Each mobile business object has a getLogRecords instance method that returns a list of all the log records that have been recorded for a particular entity row in a mobile business object:

SUPObjectList *salesorders = [SampleAppSales_order findAll];
if([salesorders size] > 0)
{
  SampleAppSales_order * so = [salesorders item:0];
  SUPObjectList *loglist = [so getLogRecords];
for(id o in loglist)
{
  LogRecordImpl *log = (LogRecordImpl*)o;
  MBOLogError(@"Log Record %llu: Operation = %@, Timestamp = %@,  
                                 
MBO = %@, key= %@,message=%@",log.messageId,log.operation,
  [SUPDateTimeUtil toString:log.timestamp],log.component,log.entityKey,log.message);
}

Mobile business objects that support dynamic queries can be queried using the synthetic attribute hasLogRecords. This attribute generates a subquery that returns true if an entity row has any log records in the database, otherwise it returns false. The following code example prints out a list of customers, including first name, last name, and whether the customer row has log records:

SUPQuery *query = [SUPQuery getInstance];
[query select:@"x.surrogateKey,x.fname,x.lname,x.hasLogRecords"];
[query from:@"Customer":@"x"];
SUPQueryResultSet *qrs = [SUP101SUP101DB executeQuery:query];
MBOLogError(@"%@",[qrs.columnNames toString]);
for(SUPDataValueList *row in qrs.array)
{
  MBOLogError(@"%@",[row toString]);
}

If there are a large number of rows in the MBO table, but only a few have log records associated with them, you may want to keep an in-memory object to track which rows have log records. You can define a class property as follows:

NSMutableArray* customerKeysWithLogRecords;

After data is downloaded from the server, initialize the array:

customerKeysWithLogRecords = [[NSMutableArray alloc] initWithCapacity:20];
SUPObjectList *allLogRecords = [SUP101SUP101DB getLogRecords:nil];
for(id<SUPLogRecord> lr in allLogRecords)
{
  if(([lr entityKey] != nil) && ([[lr component] compare:@"Customer"] == 0))
    [customerKeysWithLogRecords addObject:[lr entityKey]];
}

You do not need database access to determine if a row in the Customer MBO has a log record. The following expression returns true if a row has a log record:

BOOL hasALogRecord = [customerKeysWithLogRecords containsObject:
                                [customerRow keyToString]];

This sample code shows how to find the corresponding MBO with the LogRecord and to delete the log record when a record is processed.

- (void)processLogs
{
  SUPQuery *query = [SUPQuery getInstance];
  SUPObjectList *logRecords = [SUP101SUP101DB getLogRecords:query];

  for(id<SUPLogRecord> log in logRecords)
  {
    // Log warning message
    NSLog(@"log %@: %@ code:%d msg:%@",[log component],[log entityKey],[log code],[log message]);
    if([[log component] isEqualToString:@"Customer"])
    {
      NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
      int64_t surrogateKey = [[formatter numberFromString:[log entityKey]] longLongValue];
      [formatter release];
      SUP101Customer *c = [SUP101Customer find:surrogateKey];
      if(c.pending)
        [c cancelPending];
      [log delete];
      [log submitPending];
    }
  }
    
}