Skip to content

Commit f2e47ec

Browse files
jaygel179darinhoward
authored andcommitted
API - Add AGENT_HTTP Transport (#8)
API - Add AGENT_HTTP Transport
1 parent 494a58a commit f2e47ec

25 files changed

+806
-124
lines changed

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
flake8
12
mock==2.0.0
23
protobuf==3.9.1
34
pytest==4.3.0

setup.cfg

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,16 @@ exclude =
1111
README.md,
1212
LICENSE.md,
1313
requirements.txt,
14+
*protos*,
1415

1516

1617
[coverage:run]
1718
include =
1819
stackify/*
1920
omit =
20-
*tests*
21+
*tests*,
22+
*handler_backport.py,
23+
*protos*,
2124

2225
[tool:pytest]
2326
python_files=tests.py test.py test_*.py *_test.py tests_*.py *_tests.py

stackify/constants.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@
77

88
# using `%2F` instead of `/` as per package documentation
99
DEFAULT_SOCKET_FILE = '%2Fusr%2Flocal%2Fstackify%2Fstackify.sock'
10+
DEFAULT_HTTP_ENDPOINT = 'https://localhost:10601'
1011
SOCKET_URL = 'http+unix://' + DEFAULT_SOCKET_FILE
11-
SOCKET_LOG_URL = '/log'
12+
AGENT_LOG_URL = '/log'
1213

1314
API_REQUEST_INTERVAL_IN_SEC = 30
1415

@@ -36,3 +37,4 @@
3637

3738
TRANSPORT_TYPE_DEFAULT = 'default'
3839
TRANSPORT_TYPE_AGENT_SOCKET = 'agent_socket'
40+
TRANSPORT_TYPE_AGENT_HTTP = 'agent_http'

stackify/handler.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from stackify.constants import MAX_BATCH
1717
from stackify.constants import QUEUE_SIZE
1818
from stackify.timer import RepeatedTimer
19-
from stackify.transport import Transport
19+
from stackify.transport import configure_transport
2020

2121

2222
internal_logger = logging.getLogger(__name__)
@@ -70,7 +70,7 @@ def __init__(self, queue_, max_batch=MAX_BATCH, config=None, **kwargs):
7070

7171
self.max_batch = max_batch
7272
self.messages = []
73-
self.transport = Transport(config, **kwargs)
73+
self.transport = configure_transport(config, **kwargs)
7474
self.timer = RepeatedTimer(API_REQUEST_INTERVAL_IN_SEC, self.send_group)
7575

7676
self._started = False

stackify/timer.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,12 @@ def _time(self):
2727

2828
def start(self):
2929
if not self._started:
30+
self._started = True
3031
self.thread.setDaemon(True)
3132
self.thread.start()
3233

3334
def stop(self):
3435
if self._started:
36+
self._started = False
3537
self.event.set()
3638
self.thread.join()

stackify/transport/__init__.py

Lines changed: 21 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,14 @@
11
import logging
22

3-
from stackify.constants import LOG_SAVE_URL
4-
from stackify.constants import SOCKET_LOG_URL
3+
from stackify.constants import TRANSPORT_TYPE_AGENT_HTTP
54
from stackify.constants import TRANSPORT_TYPE_AGENT_SOCKET
65
from stackify.constants import TRANSPORT_TYPE_DEFAULT
7-
from stackify.transport.agent import AgentSocket
8-
from stackify.transport.agent.message import Log
9-
from stackify.transport.agent.message import LogGroup
6+
from stackify.transport.agent import AgentSocketTransport
7+
from stackify.transport.agent import AgentHTTPTransport
108
from stackify.transport.application import get_configuration
119
from stackify.transport.application import EnvironmentDetail
12-
from stackify.transport.default import HTTPClient
13-
from stackify.transport.default.log import LogMsg
14-
from stackify.transport.default.log import LogMsgGroup
10+
from stackify.transport.default import DefaultTransport
11+
1512

1613
internal_logger = logging.getLogger(__name__)
1714

@@ -24,93 +21,34 @@ class TransportTypes(object):
2421
Types:
2522
* DEFAULT - HTTP transport that will directly send logs to the Platform
2623
* AGENT_SOCKET - HTTP warapped Unix Socket Domain that will send logs to the StackifyAgent
24+
* AGENT_HTTP - HTTP transport that will send logs to the Agent using HTTP requests
2725
"""
2826

2927
DEFAULT = TRANSPORT_TYPE_DEFAULT
3028
AGENT_SOCKET = TRANSPORT_TYPE_AGENT_SOCKET
29+
AGENT_HTTP = TRANSPORT_TYPE_AGENT_HTTP
3130

3231
@classmethod
3332
def get_transport(self, api_config=None, env_details=None):
3433
# determine which transport to use depening on users config
3534
if api_config.transport == self.AGENT_SOCKET:
3635
internal_logger.debug('Setting Agent Socket Transport.')
37-
api_config.transport = self.AGENT_SOCKET
38-
return AgentSocket()
36+
return AgentSocketTransport(api_config, env_details)
37+
38+
if api_config.transport == self.AGENT_HTTP:
39+
internal_logger.debug('Setting Agent HTTP Transport.')
40+
return AgentHTTPTransport(api_config, env_details)
3941

4042
internal_logger.debug('Setting Default Transport.')
4143
api_config.transport = self.DEFAULT
42-
return HTTPClient(api_config, env_details)
43-
44-
@classmethod
45-
def create_message(self, record, api_config, env_details):
46-
# create message depending on which transport
47-
if api_config.transport == self.AGENT_SOCKET:
48-
return Log(record, api_config, env_details).get_object()
49-
50-
msg = LogMsg()
51-
msg.from_record(record)
52-
return msg
53-
54-
@classmethod
55-
def create_group_message(self, messages, api_config, env_details):
56-
# create group message depending on which transport
57-
if api_config.transport == self.AGENT_SOCKET:
58-
return LogGroup(messages, api_config, env_details).get_object()
59-
60-
return LogMsgGroup(messages)
61-
62-
@classmethod
63-
def get_log_url(self, api_config):
64-
# return log url depending on which transport
65-
if api_config.transport == self.AGENT_SOCKET:
66-
return api_config.socket_url + SOCKET_LOG_URL
67-
68-
return LOG_SAVE_URL
69-
70-
@classmethod
71-
def prepare_message(self, api_config, message):
72-
# convert message depending on which transport
73-
if api_config.transport == self.AGENT_SOCKET:
74-
return message.SerializeToString()
75-
76-
return message
77-
78-
79-
class Transport(object):
80-
"""
81-
Transport base class
82-
"""
83-
84-
def __init__(self, config=None, **kwargs):
85-
self.api_config = config or get_configuration(**kwargs)
86-
self.env_details = EnvironmentDetail(self.api_config)
87-
self._transport = TransportTypes.get_transport(
88-
self.api_config,
89-
self.env_details,
90-
)
91-
92-
def create_message(self, record):
93-
# create message from record
94-
return TransportTypes.create_message(
95-
record,
96-
self.api_config,
97-
self.env_details,
98-
)
44+
return DefaultTransport(api_config, env_details)
9945

100-
def create_group_message(self, messages):
101-
# create group message from list of records
102-
return TransportTypes.create_group_message(
103-
messages,
104-
self.api_config,
105-
self.env_details,
106-
)
10746

108-
def send(self, group_message):
109-
# send group message
110-
try:
111-
self._transport.send(
112-
TransportTypes.get_log_url(self.api_config),
113-
TransportTypes.prepare_message(self.api_config, group_message),
114-
)
115-
except Exception as e:
116-
internal_logger.error('Request error: {}'.format(e))
47+
def configure_transport(config=None, **kwargs):
48+
# return which transport to use depending on users input
49+
api_config = config or get_configuration(**kwargs)
50+
env_details = EnvironmentDetail(api_config)
51+
return TransportTypes.get_transport(
52+
api_config,
53+
env_details,
54+
)
Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,30 @@
1-
from .agent_socket import AgentSocket # noqa
1+
import logging
2+
3+
from stackify.constants import AGENT_LOG_URL
4+
from stackify.transport.agent import agent_http
5+
from stackify.transport.agent import agent_socket
6+
from stackify.transport.base import AgentBaseTransport
7+
8+
internal_logger = logging.getLogger(__name__)
9+
10+
11+
class AgentSocketTransport(AgentBaseTransport):
12+
"""
13+
Agent Socket Transport handles sending of logs using Unix Socket Domain
14+
"""
15+
16+
def __init__(self, api_config, env_details):
17+
super(AgentSocketTransport, self).__init__(api_config, env_details)
18+
self.url = api_config.socket_url + AGENT_LOG_URL
19+
self._transport = agent_socket.AgentSocket()
20+
21+
22+
class AgentHTTPTransport(AgentBaseTransport):
23+
"""
24+
Agent HTTP Transport handles sending of logs using HTTP requests
25+
"""
26+
27+
def __init__(self, api_config, env_details):
28+
super(AgentHTTPTransport, self).__init__(api_config, env_details)
29+
self.url = api_config.http_endpoint + AGENT_LOG_URL
30+
self._transport = agent_http.AgentHTTP()
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import logging
2+
import requests
3+
import retrying
4+
5+
internal_logger = logging.getLogger(__name__)
6+
7+
8+
class AgentHTTP(object):
9+
"""
10+
AgentHTTP class that handles HTTP post requests
11+
"""
12+
13+
def _post(self, url, payload):
14+
headers = {
15+
'Content-Type': 'application/x-protobuf',
16+
}
17+
try:
18+
return requests.post(url, payload, headers=headers)
19+
except Exception as e:
20+
internal_logger.debug('HTTP transport exception: {}.'.format(e))
21+
raise
22+
23+
@retrying.retry(wait_exponential_multiplier=1000, stop_max_delay=32000)
24+
def send(self, url, payload):
25+
# send payload through socket domain using _post method
26+
return self._post(url, payload)

stackify/transport/agent/agent_socket.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,4 @@ def _post(self, url, payload):
4242
@retrying.retry(wait_exponential_multiplier=1000, stop_max_delay=32000)
4343
def send(self, url, payload):
4444
# send payload through socket domain using _post method
45-
self._post(url, payload)
45+
return self._post(url, payload)

stackify/transport/agent/message.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,4 +122,4 @@ def __init__(self, messages, api_config, env_details, logger=None):
122122
log_group.application_location = env_details.appLocation
123123
log_group.logger = logger or __name__
124124
log_group.platform = 'python'
125-
log_group.logs.MergeFrom(messages)
125+
log_group.logs.extend(messages)

0 commit comments

Comments
 (0)