优化苹果系统日志

时间:2013-07-17 14:34:05

标签: ios objective-c macos

+ (NSArray *)systemLogDictionariesForAppName:(NSString *)appName {   
  aslmsg q = asl_new(ASL_TYPE_QUERY);
  asl_set_query(q, ASL_KEY_SENDER, [appName cStringUsingEncoding:NSASCIIStringEncoding], ASL_QUERY_OP_EQUAL);
  aslresponse r = asl_search(NULL, q);
  aslmsg m;
  uint32_t i;
  const char *key, *val;
  NSMutableArray *systemLogDictionaries = [NSMutableArray array];

  while (NULL != (m = aslresponse_next(r)))
  {
      NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
      for (i = 0; (NULL != (key = asl_key(m, i))); i++)
      {
          val = asl_get(m, key);
          NSString *stringKey = [NSString stringWithCString:key encoding:NSUTF8StringEncoding];
          NSString *stringVal = [NSString stringWithCString:val encoding:NSUTF8StringEncoding];

          [dictionary setObject:stringVal forKey:stringKey];
      }
      [systemLogDictionaries addObject:dictionary];
  }
  aslresponse_free(r);

  return systemLogDictionaries;
}

上面的代码将获得苹果系统日志。问题是,从Apple System Log(ASL)中提取所有日志大约需要8秒。有没有办法优化asl_set_query来更快地获取数据或任何其他我缺少的方式。

注意:我们可以创建一个ASL查询,它将采用时间戳,我们可以获得更少的数据来处理。这将解决我认为的问题。

1 个答案:

答案 0 :(得分:4)

ASL支持几种不同的日志记录级别,因此您可以指定更严格的级别。

例如,您可以添加另一个查询(根据他们通过逻辑AND加入的手册页):

    // ...
    asl_set_query(q, ASL_KEY_SENDER, [appName cStringUsingEncoding:NSASCIIStringEncoding], ASL_QUERY_OP_EQUAL);
    // 3 is error messages
    asl_set_query(q, ASL_KEY_LEVEL, "3", ASL_QUERY_OP_LESS_EQUAL | ASL_QUERY_OP_NUMERIC);

    //-- Check for time --//

    /* A dumped entry with your code looks like:

         ASLMessageID = 1825403;
         "CFLog Local Time" = "2013-07-20 08:33:12.943";
         "CFLog Thread" = 951f;
         Facility = "com.apple.Safari";
         GID = 20;
         Host = "XXX.local";
         Level = 4;
         Message = "CFPropertyListCreateFromXMLData(): Old-style plist parser: missing semicolon in dictionary on line 3. Parsing will be abandoned. Break on _CFPropertyListMissingSemicolon to debug.";
         PID = 183;
         ReadUID = 501;
         Sender = Safari;
         Time = 1374305592;
         TimeNanoSec = 943173000;
         UID = 501;

    Time is a Unix timestamp, so you can use it in your query with ASL_KEY_TIME and one of these operators: ASL_QUERY_OP_EQUAL, ASL_QUERY_OP_GREATER, ASL_QUERY_OP_GREATER_EQUAL, ASL_QUERY_OP_LESS, ASL_QUERY_OP_LESS_EQUAL, ASL_QUERY_OP_NOT_EQUAL

    The code below, generates a unix timestamp for yesterday and dumps all messages that occurred yesterday or later. 
    (Nevermind the dirty/hacky way I generate the timestamp, that was just for testing purposes)
*/
    NSDate *yesterday = [NSDate dateWithTimeIntervalSinceNow: -(60.0f*60.0f*24.0f)];
    NSString *theDate = [NSString stringWithFormat:@"%d", (int)[yesterday timeIntervalSince1970]];

    asl_set_query(q, ASL_KEY_TIME, [theDate cStringUsingEncoding:NSASCIIStringEncoding], ASL_QUERY_OP_GREATER_EQUAL | ASL_QUERY_OP_NUMERIC);
    aslresponse r = asl_search(NULL, q);
    //...

有关不同错误级别的更多信息,请检查:http://www.cocoanetics.com/2011/03/accessing-the-ios-system-log/

请注意,根据您设置的级别和日志消息的级别,进一步过滤可能无效(即,如果您的应用实际记录的所有消息都是相同级别)

进一步说明,与调试级别查询不同,我还没有在任何高效代码中使用时间戳查询,但在测试中它似乎工作得非常好并且正在做它应该做的事情。