Esempio n. 1
0
def test_valid_publish_statements_plot_happy():
    Program(
        Plot('A', 'foo', fx=[Max()], label="lol")
    ).validate()
    Program(
        Plot('A', 'foo', fx=None, label="lol")
    ).validate()
Esempio n. 2
0
def test_program_init_add_statement_invalid(value):
    """Ensure that neither Program's constructor nor add_statement allows
       non-statement values.
    """
    with pytest.raises(ValueError):
        Program(value)

    with pytest.raises(ValueError):
        Program().add_statements(value)
Esempio n. 3
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
Esempio n. 4
0
    def from_chart(self, chart, update_fn):
        """Given a Chart and an update fn, return a SignalFlow program.

        Arguments:
            chart: the Chart object containing the desired SignalFlow program.
            update_fn: a function of type Program -> Program, allowing you
                       to access the program of a given chart and return a
                       modified version for this detector.
        """
        if not issubclass(chart.__class__, Chart):
            msg = 'Expected a Chart but got a "{0}" instead when building ' +\
                  'a Detector named "{1}".'
            raise ValueError(msg.format(
                chart.__class__.__name__,
                self.__get__('name', 'undefined')
            ))

        program = deepcopy(chart.__get__('programText', Program()))

        if not issubclass(program.__class__, Program):
            msg = """
                  Detector.from_chart only supports Charts that implement a Program. "{0}"
                  contains a "{1}".

                  You might consider contacting the Chart author to update their configuration to
                  implement a proper `Program` from the `signal_analog.flow` module.
                  """
            raise ValueError(msg.format(
                chart.__class__.__name__,
                program.__class__.__name__
            ))

        self.options.update({'programText': str(update_fn(program))})
        return self
Esempio n. 5
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
Esempio n. 6
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))
Esempio n. 7
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))
Esempio n. 8
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)
Esempio n. 9
0
def test_program_init_valid_empty():
    assert Program().statements == []
from signal_analog.flow import Data, Detect, Filter, Program
from signal_analog.combinators import And, LT

"""
Example 1: from scratch

This is useful when you want to monitor something that isn't tied to an
existing chart or dashboard.
"""

alert_label = 'CPU is too low for 75% of the last 2 minutes!'

filters = And(Filter('app', 'my-app'), Filter('env', 'test'))
data = Data('cpu.utilization', filter=filters).publish(label='A')
cpu_too_low = Detect(When(LT(data, 50), '2m', 0.75)).publish(alert_label)
program = Program(cpu_too_low)

info_rule = Rule()\
    .for_label(alert_label)\
    .with_severity(Severity.Info)\
    .with_notifications(EmailNotification('*****@*****.**'))

detector = Detector()\
    .with_name('TEST: example detector')\
    .with_program(program)\
    .with_rules(info_rule)

"""
Example 2: from an existing chart

This is useful when you want to alert on behavior seen in a chart that was
def test_valid_publish_statement_comb_valid():
    Program(
        Op(Div(Data('foo'), Data('bar'))).publish(label='foobar')
    ).validate()
def test_valid_publish_statements_comb_invalid():
    with pytest.raises(ProgramDoesNotPublishTimeseriesError):
        Program(
            Op(Div(Data('foo'), Data('bar')))
        ).validate()
Esempio n. 13
0
def test_find_label_empty():
    assert Program().find_label('A') is None
Esempio n. 14
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
def test_valid_publish_statements_happy():
    data = Data('requests.mean').publish(label='foo')
    Program(data).validate()
def test_valid_publish_statements_default():
    data = Data('requests.mean')

    with pytest.raises(ProgramDoesNotPublishTimeseriesError):
        Program(data).validate()
Esempio n. 17
0
 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'))
Esempio n. 18
0
 def helper(p):
     return Program(Detect(LT(p.find_label('Z'), 10)).publish(label='foo'))
Esempio n. 19
0
def test_program_init_valid_statements():
    data = Data('cpu.utilization', filter=Filter('app', 'test-app'))
    program = Program(data)
    assert program.statements[0] == data
Esempio n. 20
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
Esempio n. 21
0
def test_add_statements():
    data = Data('foo').publish(label='A', enable='False')
    program = Program()
    program.add_statements(data)
    assert program.statements[0] == data
Esempio n. 22
0
 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'))
Esempio n. 23
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 detector_helper(prog):
    d = prog.find_label('A')
    return Program(Detect(LT(d, 1)).publish(alert_label))
def test_valid_publish_statements_multi():
    Program(
        Data('requests.mean'),
        Data('foo').publish(label='foo')
    ).validate()
Esempio n. 26
0
def test_detector_with_program():
    program = Program(
        Data('foo').publish(label='A'),
        Data('bar').publish(label='B'))
    d = Detector().with_program(program)
    assert d.options['programText'] == str(program)
Esempio n. 27
0
"""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):
def test_valid_publish_statements_assign_happy():
    Program(
        Assign('A', Data('foo').publish(label='lol'))
    ).validate()
Esempio n. 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'))))
def test_valid_publish_statements_assign_invalid():
    with pytest.raises(ProgramDoesNotPublishTimeseriesError):
        Program(
            Assign('A', Data('foo'))
        ).validate()