Skip to content

Commit

Permalink
Added module "fault-injection.js" for injecting errors to test applic…
Browse files Browse the repository at this point in the history
…ation resiliency. (#74)
  • Loading branch information
wanpf authored Oct 20, 2023
1 parent d8e8e4a commit 90ec8f3
Show file tree
Hide file tree
Showing 3 changed files with 359 additions and 0 deletions.
2 changes: 2 additions & 0 deletions pjs/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@
"http/access-log.js",
"http/auth.js",
"http/route.js",
"http/fault-injection.js",
"filter/request-redirect.js",
"filter/header-modifier.js",
"filter/url-rewrite.js",
Expand All @@ -156,6 +157,7 @@
"http/access-log.js",
"http/auth.js",
"http/route.js",
"http/fault-injection.js",
"filter/request-redirect.js",
"filter/header-modifier.js",
"filter/url-rewrite.js",
Expand Down
108 changes: 108 additions & 0 deletions pjs/http/fault-injection.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
((
{ config, isDebugEnabled } = pipy.solve('config.js'),

delayFaultCache = new algo.Cache(
route => (
(
range,
min = 0,
max = 0,
unit = 0.001, // default ms
delay = route?.config?.Fault?.Delay || __domain?.Fault?.Delay || config?.Configs?.Fault?.Delay,
percent = delay?.Percent,
fixed = delay?.Fixed,
) => (
percent > 0 && (
delay.Unit?.toLowerCase?.() === 's' ? (
unit = 1
) : delay.Unit?.toLowerCase?.() === 'm' && (
unit = 60
),
delay.Range ? (
range = delay.Range.split('-'),
min = range[0],
max = range[1],
min >= 0 && max >= min && (
() => (
Math.floor(Math.random() * 100) <= percent ? (
(Math.floor(Math.random() * (max - min + 1)) + min) * unit
) : 0
)
)
) : fixed > 0 && (
fixed *= unit,
() => (
Math.floor(Math.random() * 100) <= percent ? (
fixed
) : 0
)
)
) || null
)
)()
),

abortFaultCache = new algo.Cache(
route => (
(
abort = route?.config?.Fault?.Abort || __domain?.Fault?.Abort || config?.Configs?.Fault?.Abort,
percent = abort?.Percent,
status = abort?.Status,
message,
) => (
percent > 0 && status > 0 && (
__domain.RouteType === 'GRPC' ? (
message = new Message({ status: 200, headers: { 'content-type': 'application/grpc', 'grpc-encoding': 'identity' } }, null, { headers: { 'grpc-status': status, 'grpc-message': abort?.Message || '' } })
) : (
message = new Message({ status }, abort?.Message || '')
),
() => (
Math.floor(Math.random() * 100) <= percent ? (
message
) : null
)
) || null
)
)()
),

) => pipy({
_timeout: 0,
_message: null,
})

.import({
__domain: 'route',
__route: 'route',
})

.pipeline()
.branch(
() => (_timeout = delayFaultCache.get(__route)?.()) > 0, (
$=>$.handleMessageStart(
() => new Timeout(_timeout).wait()
)
), (
$=>$
)
)
.branch(
() => _message = abortFaultCache.get(__route)?.(), (
$=>$.replaceMessage(
() => _message
)
), (
$=>$.chain()
)
)
.branch(
isDebugEnabled, (
$=>$.handleMessageStart(
() => (_timeout || _message) && (
console.log('[fault-injection] delay, message:', _timeout, _message)
)
)
)
)

)()
249 changes: 249 additions & 0 deletions pjs/samples/fault-injection/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,249 @@
{
"Configs": {
"EnableDebug": true,
"ErrorPage": [
{
"Error": [
404
],
"Page": "404.html",
"Directory": "pages/"
},
{
"Error": [
502
],
"Page": "502.html",
"Directory": "pages/"
}
],
"Gzip": {
"GzipMinLength": 1024,
"GzipTypes": [
"text/css",
"text/xml",
"text/html",
"text/plain",
"application/xhtml+xml",
"application/javascript"
]
}
},
"Listeners": [
{
"Protocol": "HTTP",
"Port": 8080
},
{
"Protocol": "HTTP",
"Port": 8081
},
{
"Protocol": "HTTP",
"Port": 8082
},
{
"Protocol": "HTTP",
"Port": 50052
}
],
"RouteRules": {
"8080": {
"*": {
"RouteType": "HTTP",
"AccessLog": "/var/log/fgw-access.log",
"Fault": {
"Delay": {
"Percent": 50,
"Fixed": 300,
"Unit": "ms"
},
"Abort": {
"Percent": 50,
"Status": 503,
"Message": "fault-injection-message"
}
},
"Matches": [
{
"Path": {
"Type": "Prefix",
"Path": "/"
},
"BackendService": {
"backendService1": {
"Weight": 100
}
}
}
]
}
},
"8081": {
"*": {
"Matches": [
{
"ServerRoot": "/var/www/html",
"Index": [
"index.html",
"index.htm"
],
"TryFiles": [
"$uri",
"$uri/default/",
"=404"
]
}
]
}
},
"8082": {
"*": {
"Matches": [
{
"ServerRoot": "www2",
"Index": [
"default.html",
"index.html"
]
}
]
}
},
"50052": {
"*": {
"RouteType": "GRPC",
"Matches": [
{
"Fault": {
"Delay": {
"Percent": 50,
"Fixed": 300
},
"Abort": {
"Percent": 50,
"Status": 14,
"Message": "fault-injection-message"
}
},
"Method": {
"Type": "Exact",
"Service": "helloworld.Greeter",
"Method": "SayHello"
},
"BackendService": {
"backendService2": {
"Weight": 100
}
}
}
]
}
}
},
"Services": {
"backendService1": {
"StickyCookieName": "_srv_id",
"StickyCookieExpires": 3600,
"HealthCheck0": {
"Interval": 10,
"MaxFails": 3,
"FailTimeout": 30,
"Uri": "/",
"Matches": [
{
"Type": "status",
"Value": [
200
]
}
]
},
"Endpoints": {
"127.0.0.1:8081": {
"Weight": 50
},
"127.0.0.1:8082": {
"Weight": 50
}
}
},
"backendService2": {
"Endpoints": {
"127.0.0.1:50051": {
"Weight": 50
}
}
}
},
"Chains": {
"HTTPRoute": [
"common/access-control.js",
"common/ratelimit.js",
"common/consumer.js",
"http/codec.js",
"http/access-log.js",
"http/auth.js",
"http/route.js",
"http/fault-injection.js",
"filter/request-redirect.js",
"filter/header-modifier.js",
"filter/url-rewrite.js",
"http/service.js",
"http/metrics.js",
"http/tracing.js",
"http/logging.js",
"http/circuit-breaker.js",
"http/throttle-domain.js",
"http/throttle-route.js",
"http/error-page.js",
"http/proxy-redirect.js",
"http/forward.js",
"http/default.js"
],
"HTTPSRoute": [
"common/access-control.js",
"common/ratelimit.js",
"common/tls-termination.js",
"common/consumer.js",
"http/codec.js",
"http/access-log.js",
"http/auth.js",
"http/route.js",
"http/fault-injection.js",
"filter/request-redirect.js",
"filter/header-modifier.js",
"filter/url-rewrite.js",
"http/service.js",
"http/metrics.js",
"http/tracing.js",
"http/logging.js",
"http/circuit-breaker.js",
"http/throttle-domain.js",
"http/throttle-route.js",
"http/error-page.js",
"http/proxy-redirect.js",
"http/forward.js",
"http/default.js"
],
"TLSPassthrough": [
"common/access-control.js",
"common/ratelimit.js",
"tls/passthrough.js",
"common/consumer.js"
],
"TLSTerminate": [
"common/access-control.js",
"common/ratelimit.js",
"common/tls-termination.js",
"common/consumer.js",
"tls/forward.js"
],
"TCPRoute": [
"common/access-control.js",
"common/ratelimit.js",
"tcp/forward.js"
]
},
"Version": "0"
}

0 comments on commit 90ec8f3

Please sign in to comment.