Skip to content
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

Updated interface and enhancements idea #13

Open
nicholasjackson opened this issue Nov 16, 2020 · 0 comments
Open

Updated interface and enhancements idea #13

nicholasjackson opened this issue Nov 16, 2020 · 0 comments

Comments

@nicholasjackson
Copy link
Owner

nicholasjackson commented Nov 16, 2020

Occasionally it is desirable that fake service can behave more like real services, for this reason, I propose an update to the configuration which allows the definition of multiple endpoints for a single service. Each endpoint has its own timing information and can define a custom response payload.

The intention behind the custom response payload is to be able to simulate data transferring over the network and also to simulate real upstream services. Response payloads could either be randomly generated conforming to a defined structure or user provided.

The following shows an example configuration file which includes all the current options:

name = "fake-service"

listen_addr = "0.0.0.0:9090"

cors {
  allowed_origins = "*"
  allowed_headers = [
    "Accept",
    "Accept-Language",
    "Content-Language",
    "Origin",
    "Content-Type"
  ]
  allow_credentials = true
}
  
tracing {
  type = "zipkin" // type of tracing to use, zipkin or statsd
  collector_addr = "zipkin:2121" // location of the statsd metrics collector
}

metrics {
  type = "statsd" // type of metrics output, statsd
  collector_addr = "stastd:2121" // location of the statsd metrics collector
}

logging {
  level = "info" // log level
  output_location = "stdout" // log output location, stdout or full filepath
}

tls {
  cert_location = "./tls/certs.pem" // location of a PEM encoded cert
  key_location = "./tls/key.pem" // location of a PEM encoded key
}

# complex handler definition with all options
handler "all_products" {

  method = "GET"
  path = "/"

  timing {
    50_percentile = "10ms" // average duration for a request
    90_percentile = "20ms" // 10% of requests will take
    95_percentile = "30ms" // 5% of requests will take
    variance = "10%" // +/- timing variance, for example 50% will be 9-11ms
  }

  errors {
    rate = "10%" // percentage of requests which result in an error
    code = 500 // error code to be returned
    delay = "200ms" // delay applied to error requests
  }

  rate_limiting {
    rps = 100 // number of requests per second handled before rate limiting
    code = 503 // http response code returned when rate limiting
  }

  load_generation {
    clock_speed = 1000 // MHz of a single logical core
    cpu_cores = 3 // number of cpu core to use when applying load
    core_load = "100%" // percentage of a core to use when generating load
  }

  upstream_workers = 3 // max number of parallel upstream requests

  upstream "product_details" {
    uri = "http://localhost:9090" // location of the upstream
    method = "GET" // http method to use
    keep_alive = true // use HTTP keep alives ?
    timeout = "10s" // timeout for upstream requests
    append_query = true // append current request query string to upstream URI?
    append_headers = true // append currenct request query string to upstream request
  }
  
  upstream "currency" {
    uri = "http://localhost:9090" // location of the upstream
    method = "POST" // http method to use

    // if using http POST, payload to send to the server
    body {
      random_data {
        field "id" {
          type = "int"
          rand = "int"
        }
      }

    }

  }

  response {

    // random_data instructs fake-service to return a json payload with the
    // defined fields to be returned.
    // all returned fields contain randomized data
    // random_data can be used to generate more realistic payloads
    random_data {
      array = true // can be used to force data to be returned by an array when count = 1
      count = 2 // if > 1 payload will be returned as an array

      field "id" { // define a field to include in a random response
        type = "int"  // type of the field
        rand = "int" // random value to generate
      }
      
      field "name" {
        type = "string"
        rand = "hipsterword"
      }
      
      field "details" {
        type = "upstream_response" // allows return of an upstream call
        id = "product_details"  // id of the upstream response to include in the field
      }
      
      field "price" {
        type = "upstream_response"
        id = "currency" 
      }

    }

  }

}

# simple handler with raw response
handler "single_product" {

  method = "GET"
  path = "/{id: [0-9]}"

  response {
    content-type = "application/json" // define the content type for the response

    // raw allows raw data to be returned from the service
    raw << EOF
      { 
        "name": "apple",
        "color": "red"
      }
    EOF
  }
}

handler "product_image" {

  method = "GET"
  path = "/{id: [0-9]}"

  response {
    content-type = "image/png" // define the content type for the response

    // load the response data from a file
    file = "./images/test_image.png"
  }
}

A call to the /products path for the above service would return a JSON response similar to the below:

{
  "id": 123
  "name": "cronut",
  "details": [
    {
      "material": "random"
    }
  ],
  "price": 12.32
}

At present, the response data contains all the timing info for the service, this could still be obtained by making the request with the additional query string variables.

/products?timing_data=true&include_responses=true

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant