Skip to content

Commit

Permalink
Merge pull request #276 from rollbar/rate_limit
Browse files Browse the repository at this point in the history
Fix rate limiting with queuing behavior
  • Loading branch information
matux authored Mar 28, 2023
2 parents 6e895bf + 612e751 commit e2b536b
Show file tree
Hide file tree
Showing 9 changed files with 125 additions and 215 deletions.
12 changes: 8 additions & 4 deletions Demos/iosAppSwift/iosAppSwift/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ struct ContentView: View {
ScrollView {
VStack {
Group {
button("Log a message", action: example.logMessage)
button("Manual Logging Example", action: example.manualLogging)
.padding(.bottom)
button("Force unwrap nil") { example.forceUnwrapNil(Int?.none) }
Expand Down Expand Up @@ -90,12 +91,15 @@ struct ContentView_Previews: PreviewProvider {
struct Example {
let logger = RollbarLogger(configuration: Rollbar.configuration())

/// Some different ways to explicitly log an error to Rollbar.
func manualLogging() {
/// Log a single informational message to Rollbar.
func logMessage() {
Rollbar.infoMessage(
"Rollbar is up and running! Enjoy your remote error and log monitoring...",
data: ["key_x": "value_x", "key_y": "value_y"])
}

/// Some different ways to explicitly log an error to Rollbar.
func manualLogging() {
Rollbar.log(.error, message: "My log message")

let extraInfo = ["item_1": "value_1", "item_2": "value_2"]
Expand Down Expand Up @@ -175,8 +179,8 @@ struct Example {
print("duplicateKeys: \(key)")
var map = [key: 1, key: 1] // the illegal op.
// implementation detail:
// this function requires a bit more trickery to prevent
// the optimizer from simply removing the line above.
// this function requires a bit more effectful trickery to
// prevent the optimizer from simply removing the line above.
if let x = map[key] {
map[key] = x + x
}
Expand Down
2 changes: 1 addition & 1 deletion Demos/iosAppSwift/iosAppSwift/iosAppSwiftApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class AppDelegate: NSObject, UIApplicationDelegate {
// Optionally anonymize the IP address
//config.loggingOptions.captureIp = RollbarCaptureIpType.anonymize

// Suppress Rollbar event being logged (e.g. in XCode debug logs)
// Suppress (default) Rollbar internal logging
config.developerOptions.suppressSdkInfoLogging = true

config.telemetry.enabled = true
Expand Down
38 changes: 12 additions & 26 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 "RollbarInternalLogging.h"

@implementation RollbarDestinationRecord {
@private
Expand Down Expand Up @@ -49,22 +50,14 @@ - (instancetype)initWithDestinationID:(nonnull NSString *)destinationID
#pragma mark - methods

- (BOOL)canPost {

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

if (NSOrderedDescending == [self->_nextEarliestPost compare:[NSDate date]]) {
return NO;
}
else {
return YES;
}

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:
//self->_nextEarliestPost = self->_nextLocalWindowStart;
Expand All @@ -74,13 +67,14 @@ - (BOOL)canPostWithConfig:(nonnull RollbarConfig *)config {
if (!self->_nextEarliestPost) {
return NO;
}

if (NSOrderedDescending == [self->_nextEarliestPost compare:[NSDate date]]) {
return NO;
}
else {
return YES;

BOOL shouldPost = [self->_nextEarliestPost compare:[NSDate date]] != NSOrderedDescending;

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

return shouldPost;
}

- (void)recordPostReply:(nullable RollbarPayloadPostReply *)reply {
Expand Down Expand Up @@ -117,11 +111,10 @@ - (void)recordPostReply:(nullable RollbarPayloadPostReply *)reply {
default:
self->_nextServerWindowStart = [NSDate dateWithTimeIntervalSinceNow:reply.remainingSeconds];;
self->_serverWindowRemainingCount = reply.remainingCount;
if (self->_nextLocalWindowStart ) {
if (self->_nextLocalWindowStart) {
self->_localWindowCount = 0;
self->_nextLocalWindowStart = [NSDate dateWithTimeIntervalSinceNow:60];
}
else {
} else {
self->_localWindowCount += 1;
}
break;
Expand Down Expand Up @@ -172,11 +165,4 @@ - (nonnull NSString *)description {
return description;
}

//- (NSString *)debugDescription {
// NSString *description = [NSString stringWithFormat:@"totalLoggerRecords: %lu",
// (unsigned long)[self totalLoggerRecords]
// ];
// return description;
//}

@end
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ void RBLog(NSString *format, ...) {

va_list args;
va_start(args, format);
fprintf(
stdout, "[Rollbar] %s\n",
fprintf(stdout, "[Rollbar] %s\n",
[[[NSString alloc] initWithFormat:format arguments:args] UTF8String]);
va_end(args);
#endif
Expand All @@ -24,8 +23,7 @@ void RBErr(NSString *format, ...) {

va_list args;
va_start(args, format);
fprintf(
stderr, "[Rollbar] %s\n",
fprintf(stderr, "[Rollbar] %s\n",
[[[NSString alloc] initWithFormat:format arguments:args] UTF8String]);
va_end(args);
#endif
Expand Down
42 changes: 12 additions & 30 deletions RollbarNotifier/Sources/RollbarNotifier/RollbarPayloadPostReply.m
Original file line number Diff line number Diff line change
@@ -1,54 +1,36 @@
#import "RollbarPayloadPostReply.h"

/// Rollbar API Service enforced payload rate limit:
static NSString * const RESPONSE_HEADER_RATE_LIMIT = @"x-rate-limit-limit";
/// Rollbar API Service enforced remaining payload count until the limit is reached:
static NSString * const RESPONSE_HEADER_REMAINING_COUNT = @"x-rate-limit-remaining";
/// Rollbar API Service enforced rate limit reset time for the current limit window:
static NSString * const RESPONSE_HEADER_RESET_TIME = @"x-rate-limit-reset";
/// Rollbar API Service enforced rate limit remaining seconds of the current limit window:
static NSString * const RESPONSE_HEADER_REMAINING_SECONDS = @"x-rate-limit-remaining-seconds";
static NSString * const RESPONSE_HEADER_RESET_TIME = @"x-rate-limit-reset"; // rate limit reset time for the current limit window
static NSString * const RESPONSE_HEADER_REMAINING_COUNT = @"x-rate-limit-remaining"; // remaining payload count until the limit is reached
static NSString * const RESPONSE_HEADER_REMAINING_SECONDS = @"x-rate-limit-remaining-seconds"; // rate limit remaining seconds of the current limit window

@implementation RollbarPayloadPostReply

+ (nullable RollbarPayloadPostReply *)replyFromHttpResponse:(nonnull NSHTTPURLResponse *)httpResponse {

NSUInteger rateLimit =
[NSNumber numberWithLongLong:[httpResponse valueForHTTPHeaderField:RESPONSE_HEADER_RATE_LIMIT]]
.unsignedIntegerValue;

NSUInteger remainingCount =
[NSNumber numberWithLongLong:[httpResponse valueForHTTPHeaderField:RESPONSE_HEADER_REMAINING_COUNT]]
.unsignedIntegerValue;
NSInteger rateLimit = [[httpResponse valueForHTTPHeaderField:RESPONSE_HEADER_RATE_LIMIT] integerValue];
NSInteger remainingCount = [[httpResponse valueForHTTPHeaderField:RESPONSE_HEADER_REMAINING_COUNT] integerValue];
NSInteger remainingSeconds = [[httpResponse valueForHTTPHeaderField:RESPONSE_HEADER_REMAINING_SECONDS] integerValue];

NSUInteger remainingSeconds =
[NSNumber numberWithLongLong:[httpResponse valueForHTTPHeaderField:RESPONSE_HEADER_REMAINING_SECONDS]]
.unsignedIntegerValue;

return [[RollbarPayloadPostReply alloc] initWithStatusCode:httpResponse.statusCode
rateLimit:rateLimit
remainingCount:remainingCount
remainingSeconds:remainingSeconds
];
remainingSeconds:remainingSeconds];
}

- (instancetype)initWithStatusCode:(NSUInteger)statusCode
rateLimit:(NSUInteger)rateLimit
remainingCount:(NSUInteger)remainingCount
remainingSeconds:(NSUInteger)remainingSeconds {
remainingSeconds:(NSUInteger)remainingSeconds
{
if (self = [super init]) {
self->_statusCode = statusCode;
self->_rateLimit = rateLimit;
self->_remainingCount = remainingCount;
self->_remainingSeconds = remainingSeconds;

if (self->_remainingCount > 0) {
self->_nextPostTime = [[NSDate alloc] init];
}
else {
self->_nextPostTime = [[NSDate alloc] initWithTimeIntervalSinceNow:self->_remainingSeconds];
}
self->_nextPostTime = self->_remainingCount > 0
? [[NSDate alloc] init]
: [[NSDate alloc] initWithTimeIntervalSinceNow:self->_remainingSeconds];
}

return self;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ NS_ASSUME_NONNULL_BEGIN

- (nonnull NSArray<NSDictionary<NSString *, NSString *> *> *)getAllPayloads;

- (NSInteger)getPayloadCount;

- (BOOL)removePayloadByID:(nonnull NSString *)payloadID;

- (BOOL)removePayloadsOlderThan:(nonnull NSDate *)cutoffTime;
Expand Down
18 changes: 18 additions & 0 deletions RollbarNotifier/Sources/RollbarNotifier/RollbarPayloadRepository.m
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,24 @@ - (BOOL)removeAllDestinations {
return result;
}

- (NSInteger)getPayloadCount {
const char *sql = "SELECT COUNT(*) FROM payloads";
sqlite3_stmt *statement;
NSInteger count = 0;

if (sqlite3_prepare_v2(self->_db, sql, -1, &statement, NULL) == SQLITE_OK) {
while (sqlite3_step(statement) == SQLITE_ROW) {
count = sqlite3_column_int(statement, 0);
break;
}
} else {
RBErr(@"sqlite3_prepare_v2 error %s", sqlite3_errmsg(self->_db));
}

sqlite3_finalize(statement);
return count;
}

- (BOOL)removePayloadByID:(nonnull NSString *)payloadID {

NSString *sql =
Expand Down
Loading

0 comments on commit e2b536b

Please sign in to comment.