5
+ (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;
}

Above code will get apple system log. Problem is, it take around 8second to pull all the logs from Apple System Log (ASL). Is there any way to optimize asl_set_query to get data faster or any other way which I am missing.

Note: Can we create a ASL query which will take time stamp and we can get less number of data to process. This will solve the problem I think.

Machavity
  • 30,841
  • 27
  • 92
  • 100
AAV
  • 3,785
  • 8
  • 32
  • 59

1 Answers1

4

ASL supports a few different logging levels, so you could specify a more restrictive level.

For example you can add another query (according to the man page they are joined via the logical 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);
    //...

For some more information on the different error levels check: http://www.cocoanetics.com/2011/03/accessing-the-ios-system-log/

Note that, depending on the level you set and the level your log messages are, further filtering may have no effect (ie. if all messages that are actually logged for your app are of the same level)

Further note, unlike the debug level querying, I haven't yet used the timestamp querying in any productive code, but in a test it seems to work perfectly fine and is doing what it is supposed to do.

tttthomasssss
  • 5,852
  • 3
  • 32
  • 41
  • I already saw this post and tried but didn't help lot in my case. But thank you for your answer. – AAV Jul 19 '13 at 17:14
  • @AmitVyawahare I added timestamp querying to the answer, let me know if it works for you. – tttthomasssss Jul 20 '13 at 08:42
  • It did help but not in grate deal. – AAV Jul 22 '13 at 19:11
  • @AmitVyawahare can you further refine the timeframe you're interested, so say the last 30 seconds/minute/hour/12 hours or is that not feasible/possible in your case? – tttthomasssss Jul 22 '13 at 19:45
  • informative answer, thanks. But, will this work for iOS7? In below post user Trung commented on what seems to be a related issue: "As of IOS 7, this method won't work any more. Apple removed access to ASL due to security reason." http://stackoverflow.com/questions/6144347/using-objective-c-to-read-log-messages-posted-to-the-device-console/18927099#18927099 If Trung is correct, do you know of another (non jail-broken) way to access and search the log-data of foreign apps from within a new app, made for reporting? – Karsten Apr 04 '14 at 16:57
  • @Karsten Sorry for the late reply, busy times...I have never used it on 3rd party apps (at least not in production), so I can't tell whether there still is some way to access 3rd party logs. My guess would be that there isn't. But do feel free to post anything in the comments if you find something :). – tttthomasssss Apr 16 '14 at 18:50
  • This doesn't seem to work after iOS7, how can we get this working for all level logs after iOS7? – iOS Dev Sep 29 '16 at 11:22