-
-
Notifications
You must be signed in to change notification settings - Fork 723
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: make all internal rate limits configurable #5095
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,6 +19,7 @@ import { | |
ICspDomainOptions, | ||
IClientCachingOption, | ||
IMetricsRateLimiting, | ||
IRateLimiting, | ||
} from './types/option'; | ||
import { getDefaultLogProvider, LogLevel, validateLogProvider } from './logger'; | ||
import { defaultCustomAuthDenyAll } from './default-custom-auth-deny-all'; | ||
|
@@ -132,6 +133,23 @@ function loadMetricsRateLimitingConfig( | |
]); | ||
} | ||
|
||
function loadRateLimitingConfig(options: IUnleashOptions): IRateLimiting { | ||
const createUserMaxPerMinute = parseEnvVarNumber( | ||
process.env.CREATE_USER_RATE_LIMIT_PER_MINUTE, | ||
20, | ||
); | ||
const simpleLoginMaxPerMinute = parseEnvVarNumber( | ||
process.env.SIMPLE_LOGIN_LIMIT_PER_MINUTE, | ||
10, | ||
Comment on lines
+138
to
+143
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Curious as to why one is called "x_RATE_LIMIT_PER_MINUTE" and the other is just called "x_LIMIT_PER_MINUTE"? Not a big deal, but feels like they should have similar names to make it easier to remember. |
||
); | ||
|
||
const defaultRateLimitOptions: IRateLimiting = { | ||
createUserMaxPerMinute, | ||
simpleLoginMaxPerMinute, | ||
}; | ||
return mergeAll([defaultRateLimitOptions, options.rateLimiting || {}]); | ||
} | ||
|
||
function loadUI(options: IUnleashOptions): IUIConfig { | ||
const uiO = options.ui || {}; | ||
const ui: IUIConfig = { | ||
|
@@ -525,6 +543,8 @@ export function createConfig(options: IUnleashOptions): IUnleashConfig { | |
|
||
const metricsRateLimiting = loadMetricsRateLimitingConfig(options); | ||
|
||
const rateLimiting = loadRateLimitingConfig(options); | ||
|
||
return { | ||
db, | ||
session, | ||
|
@@ -559,6 +579,7 @@ export function createConfig(options: IUnleashOptions): IUnleashConfig { | |
disableScheduler: options.disableScheduler, | ||
isEnterprise: isEnterprise, | ||
metricsRateLimiting, | ||
rateLimiting, | ||
}; | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -190,6 +190,12 @@ export default class MetricsMonitor { | |
labelNames: ['environment'], | ||
}); | ||
|
||
const rateLimits = new client.Gauge({ | ||
name: 'rate_limits', | ||
help: 'Rate limits (per minute) for METHOD/ENDPOINT pairs', | ||
labelNames: ['endpoint', 'method'], | ||
}); | ||
|
||
async function collectStaticCounters() { | ||
try { | ||
const stats = await instanceStatsService.getStats(); | ||
|
@@ -259,6 +265,42 @@ export default class MetricsMonitor { | |
.labels({ range: clientStat.range }) | ||
.set(clientStat.count), | ||
); | ||
|
||
rateLimits.reset(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any particular reason we need to reset it here? Will we have gotten any inputs before this point that we need to get rid of? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm still not sure, I just followed the patterns for the rest of our static metrics. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In my mind since it's a gauge there shouldn't really be a need to reset it. |
||
rateLimits | ||
.labels({ endpoint: '/api/client/metrics', method: 'POST' }) | ||
.set(config.metricsRateLimiting.clientMetricsMaxPerMinute); | ||
rateLimits | ||
.labels({ | ||
endpoint: '/api/client/register', | ||
method: 'POST', | ||
}) | ||
.set(config.metricsRateLimiting.clientRegisterMaxPerMinute); | ||
rateLimits | ||
.labels({ | ||
endpoint: '/api/frontend/metrics', | ||
method: 'POST', | ||
}) | ||
.set( | ||
config.metricsRateLimiting.frontendMetricsMaxPerMinute, | ||
); | ||
rateLimits | ||
.labels({ | ||
endpoint: '/api/frontend/register', | ||
method: 'POST', | ||
}) | ||
.set( | ||
config.metricsRateLimiting.frontendRegisterMaxPerMinute, | ||
); | ||
Comment on lines
+270
to
+294
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Out of curiosity: what were all of these before? If these options are old, how were they applied? Did we do it somewhere else? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. there were no limits for register and metrics earlier besides what's configured on the loadbalancer side. |
||
rateLimits | ||
.labels({ | ||
endpoint: '/api/admin/user-admin', | ||
method: 'POST', | ||
}) | ||
.set(config.rateLimiting.createUserMaxPerMinute); | ||
rateLimits | ||
.labels({ endpoint: '/auth/simple', method: 'POST' }) | ||
.set(config.rateLimiting.simpleLoginMaxPerMinute); | ||
} catch (e) {} | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Irate limiting? 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
indeed, I was quite IRate while writing this :P