Skip to content

Commit 0bddc50

Browse files
Deprecate WavefrontProxyClient (#69)
* Deprecate WavefrontProxyClient * disabled duplicate-code check * added uri dependency * Fixed Travis CI Errors * Re-Run Travis-CI Build * incorporated review comments * Added unit tests * Fixed travis ci error * deprecated proxy and direct client * added a command to install a pkg * Fix pylint error for python2 * Fix pylint error for python2 * removed py2 support from TravisCI * removed py2 support from TravisCI * Deprecate WavefrontProxyClient * incorporated review comments * Removed parameters from super method call * incorporated review comments * Added multiclient information * Fixed travis ci errors * Update wavefront_sdk/client_factory.py Co-authored-by: Artem Ustinov <ustinov@users.noreply.github.com> * Update wavefront_sdk/client_factory.py Co-authored-by: Artem Ustinov <ustinov@users.noreply.github.com> * Update wavefront_sdk/client_factory.py Co-authored-by: Artem Ustinov <ustinov@users.noreply.github.com> * Update test/test_wavefront_client.py Co-authored-by: Artem Ustinov <ustinov@users.noreply.github.com> * Update test/test_wavefront_client.py Co-authored-by: Artem Ustinov <ustinov@users.noreply.github.com> * Update test/test_wavefront_client.py Co-authored-by: Artem Ustinov <ustinov@users.noreply.github.com> * Update test/test_wavefront_client.py Co-authored-by: Artem Ustinov <ustinov@users.noreply.github.com> * Update test/test_wavefront_client.py Co-authored-by: Artem Ustinov <ustinov@users.noreply.github.com> Co-authored-by: Artem Ustinov <ustinov@users.noreply.github.com>
1 parent 65f8834 commit 0bddc50

11 files changed

Lines changed: 1077 additions & 7 deletions

File tree

.travis.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@ python:
88
install:
99
- pip install requests
1010
- pip install tdigest
11+
- pip install Deprecated
1112
- pip install flake8 flake8-colors flake8-import-order
1213
- pip install pep8-naming
1314
- pip install pydocstyle
1415
- pip install pylint
1516
before_script:
1617
- python -m flake8
17-
- python -m pylint wavefront_sdk
18+
- python -m pylint -d duplicate-code wavefront_sdk
1819
- python -m pydocstyle
1920
script:
2021
- python -m unittest discover

README.md

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,10 @@ You can send metrics, histograms, or trace data from your application to the Wav
139139
* Use a [**Wavefront proxy**](https://docs.wavefront.com/proxies.html), which then forwards the data to the Wavefront service. This is the recommended choice for a large-scale deployment that needs resilience to internet outages, control over data queuing and filtering, and more.
140140
141141
You instantiate an object that corresponds to your choice:
142-
* Option 1: [Create a `WavefrontDirectClient`](#option-1-create-a-wavefrontdirectclient) to send data directly to a Wavefront service.
143-
* Option 2: [Create a `WavefrontProxyClient`](#option-2-create-a-wavefrontproxyclient) to send data to a Wavefront proxy.
142+
* Option 1 **(Deprecated)**: [Create a `WavefrontDirectClient`](#option-1-create-a-wavefrontdirectclient) to send data directly to a Wavefront service.
143+
* Option 2 **(Deprecated)**: [Create a `WavefrontProxyClient`](#option-2-create-a-wavefrontproxyclient) to send data to a Wavefront proxy.
144+
* Option 3: [Create a `WavefrontClient`](#option-3-create-a-wavefrontclient) to send data to a Wavefront service directly or via proxy.
145+
> **Deprecated implementations**: *`WavefrontDirectClient` and `WavefrontProxyClient` are deprecated from proxy version 7.0 onwards. We recommend all new applications to use the `WavefrontClient`.*
144146
145147
### Option 1: Create a WavefrontDirectClient
146148
When sending data via direct ingestion, you need to create a `WavefrontDirectClient`, and build it with the Wavefront URL and API token to send data directly to Wavefront.
@@ -188,7 +190,7 @@ wavefront_sender = WavefrontDirectClient(
188190
When sending data via the Wavefront proxy, you need to create a `WavefrontProxyClient`. Include the following information.
189191

190192
* The name of the host that will run the Wavefront proxy.
191-
* One or more proxy listening ports to send data to. The ports you specify depend on the kinds of data you want to send (metrics, histograms, and/or trace data). You must specify at least one listener port.
193+
* One or more proxy listening ports to send data to. The ports you specify depend on the kinds of data you want to send (metrics, histograms, and/or trace data). You must specify at least one listener port.
192194
* Optional settings for tuning communication with the proxy.
193195

194196
> **Note**: See [Advanced Proxy Configuration and Installation](https://docs.wavefront.com/proxies_configuring.html) for details.
@@ -219,6 +221,52 @@ wavefront_sender = WavefrontProxyClient(
219221
| `distribution_port` | `histogramDistListenerPorts=` |
220222
| `tracing_port` | `traceListenerPorts=` |
221223

224+
### Option 3: Create a WavefrontClient
225+
Use `WavefrontClientFactory` to create a `WavefrontClient` instance, which can send data directly to a Wavefront service or send data using a Wavefront Proxy.
226+
227+
The `WavefrontClientFactory` supports multiple client bindings. If more than one client configuration is specified, you can create a `WavefrontMultiClient` instance, which can send data to multiple Wavefront services.
228+
### Prerequisites
229+
* Sending data via Wavefront proxy?
230+
<br/>Before your application can use a `WavefrontClient` you must [set up and start a Wavefront proxy](https://docs.wavefront.com/proxies_installing.html).
231+
* Sending data via direct ingestion?
232+
* Verify that you have the Direct Data Ingestion permission. For details, see [Examine Groups, Roles, and Permissions](https://docs.wavefront.com/users_account_managing.html#examine-groups-roles-and-permissions).
233+
* The HTTP URL of your Wavefront instance. This is the URL you connect to when you log in to Wavefront, typically something like `http://<domain>.wavefront.com`.<br/> You can also use HTTP client with Wavefront Proxy version 7.0 or newer. Example: `http://proxy.acme.corp:2878`.
234+
* [Obtain the API token](http://docs.wavefront.com/wavefront_api.html#generating-an-api-token).
235+
236+
### Initialize the WavefrontClient
237+
```python
238+
from wavefront_sdk.client_factory import WavefrontClientFactory
239+
240+
# Create a sender with:
241+
# Required Parameter
242+
# URL format to send data via proxy: "proxy://<your.proxy.load.balancer.com>:<somePort>"
243+
# URL format to send data via direct ingestion: "https://TOKEN@DOMAIN.wavefront.com"
244+
# Optional Parameter
245+
# max queue size (in data points). Default: 50000
246+
# batch size (in data points). Default: 10000
247+
# flush interval (in seconds). Default: 1 second
248+
249+
client_factory = WavefrontClientFactory()
250+
client_factory.add_client(
251+
url="<URL for proxy or direct ingestions>",
252+
max_queue_size=50000,
253+
batch_size=10000,
254+
flush_interval_seconds=5)
255+
wavefront_sender = client_factory.get_client()
256+
```
257+
#### Add multiple clients to client factory to send data to multiple Wavefront services.
258+
```
259+
from wavefront_sdk.client_factory import WavefrontClientFactory
260+
261+
client_factory = WavefrontClientFactory()
262+
client_factory.add("proxy://our.proxy.lb.com:2878")
263+
client_factory.add("https://someToken@DOMAIN.wavefront.com")
264+
265+
# Send traces and spans to the tracing port. If you are directly using the sender SDK to send spans without using any other SDK, use the same port as the customTracingListenerPorts configured in the wavefront proxy. Assume you have installed and started the proxy on <proxy_hostname>.
266+
client_factory.add("http://<proxy_hostname>:30000")
267+
268+
wavefront_sender = client_factory.get_client()
269+
```
222270

223271
## Send a Single Data Point to Wavefront
224272

example.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import time
66
import uuid
77

8+
from wavefront_sdk.client_factory import WavefrontClientFactory
89
from wavefront_sdk.direct import WavefrontDirectClient
910
from wavefront_sdk.entities.histogram import histogram_granularity
1011
from wavefront_sdk.proxy import WavefrontProxyClient
@@ -106,6 +107,58 @@ def send_event_via_direct_ingestion(direct_ingestion_client):
106107
"details": "broker backup"})
107108

108109

110+
def send_metrics_multi_client(proxy_client):
111+
"""Send a metric using multi client."""
112+
proxy_client.send_metric(
113+
'python' + str(sys.version_info[0])
114+
+ '.multi.client.new york.power.usage',
115+
42422.0, None, 'localhost', None)
116+
117+
118+
def send_delta_counter_multi_client(proxy_client):
119+
"""Send a delta counter using multi client."""
120+
proxy_client.send_delta_counter(
121+
'python' + str(sys.version_info[0])
122+
+ '.delta.multi.client.counter',
123+
1.0, 'localhost', None)
124+
125+
126+
def send_histogram_multi_client(proxy_client):
127+
"""Send a histogram using multi client."""
128+
proxy_client.send_distribution(
129+
'python' + str(sys.version_info[0]) + '.multi.client.request.latency',
130+
[(30, 20), (5.1, 10)],
131+
{histogram_granularity.DAY, histogram_granularity.HOUR,
132+
histogram_granularity.MINUTE},
133+
None, 'appServer1', {'region': 'us-west'})
134+
135+
136+
def send_tracing_span_multi_client(proxy_client):
137+
"""Send a tracing span using multi client."""
138+
proxy_client.send_span(
139+
'getAllUsersFromPythonMultiClient',
140+
int(time.time()), 34350, 'localhost',
141+
uuid.UUID('7b3bf470-9456-11e8-9eb6-529269fb1459'),
142+
uuid.UUID('0313bafe-9457-11e8-9eb6-529269fb1459'),
143+
[uuid.UUID('2f64e538-9457-11e8-9eb6-529269fb1459')], None,
144+
[('application', 'Wavefront'), ('service', 'testService'),
145+
('cluster', 'testCluster'), ('shard', 'testShard'),
146+
('http.method', 'GET')], None)
147+
148+
149+
def send_event_via_multi_client(direct_ingestion_client):
150+
"""Send an event through multi ingestion."""
151+
direct_ingestion_client.send_event(
152+
'event_via_multi_client',
153+
time.time(),
154+
None,
155+
"localhost",
156+
["env:", "test"],
157+
{"severity": "severe",
158+
"type": "backup",
159+
"details": "broker backup"})
160+
161+
109162
if __name__ == '__main__':
110163
wavefront_server = sys.argv[1]
111164
token = sys.argv[2]
@@ -114,6 +167,10 @@ def send_event_via_direct_ingestion(direct_ingestion_client):
114167
distribution_port = None if len(sys.argv) <= 5 else sys.argv[5]
115168
tracing_port = None if len(sys.argv) <= 6 else sys.argv[6]
116169
event_port = None if len(sys.argv) <= 7 else sys.argv[7]
170+
# Proxy url: proxy://<proxy-host-ip>:2878
171+
proxy_url = None if len(sys.argv) <= 8 else sys.argv[8]
172+
# Direct url: https://<api-key>@<cluster-name>.wavefront.com
173+
direct_url = None if len(sys.argv) <= 9 else sys.argv[9]
117174

118175
wavefront_proxy_client = WavefrontProxyClient(
119176
host=proxy_host,
@@ -124,6 +181,11 @@ def send_event_via_direct_ingestion(direct_ingestion_client):
124181

125182
wavefront_direct_client = WavefrontDirectClient(wavefront_server, token)
126183

184+
multi_client_factory = WavefrontClientFactory()
185+
multi_client_factory.add_client(proxy_url)
186+
multi_client_factory.add_client(direct_url)
187+
multi_client = multi_client_factory.get_client()
188+
127189
try:
128190
while True:
129191
send_metrics_via_proxy(wavefront_proxy_client)
@@ -138,7 +200,14 @@ def send_event_via_direct_ingestion(direct_ingestion_client):
138200
send_delta_counter_via_direct_ingestion(wavefront_direct_client)
139201
send_event_via_direct_ingestion(wavefront_direct_client)
140202

203+
send_metrics_multi_client(multi_client)
204+
send_histogram_multi_client(multi_client)
205+
send_tracing_span_multi_client(multi_client)
206+
send_delta_counter_multi_client(multi_client)
207+
send_event_via_multi_client(multi_client)
208+
141209
time.sleep(1)
142210
finally:
143211
wavefront_proxy_client.close()
144212
wavefront_direct_client.close()
213+
multi_client.close()

setup.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
setuptools.setup(
1717
name='wavefront-sdk-python',
18-
version='1.7.6',
18+
version='1.7.7',
1919
author='Wavefront by VMware',
2020
author_email='chitimba@wavefront.com',
2121
url='https://github.com/wavefrontHQ/wavefront-sdk-python',
@@ -39,6 +39,7 @@
3939
'tests.*', 'tests')),
4040
install_requires=(
4141
'requests>=2.18.4',
42-
'tdigest>=0.5.2'
42+
'tdigest>=0.5.2',
43+
'Deprecated>=1.2.10'
4344
)
4445
)

test/test_wavefront_client.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
"""Unit Tests for Wavefront Client.
2+
3+
@Yogesh Prasad Kurmi (ykurmi@vmware.com)
4+
"""
5+
6+
import unittest
7+
8+
import wavefront_sdk
9+
from wavefront_sdk.client_factory import WavefrontClientFactory
10+
11+
12+
class WavefrontClient(unittest.TestCase):
13+
"""Test Functions of wavefront_sdk.client_factory."""
14+
15+
def test_get_server_info_from_endpoint(self):
16+
"""Test get_server_info_from_endpoint of WavefrontClientFactory"""
17+
direct_base_url = ("https://a87826d5-889d-4b23-98f0-2f3558zd007a"
18+
"@wfcluster.wavefront.com")
19+
server, token = WavefrontClientFactory(
20+
).get_server_info_from_endpoint(direct_base_url)
21+
self.assertEqual(server, "https://wfcluster.wavefront.com")
22+
self.assertEqual(token, "a87826d5-889d-4b23-98f0-2f3558zd007a")
23+
24+
proxy_base_url = "proxy://10.112.71.230:2878"
25+
server, token = WavefrontClientFactory(
26+
).get_server_info_from_endpoint(proxy_base_url)
27+
self.assertEqual(server, "http://10.112.71.230:2878")
28+
self.assertEqual(token, None)
29+
30+
http_proxy_base_url = "http://192.114.71.230:2878"
31+
server, token = WavefrontClientFactory(
32+
).get_server_info_from_endpoint(http_proxy_base_url)
33+
self.assertEqual(server, "http://192.114.71.230:2878")
34+
self.assertEqual(token, None)
35+
36+
def test_get_client(self):
37+
"""Test get_client of WavefrontClientFactory"""
38+
39+
# get_client should return None if there is no client
40+
client = WavefrontClientFactory().get_client()
41+
self.assertEqual(client, None)
42+
43+
# get_client should return instance of WavefrontClient
44+
# if there is only one client
45+
direct_base_url = ("https://a87826d5-889d-4b23-98f0-2f3558zd007a"
46+
"@wfcluster.wavefront.com")
47+
multi_client_factory = WavefrontClientFactory()
48+
multi_client_factory.add_client(direct_base_url)
49+
self.assertTrue(isinstance(multi_client_factory.get_client(),
50+
wavefront_sdk.client.WavefrontClient))
51+
52+
# get_client should return instance of WavefrontMultiClient
53+
# if there is more than one client
54+
proxy_base_url = "proxy://192.114.71.230:2878"
55+
multi_client_factory.add_client(proxy_base_url)
56+
self.assertTrue(isinstance(multi_client_factory.get_client(),
57+
wavefront_sdk.multi_clients
58+
.WavefrontMultiClient))
59+
60+
def test_existing_client(self):
61+
"""Test existing_client of WavefrontClientFactory"""
62+
server = "http://192.114.71.230:2878"
63+
64+
# existing_client should return False if client does not exists
65+
self.assertFalse(WavefrontClientFactory().existing_client(server))
66+
67+
68+
if __name__ == '__main__':
69+
# run 'python -m unittest discover' from top-level to run tests
70+
unittest.main()

wavefront_sdk/__init__.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,14 @@
99

1010
import pkg_resources
1111

12+
from .client_factory import WavefrontClientFactory
1213
from .direct import WavefrontDirectClient
1314
from .proxy import WavefrontProxyClient
1415

1516

16-
__all__ = ['WavefrontDirectClient', 'WavefrontProxyClient']
17+
__all__ = ['WavefrontDirectClient',
18+
'WavefrontProxyClient',
19+
'WavefrontClientFactory']
1720

1821
__version__ = None
1922

0 commit comments

Comments
 (0)