Skip to content

Commit 00f7e15

Browse files
authored
Merge pull request #26 from CodersOfTheNight/0.3
0.3
2 parents f97f398 + c8a44a9 commit 00f7e15

27 files changed

+480
-67
lines changed

.dockerignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
*.pyc
2+
__pycache__/

.travis.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
language: python
22
python:
33
- 3.5
4-
- 3.6
4+
#- 3.6
5+
#- 3.7
6+
7+
services:
8+
- docker
59

610
install:
7-
- pip install -r requirements/release.txt
11+
- python setup.py install
812
- pip install -r requirements/test.txt
913

1014
script:

Makefile

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
__PHONY__: all
2+
3+
pull-containers:
4+
docker-compose pull
5+
6+
rebuild-compose:
7+
docker-compose down && docker-compose build
8+
9+
run-integration-tests: pull-containers rebuild-compose
10+
docker-compose up --remove-orphans --abort-on-container-exit --exit-code-from oshino-query
11+
12+
run-dev-environment: pull-containers rebuild-compose
13+
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up --remove-orphans

compose/Dockerfile

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
FROM python:3.7-alpine
2+
3+
WORKDIR '/usr/src/oshino'
4+
5+
COPY oshino ./oshino
6+
COPY requirements ./requirements
7+
COPY tests ./tests
8+
COPY README.md ./README.md
9+
COPY setup.py .
10+
11+
COPY compose/config.yaml .
12+
13+
14+
RUN python setup.py install
15+
RUN pip install -r ./requirements/test.txt
16+
17+
CMD ["/usr/local/bin/oshino", "--config=config.yaml"]

compose/config.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
interval: 5
3+
loglevel: DEBUG
4+
riemann:
5+
host: riemann
6+
port: 5555
7+
agents:
8+
- name: health-check
9+
module: oshino.agents.http_agent.HttpAgent
10+
url: https://www.python.org
11+
tag: healthcheck

docker-compose.dev.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
version: "3"
2+
3+
services:
4+
oshino-query:
5+
command: ["/bin/sh"]
6+
riemann:
7+
ports:
8+
- "5555:5555"
9+
- "5556:5556"
10+
riemann-ui:
11+
image: "rlister/riemann-dash"
12+
depends_on:
13+
- riemann
14+
ports:
15+
- "4567:4567"

docker-compose.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
version: "3"
2+
3+
services:
4+
oshino:
5+
build:
6+
context: .
7+
dockerfile: compose/Dockerfile
8+
depends_on:
9+
- riemann
10+
oshino-query:
11+
build:
12+
context: .
13+
dockerfile: compose/Dockerfile
14+
command: ["/usr/local/bin/pytest", "tests/it_query.py"]
15+
depends_on:
16+
- oshino
17+
- riemann
18+
riemann:
19+
image: "rlister/riemann"

oshino/agents/__init__.py

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
1-
class Agent(object):
1+
from abc import ABC, abstractmethod
2+
3+
from oshino.util import current_ts, timer
4+
5+
6+
class Agent(ABC):
27

38
def __init__(self, cfg):
49
self._data = cfg
10+
self._last_run = current_ts()
511

612
def on_start(self):
713
pass
@@ -21,8 +27,60 @@ def get_logger(self):
2127
from logbook import Logger
2228
return Logger(self.__class__.__name__)
2329

30+
@abstractmethod
2431
async def process(self, event_fn):
32+
"""
33+
Each agent must implement this one to provide actual logic
34+
"""
2535
pass
2636

2737
def is_valid(self):
2838
return "name" in self._data
39+
40+
async def pull_metrics(self, event_fn, loop=None):
41+
"""
42+
Method called by core.
43+
Should not be overwritten.
44+
"""
45+
if self.lazy and not self.ready:
46+
return None
47+
logger = self.get_logger()
48+
49+
ts = timer()
50+
logger.trace("Waiting for process event")
51+
result = await self.process(event_fn)
52+
td = int(timer() - ts)
53+
logger.trace("It took: {}ms".format(td))
54+
self._last_run = current_ts()
55+
return result
56+
57+
@property
58+
def lazy(self):
59+
"""
60+
Agents with flag `lazy` gives data when they want to,
61+
not when they are requested for.
62+
"""
63+
return self._data.get("lazy", False)
64+
65+
@property
66+
def ready(self):
67+
"""
68+
Function used when agent is `lazy`.
69+
It is being processed only when `ready` condition is satisfied
70+
"""
71+
logger = self.get_logger()
72+
now = current_ts()
73+
logger.trace("Current time: {0}".format(now))
74+
logger.trace("Last Run: {0}".format(self._last_run))
75+
delta = (now - self._last_run)
76+
logger.trace("Delta: {0}, Interval: {1}"
77+
.format(delta, self.interval * 1000))
78+
return delta > self.interval * 1000
79+
80+
@property
81+
def interval(self):
82+
"""
83+
By default, lazy agents expects to have some kind of time interval.
84+
`ready` output is calculated according to this interval.
85+
"""
86+
return self._data["interval"]

oshino/agents/http_agent.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import aiohttp
22

3-
from time import time
3+
from ..util import timer
44
from . import Agent
55

66

@@ -46,13 +46,13 @@ def translate_status(self, code):
4646

4747
async def process(self, event_fn):
4848
logger = self.get_logger()
49-
ts = time()
49+
ts = timer()
5050
state = None
5151
async with aiohttp.ClientSession() as session:
5252
async with session.get(self.url) as resp:
5353
state = self.translate_status(resp.status)
54-
te = time()
55-
span = int((te - ts) * 1000)
54+
te = timer()
55+
span = int(te - ts)
5656
logger.debug("Request to {url} returned status code {code}(as {state})"
5757
"in {span} milliseconds.".format(url=self.url,
5858
code=resp.status,

oshino/agents/subprocess_agent.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import re
2+
import json
23
import asyncio
34

45
from functools import partial
@@ -49,6 +50,11 @@ def regex_transform(m, logger):
4950
return None
5051

5152

53+
def json_transform(m, logger, selector):
54+
raw = json.loads(m)
55+
return selector, raw[selector]
56+
57+
5258
def is_parsed(m):
5359
return m is not None
5460

0 commit comments

Comments
 (0)