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

feat : improvements to test configmaps & metrics #651

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions dockercoins/hasher/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
FROM ruby:alpine
RUN apk add --update build-base curl
RUN gem install sinatra
RUN gem install sinatra --version '~> 3'
RUN gem install thin
RUN gem install yaml
RUN gem install prometheus-client
ADD hasher.rb /
CMD ["ruby", "hasher.rb"]
EXPOSE 80
62 changes: 56 additions & 6 deletions dockercoins/hasher/hasher.rb
Original file line number Diff line number Diff line change
@@ -1,18 +1,68 @@
require 'digest'
require 'sinatra'
require 'socket'
require 'yaml'
require 'prometheus/client'
require 'prometheus/client/formats/text' # Import the text formatter

# Define default configuration
default_config = {
'port' => 80,
'sleep_duration' => 0.1
}

# Load configuration from YAML file if it exists, otherwise use defaults
config = if File.exist?('config.yml')
YAML.load_file('config.yml')
else
default_config
end

# Set port with precedence: ENV > YAML > default (80)
set :port, (ENV['PORT'] || config['port'] || default_config['port']).to_i
set :bind, '0.0.0.0'
set :port, 80

# Set sleep duration with precedence: ENV > YAML > default (0.1)
SLEEP_DURATION = (ENV['SLEEP_DURATION'] || config['sleep_duration'] || default_config['sleep_duration']).to_f

# Initialize Prometheus client
prometheus = Prometheus::Client.registry

# Create metrics
request_counter = prometheus.counter(:hash_requests_total, docstring: 'Total number of hash requests', labels: [:method])
request_duration = prometheus.histogram(:hash_request_duration_seconds, docstring: 'Duration of hash requests in seconds', labels: [:method])

post '/' do
# Simulate a bit of delay
sleep 0.1
content_type 'text/plain'
"#{Digest::SHA2.new().update(request.body.read)}"
start_time = Time.now

# Simulate a bit of delay using the configured sleep duration
sleep SLEEP_DURATION
content_type 'text/plain'
hash_value = "#{Digest::SHA2.new.update(request.body.read)}"

# Record metrics
request_counter.increment(labels: { method: 'POST' })
request_duration.observe(Time.now - start_time, labels: { method: 'POST' })

hash_value
end

get '/' do
"HASHER running on #{Socket.gethostname}\n"
start_time = Time.now

sleep SLEEP_DURATION
response = "HASHER running on #{Socket.gethostname}\n"

# Record metrics
request_counter.increment(labels: { method: 'GET' })
request_duration.observe(Time.now - start_time, labels: { method: 'GET' })

response
end

# Endpoint to expose metrics
get '/metrics' do
content_type 'text/plain'
# Use the Text formatter to convert metrics to the right format
Prometheus::Client::Formats::Text.marshal(prometheus)
end
3 changes: 1 addition & 2 deletions dockercoins/rng/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
FROM python:alpine
RUN pip install Flask
RUN pip install Flask pyyaml prometheus-flask-exporter
COPY rng.py /
CMD ["python", "rng.py"]
EXPOSE 80
40 changes: 31 additions & 9 deletions dockercoins/rng/rng.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,54 @@
from flask import Flask, Response
from prometheus_flask_exporter import PrometheusMetrics
import os
import socket
import time
import yaml

# Load configuration from YAML file if it exists, otherwise use defaults
default_config = {
'port': 80,
'sleep_duration': 0.1
}

if os.path.exists('config.yml'):
with open('config.yml', 'r') as file:
config = yaml.safe_load(file)
else:
config = default_config

# Get configurations with precedence: ENV > YAML > default
port = int(os.environ.get("PORT", config.get('port', default_config['port'])))
sleep_duration = float(os.environ.get("SLEEP_DURATION", config.get('sleep_duration', default_config['sleep_duration'])))

app = Flask(__name__)

# Enable Prometheus metrics
metrics = PrometheusMetrics(app)

# Enable debugging if the DEBUG environment variable is set and starts with Y
app.debug = os.environ.get("DEBUG", "").lower().startswith('y')

hostname = socket.gethostname()

urandom = os.open("/dev/urandom", os.O_RDONLY)


@app.route("/")
def index():
return "RNG running on {}\n".format(hostname)

time.sleep(sleep_duration) # Simulate processing time
return f"RNG running on {hostname}\n"

@app.route("/<int:how_many_bytes>")
def rng(how_many_bytes):
# Simulate a little bit of delay
time.sleep(0.1)
time.sleep(sleep_duration) # Simulate processing time
return Response(
os.read(urandom, how_many_bytes),
content_type="application/octet-stream")
content_type="application/octet-stream"
)

# Prometheus metrics will be exposed automatically on the /metrics endpoint
# The default metrics will include:
# 1. `flask_http_requests_total`: Total number of HTTP requests
# 2. `flask_http_request_duration_seconds`: Duration of HTTP requests

if __name__ == "__main__":
app.run(host="0.0.0.0", port=80, threaded=False)

app.run(host="0.0.0.0", port=port, threaded=False)
6 changes: 4 additions & 2 deletions dockercoins/webui/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
FROM node:4-slim
FROM node:10-slim
RUN npm install express
RUN npm install redis
RUN npm install redis@3
RUN npm install yamljs
RUN npm install prom-client
COPY files/ /files/
COPY webui.js /
CMD ["node", "webui.js"]
Expand Down
2 changes: 1 addition & 1 deletion dockercoins/webui/files/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
color: royalblue;
}
</style>
<script src="jquery.js"></script>
<script src="jquery-1.11.3.min.js"></script>
<script src="d3.min.js"></script>
<script src="rickshaw.min.js"></script>
<script>
Expand Down
41 changes: 32 additions & 9 deletions dockercoins/webui/webui.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,31 @@
var express = require('express');
var app = express();
var redis = require('redis');
"use strict";

var client = redis.createClient(6379, 'redis');
const express = require('express');
const redis = require('redis');
const YAML = require('yamljs');
const fs = require('fs');

const app = express();

// Load configuration from YAML file if it exists, otherwise use defaults
let config = {
redis_host: 'redis',
redis_port: 6379,
listen_port: 80
};

if (fs.existsSync('config.yml')) {
const yamlConfig = YAML.load('config.yml');
config = Object.assign({}, config, yamlConfig);
}

// Environment variables override YAML settings
const REDIS_HOST = process.env.REDIS_HOST || config.redis_host;
const REDIS_PORT = parseInt(process.env.REDIS_PORT) || config.redis_port;
const LISTEN_PORT = parseInt(process.env.LISTEN_PORT) || config.listen_port;

// Initialize Redis client with configured host and port
const client = redis.createClient(REDIS_PORT, REDIS_HOST);
client.on("error", function (err) {
console.error("Redis error", err);
});
Expand All @@ -14,8 +37,8 @@ app.get('/', function (req, res) {
app.get('/json', function (req, res) {
client.hlen('wallet', function (err, coins) {
client.get('hashes', function (err, hashes) {
var now = Date.now() / 1000;
res.json( {
const now = Date.now() / 1000;
res.json({
coins: coins,
hashes: hashes,
now: now
Expand All @@ -26,7 +49,7 @@ app.get('/json', function (req, res) {

app.use(express.static('files'));

var server = app.listen(80, function () {
console.log('WEBUI running on port 80');
// Start server with configured listen port
const server = app.listen(LISTEN_PORT, function () {
console.log(`WEBUI running on port ${LISTEN_PORT}`);
});

3 changes: 1 addition & 2 deletions dockercoins/worker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
FROM python:alpine
RUN pip install redis
RUN pip install requests
RUN pip install redis pyyaml requests
COPY worker.py /
CMD ["python", "worker.py"]
50 changes: 37 additions & 13 deletions dockercoins/worker/worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,56 @@
from redis import Redis
import requests
import time
import yaml

# Load configuration from YAML file if it exists, otherwise use defaults
default_config = {
'redis_host': 'redis',
'redis_port': 6379,
'hasher_host': 'hasher',
'hasher_port': 80,
'rng_host': 'rng',
'rng_port': 80,
'sleep_duration': 0.1
}

if os.path.exists('config.yml'):
with open('config.yml', 'r') as file:
config = yaml.safe_load(file)
else:
config = default_config

# Environment variables override YAML settings
DEBUG = os.environ.get("DEBUG", "").lower().startswith("y")

REDIS_HOST = os.environ.get("REDIS_HOST", config.get('redis_host', default_config['redis_host']))
REDIS_PORT = int(os.environ.get("REDIS_PORT", config.get('redis_port', default_config['redis_port'])))
HASHER_HOST = os.environ.get("HASHER_HOST", config.get('hasher_host', default_config['hasher_host']))
HASHER_PORT = int(os.environ.get("HASHER_PORT", config.get('hasher_port', default_config['hasher_port'])))
RNG_HOST = os.environ.get("RNG_HOST", config.get('rng_host', default_config['rng_host']))
RNG_PORT = int(os.environ.get("RNG_PORT", config.get('rng_port', default_config['rng_port'])))
SLEEP_DURATION = float(os.environ.get("SLEEP_DURATION", config.get('sleep_duration', default_config['sleep_duration'])))

# Configure logging
log = logging.getLogger(__name__)
if DEBUG:
logging.basicConfig(level=logging.DEBUG)
else:
logging.basicConfig(level=logging.INFO)
logging.getLogger("requests").setLevel(logging.WARNING)


redis = Redis("redis")
# Initialize Redis with configured host and port
redis = Redis(host=REDIS_HOST, port=REDIS_PORT)


def get_random_bytes():
r = requests.get("http://rng/32")
# Use RNG_HOST and RNG_PORT for the RNG service
r = requests.get(f"http://{RNG_HOST}:{RNG_PORT}/32")
return r.content


def hash_bytes(data):
r = requests.post("http://hasher/",
data=data,
headers={"Content-Type": "application/octet-stream"})
# Use HASHER_HOST and HASHER_PORT for the hasher service
r = requests.post(f"http://{HASHER_HOST}:{HASHER_PORT}/", data=data, headers={"Content-Type": "application/octet-stream"})
hex_hash = r.text
return hex_hash

Expand All @@ -35,8 +62,7 @@ def work_loop(interval=1):
loops_done = 0
while True:
if time.time() > deadline:
log.info("{} units of work done, updating hash counter"
.format(loops_done))
log.info("{} units of work done, updating hash counter".format(loops_done))
redis.incrby("hashes", loops_done)
loops_done = 0
deadline = time.time() + interval
Expand All @@ -46,7 +72,7 @@ def work_loop(interval=1):

def work_once():
log.debug("Doing one unit of work")
time.sleep(0.1)
time.sleep(SLEEP_DURATION) # Use the configured sleep duration
random_bytes = get_random_bytes()
hex_hash = hash_bytes(random_bytes)
if not hex_hash.startswith('0'):
Expand All @@ -62,9 +88,7 @@ def work_once():
while True:
try:
work_loop()
except:
except Exception:
log.exception("In work loop:")
log.error("Waiting 10s and restarting.")
time.sleep(10)