Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save oliver-zehentleitner/01635ac085ddee4b066481f9751f864e to your computer and use it in GitHub Desktop.

Select an option

Save oliver-zehentleitner/01635ac085ddee4b066481f9751f864e to your computer and use it in GitHub Desktop.
Grafana Cloud k6 fast limit-finder test for pushing distributed UBDCC REST API load across all running ASCII DepthCaches while using low-cardinality tags.
import http from 'k6/http';
import { check, fail } from 'k6';
const BASE_URL = __ENV.BASE_URL || 'http://YOUR_UBDCC_IP';
const LIMIT = __ENV.LIMIT || '100';
const ONLY_RUNNING = (__ENV.ONLY_RUNNING || 'true') === 'true';
export const options = {
cloud: {
distribution: {
frankfurt: { loadZone: 'amazon:de:frankfurt', percent: 100 },
},
},
systemTags: [
'status',
'method',
'name',
'scenario',
'group',
'check',
'error',
'error_code',
],
scenarios: {
distributed_dynamic_markets_fast_limit_finder: {
executor: 'ramping-arrival-rate',
startRate: 100,
timeUnit: '1s',
preAllocatedVUs: 500,
maxVUs: 2000,
stages: [
{ target: 300, duration: '1m' },
{ target: 500, duration: '1m' },
{ target: 700, duration: '1m' },
{ target: 900, duration: '1m' },
{ target: 1100, duration: '1m' },
{ target: 0, duration: '30s' },
],
},
},
thresholds: {
http_req_failed: ['rate<0.05'],
http_req_duration: ['p(95)<5000'],
checks: ['rate>0.95'],
},
};
function allReplicasRunning(depthcache) {
const distribution = depthcache.DISTRIBUTION || {};
const desiredQuantity = depthcache.DESIRED_QUANTITY || 0;
const runningReplicas = Object.values(distribution).filter(
(replica) => replica.STATUS === 'running'
).length;
return desiredQuantity > 0 && runningReplicas >= desiredQuantity;
}
function isAsciiSymbol(symbol) {
return /^[A-Z0-9]+$/.test(symbol);
}
export function setup() {
const url = `${BASE_URL}/get_depthcache_list`;
const res = http.get(url, {
timeout: '30s',
tags: {
name: 'get_depthcache_list',
},
});
if (res.status !== 200) {
fail(`Failed to fetch depthcache list: HTTP ${res.status}`);
}
const data = res.json();
if (!data.depthcache_list || typeof data.depthcache_list !== 'object') {
fail('Unsupported response format from /get_depthcache_list');
}
const markets = [];
let totalDepthCaches = 0;
let skippedNonAscii = 0;
let skippedNotRunning = 0;
let skippedInvalid = 0;
for (const [exchangeName, exchangeMarkets] of Object.entries(data.depthcache_list)) {
for (const [marketName, depthcache] of Object.entries(exchangeMarkets)) {
totalDepthCaches++;
const exchange = depthcache.EXCHANGE || exchangeName;
const market = depthcache.MARKET || marketName;
if (!exchange || !market) {
skippedInvalid++;
continue;
}
if (!isAsciiSymbol(market)) {
skippedNonAscii++;
continue;
}
if (ONLY_RUNNING && !allReplicasRunning(depthcache)) {
skippedNotRunning++;
continue;
}
markets.push({
exchange,
market,
});
}
}
if (markets.length === 0) {
fail('No usable depthcache markets found.');
}
console.log(`Total DepthCaches found: ${totalDepthCaches}`);
console.log(`Loaded usable DepthCaches: ${markets.length}`);
console.log(`Skipped non-ASCII markets: ${skippedNonAscii}`);
console.log(`Skipped not fully running: ${skippedNotRunning}`);
console.log(`Skipped invalid entries: ${skippedInvalid}`);
console.log(`ONLY_RUNNING=${ONLY_RUNNING}`);
console.log(`LIMIT=${LIMIT}`);
return {
markets,
};
}
export default function (data) {
const item = data.markets[Math.floor(Math.random() * data.markets.length)];
const endpoint = Math.random() < 0.5 ? 'get_asks' : 'get_bids';
const url =
`${BASE_URL}/${endpoint}` +
`?exchange=${encodeURIComponent(item.exchange)}` +
`&market=${encodeURIComponent(item.market)}` +
`&limit_count=${encodeURIComponent(LIMIT)}`;
const res = http.get(url, {
timeout: '5s',
tags: {
name: endpoint,
endpoint,
exchange: item.exchange,
test_type: 'distributed_dynamic_markets',
test_phase: 'fast_limit_finder_low_cardinality',
},
});
check(res, {
'request did not timeout': (r) => r.status !== 0,
'status is 200': (r) => r.status === 200,
'body is not empty': (r) => r.body && r.body.length > 10,
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment