def test_kpss(): data = Data("cpu.utilization", filter=Filter('app', 'test-app'))\ .kpss(over='1h')\ .publish(label = 'a') assert data.call_stack[0].name == 'kpss' # mode should default to level assert data.call_stack[0].args == [ KWArg("over", '1h'), KWArg("mode", 'level') ] data = Data("cpu.utilization", filter=Filter('app', 'test-app'))\ .kpss(over='2m', mode='trend')\ .publish(label = 'a') # should allow trend assert data.call_stack[0].args == [ KWArg("over", '2m'), KWArg("mode", 'trend') ] try: Data("cpu.utilization", filter=Filter('app', 'test-app'))\ .kpss(over='2m', mode='tr3nd') assert False except ValueError as ve: assert str(ve) == 'kpss mode must be level|trend'
def test_detector_with_assign_combinator(): """ We should correctly generate a detector comprised of two assignment functions """ cpu_util_string = 'cpu.utilization' sum_string = 'utilization_sum' count_string = 'utilization_count' mean_string = 'utilization_mean' sum_data = Data(cpu_util_string).sum() count_data = Data(cpu_util_string).count() utilization_sum = Assign(sum_string, sum_data) utilization_count = Assign(count_string, count_data) mean_data = Div(Ref(sum_string), Ref(count_string)) utilization_mean = Assign(mean_string, mean_data) detect = Detect(When(GT(Ref(mean_string), 50))).publish(label='detector') program = Program(utilization_sum, utilization_count, utilization_mean, detect) detector = Detector().with_program(program) assert detector.options["programText"] == "{0}\n{1}\n{2}\n{3}".format( str(utilization_sum), str(utilization_count), str(utilization_mean), str(detect)) assert program.statements.pop() == detect assert program.statements.pop() == utilization_mean assert program.statements.pop() == utilization_count assert program.statements.pop() == utilization_sum
def test_op_combines_mul(): data1 = Data('request.mean')\ .publish(label='A') data2 = Data('request.count')\ .publish(label='B') muldata = Op(Mul(data1, data2)) program = Program(muldata) assert program.statements[0] == muldata
def test_over_by_methods_single_invocation(): """Ensure that by/over methods don't allow you to supply both in a single call.""" with pytest.raises(ValueError): Data('foo').count(by='dimension', over='1m') data_by = Data('bar').count(by='foo') data_over = Data('baz').count(over='1m') assert data_by.call_stack[0].args[0].arg == 'foo' assert data_over.call_stack[0].args[1].arg == '1m'
def test_integrate(): data = Data("cpu.utilization", filter=Filter('app', 'test-app'))\ .integrate()\ .publish(label = 'a') assert data.call_stack[0].name == 'integrate' assert data.call_stack[0].args == []
def test_fill(): data = Data("cpu.utilization", filter=Filter('app', 'test-app'))\ .fill(value=42, duration="1m")\ .publish(label = 'a') assert data.call_stack[0].name =='fill' assert data.call_stack[0].args == [KWArg("value", 42), KWArg("duration", '1m')]
def test_detector_from_chart_not_program(): """We should throw an error if we receive a chart that doesn't have a proper program. """ program = Data('awesome.metrics').publish(label='A') chart = TimeSeriesChart().with_program(program) with pytest.raises(ValueError): Detector().from_chart(chart, lambda x: x)
def test_detector_from_chart(): program = Program(Data('cpu.utilization').publish(label='Z')) chart = TimeSeriesChart().with_program(program) def helper(p): return Program(Detect(LT(p.find_label('Z'), 10)).publish(label='foo')) detector = Detector().from_chart(chart, helper) assert detector.options['programText'] == str(helper(program))
def test_count_percentage_by_methods(): # TODO consider making this test use dynamic fn calls to test all stream # methods with the same signature. data = Data('cpu.utilization', filter=Filter('app', 'test-app'))\ .top(count=3, percentage=22.3, by=["env", "datacenter"])\ .bottom(count=4, percentage=22.4, by=["env", "datacenter"])\ .publish(label='A') assert data.call_stack[0].args == [KWArg("count", 3), KWArg("percentage", 22.3), KWArg("by", ["env", "datacenter"])] assert data.call_stack[1].args == [KWArg("count", 4), KWArg("percentage", 22.4), KWArg("by", ["env", "datacenter"])]
def fun(name, threshold): program = Program( Detect(GT(Data("cpu.utilization"), threshold)).publish(label=name)) rule = (Rule().for_label(name).with_severity( Severity.Info).with_notifications( EmailNotification("*****@*****.**"))) return (Detector(session=session).with_name(name).with_program( program).with_rules(rule))
def test_detector_from_chart_mod_prog(): """We shouldn't be able to muck about with programs from charts.""" program = Program(Data('disk.utilization').publish(label='X')) prog_size = len(program.statements) chart = TimeSeriesChart().with_program(program) def bad_helper(p): p.add_statements(Data("I shouldn't exist").publish(label='Y')) return Program(Detect(LT(p.find_label('Z'), 10)).publish(label='foo')) Detector().from_chart(chart, bad_helper) # bad_helper should not be allowed to add new program statements to # the originating chart's program. assert prog_size == len(program.statements)
def test_cli_create_force_success(): program = Data('cpu.utilization').publish() chart = TimeSeriesChart().with_name('lol').with_program(program) with global_recorder.use_cassette('cli_create_force_success', serialize_with='prettyjson'): dashboard = Dashboard(session=global_session)\ .with_name('testy mctesterson')\ .with_charts(chart) cli = CliBuilder().with_resources(dashboard).build() runner = CliRunner() result = runner.invoke(cli, args=['--api-key', 'foo', 'create', '-f']) assert result.exit_code == 0
def test_cli_create_interactive_failure(sfx_recorder, session): program = Data('cpu.utilization').publish() chart = TimeSeriesChart().with_name('lol').with_program(program) with sfx_recorder.use_cassette('cli_create_interactive_failure', serialize_with='prettyjson'): dashboard = Dashboard(session=session)\ .with_name('testy mctesterson')\ .with_charts(chart) cli = CliBuilder().with_resources(dashboard).build() runner = CliRunner() result = runner.invoke(cli, args=['--api-key', 'foo', 'create', '-i'], input='n') click.echo(result.exception) assert result.exception
def test_valid_publish_statement_comb_valid(): Program( Op(Div(Data('foo'), Data('bar'))).publish(label='foobar') ).validate()
"""Examples for the `signal_analog.charts` module.""" from signal_analog.charts \ import TimeSeriesChart, PlotType, PublishLabelOptions, PaletteColor from signal_analog.flow import Data, Filter, Program from signal_analog.combinators import And """ Example 1: single-use chart This is useful when you just want to create a chart and aren't worried about re-usability. """ # Look at the mean of the cpu.user metric for my-app in the prod environment app_filter = And(Filter('app', 'my-app'), Filter('env', 'prod')) program = Program(Data('cpu.user', filter=app_filter).mean().publish('A')) chart = TimeSeriesChart()\ .with_name('CPU Used %')\ .with_description('% CPU used by user')\ .stack_chart(True)\ .with_default_plot_type(PlotType.area_chart)\ .with_program(program) """ Example 2: make a re-usable chart (or template) This is useful when you want your chart to be broadly applicable/used by others """ class UserCpuUsedPercentChart(TimeSeriesChart):
#!/usr/bin/env python """Examples for the `signal_analog.dashboards` module.""" from signal_analog.flow import Data, Filter from signal_analog.charts import TimeSeriesChart from signal_analog.dashboards import Dashboard from signal_analog.combinators import And """ Example 1: Creating a new Dashboard This creates a new dashboard for the app specified and with the charts provided """ filters = And(Filter('app', 'my-app'), Filter('env', 'test')) program = Data('cpu.utilization', filter=filters).publish() chart = TimeSeriesChart().with_name('Chart_Name').with_program(program) dashboard_with_single_chart = Dashboard()\ .with_name('Dashboard Name')\ .with_charts(chart) """ Example 2: Creating a new Dashboard with multiple charts """ # With the same filters as above example, program = Data('cpu.utilization', filter=filters).publish() chart = TimeSeriesChart().with_name('Chart_Name').with_program(program) program1 = Data('network.utilization', filter=filters).publish() chart1 = TimeSeriesChart().with_name('Chart_Name').with_program(program) program2 = Data('api_errors', filter=filters).publish()
def test_chart_with_program(): expected = Data('Ms. Communication') chart = Chart().with_program(expected) assert chart.options['programText'] == expected
def test_dimensions_method_happy(): data = Data('bar').dimensions(aliases={'foo': 'baz'}).publish(label='foo') assert data.call_stack[0].args[0] == KWArg("aliases", {'foo': 'baz'}) data = Data('bar').dimensions(renames={'foo': 'baz'}).publish(label='foo') assert data.call_stack[0].args[1] == KWArg("renames", {'foo': 'baz'})
def test_when(): data1 = Data('request.mean')\ .publish(label='A') when = When(GT(data1, 50), '5m', 0.5) program = Program(when) assert program.statements[0] == when
def test_find_label_unpublished(): data = Data('cpu.utilization', filter=Filter('app', 'test-app')) program = Program(data) assert program.find_label('A') is None
def test_find_label_published(): data = Data('cpu.utilization', filter=Filter('app', 'test-app'))\ .publish(label='A') program = Program(data) assert program.find_label('A') == data
def test_dimensions_invalid(): with pytest.raises(ValueError): data = Data('bar').dimensions(aliases={}, renames={})
def mk_chart(name): program = Data('cpu.utilization').publish() return TimeSeriesChart(session=global_session)\ .with_name(name)\ .with_program(program)
def __program__(self, app, env): app_filter = And(Filter('app', 'my-app'), Filter('env', 'prod')) return Program(Data('cpu.user', filter=app_filter).mean().publish('A'))
def test_ewma_happy(): data = Data('foo').ewma(1) assert data.call_stack[0].args[0].arg == 1 data = Data('foo').ewma(over='1m') assert data.call_stack[0].args[0] == KWArg("over", '1m')
def test_ewma_invalid(): with pytest.raises(ValueError): Data('foo').ewma(1, '1m')
#!/usr/bin/env python """Examples for the `signal_analog.filters` module.""" from signal_analog.flow import Data, Filter from signal_analog.charts import TimeSeriesChart from signal_analog.dashboards import Dashboard from signal_analog.combinators import And from signal_analog.filters import DashboardFilters, FilterVariable, FilterSource, FilterTime """ Example 1: Creating a new Dashboard with Filter Variable This creates a new dashboard for the app specified and with the charts provided and with the Dashboard Filter provided """ filters = And(Filter('app', 'my-app'), Filter('env', 'test')) program = Data('cpu.utilization', filter=filters).publish() chart = TimeSeriesChart().with_name('Chart_Name').with_program(program) app_var = FilterVariable().with_alias('application name') \ .with_property('app') \ .with_is_required(True) \ .with_value('my-app') app_filter = DashboardFilters() \ .with_variables(app_var) dashboard_with_single_filter_variable = Dashboard()\ .with_name('Dashboard Name')\ .with_charts(chart)\ .with_filters(app_filter) """ Example 2: Creating a new Dashboard with multiple filters
def test_program_init_valid_statements(): data = Data('cpu.utilization', filter=Filter('app', 'test-app')) program = Program(data) assert program.statements[0] == data
#!/usr/bin/env python """Examples of how to use the `signal_analog.flow` module. Some basic understanding of SignalFx is assumed. """ from signal_analog.flow import Data, Filter, Program # A program is a convenient wrapper around SignalFlow statements with a few # utilities like `find_label` that returns a SignalFlow statement based on it's # label. program = Program() # A timeseries representing the 'cpu.utilization' metric that is filtered # down to just the 'shoeadmin' application. Also analyze the mean over the # previous minute and compare it to the data from last week. data = Data('cpu.utilization', filter=Filter('app', 'shoeadmin'))\ .mean(over='1m')\ .timeshift('1w')\ .publish('A') program.add_statements(data) print('{0}\n\t{1}'.format(program, str(program) == str(program.find_label('A'))))
def test_add_statements(): data = Data('foo').publish(label='A', enable='False') program = Program() program.add_statements(data) assert program.statements[0] == data