Skip to content

Commit e18608e

Browse files
committed
Class hierarchy for TelemetryMetrics
1 parent f251ade commit e18608e

File tree

7 files changed

+256
-13
lines changed

7 files changed

+256
-13
lines changed

splunklib/modularinput/script.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
from .event_writer import EventWriter
2626
from .input_definition import InputDefinition
2727
from .validation_definition import ValidationDefinition
28-
from ..wire._internal import Telemetry, TelemetryMetric
28+
from ..wire._internal import Telemetry, EventTelemetryMetric
2929

3030
try:
3131
import xml.etree.cElementTree as ET
@@ -76,8 +76,7 @@ def run_script(self, args, event_writer, input_stream):
7676
self._input_definition = InputDefinition.parse(input_stream)
7777

7878
# create a telemetry metric
79-
metric = TelemetryMetric(**{
80-
'metric_type': 'event',
79+
metric = EventTelemetryMetric(**{
8180
'component': 'splunk-sdk-python',
8281
'data': {
8382
'version': splunklib.__version__

splunklib/wire/_internal/__init__.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,6 @@
1414
# License for the specific language governing permissions and limitations
1515
# under the License.
1616

17+
from .aggregate_telemetry_metric import *
18+
from .event_telemetry_metric import *
1719
from .telemetry import *
18-
from .telemetry_metric import *
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# coding=utf-8
2+
#
3+
# Copyright © 2011-2020 Splunk, Inc.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License"): you may
6+
# not use this file except in compliance with the License. You may obtain
7+
# a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14+
# License for the specific language governing permissions and limitations
15+
# under the License.
16+
17+
from splunklib.wire._internal.telemetry_metric import TelemetryMetric
18+
19+
class AggregateTelemetryMetric(TelemetryMetric):
20+
METRIC_TYPE = 'aggregate'
21+
22+
def __init__(self, component, data,
23+
opt_in_required=2,
24+
version=None,
25+
timestamp=None,
26+
visibility=None,
27+
index_data=None,
28+
begin=None,
29+
end=None):
30+
super(AggregateTelemetryMetric, self).__init__(
31+
AggregateTelemetryMetric.METRIC_TYPE,
32+
component,
33+
data,
34+
opt_in_required=opt_in_required,
35+
version=version,
36+
timestamp=timestamp,
37+
visibility=visibility,
38+
index_data=index_data
39+
)
40+
41+
self.begin = begin
42+
self.end = end
43+
44+
@property
45+
def begin(self):
46+
return self._begin
47+
48+
@begin.setter
49+
def begin(self, value):
50+
self._begin = value
51+
52+
@property
53+
def end(self):
54+
return self._end
55+
56+
@end.setter
57+
def end(self, value):
58+
self._end = value
59+
60+
def to_wire(self):
61+
wire = super(AggregateTelemetryMetric, self).to_wire()
62+
63+
if self.begin is not None:
64+
wire['begin'] = self.begin
65+
66+
if self.end is not None:
67+
wire['end'] = self.end
68+
69+
return wire
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# coding=utf-8
2+
#
3+
# Copyright © 2011-2020 Splunk, Inc.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License"): you may
6+
# not use this file except in compliance with the License. You may obtain
7+
# a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14+
# License for the specific language governing permissions and limitations
15+
# under the License.
16+
17+
from splunklib.wire._internal.telemetry_metric import TelemetryMetric
18+
19+
class EventTelemetryMetric(TelemetryMetric):
20+
METRIC_TYPE = 'event'
21+
22+
def __init__(self, component, data,
23+
opt_in_required=2,
24+
version=None,
25+
timestamp=None,
26+
visibility=None,
27+
index_data=None,
28+
user_id=None,
29+
experience_id=None):
30+
super(EventTelemetryMetric, self).__init__(
31+
EventTelemetryMetric.METRIC_TYPE,
32+
component,
33+
data,
34+
opt_in_required=opt_in_required,
35+
version=version,
36+
timestamp=timestamp,
37+
visibility=visibility,
38+
index_data=index_data
39+
)
40+
41+
self.user_id = user_id
42+
self.experience_id = experience_id
43+
44+
@property
45+
def user_id(self):
46+
return self._user_id
47+
48+
@user_id.setter
49+
def user_id(self, value):
50+
self._user_id = value
51+
52+
@property
53+
def experience_id(self):
54+
return self._experience_id
55+
56+
@experience_id.setter
57+
def experience_id(self, value):
58+
self._experience_id = value
59+
60+
def to_wire(self):
61+
wire = super(EventTelemetryMetric, self).to_wire()
62+
63+
if self.user_id is not None:
64+
wire['userID'] = self.user_id
65+
66+
if self.experience_id is not None:
67+
wire['experienceID'] = self.experience_id
68+
69+
return wire

splunklib/wire/_internal/telemetry_metric.py

+61-3
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,24 @@
1414
# License for the specific language governing permissions and limitations
1515
# under the License.
1616

17-
class TelemetryMetric:
18-
def __init__(self, metric_type, component, data, opt_in_required=2):
17+
from abc import ABCMeta
18+
from splunklib import six
19+
20+
class TelemetryMetric(six.with_metaclass(ABCMeta, object)):
21+
def __init__(self, metric_type, component, data,
22+
opt_in_required=2,
23+
version=None,
24+
index_data=None,
25+
timestamp=None,
26+
visibility=None):
1927
self.metric_type = metric_type
2028
self.component = component
2129
self.data = data
2230
self.opt_in_required = opt_in_required
31+
self.version = version
32+
self.index_data = index_data
33+
self.timestamp = timestamp
34+
self.visibility = visibility
2335

2436
@property
2537
def metric_type(self):
@@ -53,10 +65,56 @@ def opt_in_required(self):
5365
def opt_in_required(self, value):
5466
self._opt_in_required = value
5567

68+
@property
69+
def version(self):
70+
return self._version
71+
72+
@version.setter
73+
def version(self, value):
74+
self._version = value
75+
76+
@property
77+
def index_data(self):
78+
return self._index_data
79+
80+
@index_data.setter
81+
def index_data(self, value):
82+
self._index_data = value
83+
84+
@property
85+
def timestamp(self):
86+
return self._timestamp
87+
88+
@timestamp.setter
89+
def timestamp(self, value):
90+
self._timestamp = value
91+
92+
@property
93+
def visibility(self):
94+
return self._visibility
95+
96+
@visibility.setter
97+
def visibility(self, value):
98+
self._visibility = value
99+
56100
def to_wire(self):
57-
return {
101+
wire = {
58102
'type': self.metric_type,
59103
'component': self.component,
60104
'data': self.data,
61105
'optInRequired': self.opt_in_required,
62106
}
107+
108+
if self.version is not None:
109+
wire['version'] = self.version
110+
111+
if self.index_data is not None:
112+
wire['indexData'] = self.index_data
113+
114+
if self.timestamp is not None:
115+
wire['timestamp'] = self.timestamp
116+
117+
if self.visibility is not None:
118+
wire['visibility'] = self.visibility
119+
120+
return wire

tests/modularinput/test_script.py

+11-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from mock import Mock, patch
66

7-
from splunklib import six
7+
from splunklib import six, __version__
88
from splunklib.client import Service
99
from splunklib.modularinput import Script, EventWriter, Scheme, Argument, Event
1010

@@ -219,6 +219,15 @@ def stream_events(self, inputs, ew):
219219
def test_telemetry(capsys):
220220
"""Check that writing telemetry goes smoothly."""
221221

222+
EXPECTED_TELEMETRY_BODY = {
223+
'type': 'event',
224+
'component': 'splunk-sdk-python',
225+
'data': {
226+
'version': __version__,
227+
},
228+
'optInRequired': 2
229+
}
230+
222231
# Override abstract methods
223232
class NewScript(Script):
224233
def get_scheme(self):
@@ -246,7 +255,7 @@ def stream_events(self, _inputs, ew):
246255
assert post_args == ('telemetry-metric/',)
247256
assert post_kwargs == {
248257
'app': None,
249-
'body': '{"type": "event", "component": "splunk-sdk-python", "data": {"version": "1.6.13"}, "optInRequired": 2}',
258+
'body': json.dumps(EXPECTED_TELEMETRY_BODY),
250259
'headers': [('Content-Type', 'application/json')],
251260
'owner': None,
252261
'sharing': None

tests/test_telemetry.py

+42-4
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@
1818
import pytest
1919

2020
from tests import testlib
21-
from splunklib.wire._internal.telemetry import Telemetry
22-
from splunklib.wire._internal.telemetry_metric import TelemetryMetric
21+
from splunklib.wire._internal import Telemetry, EventTelemetryMetric, AggregateTelemetryMetric
2322

2423
@pytest.mark.app
2524
class TestTelemetry(testlib.SDKTestCase):
@@ -33,8 +32,7 @@ def setUp(self):
3332

3433
def test_submit(self):
3534
# create a telemetry metric
36-
metric = TelemetryMetric(**{
37-
'metric_type': 'event',
35+
metric = EventTelemetryMetric(**{
3836
'component': 'telemetry_test_case',
3937
'data': {
4038
'testValue': 32
@@ -46,3 +44,43 @@ def test_submit(self):
4644

4745
# it should return a 201
4846
self.assertEqual(response.status, 201)
47+
48+
def test_event_submit(self):
49+
# create a telemetry metric
50+
metric = EventTelemetryMetric(**{
51+
'component': 'telemetry_test_case',
52+
'data': {
53+
'testValue': 32
54+
},
55+
'version': 'test',
56+
'index_data': False,
57+
'timestamp': 0,
58+
'visibility': ['anonymous'],
59+
})
60+
61+
# call out to telemetry
62+
response, _body = self.telemetry.submit(metric.to_wire())
63+
64+
# it should return a 201
65+
self.assertEqual(response.status, 201)
66+
67+
def test_aggregate_submit(self):
68+
# create a telemetry metric
69+
metric = AggregateTelemetryMetric(**{
70+
'component': 'telemetry_test_case',
71+
'data': {
72+
'testValue': 32
73+
},
74+
'version': 'test',
75+
'index_data': False,
76+
'timestamp': 3,
77+
'visibility': ['anonymous'],
78+
'begin': 0,
79+
'end': 1,
80+
})
81+
82+
# call out to telemetry
83+
response, _body = self.telemetry.submit(metric.to_wire())
84+
85+
# it should return a 201
86+
self.assertEqual(response.status, 201)

0 commit comments

Comments
 (0)