Application Layer

Setup

Step by step

In a hurry? Skip to Complete examples.

  • Construct an ApplicationCoordinates instance.
  • Construct a TrafficCoordinates instance.
  • Optionally (if using a custom TrafficCoordinates instance) construct a GremlinService singleton.
  • Optionally (if using a custom TrafficCoordinates instance) inject the fault using com.gremlin.GremlinService#applyImpact(trafficCoordinates). Add this line of code anywhere in your application, you wish the fault to be injected.
  • Click here to create a new Attack.
  • Select an Application Query.
  • Set the necessary fields for the selected Application Query.
  • Select a Traffic Query.
  • Choose a Gremlin attack - Set the amount of latency in ms to apply and optionally throw a RuntimeException within your application.
  • Run the attack - Set the duration in seconds for how long the attack will last.
  • Test your application to observe the impact of the attack.

Complete examples

ALFI AWS

java
1package com.alfilambda;
2
3import com.amazonaws.services.lambda.runtime.Context;
4import com.amazonaws.services.lambda.runtime.LambdaLogger;
5import com.amazonaws.services.lambda.runtime.RequestHandler;
6import com.gremlin.*;
7import com.gremlin.aws.AwsApplicationCoordinatesResolver;
8
9import java.time.Duration;
10import java.time.Instant;
11import java.util.Map;
12
13public class AlfiDemoHandler implements RequestHandler<Map<String,String>, String> {
14
15 private final GremlinService gremlinService;
16
17 public AlfiDemoHandler() {
18 final GremlinServiceFactory factory = new GremlinServiceFactory(new GremlinCoordinatesProvider() {
19 @Override
20 public ApplicationCoordinates initializeApplicationCoordinates() {
21 ApplicationCoordinates coords = AwsApplicationCoordinatesResolver.inferFromEnvironment()
22 .orElseThrow(IllegalStateException::new);
23 return coords;
24 }
25 });
26 gremlinService = factory.getGremlinService();
27 }
28
29 @Override
30 public String handleRequest(Map<String, String> input, Context context) {
31 Instant start = Instant.now();
32 TrafficCoordinates trafficCoordinates = new TrafficCoordinates.Builder()
33 .withType(this.getClass().getSimpleName())
34 .withField("method", "handleRequest")
35 .build();
36 gremlinService.applyImpact(trafficCoordinates);
37 LambdaLogger logger = context.getLogger();
38 Instant finish = Instant.now();
39 long timeElapsed = Duration.between(start, finish).toMillis(); //in millis
40 logger.log(String.format("Lambda took %s millis", timeElapsed));
41 return new String("200 OK");
42 }
43}

ALFI DynamoDB

java
1package com.example.alfidynamodb.config;
2
3import com.amazonaws.ClientConfiguration;
4import com.amazonaws.handlers.RequestHandler2;
5import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
6import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
7import com.gremlin.*;
8import com.gremlin.aws.GremlinDynamoRequestInterceptor;
9import org.springframework.beans.factory.annotation.Value;
10import org.springframework.context.annotation.Bean;
11import org.springframework.context.annotation.Configuration;
12@Configuration
13public class AlfiConfig {
14
15 private static final String APPLICATION_QUERY_NAME = "ALFIDemoApplication";
16 private static final int CLIENT_EXECUTION_TIMEOUT = 1500;
17 private static final int CLIENT_REQUEST_TIMEOUT = 500;
18
19 @Value("${aws.region}")
20 private String region;
21
22
23 public GremlinCoordinatesProvider gremlinCoordinatesProvider() {
24 return new GremlinCoordinatesProvider() {
25 @Override
26 public ApplicationCoordinates initializeApplicationCoordinates() {
27 return new ApplicationCoordinates.Builder()
28 .withType(APPLICATION_QUERY_NAME)
29 .build();
30 }
31 };
32 }
33
34 public GremlinServiceFactory gremlinServiceFactory() {
35 return new GremlinServiceFactory(gremlinCoordinatesProvider());
36 }
37
38 public GremlinService gremlinService() {
39 return gremlinServiceFactory().getGremlinService();
40 }
41
42 @Bean
43 public AmazonDynamoDB amazonDynamoDB() {
44 final RequestHandler2 gremlinDynamoInterceptor = new GremlinDynamoRequestInterceptor(gremlinService(), CLIENT_EXECUTION_TIMEOUT, CLIENT_REQUEST_TIMEOUT);
45 return AmazonDynamoDBClientBuilder.standard()
46 .withRegion(region)
47 .withClientConfiguration(new ClientConfiguration()
48 .withClientExecutionTimeout(CLIENT_EXECUTION_TIMEOUT)
49 .withConnectionTimeout(CLIENT_REQUEST_TIMEOUT)
50 .withMaxErrorRetry(2)
51 )
52 .withRequestHandlers(gremlinDynamoInterceptor).build();
53 }
54
55}
java
1package com.example.alfidynamodb.persistence;
2
3import com.amazonaws.AmazonServiceException;
4import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
5import com.amazonaws.services.dynamodbv2.model.AttributeValue;
6import com.amazonaws.services.dynamodbv2.model.GetItemRequest;
7import com.amazonaws.services.kms.model.NotFoundException;
8import org.slf4j.Logger;
9import org.slf4j.LoggerFactory;
10import org.springframework.beans.factory.annotation.Autowired;
11import org.springframework.beans.factory.annotation.Value;
12import org.springframework.stereotype.Component;
13
14import java.util.HashMap;
15import java.util.Map;
16@Component
17public class GetItemRequester {
18
19 private final Logger LOG = LoggerFactory.getLogger(getClass().getName());
20
21 @Value("${dynamo.db.table}")
22 private String table;
23
24 private final AmazonDynamoDB amazonDynamoDB;
25
26 public GetItemRequester(@Autowired AmazonDynamoDB amazonDynamoDB) {
27 this.amazonDynamoDB = amazonDynamoDB;
28 }
29
30 public Map<String, AttributeValue> getItem(String id) {
31 long startTime = System.currentTimeMillis();
32 try {
33
34 LOG.info(String.format("Querying DynamoDB for item with ID %s...", id));
35 Map<String, AttributeValue> returnedItem = amazonDynamoDB.getItem(createRequestWithId(id)).getItem();
36 if (returnedItem != null) {
37 return returnedItem;
38 } else {
39 throw new NotFoundException(String.format("Item with id %s not found!", id));
40 }
41 } catch (AmazonServiceException e) {
42 LOG.error(e.getMessage());
43 throw e;
44 } finally {
45 long endTime = System.currentTimeMillis();
46 long duration = (endTime - startTime);
47 LOG.info(String.format("Call to DynamoDB took %s milliseconds.", duration));
48 }
49 }
50
51 private GetItemRequest createRequestWithId(String id) {
52 HashMap<String, AttributeValue> keyToGet = new HashMap<>();
53 keyToGet.put("id", new AttributeValue(id));
54 return new GetItemRequest().withKey(keyToGet).withTableName(table);
55 }
56}

ALFI HTTP Servlet Filter

java
1package com.example.rec;
2
3import com.gremlin.ApplicationCoordinates;
4import com.gremlin.GremlinCoordinatesProvider;
5import com.gremlin.GremlinService;
6import com.gremlin.GremlinServiceFactory;
7import com.gremlin.http.servlet.GremlinServletFilter;
8import org.springframework.boot.web.servlet.FilterRegistrationBean;
9import org.springframework.context.annotation.Bean;
10import org.springframework.context.annotation.Configuration;
11
12@Configuration
13public class WebConfig {
14
15 @Bean
16 public FilterRegistrationBean recommendationsFilterRegistrationBean() {
17 FilterRegistrationBean registrationBean = new FilterRegistrationBean();
18 registrationBean.setName("recs");
19
20 final GremlinCoordinatesProvider alfiCoordinatesProvider = new GremlinCoordinatesProvider() {
21 @Override
22 public ApplicationCoordinates initializeApplicationCoordinates() {
23 return new ApplicationCoordinates.Builder()
24 .withType("local")
25 .withField("service", "recommendations")
26 .build();
27 }
28 };
29 final GremlinServiceFactory alfiFactory = new GremlinServiceFactory(alfiCoordinatesProvider);
30 final GremlinService alfi = alfiFactory.getGremlinService();
31
32 GremlinServletFilter alfiFilter = new GremlinServletFilter(alfi);
33 registrationBean.setFilter(alfiFilter);
34 registrationBean.setOrder(1);
35 return registrationBean;
36 }
37
38}

ALFI Apache Http Client

java
1package com.example.alfiapachehttpclient.config;
2
3import org.springframework.context.annotation.Bean;
4import org.springframework.context.annotation.Configuration;
5import com.gremlin.*;
6
7@Configuration
8public class ALFIConfig {
9
10 private static final String APPLICATION_QUERY_NAME = "ALFIApacheHttpClientDemo";
11
12 public GremlinCoordinatesProvider gremlinCoordinatesProvider() {
13 return new GremlinCoordinatesProvider() {
14 @Override
15 public ApplicationCoordinates initializeApplicationCoordinates() {
16 return new ApplicationCoordinates.Builder()
17 .withType(APPLICATION_QUERY_NAME)
18 .build();
19 }
20 };
21 }
22
23 public GremlinServiceFactory gremlinServiceFactory() {
24 return new GremlinServiceFactory(gremlinCoordinatesProvider());
25 }
26
27 @Bean
28 public GremlinService gremlinService() {
29 return gremlinServiceFactory().getGremlinService();
30 }
31
32}
java
1package com.example.alfiapachehttpclient.config;
2
3import com.gremlin.GremlinService;
4import com.gremlin.http.client.GremlinApacheHttpRequestInterceptor;
5import org.apache.http.client.config.RequestConfig;
6import org.apache.http.impl.client.CloseableHttpClient;
7import org.apache.http.impl.client.HttpClientBuilder;
8import org.springframework.beans.factory.annotation.Autowired;
9import org.springframework.context.annotation.Bean;
10import org.springframework.context.annotation.Configuration;
11
12@Configuration
13public class ApacheClientConfig {
14
15 private final GremlinService gremlinService;
16 private static final int CONNECTION_TIMEOUT = 1000;
17 private static final int SOCKET_TIMEOUT = 3000;
18
19 @Autowired
20 public ApacheClientConfig(GremlinService gremlinService) {
21 this.gremlinService = gremlinService;
22 }
23
24 @Bean
25 public CloseableHttpClient closableHttpClient() {
26 RequestConfig requestConfig = RequestConfig.custom()
27 .setConnectTimeout(CONNECTION_TIMEOUT)
28 .setSocketTimeout(SOCKET_TIMEOUT)
29 .build();
30
31 final GremlinApacheHttpRequestInterceptor gremlinInterceptor =
32 new GremlinApacheHttpRequestInterceptor(gremlinService, "alfi-client-demo");
33 final HttpClientBuilder clientBuilder = HttpClientBuilder
34 .create()
35 .addInterceptorFirst(gremlinInterceptor)
36 .setDefaultRequestConfig(requestConfig);
37
38 return clientBuilder.build();
39 }
40
41
42}
java
1package com.example.alfiapachehttpclient.controller;
2
3import org.apache.http.HttpEntity;
4import org.apache.http.client.methods.CloseableHttpResponse;
5import org.apache.http.client.methods.HttpGet;
6import org.apache.http.impl.client.CloseableHttpClient;
7import org.apache.http.util.EntityUtils;
8import org.slf4j.Logger;
9import org.slf4j.LoggerFactory;
10import org.springframework.beans.factory.annotation.Autowired;
11import org.springframework.http.HttpStatus;
12import org.springframework.http.ResponseEntity;
13import org.springframework.web.bind.annotation.GetMapping;
14import org.springframework.web.bind.annotation.ResponseBody;
15import org.springframework.web.bind.annotation.RestController;
16
17import java.io.IOException;
18
19@RestController
20public class MainController {
21
22 private final Logger LOG = LoggerFactory.getLogger(getClass().getName());
23
24 private final CloseableHttpClient closeableHttpClient;
25 private CloseableHttpResponse closeableHttpResponse;
26
27 @Autowired
28 public MainController(CloseableHttpClient closeableHttpClient) {
29 this.closeableHttpClient = closeableHttpClient;
30 }
31
32 @GetMapping("/")
33 public @ResponseBody
34 ResponseEntity<String> hello() {
35 final String URI = "https://www.gremlin.com/";
36 HttpGet httpGet = new HttpGet(URI);
37 String responseContent = null;
38 long startTime = System.currentTimeMillis();
39 try {
40 LOG.info(String.format("Executing GET request to %s...", URI));
41 closeableHttpResponse = closeableHttpClient.execute(httpGet);
42 HttpEntity httpEntity = closeableHttpResponse.getEntity();
43 responseContent = EntityUtils.toString(httpEntity);
44 EntityUtils.consume(httpEntity);
45 LOG.info(responseContent);
46 } catch (IOException e) {
47 e.printStackTrace();
48 } finally {
49 long endTime = System.currentTimeMillis();
50 long duration = (endTime - startTime);
51 LOG.info(String.format("GET Request took %d milliseconds", duration));
52 try {
53 closeableHttpResponse.close();
54 } catch (IOException e) {
55 e.printStackTrace();
56 }
57 }
58 return new ResponseEntity<>(responseContent, HttpStatus.OK);
59 }
60}

ALFI Core

java
1package com.gremlin.todo.config;
2
3import com.gremlin.*;
4import com.gremlin.todo.ToDoApplication;
5import org.springframework.context.annotation.Bean;
6import org.springframework.stereotype.Service;
7
8import javax.annotation.PostConstruct;
9
10@Configuration
11public class ALFIConfig {
12
13 public GremlinCoordinatesProvider gremlinCoordinatesProvider() {
14 return new GremlinCoordinatesProvider() {
15 @Override
16 public ApplicationCoordinates initializeApplicationCoordinates() {
17 return new ApplicationCoordinates.Builder()
18 .withType("MyApplication")
19 .withField("service", "to-do")
20 .build();
21 }
22 };
23 }
24
25 public GremlinServiceFactory gremlinServiceFactory() {
26 return new GremlinServiceFactory(gremlinCoordinatesProvider());
27 }
28
29 @Bean
30 public GremlinService gremlinService() {
31 return gremlinServiceFactory().getGremlinService();
32 }
33
34}
java
1package com.gremlin.todo.controller;
2
3import com.gremlin.todo.aspect.AdvancedAttack;
4import com.gremlin.todo.aspect.Attack;
5import com.gremlin.todo.dto.ToDoDto;
6import com.gremlin.todo.model.ToDo;
7import com.gremlin.todo.service.ToDoService;
8import org.bson.types.ObjectId;
9import org.springframework.beans.factory.annotation.Autowired;
10import org.springframework.http.HttpEntity;
11import org.springframework.http.HttpStatus;
12import org.springframework.http.ResponseEntity;
13import org.springframework.web.bind.annotation.*;
14
15import java.util.Collection;
16
17@RestController
18public class MyController {
19 private final GremlinService gremlinService;
20 private TrafficCoordinates getAllToDosCoordinates;
21
22 @Autowired
23 public MyController(GremlinService gremlinService) {
24 this.gremlinService = gremlinService;
25 }
26
27 @GetMapping("/all")
28 public Collection<ToDo> getAllToDos() {
29 gremlinService.applyImpact(this.getAllToDosCoordinates);
30 return toDoService.findAll();
31 }
32
33 @PostConstruct() {
34 getAllToDosCoordinates = new TrafficCoordinates
35 .Builder()
36 .withType("MyController")
37 .withField("method", "getAllToDos")
38 .build();
39 }
40
41}