Skip to content

Commit

Permalink
Merge pull request #3 from batala/docker-3
Browse files Browse the repository at this point in the history
docker-3
  • Loading branch information
batala authored Jan 16, 2024
2 parents 8de19eb + ad457ad commit 58e6a7a
Show file tree
Hide file tree
Showing 29 changed files with 1,259 additions and 0 deletions.
6 changes: 6 additions & 0 deletions src/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
docker-compose.yml
build_info.txt
prometheus/

## python specific
*.pyc
1 change: 1 addition & 0 deletions src/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Micorservices
15 changes: 15 additions & 0 deletions src/comment/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
FROM ruby:2.2
RUN apt-get update -qq && apt-get install -y build-essential

ENV APP_HOME /app
RUN mkdir $APP_HOME
WORKDIR $APP_HOME

ADD Gemfile* $APP_HOME/
RUN bundle install
ADD . $APP_HOME

ENV COMMENT_DATABASE_HOST comment_db
ENV COMMENT_DATABASE comments

CMD ["puma"]
10 changes: 10 additions & 0 deletions src/comment/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
source 'https://rubygems.org'

gem 'sinatra', '~> 2.0.2'
gem 'bson_ext'
gem 'mongo'
gem 'puma'
gem 'prometheus-client'
gem "rack", '>= 2.0.6'
gem 'rufus-scheduler'
gem 'tzinfo-data'
50 changes: 50 additions & 0 deletions src/comment/Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
GEM
remote: https://rubygems.org/
specs:
bson (4.3.0)
bson_ext (1.5.1)
et-orbi (1.1.6)
tzinfo
fugit (1.1.6)
et-orbi (~> 1.1, >= 1.1.6)
raabro (~> 1.1)
mongo (2.6.2)
bson (>= 4.3.0, < 5.0.0)
mustermann (1.0.3)
prometheus-client (0.8.0)
quantile (~> 0.2.1)
puma (3.12.0)
quantile (0.2.1)
raabro (1.1.6)
rack (2.0.6)
rack-protection (2.0.4)
rack
rufus-scheduler (3.5.2)
fugit (~> 1.1, >= 1.1.5)
sinatra (2.0.4)
mustermann (~> 1.0)
rack (~> 2.0)
rack-protection (= 2.0.4)
tilt (~> 2.0)
thread_safe (0.3.6)
tilt (2.0.9)
tzinfo (1.2.5)
thread_safe (~> 0.1)
tzinfo-data (1.2018.7)
tzinfo (>= 1.0.0)

PLATFORMS
ruby

DEPENDENCIES
bson_ext
mongo
prometheus-client
puma
rack (>= 2.0.6)
rufus-scheduler
sinatra (~> 2.0.2)
tzinfo-data

BUNDLED WITH
1.17.2
1 change: 1 addition & 0 deletions src/comment/VERSION
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0.0.3
132 changes: 132 additions & 0 deletions src/comment/comment_app.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
require 'sinatra'
require 'json/ext'
require 'uri'
require 'mongo'
require 'prometheus/client'
require 'rufus-scheduler'
require_relative 'helpers'

# Database connection info
COMMENT_DATABASE_HOST ||= ENV['COMMENT_DATABASE_HOST'] || '127.0.0.1'
COMMENT_DATABASE_PORT ||= ENV['COMMENT_DATABASE_PORT'] || '27017'
COMMENT_DATABASE ||= ENV['COMMENT_DATABASE'] || 'test'
DB_URL ||= "mongodb://#{COMMENT_DATABASE_HOST}:#{COMMENT_DATABASE_PORT}"

# App version and build info
if File.exist?('VERSION')
VERSION ||= File.read('VERSION').strip
else
VERSION ||= "version_missing"
end

if File.exist?('build_info.txt')
BUILD_INFO = File.readlines('build_info.txt')
else
BUILD_INFO = Array.new(2, "build_info_missing")
end

configure do
Mongo::Logger.logger.level = Logger::WARN
db = Mongo::Client.new(DB_URL, database: COMMENT_DATABASE,
heartbeat_frequency: 2)
set :mongo_db, db[:comments]
set :bind, '0.0.0.0'
set :server, :puma
set :logging, false
set :mylogger, Logger.new(STDOUT)
end

# Create and register metrics
prometheus = Prometheus::Client.registry
comment_health_gauge = Prometheus::Client::Gauge.new(
:comment_health,
'Health status of Comment service'
)
comment_health_db_gauge = Prometheus::Client::Gauge.new(
:comment_health_mongo_availability,
'Check if MongoDB is available to Comment'
)
comment_count = Prometheus::Client::Counter.new(
:comment_count,
'A counter of new comments'
)
prometheus.register(comment_health_gauge)
prometheus.register(comment_health_db_gauge)
prometheus.register(comment_count)

# Schedule health check function
scheduler = Rufus::Scheduler.new
scheduler.every '5s' do
check = JSON.parse(healthcheck_handler(DB_URL, VERSION))
set_health_gauge(comment_health_gauge, check['status'])
set_health_gauge(comment_health_db_gauge, check['dependent_services']['commentdb'])
end

before do
env['rack.logger'] = settings.mylogger # set custom logger
end

after do
request_id = env['HTTP_REQUEST_ID'] || 'null'
logger.info('service=comment | event=request | ' \
"path=#{env['REQUEST_PATH']}\n" \
"request_id=#{request_id} | " \
"remote_addr=#{env['REMOTE_ADDR']} | " \
"method= #{env['REQUEST_METHOD']} | " \
"response_status=#{response.status}")
end

# retrieve post's comments
get '/:id/comments' do
id = obj_id(params[:id])
begin
posts = settings.mongo_db.find(post_id: id.to_s).to_a.to_json
rescue StandardError => e
log_event('error', 'find_post_comments',
"Couldn't retrieve comments from DB. Reason: #{e.message}",
params)
halt 500
else
log_event('info', 'find_post_comments',
'Successfully retrieved post comments from DB', params)
posts
end
end

# add a new comment
post '/add_comment/?' do
begin
prms = { post_id: params['post_id'],
name: params['name'],
email: params['email'],
body: params['body'],
created_at: params['created_at'] }
rescue StandardError => e
log_event('error', 'add_comment',
"Bat input data. Reason: #{e.message}", prms)
end
db = settings.mongo_db
begin
result = db.insert_one post_id: params['post_id'], name: params['name'],
email: params['email'], body: params['body'],
created_at: params['created_at']
db.find(_id: result.inserted_id).to_a.first.to_json
rescue StandardError => e
log_event('error', 'add_comment',
"Failed to create a comment. Reason: #{e.message}", params)
halt 500
else
log_event('info', 'add_comment',
'Successfully created a new comment', params)
comment_count.increment
end
end

# health check endpoint
get '/healthcheck' do
healthcheck_handler(DB_URL, VERSION)
end

get '/*' do
halt 404, 'Page not found'
end
10 changes: 10 additions & 0 deletions src/comment/config.ru
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
require './comment_app'
require 'rack'
require 'prometheus/middleware/collector'
require 'prometheus/middleware/exporter'

use Rack::Deflater, if: ->(_, _, _, body) { body.any? && body[0].length > 512 }
use Prometheus::Middleware::Collector
use Prometheus::Middleware::Exporter

run Sinatra::Application
6 changes: 6 additions & 0 deletions src/comment/docker_build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/bash

echo `git show --format="%h" HEAD | head -1` > build_info.txt
echo `git rev-parse --abbrev-ref HEAD` >> build_info.txt

docker build -t $USER_NAME/comment .
75 changes: 75 additions & 0 deletions src/comment/helpers.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
def obj_id(val)
begin
BSON::ObjectId.from_string(val)
rescue BSON::ObjectId::Invalid
nil
end
end

def document_by_id(id)
id = obj_id(id) if String === id
if id.nil?
{}.to_json
else
document = settings.mongo_db.find(_id: id).to_a.first
(document || {}).to_json
end
end

def healthcheck_handler(db_url, version)
begin
commentdb_test = Mongo::Client.new(db_url,
server_selection_timeout: 2)
commentdb_test.database_names
commentdb_test.close
rescue StandardError
commentdb_status = 0
else
commentdb_status = 1
end

status = commentdb_status
healthcheck = {
status: status,
dependent_services: {
commentdb: commentdb_status
},
version: version
}

healthcheck.to_json
end

def set_health_gauge(metric, value)
metric.set(
{
version: VERSION,
commit_hash: BUILD_INFO[0].strip,
branch: BUILD_INFO[1].strip
},
value
)
end

def log_event(type, name, message, params = '{}')
case type
when 'error'
logger.error('service=comment | ' \
"event=#{name} | " \
"request_id=#{request.env['HTTP_REQUEST_ID']}\n" \
"message=\'#{message}\'\n" \
"params: #{params.to_json}")
when 'info'
logger.info('service=comment | ' \
"event=#{name} | " \
"request_id=#{request.env['HTTP_REQUEST_ID']}\n" \
"message=\'#{message}\'\n" \
"params: #{params.to_json}")
when 'warning'
logger.warn('service=comment | ' \
"event=#{name} | " \
"request_id=#{request.env['HTTP_REQUEST_ID']}\n" \
"message=\'#{message}\'\n" \
"params: #{params.to_json}")
end
end
13 changes: 13 additions & 0 deletions src/post-py/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
FROM python:3.6.0-alpine

WORKDIR /app
ADD . /app

RUN apk --no-cache --update add build-base && \
pip install -r /app/requirements.txt && \
apk del build-base

ENV POST_DATABASE_HOST post_db
ENV POST_DATABASE posts

ENTRYPOINT ["python3", "post_app.py"]
1 change: 1 addition & 0 deletions src/post-py/VERSION
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0.0.2
6 changes: 6 additions & 0 deletions src/post-py/docker_build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/bash

echo `git show --format="%h" HEAD | head -1` > build_info.txt
echo `git rev-parse --abbrev-ref HEAD` >> build_info.txt

docker build -t $USER_NAME/post .
40 changes: 40 additions & 0 deletions src/post-py/helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import structlog
from pymongo import MongoClient
from pymongo.errors import ConnectionFailure
from json import dumps
from flask import request


log = structlog.get_logger()


def http_healthcheck_handler(mongo_host, mongo_port, version):
postdb = MongoClient(mongo_host, int(mongo_port),
serverSelectionTimeoutMS=2000)
try:
postdb.admin.command('ismaster')
except ConnectionFailure:
postdb_status = 0
else:
postdb_status = 1

status = postdb_status
healthcheck = {
'status': status,
'dependent_services': {
'postdb': postdb_status
},
'version': version
}
return dumps(healthcheck)


def log_event(event_type, name, message, params={}):
request_id = request.headers['Request-Id'] \
if 'Request-Id' in request.headers else None
if event_type == 'info':
log.info(name, service='post', request_id=request_id,
message=message, params=params)
elif event_type == 'error':
log.error(name, service='post', request_id=request_id,
message=message, params=params)
Loading

0 comments on commit 58e6a7a

Please sign in to comment.