Skip to content

Commit 65ad503

Browse files
Merge pull request #141 from ns1/decisions_endpoint_SDK
Adding decisions endpoint into SDK
2 parents 027d70c + 01181e2 commit 65ad503

File tree

5 files changed

+755
-1
lines changed

5 files changed

+755
-1
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 0.26.0 (August 28th, 2025)
2+
3+
ENHANCEMENTS:
4+
* Adds support for pulsar decision endpoints
5+
16
## 0.25.0 (August 28th, 2025)
27

38
ENHANCEMENTS:

examples/pulsar_decisions.py

Lines changed: 300 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,300 @@
1+
#!/usr/bin/env python
2+
#
3+
# Copyright (c) 2014, 2025 NSONE, Inc.
4+
#
5+
# License under The MIT License (MIT). See LICENSE in project root.
6+
#
7+
"""
8+
Example usage of Pulsar Decisions API endpoints.
9+
This example demonstrates how to query Pulsar decision analytics data
10+
using the ns1-python library.
11+
"""
12+
from ns1 import NS1
13+
import time
14+
15+
# NS1 will use config in ~/.nsone by default
16+
api = NS1()
17+
18+
# to specify an apikey here instead, use:
19+
20+
# from ns1 import Config
21+
# config = Config()
22+
# config.createFromAPIKey('<<CLEARTEXT API KEY>>')
23+
# api = NS1(config=config)
24+
25+
# Get current timestamp and 1 hour ago for time-based queries
26+
end_time = int(time.time())
27+
start_time = end_time - 3600 # 1 hour ago
28+
29+
30+
def main():
31+
"""
32+
Demonstrate various Pulsar Decisions API endpoints.
33+
"""
34+
print("=" * 60)
35+
print("Pulsar Decisions API Examples")
36+
print("=" * 60)
37+
38+
############################
39+
# GET DECISIONS DATA #
40+
############################
41+
print("\n1. Getting decisions data...")
42+
try:
43+
decisions = api.pulsardecisions().get_decisions(
44+
start=start_time, end=end_time, period="1h"
45+
)
46+
print(f" Total decisions: {decisions.get('total', 0)}")
47+
print(f" Number of graphs: {len(decisions.get('graphs', []))}")
48+
except Exception as e:
49+
print(f" Error: {e}")
50+
51+
############################
52+
# GET REGIONAL GRAPH DATA #
53+
############################
54+
print("\n2. Getting regional graph data...")
55+
try:
56+
region_data = api.pulsardecisions().get_decisions_graph_region(
57+
start=start_time, end=end_time
58+
)
59+
print(f" Regions found: {len(region_data.get('data', []))}")
60+
for region in region_data.get("data", [])[:3]: # Show first 3
61+
print(
62+
f" - {region.get('region')}: {len(region.get('counts', []))} job counts"
63+
)
64+
except Exception as e:
65+
print(f" Error: {e}")
66+
67+
##############################
68+
# GET TIME-SERIES GRAPH DATA #
69+
##############################
70+
print("\n3. Getting time-series graph data...")
71+
try:
72+
time_data = api.pulsardecisions().get_decisions_graph_time(
73+
start=start_time, end=end_time, period="5m"
74+
)
75+
print(f" Time points: {len(time_data.get('data', []))}")
76+
if time_data.get("data"):
77+
first_point = time_data["data"][0]
78+
print(f" First timestamp: {first_point.get('timestamp')}")
79+
print(
80+
f" Job counts at first point: {len(first_point.get('counts', []))}"
81+
)
82+
except Exception as e:
83+
print(f" Error: {e}")
84+
85+
##############################
86+
# GET AREA-BASED DECISIONS #
87+
##############################
88+
print("\n4. Getting area-based decisions...")
89+
try:
90+
area_data = api.pulsardecisions().get_decisions_area(
91+
start=start_time, end=end_time, area="US"
92+
)
93+
print(f" Areas found: {len(area_data.get('areas', []))}")
94+
for area in area_data.get("areas", [])[:3]: # Show first 3
95+
print(
96+
f" - {area.get('area_name')}: {area.get('count')} decisions"
97+
)
98+
except Exception as e:
99+
print(f" Error: {e}")
100+
101+
##############################
102+
# GET ASN-BASED DECISIONS #
103+
##############################
104+
print("\n5. Getting ASN-based decisions...")
105+
try:
106+
asn_data = api.pulsardecisions().get_decisions_asn(
107+
start=start_time, end=end_time
108+
)
109+
print(f" ASNs found: {len(asn_data.get('data', []))}")
110+
for asn in asn_data.get("data", [])[:3]: # Show first 3
111+
print(
112+
f" - ASN {asn.get('asn')}: {asn.get('count')} decisions "
113+
f"({asn.get('traffic_distribution', 0)*100:.1f}% of traffic)"
114+
)
115+
except Exception as e:
116+
print(f" Error: {e}")
117+
118+
##############################
119+
# GET RESULTS OVER TIME #
120+
##############################
121+
print("\n6. Getting results over time...")
122+
try:
123+
results_time = api.pulsardecisions().get_decisions_results_time(
124+
start=start_time,
125+
end=end_time,
126+
job="your-job-id", # Replace with actual job ID
127+
)
128+
print(f" Time points: {len(results_time.get('data', []))}")
129+
if results_time.get("data"):
130+
first_point = results_time["data"][0]
131+
print(
132+
f" Results at first point: {len(first_point.get('results', []))}"
133+
)
134+
except Exception as e:
135+
print(f" Error: {e}")
136+
137+
##############################
138+
# GET RESULTS BY AREA #
139+
##############################
140+
print("\n7. Getting results by area...")
141+
try:
142+
results_area = api.pulsardecisions().get_decisions_results_area(
143+
start=start_time, end=end_time
144+
)
145+
print(f" Areas found: {len(results_area.get('area', []))}")
146+
for area in results_area.get("area", [])[:3]: # Show first 3
147+
print(
148+
f" - {area.get('area')}: {area.get('decision_count')} decisions, "
149+
f"{len(area.get('results', []))} unique results"
150+
)
151+
except Exception as e:
152+
print(f" Error: {e}")
153+
154+
##############################
155+
# GET FILTER DATA OVER TIME #
156+
##############################
157+
print("\n8. Getting filter data over time...")
158+
try:
159+
filters_time = api.pulsardecisions().get_filters_time(
160+
start=start_time, end=end_time
161+
)
162+
print(f" Time points: {len(filters_time.get('filters', []))}")
163+
if filters_time.get("filters"):
164+
first_point = filters_time["filters"][0]
165+
print(
166+
f" Filters at first point: {len(first_point.get('filters', {}))}"
167+
)
168+
except Exception as e:
169+
print(f" Error: {e}")
170+
171+
###################################
172+
# GET CUSTOMER-SPECIFIC DECISIONS #
173+
###################################
174+
print("\n9. Getting customer-specific decisions...")
175+
try:
176+
customer_id = "your-customer-id" # Replace with actual customer ID
177+
customer_data = api.pulsardecisions().get_decision_customer(
178+
customer_id, start=start_time, end=end_time
179+
)
180+
print(f" Data points: {len(customer_data.get('data', []))}")
181+
if customer_data.get("data"):
182+
total = sum(
183+
point.get("total", 0) for point in customer_data["data"]
184+
)
185+
print(f" Total decisions: {total}")
186+
except Exception as e:
187+
print(f" Error: {e}")
188+
189+
###################################
190+
# GET RECORD-SPECIFIC DECISIONS #
191+
###################################
192+
print("\n10. Getting record-specific decisions...")
193+
try:
194+
customer_id = "your-customer-id" # Replace with actual customer ID
195+
domain = "example.com"
196+
rec_type = "A"
197+
record_data = api.pulsardecisions().get_decision_record(
198+
customer_id, domain, rec_type, start=start_time, end=end_time
199+
)
200+
print(f" Data points: {len(record_data.get('data', []))}")
201+
if record_data.get("data"):
202+
total = sum(point.get("total", 0) for point in record_data["data"])
203+
print(f" Total decisions for {domain}/{rec_type}: {total}")
204+
except Exception as e:
205+
print(f" Error: {e}")
206+
207+
####################################
208+
# GET TOTAL DECISIONS FOR CUSTOMER #
209+
####################################
210+
print("\n11. Getting total decisions for customer...")
211+
try:
212+
customer_id = "your-customer-id" # Replace with actual customer ID
213+
total_data = api.pulsardecisions().get_decision_total(
214+
customer_id, start=start_time, end=end_time
215+
)
216+
print(f" Total decisions: {total_data.get('total', 0)}")
217+
except Exception as e:
218+
print(f" Error: {e}")
219+
220+
################################
221+
# GET DECISIONS BY RECORD #
222+
################################
223+
print("\n12. Getting decisions by record...")
224+
try:
225+
records_data = api.pulsardecisions().get_decisions_records(
226+
start=start_time, end=end_time
227+
)
228+
print(f" Total decisions: {records_data.get('total', 0)}")
229+
print(f" Number of records: {len(records_data.get('records', {}))}")
230+
for record_key, record_info in list(
231+
records_data.get("records", {}).items()
232+
)[:3]:
233+
print(
234+
f" - {record_key}: {record_info.get('count')} decisions "
235+
f"({record_info.get('percentage_of_total', 0):.1f}%)"
236+
)
237+
except Exception as e:
238+
print(f" Error: {e}")
239+
240+
##############################
241+
# GET RESULTS BY RECORD #
242+
##############################
243+
print("\n13. Getting results by record...")
244+
try:
245+
results_record = api.pulsardecisions().get_decisions_results_record(
246+
start=start_time, end=end_time
247+
)
248+
print(f" Number of records: {len(results_record.get('record', {}))}")
249+
for record_key, record_info in list(
250+
results_record.get("record", {}).items()
251+
)[:3]:
252+
print(
253+
f" - {record_key}: {record_info.get('decision_count')} decisions, "
254+
f"{len(record_info.get('results', {}))} unique results"
255+
)
256+
except Exception as e:
257+
print(f" Error: {e}")
258+
259+
##################################
260+
# QUERYING WITH MULTIPLE FILTERS #
261+
##################################
262+
print("\n14. Querying with multiple filters...")
263+
try:
264+
filtered_data = api.pulsardecisions().get_decisions(
265+
start=start_time,
266+
end=end_time,
267+
period="1h",
268+
area="US",
269+
job="your-job-id", # Replace with actual job ID
270+
agg="sum",
271+
)
272+
print(
273+
f" Total decisions (filtered): {filtered_data.get('total', 0)}"
274+
)
275+
except Exception as e:
276+
print(f" Error: {e}")
277+
278+
##################################
279+
# QUERYING WITH MULTIPLE JOBS #
280+
##################################
281+
print("\n15. Querying with multiple jobs...")
282+
try:
283+
multi_job_data = api.pulsardecisions().get_decisions(
284+
start=start_time,
285+
end=end_time,
286+
jobs=["job1", "job2", "job3"], # Replace with actual job IDs
287+
)
288+
print(
289+
f" Total decisions (multi-job): {multi_job_data.get('total', 0)}"
290+
)
291+
except Exception as e:
292+
print(f" Error: {e}")
293+
294+
print("\n" + "=" * 60)
295+
print("Examples completed!")
296+
print("=" * 60)
297+
298+
299+
if __name__ == "__main__":
300+
main()

ns1/__init__.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#
66
from .config import Config
77

8-
version = "0.25.0"
8+
version = "0.26.0"
99

1010

1111
class NS1:
@@ -251,6 +251,16 @@ def billing_usage(self):
251251

252252
return ns1.rest.billing_usage.BillingUsage(self.config)
253253

254+
def pulsardecisions(self):
255+
"""
256+
Return a new raw REST interface to Pulsar Decisions resources
257+
258+
:rtype: :py:class:`ns1.rest.pulsar_decisions.Decisions`
259+
"""
260+
import ns1.rest.pulsar_decisions
261+
262+
return ns1.rest.pulsar_decisions.Decisions(self.config)
263+
254264
# HIGH LEVEL INTERFACE
255265
def loadZone(self, zone, callback=None, errback=None):
256266
"""

0 commit comments

Comments
 (0)