Skip to content

Commit

Permalink
Merge pull request #277 from rollbar/rate_limit_drop
Browse files Browse the repository at this point in the history
Make rate limit behavior configurable for dropping or queuing
  • Loading branch information
matux committed Mar 30, 2023
2 parents e2b536b + 85201ee commit 80a4cd4
Show file tree
Hide file tree
Showing 17 changed files with 206 additions and 248 deletions.
8 changes: 6 additions & 2 deletions Demos/iosAppSwift/iosAppSwift/iosAppSwiftApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,15 @@ class AppDelegate: NSObject, UIApplicationDelegate {

config.loggingOptions.codeVersion = codeVersion

// Optionally defined whether rate limited occurrences should be dropped or
// kept in a queue. Defaults to drop.
config.loggingOptions.rateLimitBehavior = .queue

// Optionally anonymize the IP address
//config.loggingOptions.captureIp = RollbarCaptureIpType.anonymize

// Suppress (default) Rollbar internal logging
config.developerOptions.suppressSdkInfoLogging = true
// Suppress internal Rollbar logging. Defaults to true.
config.developerOptions.suppressSdkInfoLogging = false

config.telemetry.enabled = true
config.telemetry.captureLog = true
Expand Down
5 changes: 3 additions & 2 deletions RollbarCommon/Sources/RollbarCommon/DTOs/RollbarDTO.m
Original file line number Diff line number Diff line change
Expand Up @@ -330,15 +330,16 @@ -(BOOL)isEmpty {

#pragma mark - Initializers

- (instancetype)initWithJSONString: (NSString *)jsonString {
- (instancetype)initWithJSONString:(NSString *)jsonString {
NSAssert(jsonString && jsonString.length > 0, @"jsonString cannot be nil");
self = [self init];
if (self) {
[self deserializeFromJSONString:jsonString];
}
return self;
}

- (instancetype)initWithJSONData: (NSData *)data {
- (instancetype)initWithJSONData:(NSData *)data {
self = [self init];
if (self) {
[self deserializeFromJSONData:data];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
static RollbarLevel const DEFAULT_LOG_LEVEL = RollbarLevel_Info;
static RollbarLevel const DEFAULT_CRASH_LEVEL = RollbarLevel_Error;
static NSUInteger const DEFAULT_MAX_REPORTS_PER_MINUTE = 60;
static RollbarRateLimitBehavior const DEFAULT_RATE_LIMIT_BEHAVIOR = RollbarRateLimitBehavior_Drop;
static RollbarCaptureIpType const DEFAULT_IP_CAPTURE_TYPE = RollbarCaptureIpType_Full;

#if TARGET_OS_IPHONE
Expand All @@ -18,6 +19,7 @@
static NSString * const DFK_LOG_LEVEL = @"logLevel";
static NSString * const DFK_CRASH_LEVEL = @"crashLevel";
static NSString * const DFK_MAX_REPORTS_PER_MINUTE = @"maximumReportsPerMinute";
static NSString * const DFK_RATE_LIMIT_BEHAVIOR = @"rateLimitBehavior";
static NSString * const DFK_IP_CAPTURE_TYPE = @"captureIp";
static NSString * const DFK_CODE_VERSION = @"codeVersion";
static NSString * const DFK_FRAMEWORK = @"framework";
Expand All @@ -32,15 +34,17 @@ @implementation RollbarLoggingOptions
- (instancetype)initWithLogLevel:(RollbarLevel)logLevel
crashLevel:(RollbarLevel)crashLevel
maximumReportsPerMinute:(NSUInteger)maximumReportsPerMinute
rateLimitBehavior:(RollbarRateLimitBehavior)rateLimitBehavior
captureIp:(RollbarCaptureIpType)captureIp
codeVersion:(nullable NSString *)codeVersion
framework:(nullable NSString *)framework
requestId:(nullable NSString *)requestId {
requestId:(nullable NSString *)requestId
{
self = [super initWithDictionary:@{
DFK_LOG_LEVEL: [RollbarLevelUtil RollbarLevelToString:logLevel],
DFK_CRASH_LEVEL: [RollbarLevelUtil RollbarLevelToString:crashLevel],
DFK_MAX_REPORTS_PER_MINUTE: [NSNumber numberWithUnsignedInteger:maximumReportsPerMinute],
DFK_RATE_LIMIT_BEHAVIOR: [NSNumber numberWithBool:rateLimitBehavior],
DFK_IP_CAPTURE_TYPE: [RollbarCaptureIpTypeUtil CaptureIpTypeToString:DEFAULT_IP_CAPTURE_TYPE],
DFK_CODE_VERSION: codeVersion ? codeVersion : [NSNull null],
DFK_FRAMEWORK: framework ? framework : OPERATING_SYSTEM,
Expand All @@ -52,13 +56,15 @@ - (instancetype)initWithLogLevel:(RollbarLevel)logLevel
- (instancetype)initWithLogLevel:(RollbarLevel)logLevel
crashLevel:(RollbarLevel)crashLevel
maximumReportsPerMinute:(NSUInteger)maximumReportsPerMinute
rateLimitBehavior:(RollbarRateLimitBehavior)rateLimitBehavior
codeVersion:(nullable NSString *)codeVersion
framework:(nullable NSString *)framework
requestId:(nullable NSString *)requestId {
requestId:(nullable NSString *)requestId
{
self = [self initWithLogLevel:logLevel
crashLevel:crashLevel
maximumReportsPerMinute:maximumReportsPerMinute
rateLimitBehavior:rateLimitBehavior
captureIp:DEFAULT_IP_CAPTURE_TYPE
codeVersion:codeVersion
framework:framework
Expand All @@ -71,11 +77,12 @@ - (instancetype)initWithLogLevel:(RollbarLevel)logLevel
captureIp:(RollbarCaptureIpType)captureIp
codeVersion:(nullable NSString *)codeVersion
framework:(nullable NSString *)framework
requestId:(nullable NSString *)requestId {
requestId:(nullable NSString *)requestId
{
self = [self initWithLogLevel:logLevel
crashLevel:crashLevel
maximumReportsPerMinute:DEFAULT_MAX_REPORTS_PER_MINUTE
rateLimitBehavior:DEFAULT_RATE_LIMIT_BEHAVIOR
captureIp:captureIp
codeVersion:codeVersion
framework:framework
Expand All @@ -87,11 +94,12 @@ - (instancetype)initWithLogLevel:(RollbarLevel)logLevel
crashLevel:(RollbarLevel)crashLevel
codeVersion:(nullable NSString *)codeVersion
framework:(nullable NSString *)framework
requestId:(nullable NSString *)requestId {
requestId:(nullable NSString *)requestId
{
self = [self initWithLogLevel:logLevel
crashLevel:crashLevel
maximumReportsPerMinute:DEFAULT_MAX_REPORTS_PER_MINUTE
rateLimitBehavior:DEFAULT_RATE_LIMIT_BEHAVIOR
captureIp:DEFAULT_IP_CAPTURE_TYPE
codeVersion:codeVersion
framework:framework
Expand All @@ -101,11 +109,13 @@ - (instancetype)initWithLogLevel:(RollbarLevel)logLevel

- (instancetype)initWithLogLevel:(RollbarLevel)logLevel
crashLevel:(RollbarLevel)crashLevel
maximumReportsPerMinute:(NSUInteger)maximumReportsPerMinute {

maximumReportsPerMinute:(NSUInteger)maximumReportsPerMinute
rateLimitBehavior:(RollbarRateLimitBehavior)rateLimitBehavior
{
self = [self initWithLogLevel:logLevel
crashLevel:crashLevel
maximumReportsPerMinute:maximumReportsPerMinute
rateLimitBehavior:rateLimitBehavior
captureIp:DEFAULT_IP_CAPTURE_TYPE
codeVersion:nil
framework:nil
Expand All @@ -118,7 +128,8 @@ - (instancetype)initWithLogLevel:(RollbarLevel)logLevel

return [self initWithLogLevel:logLevel
crashLevel:crashLevel
maximumReportsPerMinute:DEFAULT_MAX_REPORTS_PER_MINUTE];
maximumReportsPerMinute:DEFAULT_MAX_REPORTS_PER_MINUTE
rateLimitBehavior:DEFAULT_RATE_LIMIT_BEHAVIOR];
}

- (instancetype)init {
Expand All @@ -144,6 +155,11 @@ - (NSUInteger)maximumReportsPerMinute {
withDefault:DEFAULT_MAX_REPORTS_PER_MINUTE];
}

- (RollbarRateLimitBehavior)rateLimitBehavior {
return [self safelyGetBoolByKey:DFK_RATE_LIMIT_BEHAVIOR
withDefault:DEFAULT_RATE_LIMIT_BEHAVIOR];
}

- (RollbarCaptureIpType)captureIp {
NSString *valueString = [self safelyGetStringByKey:DFK_IP_CAPTURE_TYPE];
return [RollbarCaptureIpTypeUtil CaptureIpTypeFromString:valueString];
Expand All @@ -167,8 +183,7 @@ @implementation RollbarMutableLoggingOptions

#pragma mark - initializers

-(instancetype)init {

- (instancetype)init {
if (self = [super init]) {
return self;
}
Expand All @@ -180,6 +195,7 @@ -(instancetype)init {
@dynamic logLevel;
@dynamic crashLevel;
@dynamic maximumReportsPerMinute;
@dynamic rateLimitBehavior;
@dynamic captureIp;
@dynamic codeVersion;
@dynamic framework;
Expand All @@ -199,31 +215,23 @@ - (void)setMaximumReportsPerMinute:(NSUInteger)value {
[self setUInteger:value forKey:DFK_MAX_REPORTS_PER_MINUTE];
}

- (void)setRateLimitBehavior:(RollbarRateLimitBehavior)behavior {
[self setInteger:behavior forKey:DFK_RATE_LIMIT_BEHAVIOR];
}

- (void)setCaptureIp:(RollbarCaptureIpType)value {
NSString *valueString = [RollbarCaptureIpTypeUtil CaptureIpTypeToString:value];
[self setString:valueString forKey:DFK_IP_CAPTURE_TYPE];
}

//- (nullable NSString *)codeVersion {
// return [self getDataByKey:DFK_CODE_VERSION];
//}

- (void)setCodeVersion:(nullable NSString *)value {
[self setData:value byKey:DFK_CODE_VERSION];
}

//- (nullable NSString *)framework; {
// return [self getDataByKey:DFK_FRAMEWORK];
//}

- (void)setFramework:(nullable NSString *)value {
[self setData:value byKey:DFK_FRAMEWORK];
}

//- (nullable NSString *)requestId {
// return [self getDataByKey:DFK_REQUEST_ID];
//}

- (void)setRequestId:(nullable NSString *)value {
[self setData:value byKey:DFK_REQUEST_ID];
}
Expand Down
7 changes: 1 addition & 6 deletions RollbarNotifier/Sources/RollbarNotifier/Rollbar.m
Original file line number Diff line number Diff line change
Expand Up @@ -380,16 +380,11 @@ + (void)criticalError:(NSError *)error data:(NSDictionary<NSString *, id> *)data
#pragma mark - Send manually constructed JSON payload

+ (void)sendJsonPayload:(NSData *)payload {

[[RollbarThread sharedInstance] sendPayload:payload
usingConfig:[Rollbar configuration]
];
[[RollbarThread sharedInstance] sendPayload:payload withConfig:[Rollbar configuration]];
}


#pragma mark - Telemetry API


#pragma mark - Dom

+ (void)recordViewEventForLevel:(RollbarLevel)level
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ NS_ASSUME_NONNULL_BEGIN

@property (readonly, nonnull) RollbarRegistry *registry;

- (BOOL)canPost;
- (BOOL)canPostWithConfig:(nonnull RollbarConfig *)config;
- (void)recordPostReply:(nullable RollbarPayloadPostReply *)reply;
- (void)recordPostReply:(nullable RollbarPayloadPostReply *)reply
withConfig:(nonnull RollbarConfig *)config;

- (instancetype)initWithConfig:(nonnull RollbarConfig *)config
andRegistry:(nonnull RollbarRegistry *)registry
Expand Down
40 changes: 20 additions & 20 deletions RollbarNotifier/Sources/RollbarNotifier/RollbarDestinationRecord.m
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#import "RollbarDestinationRecord.h"
#import "RollbarRegistry.h"
#import "RollbarInfrastructure.h"
#import "RollbarInternalLogging.h"

@implementation RollbarDestinationRecord {
Expand All @@ -8,6 +9,10 @@ @implementation RollbarDestinationRecord {

#pragma mark - property accessors

- (RollbarRateLimitBehavior)rateLimitBehavior {
return RollbarInfrastructure.sharedInstance.configuration.loggingOptions.rateLimitBehavior;
}

#pragma mark - initializers

- (instancetype)initWithConfig:(nonnull RollbarConfig *)config
Expand Down Expand Up @@ -49,14 +54,6 @@ - (instancetype)initWithDestinationID:(nonnull NSString *)destinationID

#pragma mark - methods

- (BOOL)canPost {
if (!self->_nextEarliestPost) {
return NO;
}

return [self->_nextEarliestPost compare:[NSDate date]] != NSOrderedDescending;
}

- (BOOL)canPostWithConfig:(nonnull RollbarConfig *)config {
if (self->_nextLocalWindowStart && (self->_localWindowCount >= config.loggingOptions.maximumReportsPerMinute)) {
// we already exceeded local rate limits, let's wait till the next local rate limiting window:
Expand All @@ -71,14 +68,15 @@ - (BOOL)canPostWithConfig:(nonnull RollbarConfig *)config {
BOOL shouldPost = [self->_nextEarliestPost compare:[NSDate date]] != NSOrderedDescending;

if (shouldPost) {
RBLog(@"%@%@ :: GO", self->_nextEarliestPost, [NSDate date]);
RBLog(@"Rate limit %@%@ :: GO", self->_nextEarliestPost, [NSDate date]);
}

return shouldPost;
}

- (void)recordPostReply:(nullable RollbarPayloadPostReply *)reply {

- (void)recordPostReply:(nullable RollbarPayloadPostReply *)reply
withConfig:(nonnull RollbarConfig *)config
{
if (!reply) {
//no response from the server to our lates POST of a payload,
//let's hold on on posting to the destination for 1 minute:
Expand All @@ -90,25 +88,30 @@ - (void)recordPostReply:(nullable RollbarPayloadPostReply *)reply {
return; // nothing else to do...
}

switch(reply.statusCode) {
case 429: // too many requests
self->_nextLocalWindowStart = [NSDate dateWithTimeIntervalSinceNow:reply.remainingSeconds];;
self->_serverWindowRemainingCount = 0;
break;
switch (reply.statusCode) {
case 403: // access denied
case 404: // not found
RBLog(@"\tQueuing record");
//let's hold on on posting to the destination for 1 minute:
self->_nextEarliestPost = [NSDate dateWithTimeIntervalSinceNow:60];
self->_localWindowCount = 0;
self->_serverWindowRemainingCount = 0;
self->_nextLocalWindowStart = self->_nextEarliestPost;
self->_nextServerWindowStart = nil;
return; // nothing else to do...
case 429: // too many requests
if (self.rateLimitBehavior == RollbarRateLimitBehavior_Queue) {
RBLog(@"\tQueuing record");
self->_nextLocalWindowStart = [NSDate dateWithTimeIntervalSinceNow:reply.remainingSeconds];
self->_serverWindowRemainingCount = 0;
break;
}
case 200: // OK
case 400: // bad request
case 413: // request entity too large
case 422: // unprocessable entity
default:
RBLog(@"\tDropping record");
self->_nextServerWindowStart = [NSDate dateWithTimeIntervalSinceNow:reply.remainingSeconds];;
self->_serverWindowRemainingCount = reply.remainingCount;
if (self->_nextLocalWindowStart) {
Expand Down Expand Up @@ -150,7 +153,6 @@ - (nonnull NSString *)description {
" nextLocalWindowStart: %@\n"
" nextServerWindowStart: %@\n"
" nextEarliestPost: %@\n"
" canPost: %@\n"
,
super.description,
self->_destinationID,
Expand All @@ -159,9 +161,7 @@ - (nonnull NSString *)description {
self->_serverWindowRemainingCount,
self->_nextLocalWindowStart,
self->_nextServerWindowStart,
self->_nextEarliestPost,
[self canPost] ? @"YES" : @"NO"
];
self->_nextEarliestPost];
return description;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#import "RollbarTelemetry.h"
#import "RollbarCrashCollector.h"
#import "RollbarInternalLogging.h"
#import "RollbarThread.h"

NS_ASSUME_NONNULL_BEGIN

Expand Down Expand Up @@ -49,8 +50,11 @@ - (nonnull instancetype)configureWith:(nonnull RollbarConfig *)config {
[self.collector install];
[self.collector sendAllReports];

NSLog(@"Rollbar is running")

// Create RollbarThread and begin processing persisted occurrences
if ([[RollbarThread sharedInstance] active]) {
NSLog(@"Rollbar is running")
}

return self;
}

Expand Down
Loading

0 comments on commit 80a4cd4

Please sign in to comment.