7

インストルメンテーション ロジックをアプリに追加して、さまざまな API 呼び出しのレイテンシを追跡する任務を負っています。RACSignal (遅延実行 API 呼び出し) を返すメソッドにタイミング計測を追加する、クリーンで副作用のない方法を考え出すのに苦労しています。

考慮事項

  • ReactiveCocoa @ 1.9.5 を使用 (現時点ではアップグレードできません)
  • Parse-RACExtensions @ 0.0.2 の使用
  • Parse-RACExtensions を変更するのではなく、ViewModel レイヤーでタイミングを設定することをお勧めします。これは、クエリ パラメーターなど、ログに記録したい追加情報が VM にあり、すべての API 呼び出しをインストルメント化する必要がないためです。
  • completedイベントの受信時にのみタイミングを記録する
  • 無痛計測の精神で、発信者の負担は可能な限り小さくする必要があります。

試みられた解決策

私が思いついた唯一のことは、タイマー ロジックを処理する具体的な RACSubscriber サブクラスを作成することです。厄介なサブクラスに加えて、これは明示的な を必要とするため、明らかに理想的ではありません。これには、ソース信号のsubscribe:オンが必要です。replayさらに、シグナルへの一時的なハンドルを取得するために少なくともリファクタリングする必要があるため、発信者に負担がかかります。

@interface SignalTimer : RACSubscriber

@property (nonatomic) NSDate *startDate;

@end

@implementation SignalTimer

- (void)didSubscribeWithDisposable:(RACDisposable *)disposable
{
    [super didSubscribeWithDisposable:disposable];

    self.startDate = [NSDate date];
}

- (void)sendCompleted
{
    NSTimeInterval duration = [[NSDate date] timeIntervalSinceDate:self.startDate];
    NSLog(@"Time elapsed: %f", duration);

    [super sendCompleted];
}

@end

使用法は次のようになります。

- (RACSignal*)saveFoo:(Foo*)fooParseObj {
    RACSignal *save = [[fooParseObj rac_save] replay]; // Don't forget replay!
    [save subscribe:[[SignalTimer alloc] initWithName@"Saving the user's foo object"]];
    return save;
}

明らかに、私はこの実装に満足していません。

最終的な考え

理想的には、このような連鎖可能なメソッドが欲しいのですが、それを達成する方法がわかりませんでした/カテゴリメソッド内で厄介な副作用なしにコールドシグナルを処理できるかどうか (replayレシーバーの呼び出しなど) .

[[[fooParseObj rac_save] logTimingsWithName:@"Saving the user's foo object"] subscribeNext:...];

考え?

4

1 に答える 1

2

だから、私はこの道を必要以上に難しくしていたと思います。次のカテゴリのソリューションは、はるかに慣用的なように思えますが、フィードバックをお待ちしています。

@interface RACSignal (Timing)

- (instancetype)logTimingWithName:(NSString*)name;

@end

@implementation RACSignal (Timing)

- (instancetype)logTimingWithName:(NSString*)name
{
    return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {

        NSDate* startDate = [NSDate date];

        return [self subscribeNext:^(id x) {
            [subscriber sendNext:x];
        } error:^(NSError *error) {
            [subscriber sendError:error];
        } completed:^{
            NSTimeInterval duration = [[NSDate date] timeIntervalSinceDate:startDate];
            NSLog(@"%@: %f sec", name, duration);

            [subscriber sendCompleted];
        }];
    }];
}

@end
于 2013-12-31T21:16:45.223 に答える