clickhouse logging

This commit is contained in:
Johan B.W. de Vries 2023-04-14 14:45:34 +02:00
parent 628fb775e8
commit 0d0af0e728
9 changed files with 90 additions and 24 deletions

View File

@ -4,6 +4,9 @@ run-controller: sast
run-worker: sast run-worker: sast
venv/bin/python -m phasmplatform.worker venv/bin/python -m phasmplatform.worker
clickhouse-sh:
docker compose exec clickhouse /usr/bin/clickhouse client
redis-sh: redis-sh:
docker compose exec -it redis redis-cli docker compose exec -it redis redis-cli

View File

@ -5,3 +5,10 @@ port = 17859
[controller.redis.read] [controller.redis.read]
host = 'localhost' host = 'localhost'
port = 17859 port = 17859
[worker.clickhouse.write]
host = 'localhost'
port = 17858
username = 'default'
password = ''
database = 'phasm_platform'

1
config/clickhouse/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/data

View File

@ -0,0 +1,17 @@
CREATE DATABASE IF NOT EXISTS phasm_platform;
USE phasm_platform;
CREATE TABLE routing_logs
(
timestamp DateTime64(6, 'UTC'),
from_service String,
from_container String,
from_method String,
to_service String,
to_container String,
to_method String,
result String,
)
ENGINE = MergeTree
ORDER BY timestamp;

View File

@ -3,3 +3,10 @@ services:
image: 'redis:7.0-alpine' image: 'redis:7.0-alpine'
ports: ports:
- '17859:6379' - '17859:6379'
clickhouse:
image: 'clickhouse/clickhouse-server:22.8-alpine'
ports:
- '17858:8123'
volumes:
- './config/clickhouse/data:/var/lib/clickhouse/'

View File

@ -1,5 +1,6 @@
from typing import TYPE_CHECKING, BinaryIO from typing import TYPE_CHECKING, BinaryIO
from clickhouse_connect.driver.httpclient import HttpClient as ClickHouseHttpClient # type: ignore
import redis import redis
if TYPE_CHECKING: if TYPE_CHECKING:
@ -26,13 +27,27 @@ class ControllerConfig:
self.redis_write = redis_write self.redis_write = redis_write
class WorkerConfig:
__slots__ = ('clickhouse_write', )
clickhouse_write: ClickHouseHttpClient
def __init__(
self,
clickhouse_write: ClickHouseHttpClient,
) -> None:
self.clickhouse_write = clickhouse_write
class Config: class Config:
__slots__ = ('controller_config', ) __slots__ = ('controller_config', 'worker_config')
controller_config: ControllerConfig controller_config: ControllerConfig
worker_config: WorkerConfig
def __init__(self, controller_config: ControllerConfig) -> None: def __init__(self, controller_config: ControllerConfig, worker_config: WorkerConfig) -> None:
self.controller_config = controller_config self.controller_config = controller_config
self.worker_config = worker_config
def from_toml(toml: BinaryIO) -> Config: def from_toml(toml: BinaryIO) -> Config:
@ -55,4 +70,15 @@ def from_toml(toml: BinaryIO) -> Config:
controller_config = ControllerConfig(redis_read, redis_write) controller_config = ControllerConfig(redis_read, redis_write)
return Config(controller_config) clickhouse_write = ClickHouseHttpClient(
interface='http',
host=toml_dict['worker']['clickhouse']['write']['host'],
port=toml_dict['worker']['clickhouse']['write']['port'],
username=toml_dict['worker']['clickhouse']['write']['username'],
password=toml_dict['worker']['clickhouse']['write']['password'],
database=toml_dict['worker']['clickhouse']['write']['database'],
)
worker_config = WorkerConfig(clickhouse_write)
return Config(controller_config, worker_config)

View File

@ -1,16 +1,18 @@
from typing import Dict, List, Optional, Tuple from typing import Callable, Dict, List, Optional, Tuple
import datetime
import functools
import sys import sys
import threading import threading
import time import time
from queue import Empty, Queue from queue import Empty, Queue
from phasmplatform.common import valuetype from phasmplatform.common import valuetype
from phasmplatform.common.config import from_toml as config_from_toml from phasmplatform.common.config import WorkerConfig, from_toml as config_from_toml
from phasmplatform.common.method import Method, MethodArgument, MethodCall from phasmplatform.common.method import Method, MethodArgument, MethodCall
from phasmplatform.common.router import MethodCallRouterInterface from phasmplatform.common.router import MethodCallRouterInterface
from phasmplatform.common.service import Service, ServiceDiscoveryInterface from phasmplatform.common.service import Service, ServiceDiscoveryInterface
from phasmplatform.common.value import NoneValue from phasmplatform.common.value import Value, NoneValue
from phasmplatform.common.state import from_toml as state_from_toml from phasmplatform.common.state import from_toml as state_from_toml
from .runners.base import RunnerInterface from .runners.base import RunnerInterface
@ -70,32 +72,45 @@ class LocalhostServiceDiscovery(ServiceDiscoveryInterface):
class LocalhostMethodCallRouter(MethodCallRouterInterface): class LocalhostMethodCallRouter(MethodCallRouterInterface):
def __init__(self, service_discovery: LocalhostServiceDiscovery) -> None: def __init__(self, config: WorkerConfig, service_discovery: LocalhostServiceDiscovery) -> None:
self.config = config
self.service_discovery = service_discovery self.service_discovery = service_discovery
def send_call(self, service: Service, call: MethodCall) -> None: def send_call(self, service: Service, call: MethodCall) -> None:
self.config.clickhouse_write.insert('routing_logs', [
[datetime.datetime.now(tz=datetime.timezone.utc), service.name, call.method.name],
], ['timestamp', 'to_service', 'to_method'])
call.on_success = functools.partial(self._send_call_on_succes, service, call, call.on_success)
assert service.name in self.service_discovery.services assert service.name in self.service_discovery.services
queue = self.service_discovery.services[service.name][1] queue = self.service_discovery.services[service.name][1]
print('send_call', service, call, queue)
queue.put(call) queue.put(call)
def _send_call_on_succes(self, service: Service, call: MethodCall, orig_on_succes: Callable[[Value], None], value: Value) -> None:
self.config.clickhouse_write.insert('routing_logs', [
[datetime.datetime.now(tz=datetime.timezone.utc), service.name, call.method.name, repr(value.data)],
], ['timestamp', 'to_service', 'to_method', 'result'])
orig_on_succes(value)
def main() -> int: def main() -> int:
with open('config.toml', 'rb') as fil: with open('config.toml', 'rb') as fil:
config = config_from_toml(fil) config = config_from_toml(fil)
del config
with open('./examples/echoserver.toml', 'rb') as fil: with open('./examples/echoserver.toml', 'rb') as fil:
state = state_from_toml(fil) state = state_from_toml(fil)
print(state)
del state
# TODO: Replace the stuff below with the loading from the example state
localhost_queue: Queue[MethodCall] = Queue() localhost_queue: Queue[MethodCall] = Queue()
echo_client_queue: Queue[MethodCall] = Queue() echo_client_queue: Queue[MethodCall] = Queue()
echo_server_queue: Queue[MethodCall] = Queue() echo_server_queue: Queue[MethodCall] = Queue()
service_discovery = LocalhostServiceDiscovery() service_discovery = LocalhostServiceDiscovery()
method_call_router = LocalhostMethodCallRouter(service_discovery) method_call_router = LocalhostMethodCallRouter(config.worker_config, service_discovery)
localhost = LocalhostRunner() localhost = LocalhostRunner()
service_discovery.register_service(make_prelude(), localhost_queue) service_discovery.register_service(make_prelude(), localhost_queue)

View File

@ -126,23 +126,11 @@ class WasmTimeRunner(BaseRunner):
call = MethodCall(method, call_args, on_success, on_error) call = MethodCall(method, call_args, on_success, on_error)
print(
'send_service_call',
'from-service=?', 'from-method=?', # TODO
f'to-service={service.name}', f'to-method={method.name}',
*args,
)
self.method_call_router.send_call(service, call) self.method_call_router.send_call(service, call)
try: try:
value = queue.get(block=True, timeout=10) value = queue.get(block=True, timeout=10)
except Empty: except Empty:
print(
'send_service_call',
'from-service=?', 'from-method=?', # TODO
f'to-service={service.name}', f'to-method={method.name}',
'TIMEOUT',
)
raise Exception() # TODO raise Exception() # TODO
return self.value_to_wasm(value) return self.value_to_wasm(value)

View File

@ -1,3 +1,5 @@
clickhouse-connect==0.5.20
numpy==1.24.2
pywasm3==0.5.0 pywasm3==0.5.0
redis==4.5.4 redis==4.5.4
tomli==2.0.1 ; python_version < '3.11' tomli==2.0.1 ; python_version < '3.11'