Skip to content
This repository has been archived by the owner on Oct 18, 2022. It is now read-only.

Create plugins

Tomohiro Moro edited this page Oct 9, 2016 · 4 revisions

There are three types of plugins: Filter, Output, Buffered Output.

Output and Buffered Output are categorized Output plugins.

Filter plugin

Role of Filter plugin is convert anyObject to PURLog. PURLog is internal log object of Puree system. PURLog has tag, date and userInfo properties. Your custom filter plugin makes one or multiple PURLog instance from given anyObject. If you want include custom class object in PURLog userInfo, custom class requires NSCoding compliant.

Filter plugins must inherit PURFilter class. Override logsWithObject:tag:captured: method and implement return log objects.

Example:

// Swift

class ActivityFilter: PURFilter {
    override func configure(settings: [String : Any]) {
        super.configure(settings: settings)

        // configure filter plugin
    }

    override func logs(object: Any, tag: String, captured: String?) -> [PURLog] {
        let currentDate = logger.currentDate()

        switch object {
        case let recipe as Recipe:
            return [PURLog(tag: tag, date: currentDate, userInfo: ["recipe_id": recipe.identifier, "recipe_title": recipe.title])]
        case let bargainItem as BargainItem:
            return [PURLog(tag: tag, date: currentDate, userInfo: ["item_id": bargainItem.identifier, "item_name": bargainItem.name])]
        default:
            return []
        }
    }
}
// Objective-C

#import <Puree/Puree.h>

@interface ActivityFilter: PURFilter

@end

@implementation ActivityFilter

- (void)configure:(NSDictionary<NSString *,id> *)settings
{
    [super configure:settings];

    // configure filter plugin
}

- (NSArray<PURLog *> *)logsWithObject:(id)object tag:(NSString *)tag captured:(NSString *)captured
{
    NSDate *currentDate = [self.logger currentDate];

    if ([object isKindOfClass:[Recipe class]]) {
        Recipe *recipe = object;
        return @[[[PURLog alloc] initWithTag:tag date:currentDate userInfo:@{@"recipe_id": recipe.identifier, @"recipe_title": recipe.title}]];
    } else if ([object isKindOfClass:[BargainItem class]]) {
        BargainItem *bargainItem = object;
        return @[[[PURLog alloc] initWithTag:tag date:currentDate userInfo:@{@"item_id": bargainItem.identifier, @"item_name": bargainItem.name}]];
    }
    return @[];
}

@end

Output plugin

Role of Output plugin is output log. This type plugin is unbuffered, no retry. Output plugin better suited for perform reliable output(e.g. console output, any logging library).

Output plugins must inherit PUROutput class. Override emitLog: method and implement output log procedure.

Example:

// Swift

class ConsoleOutput: PUROutput {
    override func configure(settings: [String : Any]) {
        super.configure(settings: settings)

        // configure output plugin
    }

    override func emit(log: PURLog) {
        print("tag: \(log.tag), date: \(log.date), \(log.userInfo)")
    }
}
// Objective-C

#import <Puree/Puree.h>

@interface ConsoleOutput : PUROutput

@end

@implementation ConsoleOutput

- (void)configure:(NSDictionary<NSString *,id> *)settings
{
    [super configure:settings];

    // configure output plugin
}

- (void)emitLog:(PURLog *)log
{
    NSLog(@"tag: %@, date: %@, %@", log.tag, log.date, log.userInfo);
}

@end

PUROutput class has special method and call suitable timing.

  • start - configured output plugin first.
  • suspend - timing of application did enter background.
  • resume - timing of application will enter foreground.

Buffered output plugin

Buffered output plugin is one of output plugin. This type plugin buffer logs, and retry output process in failure situation. Buffered Output plugin better suited for need collect logs per send request, use network situation, etc.

Buffered output plugins must inherit PURBufferedOutput class. Override writeChunk:completion: method and implement output buffered logs procedure. Chunk(PURBufferedOutputChunk) is container of buffered logs, You can retrieve logs this object. Completion is handler of output buffering logs. You must call this completion handler when complete output procedure, with result(true / false, YES / NO). If specified false, retry output process. The default is 3 times.

Example:

// Swift

class LogServerOutput: PURBufferedOutput {
    override func configure(settings: [String : Any]) {
        super.configure(settings: settings)

        // configure buffered output plugin
    }

    override func write(chunk: PURBufferedOutputChunk, completion: @escaping (Bool) -> Void) {
        let logDictList: [[String : Any]] = chunk.logs.map { log in
            var logDict = log.userInfo
            logDict["date"] = log.date
            return logDict
        }

        guard let logData = try? JSONSerialization.data(withJSONObject: logDictList, options: []) else {
            fatalError("cannot convert to JSON")
        }

        let request = URLRequest(url: URL(string:"https://logserver")!)
        let task = URLSession.shared.uploadTask(with: request, from: logData) { data, response, error in
            guard let httpResponse = response as? HTTPURLResponse else {
                completion(false)
                return
            }

            if error != nil || httpResponse.statusCode != 201 {
                completion(false)
                return
            }
            completion(true)
        }
        task.resume()
    }
}
// Objective-C

#import <Puree/Puree.h>

@interface LogServerOutput: PURBufferedOutput

@end

@implementation LogServerOutput

- (void)configure:(NSDictionary<NSString *,id> *)settings
{
    [super configure:settings];

    // configure buffered output plugin
}

- (void)writeChunk:(PURBufferedOutputChunk *)chunk completion:(void (^)(BOOL))completion
{
    NSMutableArray *logs = [NSMutableArray new];
    for (PURLog *log in chunk.logs) {
        NSMutableDictionary *logDict = [log.userInfo mutableCopy];
        logDict[@"date"] = log.date;

        [logs addObject:logDict];
    }

    NSData *logData = [NSJSONSerialization dataWithJSONObject:logs options:0 error:NULL];
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"https://logserver"]];
    NSURLSessionUploadTask *task = [[NSURLSession sharedSession] uploadTaskWithRequest:request
                                                                              fromData:logData
                                                                     completionHandler:^(NSData *data, NSURLResponse *response, NSError *error){
                                                                         NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
                                                                         if (error || httpResponse.statusCode != 201) {
                                                                             completion(NO);
                                                                             return;
                                                                         }
                                                                         completion(YES);
                                                                     }];
    [task resume];
}

@end

You can customize some properties of PURBufferedOutput, sub classes.

  • PURBufferedOutputSettingsLogLimitKey - Number of buffering logs(default: 5).
  • PURBufferedOutputSettingsFlushIntervalKey - Interval seconds of log flushing(default: 10).
  • PURBufferedOutputSettingsMaxRetryCountKey - Max retry count of log flushing(default: 3)
Clone this wiki locally