Merge pull request #46 from instana/geo
This commit is contained in:
@@ -48,6 +48,20 @@ app.use((req, res, next) => {
|
||||
next();
|
||||
});
|
||||
|
||||
app.use((req, res, next) => {
|
||||
let dcs = [
|
||||
"asia-northeast2",
|
||||
"asia-south1",
|
||||
"europe-west3",
|
||||
"us-east1",
|
||||
"us-west1"
|
||||
];
|
||||
let span = instana.currentSpan();
|
||||
span.annotate('custom.sdk.tags.datacenter', dcs[Math.floor(Math.random() * dcs.length)]);
|
||||
|
||||
next();
|
||||
});
|
||||
|
||||
app.use(bodyParser.urlencoded({ extended: true }));
|
||||
app.use(bodyParser.json());
|
||||
|
||||
|
@@ -38,6 +38,20 @@ app.use((req, res, next) => {
|
||||
next();
|
||||
});
|
||||
|
||||
app.use((req, res, next) => {
|
||||
let dcs = [
|
||||
"asia-northeast2",
|
||||
"asia-south1",
|
||||
"europe-west3",
|
||||
"us-east1",
|
||||
"us-west1"
|
||||
];
|
||||
let span = instana.currentSpan();
|
||||
span.annotate('custom.sdk.tags.datacenter', dcs[Math.floor(Math.random() * dcs.length)]);
|
||||
|
||||
next();
|
||||
});
|
||||
|
||||
app.use(bodyParser.urlencoded({ extended: true }));
|
||||
app.use(bodyParser.json());
|
||||
|
||||
|
@@ -26,6 +26,14 @@ var (
|
||||
rabbitCloseError chan *amqp.Error
|
||||
rabbitReady chan bool
|
||||
errorPercent int
|
||||
|
||||
dataCenters = []string{
|
||||
"asia-northeast2",
|
||||
"asia-south1",
|
||||
"europe-west3",
|
||||
"us-east1",
|
||||
"us-west1",
|
||||
}
|
||||
)
|
||||
|
||||
func connectToRabbitMQ(uri string) *amqp.Connection {
|
||||
@@ -115,6 +123,9 @@ func createSpan(headers map[string]interface{}, order string) {
|
||||
log.Println("Creating child span")
|
||||
// create child span
|
||||
span = tracer.StartSpan("getOrder", ot.ChildOf(spanContext))
|
||||
|
||||
fakeDataCenter := dataCenters[rand.Intn(len(dataCenters))]
|
||||
span.SetTag("datacenter", fakeDataCenter)
|
||||
} else {
|
||||
log.Println(err)
|
||||
log.Println("Failed to get context from headers")
|
||||
@@ -154,6 +165,8 @@ func processSale(parentSpan ot.Span) {
|
||||
}
|
||||
|
||||
func main() {
|
||||
rand.Seed(time.Now().Unix())
|
||||
|
||||
// Instana tracing
|
||||
ot.InitGlobalTracer(instana.NewTracerWithOptions(&instana.Options{
|
||||
Service: Service,
|
||||
|
@@ -22,6 +22,11 @@ services:
|
||||
- mongodb
|
||||
networks:
|
||||
- robot-shop
|
||||
healthcheck:
|
||||
test: [ "CMD", "curl", "-H", "X-INSTANA-SYNTHETIC: 1", "-f", "http://localhost:8080/health" ]
|
||||
interval: 1s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
user:
|
||||
build:
|
||||
context: user
|
||||
@@ -31,6 +36,11 @@ services:
|
||||
- redis
|
||||
networks:
|
||||
- robot-shop
|
||||
healthcheck:
|
||||
test: [ "CMD", "curl", "-H", "X-INSTANA-SYNTHETIC: 1", "-f", "http://localhost:8080/health" ]
|
||||
interval: 1s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
cart:
|
||||
build:
|
||||
context: cart
|
||||
@@ -39,6 +49,11 @@ services:
|
||||
- redis
|
||||
networks:
|
||||
- robot-shop
|
||||
healthcheck:
|
||||
test: [ "CMD", "curl", "-H", "X-INSTANA-SYNTHETIC: 1", "-f", "http://localhost:8080/health" ]
|
||||
interval: 1s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
mysql:
|
||||
build:
|
||||
context: mysql
|
||||
@@ -83,6 +98,11 @@ services:
|
||||
- rabbitmq
|
||||
networks:
|
||||
- robot-shop
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-H", "X-INSTANA-SYNTHETIC: 1", "-f", "http://localhost:8080/health"]
|
||||
interval: 1s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
# Uncomment to change payment gateway
|
||||
#environment:
|
||||
#PAYMENT_GATEWAY: "https://www.worldpay.com"
|
||||
@@ -107,9 +127,13 @@ services:
|
||||
- "8080:8080"
|
||||
networks:
|
||||
- robot-shop
|
||||
#environment:
|
||||
# NGINX_INJECT_FAKE_IP: "1"
|
||||
# Uncomment to enable Instana EUM
|
||||
healthcheck:
|
||||
test: [ "CMD", "curl", "-H", "X-INSTANA-SYNTHETIC: 1", "-f", "http://localhost:8080/" ]
|
||||
interval: 1s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
# Uncomment to enable Instana EUM
|
||||
# environment:
|
||||
# INSTANA_EUM_KEY: <your eum key>
|
||||
# INSTANA_EUM_REPORTING_URL: https://eum-us-west-2.instana.io
|
||||
# INSTANA_EUM_REPORTING_URL: https://eum-eu-west-1.instana.io
|
||||
|
@@ -1,4 +1,6 @@
|
||||
import os
|
||||
import random
|
||||
|
||||
from locust import HttpUser, task, between
|
||||
from random import choice
|
||||
from random import randint
|
||||
@@ -6,30 +8,52 @@ from random import randint
|
||||
class UserBehavior(HttpUser):
|
||||
wait_time = between(2, 10)
|
||||
|
||||
# source: https://tools.tracemyip.org/search--ip/list
|
||||
fake_ip_addresses = [
|
||||
# white house
|
||||
"156.33.241.5",
|
||||
# Hollywood
|
||||
"34.196.93.245",
|
||||
# Chicago
|
||||
"98.142.103.241",
|
||||
# Los Angeles
|
||||
"192.241.230.151",
|
||||
# Berlin
|
||||
"46.114.35.116",
|
||||
# Singapore
|
||||
"52.77.99.130",
|
||||
# Sydney
|
||||
"60.242.161.215"
|
||||
]
|
||||
|
||||
def on_start(self):
|
||||
""" on_start is called when a Locust start before any task is scheduled """
|
||||
print('Starting')
|
||||
|
||||
@task
|
||||
def login(self):
|
||||
fake_ip = random.choice(self.fake_ip_addresses)
|
||||
|
||||
credentials = {
|
||||
'name': 'user',
|
||||
'password': 'password'
|
||||
}
|
||||
res = self.client.post('/api/user/login', json=credentials)
|
||||
res = self.client.post('/api/user/login', json=credentials, headers={'x-forwarded-for': fake_ip})
|
||||
print('login {}'.format(res.status_code))
|
||||
|
||||
|
||||
@task
|
||||
def load(self):
|
||||
self.client.get('/')
|
||||
user = self.client.get('/api/user/uniqueid').json()
|
||||
fake_ip = random.choice(self.fake_ip_addresses)
|
||||
|
||||
self.client.get('/', headers={'x-forwarded-for': fake_ip})
|
||||
user = self.client.get('/api/user/uniqueid', headers={'x-forwarded-for': fake_ip}).json()
|
||||
uniqueid = user['uuid']
|
||||
print('User {}'.format(uniqueid))
|
||||
|
||||
self.client.get('/api/catalogue/categories')
|
||||
self.client.get('/api/catalogue/categories', headers={'x-forwarded-for': fake_ip})
|
||||
# all products in catalogue
|
||||
products = self.client.get('/api/catalogue/products').json()
|
||||
products = self.client.get('/api/catalogue/products', headers={'x-forwarded-for': fake_ip}).json()
|
||||
for i in range(2):
|
||||
item = None
|
||||
while True:
|
||||
@@ -39,28 +63,28 @@ class UserBehavior(HttpUser):
|
||||
|
||||
# vote for item
|
||||
if randint(1, 10) <= 3:
|
||||
self.client.put('/api/ratings/api/rate/{}/{}'.format(item['sku'], randint(1, 5)))
|
||||
self.client.put('/api/ratings/api/rate/{}/{}'.format(item['sku'], randint(1, 5)), headers={'x-forwarded-for': fake_ip})
|
||||
|
||||
self.client.get('/api/catalogue/product/{}'.format(item['sku']))
|
||||
self.client.get('/api/ratings/api/fetch/{}'.format(item['sku']))
|
||||
self.client.get('/api/cart/add/{}/{}/1'.format(uniqueid, item['sku']))
|
||||
self.client.get('/api/catalogue/product/{}'.format(item['sku']), headers={'x-forwarded-for': fake_ip})
|
||||
self.client.get('/api/ratings/api/fetch/{}'.format(item['sku']), headers={'x-forwarded-for': fake_ip})
|
||||
self.client.get('/api/cart/add/{}/{}/1'.format(uniqueid, item['sku']), headers={'x-forwarded-for': fake_ip})
|
||||
|
||||
cart = self.client.get('/api/cart/cart/{}'.format(uniqueid)).json()
|
||||
cart = self.client.get('/api/cart/cart/{}'.format(uniqueid), headers={'x-forwarded-for': fake_ip}).json()
|
||||
item = choice(cart['items'])
|
||||
self.client.get('/api/cart/update/{}/{}/2'.format(uniqueid, item['sku']))
|
||||
self.client.get('/api/cart/update/{}/{}/2'.format(uniqueid, item['sku']), headers={'x-forwarded-for': fake_ip})
|
||||
|
||||
# country codes
|
||||
code = choice(self.client.get('/api/shipping/codes').json())
|
||||
city = choice(self.client.get('/api/shipping/cities/{}'.format(code['code'])).json())
|
||||
code = choice(self.client.get('/api/shipping/codes', headers={'x-forwarded-for': fake_ip}).json())
|
||||
city = choice(self.client.get('/api/shipping/cities/{}'.format(code['code']), headers={'x-forwarded-for': fake_ip}).json())
|
||||
print('code {} city {}'.format(code, city))
|
||||
shipping = self.client.get('/api/shipping/calc/{}'.format(city['uuid'])).json()
|
||||
shipping = self.client.get('/api/shipping/calc/{}'.format(city['uuid']), headers={'x-forwarded-for': fake_ip}).json()
|
||||
shipping['location'] = '{} {}'.format(code['name'], city['name'])
|
||||
print('Shipping {}'.format(shipping))
|
||||
# POST
|
||||
cart = self.client.post('/api/shipping/confirm/{}'.format(uniqueid), json=shipping).json()
|
||||
cart = self.client.post('/api/shipping/confirm/{}'.format(uniqueid), json=shipping, headers={'x-forwarded-for': fake_ip}).json()
|
||||
print('Final cart {}'.format(cart))
|
||||
|
||||
order = self.client.post('/api/payment/pay/{}'.format(uniqueid), json=cart).json()
|
||||
order = self.client.post('/api/payment/pay/{}'.format(uniqueid), json=cart, headers={'x-forwarded-for': fake_ip}).json()
|
||||
print('Order {}'.format(order))
|
||||
|
||||
@task
|
||||
@@ -68,6 +92,6 @@ class UserBehavior(HttpUser):
|
||||
if os.environ.get('ERROR') == '1':
|
||||
print('Error request')
|
||||
cart = {'total': 0, 'tax': 0}
|
||||
self.client.post('/api/payment/pay/partner-57', json=cart)
|
||||
self.client.post('/api/payment/pay/partner-57', json=cart, headers={'x-forwarded-for': fake_ip})
|
||||
|
||||
|
||||
|
@@ -1,3 +1,5 @@
|
||||
import random
|
||||
|
||||
import instana
|
||||
import os
|
||||
import sys
|
||||
@@ -171,6 +173,29 @@ def countItems(items):
|
||||
|
||||
return count
|
||||
|
||||
class InstanaDataCenterMiddleware():
|
||||
data_centers = [
|
||||
"us-east1",
|
||||
"us-east2",
|
||||
"us-east3",
|
||||
"us-east4",
|
||||
"us-central1",
|
||||
"us-west1",
|
||||
"us-west2",
|
||||
"eu-west3",
|
||||
"eu-west4"
|
||||
]
|
||||
|
||||
def __init__(self, app):
|
||||
self.app = app
|
||||
|
||||
def __call__(self, environ, start_response):
|
||||
span = ot.tracer.active_span
|
||||
|
||||
span.log_kv({'datacenter': random.choice(self.data_centers)})
|
||||
|
||||
return self.app(environ, start_response)
|
||||
|
||||
|
||||
# RabbitMQ
|
||||
publisher = Publisher(app.logger)
|
||||
@@ -182,4 +207,5 @@ if __name__ == "__main__":
|
||||
app.logger.info('Payment gateway {}'.format(PAYMENT_GATEWAY))
|
||||
port = int(os.getenv("SHOP_PAYMENT_PORT", "8080"))
|
||||
app.logger.info('Starting on port {}'.format(port))
|
||||
app.wsgi_app = InstanaDataCenterMiddleware(app.wsgi_app)
|
||||
app.run(host='0.0.0.0', port=port)
|
||||
|
@@ -13,7 +13,8 @@
|
||||
"symfony/dependency-injection": "^5.0",
|
||||
"symfony/framework-bundle": "^5.0",
|
||||
"doctrine/annotations": "^1.10",
|
||||
"symfony/monolog-bundle": "^3.5"
|
||||
"symfony/monolog-bundle": "^3.5",
|
||||
"instana/instana-php-sdk": "^1.10"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
42
ratings/html/src/EventListener/InstanaDataCenterListener.php
Normal file
42
ratings/html/src/EventListener/InstanaDataCenterListener.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Instana\RobotShop\Ratings\EventListener;
|
||||
|
||||
use Instana\InstanaRuntimeException;
|
||||
use Instana\Tracer;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class InstanaDataCenterListener
|
||||
{
|
||||
private static $dataCenters = [
|
||||
"asia-northeast2",
|
||||
"asia-south1",
|
||||
"europe-west3",
|
||||
"us-east1",
|
||||
"us-west1"
|
||||
];
|
||||
|
||||
/**
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
public function __construct(LoggerInterface $logger)
|
||||
{
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
public function __invoke()
|
||||
{
|
||||
try {
|
||||
$entry = Tracer::getEntrySpan();
|
||||
|
||||
$dataCenter = self::$dataCenters[array_rand(self::$dataCenters)];
|
||||
$entry->annotate('datacenter', $dataCenter);
|
||||
|
||||
$this->logger->info(sprintf('Annotated DataCenter %s', $dataCenter));
|
||||
} catch (InstanaRuntimeException $exception) {
|
||||
$this->logger->error('Unable to annotate entry span: %s', $exception->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
@@ -6,6 +6,7 @@ namespace Instana\RobotShop\Ratings;
|
||||
|
||||
use Instana\RobotShop\Ratings\Controller\HealthController;
|
||||
use Instana\RobotShop\Ratings\Controller\RatingsApiController;
|
||||
use Instana\RobotShop\Ratings\EventListener\InstanaDataCenterListener;
|
||||
use Instana\RobotShop\Ratings\Integration\InstanaHeadersLoggingProcessor;
|
||||
use Instana\RobotShop\Ratings\Service\CatalogueService;
|
||||
use Instana\RobotShop\Ratings\Service\HealthCheckService;
|
||||
@@ -120,6 +121,12 @@ class Kernel extends BaseKernel implements EventSubscriberInterface
|
||||
->addMethodCall('setLogger', [new Reference('logger')])
|
||||
->addTag('controller.service_arguments')
|
||||
->setAutowired(true);
|
||||
|
||||
$c->register(InstanaDataCenterListener::class)
|
||||
->addTag('kernel.event_listener', [
|
||||
'event' => 'kernel.request'
|
||||
])
|
||||
->setAutowired(true);
|
||||
}
|
||||
|
||||
protected function configureRoutes(RouteCollectionBuilder $routes)
|
||||
|
@@ -36,6 +36,12 @@
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.instana</groupId>
|
||||
<artifactId>instana-java-sdk</artifactId>
|
||||
<version>1.2.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
@@ -46,7 +52,7 @@
|
||||
<artifactId>httpclient</artifactId>
|
||||
<version>4.5.12</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
|
@@ -1,7 +1,10 @@
|
||||
package com.instana.robotshop.shipping;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import com.instana.sdk.support.SpanSupport;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@@ -11,14 +14,29 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.retry.annotation.EnableRetry;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableRetry
|
||||
public class ShippingServiceApplication {
|
||||
@EnableWebMvc
|
||||
public class ShippingServiceApplication implements WebMvcConfigurer {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(ShippingServiceApplication.class, args);
|
||||
}
|
||||
private static final String[] DATA_CENTERS = {
|
||||
"asia-northeast2",
|
||||
"asia-south1",
|
||||
"europe-west3",
|
||||
"us-east1",
|
||||
"us-west1"
|
||||
};
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(ShippingServiceApplication.class, args);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public BeanPostProcessor dataSourceWrapper() {
|
||||
@@ -26,7 +44,7 @@ public class ShippingServiceApplication {
|
||||
}
|
||||
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
private class DataSourcePostProcessor implements BeanPostProcessor {
|
||||
private static class DataSourcePostProcessor implements BeanPostProcessor {
|
||||
@Override
|
||||
public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException {
|
||||
if (bean instanceof DataSource) {
|
||||
@@ -40,4 +58,19 @@ public class ShippingServiceApplication {
|
||||
return bean;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor(new InstanaDatacenterTagInterceptor());
|
||||
}
|
||||
|
||||
private static class InstanaDatacenterTagInterceptor extends HandlerInterceptorAdapter {
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
|
||||
SpanSupport.annotate("datacenter", DATA_CENTERS[new Random().nextInt(DATA_CENTERS.length)]);
|
||||
|
||||
return super.preHandle(request, response, handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -41,6 +41,20 @@ app.use((req, res, next) => {
|
||||
next();
|
||||
});
|
||||
|
||||
app.use((req, res, next) => {
|
||||
let dcs = [
|
||||
"asia-northeast2",
|
||||
"asia-south1",
|
||||
"europe-west3",
|
||||
"us-east1",
|
||||
"us-west1"
|
||||
];
|
||||
let span = instana.currentSpan();
|
||||
span.annotate('custom.sdk.tags.datacenter', dcs[Math.floor(Math.random() * dcs.length)]);
|
||||
|
||||
next();
|
||||
});
|
||||
|
||||
app.use(bodyParser.urlencoded({ extended: true }));
|
||||
app.use(bodyParser.json());
|
||||
|
||||
|
@@ -2,11 +2,6 @@ FROM nginx:1.19
|
||||
|
||||
EXPOSE 8080
|
||||
|
||||
RUN sed -i '1i load_module \"modules/ngx_http_js_module.so\";' /etc/nginx/nginx.conf && \
|
||||
sed -i '1i load_module \"modules/ngx_stream_js_module.so\";' /etc/nginx/nginx.conf
|
||||
|
||||
COPY instana_random_geo.js /opt/nginx_js/instana_random_geo.js
|
||||
|
||||
ENV CATALOGUE_HOST=catalogue \
|
||||
USER_HOST=user \
|
||||
CART_HOST=cart \
|
||||
|
@@ -54,32 +54,26 @@ server {
|
||||
#}
|
||||
|
||||
location /api/catalogue/ {
|
||||
proxy_set_header x-forwarded-for $fake_ip;
|
||||
proxy_pass http://${CATALOGUE_HOST}:8080/;
|
||||
}
|
||||
|
||||
location /api/user/ {
|
||||
proxy_set_header x-forwarded-for $fake_ip;
|
||||
proxy_pass http://${USER_HOST}:8080/;
|
||||
}
|
||||
|
||||
location /api/cart/ {
|
||||
proxy_set_header x-forwarded-for $fake_ip;
|
||||
proxy_pass http://${CART_HOST}:8080/;
|
||||
}
|
||||
|
||||
location /api/shipping/ {
|
||||
proxy_set_header X-Forwarded-For $fake_ip;
|
||||
proxy_pass http://${SHIPPING_HOST}:8080/;
|
||||
}
|
||||
|
||||
location /api/payment/ {
|
||||
proxy_set_header x-forwarded-for $fake_ip;
|
||||
proxy_pass http://${PAYMENT_HOST}:8080/;
|
||||
}
|
||||
|
||||
location /api/ratings/ {
|
||||
proxy_set_header x-forwarded-for $fake_ip;
|
||||
proxy_pass http://${RATINGS_HOST}:80/;
|
||||
}
|
||||
|
||||
|
@@ -1,23 +0,0 @@
|
||||
var items = [
|
||||
// white house
|
||||
"156.33.241.5",
|
||||
// Hollywood
|
||||
"34.196.93.245",
|
||||
// Chicago
|
||||
"98.142.103.241",
|
||||
// Los Angeles
|
||||
"192.241.230.151",
|
||||
// Europe
|
||||
"34.105.212.119"
|
||||
];
|
||||
|
||||
// we get a random ip address to simulate specific locations of the requester
|
||||
function get(r) {
|
||||
if (process.env.NGINX_INJECT_FAKE_IP != '1') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return items[Math.floor(Math.random() * items.length)];
|
||||
}
|
||||
|
||||
export default get;
|
Reference in New Issue
Block a user