Как перехватить вывод stderr и отправить сообщения в удаленный файл журнала с помощью запроса POST в задаче c? - PullRequest
0 голосов
/ 11 января 2019

У меня есть простой веб-сервис онлайн для прослушивания почтовых запросов. Он записывает в локальный файл строки, отправленные ему в качестве параметров в теле.

Теперь у меня есть приложение ios, и я хочу отправлять каждое сообщение stderr приложения в веб-службу для регистрации ошибок в онлайн-файле и возможности удаленного просмотра ошибок приложения в реальном времени.

Я знаю, что могу перенаправить сообщения stderr в файл (локальный для устройства), как это

+ (void) redirectNSLogToDocuments {
    NSArray *allPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [allPaths objectAtIndex:0];
    NSString *pathForLog = [documentsDirectory stringByAppendingPathComponent:@"errLog.txt"];
    freopen([pathForLog cStringUsingEncoding:NSASCIIStringEncoding],"a+",stderr);
}

Я знаю, что могу отправить запрос на публикацию следующим образом, и поэтому записать строку 'errorString' в удаленный журнал

    NSString *errorString=@"errorIOS";
    NSString *errorData =[NSString stringWithFormat:@"errorString=%@",errorString];
    NSData *postData = [errorData dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
    NSString *postLength = [NSString stringWithFormat:@"%d",[postData length]];
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
    [request setURL:[NSURL URLWithString:@"http://mywebserviceurl"]];
    [request setHTTPMethod:@"POST"];
    [request setValue:postLength forHTTPHeaderField:@"Content-Length"];
    [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
    [request setHTTPBody:postData];
    NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];

Но если я хочу перенаправить сообщения stderr так, чтобы каждый раз, когда выдавалось сообщение об ошибке, он запускал почтовый запрос в мой веб-сервис и записывал сообщение в удаленный журнал вместо записи в локальный файл устройства?

1 Ответ

0 голосов
/ 11 января 2019

stderr можно поймать, прикрепив трубу с этим кодом

NSPipe* pipe = [NSPipe pipe];
NSFileHandle* pipeReadHandle = [pipe fileHandleForReading];
dup2([[pipe fileHandleForWriting] fileDescriptor], fileno(stderr));
dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, [pipeReadHandle fileDescriptor], 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
dispatch_source_set_event_handler(source, ^{
    void* data = malloc(4096);
    ssize_t readResult = 0;
    do
    {
        errno = 0;
        readResult = read([pipeReadHandle fileDescriptor], data, 4096);
    } while (readResult == -1 && errno == EINTR);
    if (readResult > 0)
    {
        //AppKit UI should only be updated from the main thread
        dispatch_async(dispatch_get_main_queue(),^{
            NSString* stdOutString = [[NSString alloc] initWithBytesNoCopy:data length:readResult encoding:NSUTF8StringEncoding freeWhenDone:YES];
            NSAttributedString* stdOutAttributedString = [[NSAttributedString alloc] initWithString:stdOutString];
            [appFunctions postDataToRemoteLogWithMessage:stdOutAttributedString];
        });
    }
    else{free(data);}
});
dispatch_resume(source);

Таким образом, добавив функцию, можно достичь результата

+ (NSString *) postDataToRemoteLogWithMessage:(NSString *)errorString{
    // Send post request to webservice
    NSString *errorData =[NSString stringWithFormat:@"errorString=%@",errorString];
    NSData *postData = [errorData dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
    NSString *postLength = [NSString stringWithFormat:@"%d",[postData length]];
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
    [request setURL:[NSURL URLWithString:@"http://mywebserviceurl"]];
    [request setHTTPMethod:@"POST"];
    [request setValue:postLength forHTTPHeaderField:@"Content-Length"];
    [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
    [request setHTTPBody:postData];
    NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
    if(conn) {
        //NSLog(@"Connection Successful");
    } else {
        //NSLog(@"Connection could not be made");
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...