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'
Exemple #2
0
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
Exemple #3
0
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')]
Exemple #7
0
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)
Exemple #8
0
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"])]
Exemple #10
0
    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))
Exemple #11
0
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):
Exemple #16
0
#!/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'})
Exemple #19
0
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
Exemple #20
0
def test_find_label_unpublished():
    data = Data('cpu.utilization', filter=Filter('app', 'test-app'))
    program = Program(data)

    assert program.find_label('A') is None
Exemple #21
0
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={})
Exemple #23
0
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')
Exemple #27
0
#!/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
Exemple #28
0
def test_program_init_valid_statements():
    data = Data('cpu.utilization', filter=Filter('app', 'test-app'))
    program = Program(data)
    assert program.statements[0] == data
Exemple #29
0
#!/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'))))
Exemple #30
0
def test_add_statements():
    data = Data('foo').publish(label='A', enable='False')
    program = Program()
    program.add_statements(data)
    assert program.statements[0] == data