Merge pull request #46 from instana/geo

This commit is contained in:
Cedric Ziel
2020-11-02 13:28:35 +01:00
committed by GitHub
15 changed files with 245 additions and 61 deletions

View File

@@ -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());

View File

@@ -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());

View File

@@ -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,

View File

@@ -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

View File

@@ -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})

View File

@@ -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)

View File

@@ -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": {

View 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());
}
}
}

View File

@@ -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)

View File

@@ -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>

View File

@@ -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);
}
}
}

View File

@@ -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());

View File

@@ -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 \

View File

@@ -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/;
}

View File

@@ -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;