Exemple #1
0
def _gen_string_filter(source, string_field, op, op_value, param=''):
    """
    get string field function

    """

    if not op or op not in _string_condition_ops:
        raise RuntimeError('string类型不支持({})操作'.format(utf8(op)))

    if op == 'in':
        parts = op_value.split(',')
        if len(parts) > 10:
            raise RuntimeError('属于最多支持10个属性')

        condition = [_gen_string_filter(source, string_field, '==', part, param).get_dict() for part in parts]
        return Filter('', '', '', '', '', '', 'or', '', condition)

    elif op == '!in':
        parts = op_value.split(',')
        if len(parts) > 10:
            raise RuntimeError('属于最多支持10个属性')

        condition = [_gen_string_filter(source, string_field, '!=', part, param).get_dict() for part in parts]
        return Filter('', '', '', '', '', '', 'and', '', condition)

    if op == 'regex':
        op = 'match'
    elif op == '!regex':
        op = '!match'
    elif op == 'contain':
        op = 'contains'
    elif op == '!contain':
        op = '!contains'

    return Filter(source, string_field, '', '', op, utf8(op_value), 'simple', param, None)
Exemple #2
0
def test_variable_filter():
    filter_dict = {
        'source': 'HTTP_DYNAMIC',
        'object': 'c_ip',
        'object_type': 'string',
        'object_subtype': '',
        'operation': '==',
        'value': '1',
        'param': '',
        'type': 'simple',
    }

    filter = Filter.from_dict(filter_dict)
    filter.sanity_check()
    assert not filter.is_empty()
    assert filter.get_dict() == filter_dict

    # 空的filter
    filter_dict = {
    }

    filter = Filter.from_dict(filter_dict)
    filter.sanity_check()
    assert filter.is_empty()
    assert filter.get_dict() == filter_dict

    # complex filter
    filter_dict = {
        'source': 'HTTP_DYNAMIC',
        'object': 'c_ip',
        'object_type': 'string',
        'object_subtype': '',
        'operation': '==',
        'value': '1',
        'param': '',
        'type': 'simple',
    }
    complex_filter_dict = {
        'type': 'and',
        'condition': [filter_dict, filter_dict]
    }
    complex_filter = Filter.from_dict(complex_filter_dict)
    complex_filter.sanity_check()
    assert not complex_filter.is_empty()
    assert complex_filter.get_dict() == complex_filter_dict
Exemple #3
0
def gen_counter_from_interval_count_exp(count_exp, counter_name):
    """ 为interval生成新的counter.

    新模式

    :param count_exp:
    :param counter_name:
    :return:
    """

    # 统计的事件
    source_event_id = count_exp.source_event
    counter_function = Function('last', '', 'timestamp', '', '', '')

    sub_filters = []
    for c in count_exp.condition:
        left = c['left']
        op = c['op']
        right = c['right']
        if op == '=':
            # 等于变量,在counter fix的时候被自动修正
            continue

        sub_filters.append(
            gen_ordinary_filter(source_event_id[1], left, op,
                                right).get_dict())

    counter_filter = Filter('', '', '', '', '', '', 'and', '', sub_filters)

    remark = 'first temp variable from interval counter'

    counter_variable = VariableModel('realtime', 'nebula', counter_name,
                                     remark, remark, '', 'enable', 'aggregate',
                                     '', '', '', [{
                                         'app': source_event_id[0],
                                         'name': source_event_id[1]
                                     }], counter_filter.get_dict(), {
                                         'type': 'ever',
                                         'value': ''
                                     }, counter_function.get_dict(),
                                     count_exp.groupby)
    add_variable_to_registry(counter_variable)
    return counter_variable
Exemple #4
0
def gen_ip_trigger_variable_from_strategy(strategy,
                                          trigger_variable_name,
                                          is_delay=False):
    """
    产生ip维度的trigger变量
    new mode

    :return:
    """

    if not strategy:
        return

    conditions = []
    trigger_event = get_trigger_event(strategy, is_delay)

    for t in strategy.terms:
        left = t.left
        if left.type == 'event':
            c = gen_filter_from_event_exp(left, t.op, t.right)
            if c:
                conditions.append(c)

    # location condition has lower priority
    for t in strategy.terms:
        left = t.left
        if left.type == 'func' and left.subtype == 'getlocation':
            c = gen_filter_from_location_exp(left, trigger_event)
            if c:
                conditions.append(c)

    total_filter = {}
    if is_delay:
        total_filter = gen_ordinary_filter(trigger_event[1], 'delay_strategy',
                                           '==', strategy.name).get_dict()
    else:
        if conditions:
            conditions = [_.get_dict() for _ in conditions]
            total_filter = Filter('', '', '', '', '', '', 'and', '',
                                  conditions).get_dict()
    remark = 'ip trigger for strategy {}'.format(utf8(strategy.name))
    variable = VariableModel('realtime', 'nebula', trigger_variable_name,
                             remark, remark, '', 'enable', 'filter', '', '',
                             '', [{
                                 'app': trigger_event[0],
                                 'name': trigger_event[1]
                             }], total_filter, {}, {}, ['c_ip'])
    add_variable_to_registry(variable)

    return variable
Exemple #5
0
def test_simplified_filter():
    """
    简化的filter
    :return:
    """

    filter_dict = {
        'source': 'HTTP_DYNAMIC',
        'object': 'c_ip',
        'object_type': 'string',
        'object_subtype': '',
        'operation': '',
        'value': '1',
        'type': 'simple',
    }

    with raises(RuntimeError):
        filter = Filter.from_dict(filter_dict)
        filter.sanity_check()
Exemple #6
0
def _gen_number_filter(source, number_field, op, op_value, is_long=False):
    """
    get number field function

    """

    if not op or op not in _number_condition_ops:
        raise RuntimeError('数字类型不支持({})操作'.format(utf8(op)))

    if op == 'between':
        parts = op_value.split(',')
        if len(parts) != 2:
            raise RuntimeError('介于需要两个参数')
        left, right = parts
        left_condition = Filter(source, number_field, '', '', '>=', utf8(left), 'simple', '', None).get_dict()
        right_condition = Filter(source, number_field, '', '', '<=', utf8(right), 'simple', '', None).get_dict()
        return Filter('', '', '', '', '', '', 'and', '', [left_condition, right_condition])
    elif op == 'in':
        parts = op_value.split(',')
        if len(parts) > 10:
            raise RuntimeError('属于最多支持10个属性')

        condition = [_gen_number_filter(source, number_field, '==', part, is_long).get_dict() for part in parts]
        return Filter('', '', '', '', '', '', 'or', '', condition)
    elif op == '!in':
        parts = op_value.split(',')
        if len(parts) > 10:
            raise RuntimeError('属于最多支持10个属性')

        condition = [_gen_number_filter(source, number_field, '!=', part, is_long).get_dict() for part in parts]
        return Filter('', '', '', '', '', '', 'and', '', condition)

    # simple condition
    try:
        if is_long:
            op_value = int(op_value)
        else:
            op_value = float(op_value)
    except:
        raise RuntimeError('({})不是数字'.format(utf8(op_value)))

    return Filter(source, number_field, '', '', op, utf8(op_value), 'simple', '', None)
Exemple #7
0
def test_invalid_filter():
    filter_dict = {
        'source': 'HTTP_DYNAMIC',
        'object': 'c_ip',
        'object_type': 'string',
        'object_subtype': '',
        'operation': '',
        'value': '1',
        'param': '',
        'condition': [],
        'type': 'simple',
    }

    with raises(RuntimeError):
        filter = Filter.from_dict(filter_dict)
        filter.sanity_check()

    # null object
    filter_dict = {
        'source': 'HTTP_DYNAMIC',
        'object': '',
        'object_type': 'string',
        'object_subtype': '',
        'operation': '==',
        'value': '1',
        'param': '',
        'condition': [],
        'type': 'simple',
    }

    with raises(RuntimeError):
        filter = Filter.from_dict(filter_dict)
        filter.sanity_check()

    # invalid type
    filter_dict = {
        'source': 'HTTP_DYNAMIC',
        'object': 'c_ip',
        'object_type': 'kv',
        'object_subtype': '',
        'operation': '==',
        'value': '1',
        'param': '',
        'condition': [],
        'type': 'simple',
    }

    with raises(RuntimeError):
        filter = Filter.from_dict(filter_dict)
        filter.sanity_check()

    # invalid operation
    filter_dict = {
        'source': 'HTTP_DYNAMIC',
        'object': 'c_ip',
        'object_type': 'string',
        'object_subtype': '',
        'operation': '>=',
        'value': '1',
        'param': '',
        'condition': [],
        'type': 'simple',
    }

    with raises(RuntimeError):
        filter = Filter.from_dict(filter_dict)
        filter.sanity_check()

    # invalid type
    filter_dict = {
        'source': 'HTTP_DYNAMIC',
        'object': 'c_ip',
        'object_type': 'string',
        'object_subtype': '',
        'operation': '==',
        'value': '1',
        'param': '',
        'condition': [],
        'type': 'invalid type',
    }

    with raises(RuntimeError):
        filter = Filter.from_dict(filter_dict)
        filter.sanity_check()
    def get(self):
        """
        get nebula online variables
        
        @API
        summary: get nebula online variables
        notes: get nebula online variables for online kv
        tags:
          - nebula
        parameters:
        produces:
          - application/json        
        """

        self.set_header('content-type', 'application/json')
        # try:
        if True:
            default_variables = VariableModelCustDao().list_all_models()
            default_variables = filter(
                lambda model: model.module in {'base', 'realtime'},
                default_variables)

            # hack for distinct count
            for dv in default_variables:
                if 'distinct' in dv.function.method and dv.function.object_type == 'string':
                    # 增加一个不为空的field
                    function = dv.function
                    not_null_filter = Filter(function.source, function.object,
                                             function.object_type,
                                             function.object_subtype, '!=', '',
                                             'simple', '', [])
                    if dv.filter and not dv.filter.is_empty():
                        dv.filter = Filter(
                            '', '', '', '', '', '', 'and', '',
                            [dv.filter.get_dict(),
                             not_null_filter.get_dict()])
                    else:
                        dv.filter = Filter('', '', '', '', '', '', 'and', '',
                                           [not_null_filter.get_dict()])
            # end of hack

            all_generated_variables = []
            all_used_variables = []
            strategies = context.nebula_strategies
            strategies = filter(
                lambda s: (s.status in ["test", "online"] and s.start_effect <=
                           millis_now() <= s.end_effect), strategies)
            for s in strategies:
                generated_variables, used_variables = gen_variables_from_strategy(
                    s, effective_check=True)
                all_generated_variables.extend(generated_variables)
                all_used_variables.extend(used_variables)

            # recursively calcuated all_used_variables:
            while True:
                new_used_variable_found = False
                for used_variable_name in all_used_variables[:]:
                    for source in get_variable_from_registry(
                            'nebula', used_variable_name).source:
                        if source['name'] not in all_used_variables:
                            all_used_variables.append(source['name'])
                            new_used_variable_found = True
                if not new_used_variable_found:
                    break

            default_variables = [
                _ for _ in default_variables if _.name in all_used_variables
                or _.type in {'event', 'filter'}
            ]
            result = default_variables + all_generated_variables
            result = [_.get_dict() for _ in result]
            self.finish(
                json_dumps({
                    "status": 0,
                    "msg": "ok",
                    "values": result
                }))
Exemple #9
0
def gen_counters_and_filters_from_count_exp(term, termid, name_pattern,
                                            trigger_variable_name):
    """
    从count函数配置中生成新的counter.

    返回: (all counters, collect counter, filters),这里有三块内容
    all counters: 所有生成的counter, 包括用来参与策略计算的counter和中间counter
    collect counter:最终参与策略计算的counter,这一个list就去掉了一些中间counter
    fitlers:collect counters关联的filters

    """

    # 统计的事件
    count_exp = term.left
    source_event_id = count_exp.source_event

    sub_filters = []
    for c in count_exp.condition:
        left = c['left']
        op = c['op']
        right = c['right']
        if op == '=':
            # 等于变量,在counter fix的时候被自动修正
            continue

        sub_filters.append(
            gen_ordinary_filter(source_event_id[1], left, op,
                                right).get_dict())

    # distinct string should be non empty
    if 'distinct' in count_exp.algorithm:
        for field in count_exp.operand:
            # noinspection PyBroadException
            try:
                sub_filters.append(
                    gen_ordinary_filter(source_event_id[1], field, '!=',
                                        '').get_dict())
            except:
                pass

    counter_filter = Filter('', '', '', '', '', '', 'and', '', sub_filters)

    if 'interval' == count_exp.algorithm:
        first_counter_name = name_pattern % '_1_'
        remark = 'interval 1st counter variable(last counter event) for term %s' % termid
        first_counter_function = Function('last', '', 'timestamp', '', '')
        first_variable = VariableModel('realtime', 'nebula',
                                       first_counter_name, remark, remark, '',
                                       'enable', 'aggregate', '', '', '',
                                       [{
                                           'app': source_event_id[0],
                                           'name': source_event_id[1]
                                       }], counter_filter.get_dict(), {
                                           'type': 'last_n_seconds',
                                           'value': count_exp.interval
                                       }, first_counter_function.get_dict(),
                                       count_exp.groupby)
        add_variable_to_registry(first_variable)

        second_counter_name = name_pattern % '_2_'
        remark = 'interval 2nd counter variable(last trigger event) for term %s' % termid
        second_source = [
            {
                'app': 'nebula',
                'name': trigger_variable_name
            },
        ]
        second_counter_function = Function('last', '', 'timestamp', '', '')
        second_variable = VariableModel('realtime', 'nebula',
                                        second_counter_name, remark, remark,
                                        '', 'enable', 'aggregate', '', '', '',
                                        second_source, {}, {
                                            'type': 'last_n_seconds',
                                            'value': count_exp.interval
                                        }, second_counter_function.get_dict(),
                                        count_exp.groupby)
        add_variable_to_registry(second_variable)

        third_counter_name = name_pattern % '_3_'
        remark = 'interval 3rd dual variable(-value) for term %s' % termid
        third_source = [
            {
                'app': 'nebula',
                'name': second_counter_name
            },
            {
                'app': 'nebula',
                'name': first_counter_name
            },
        ]
        third_counter_function = Function('-', '', 'value', '', '')
        third_variable = VariableModel('realtime', 'nebula',
                                       third_counter_name, remark, remark, '',
                                       'enable', 'dual', '', '', '',
                                       third_source, {}, {
                                           'type': 'last_n_seconds',
                                           'value': count_exp.interval
                                       }, third_counter_function.get_dict(),
                                       count_exp.groupby)
        add_variable_to_registry(third_variable)
        f = gen_ordinary_filter(third_counter_name, 'value', term.op,
                                term.right.value)
        additional_f = gen_ordinary_filter(third_counter_name, 'value', '>',
                                           '0')
        return [first_variable, second_variable,
                third_variable], third_variable, [f, additional_f]
    else:
        counter_function = gen_function(count_exp.algorithm,
                                        count_exp.operand[0])
        counter_name = name_pattern % ''
        remark = 'temp counter for term %s' % termid
        counter_variable = VariableModel('realtime', 'nebula', counter_name,
                                         remark, remark, '', 'enable',
                                         'aggregate', '', '', '',
                                         [{
                                             'app': source_event_id[0],
                                             'name': source_event_id[1]
                                         }], counter_filter.get_dict(), {
                                             'type': 'last_n_seconds',
                                             'value': count_exp.interval
                                         }, counter_function.get_dict(),
                                         count_exp.groupby)
        add_variable_to_registry(counter_variable)
        f = gen_ordinary_filter(counter_name, 'value', term.op,
                                term.right.value)
        return [counter_variable], counter_variable, [f]
Exemple #10
0
def gen_dimension_collector_variable_from_strategy(s,
                                                   collect_variable_name,
                                                   trigger_variable_name,
                                                   dimension,
                                                   before_sleep=True,
                                                   is_delay=False):
    """
    为IP/UID/DID产生collector变量
    :param s: 策略
    :param collect_variable_name: collector变量
    :param trigger_variable_name: trigger变量
    :param dimension: 维度,ip/uid/did
    :param before_sleep: 是否找sleep之前的条款
    :param is_delay: 是否生成delaycollector
    :return: 产生该维度的变量
    """

    sources = list()
    sources.append({'app': 'nebula', 'name': trigger_variable_name})

    variables, variables_conditions = gen_getvariables_filters_from_strategy(
        s, dimension, before_sleep)
    for v in variables:
        sources.append({'app': v[0], 'name': v[1]})

    counters, collect_counters, counter_conditions = gen_counters_and_filters_from_strategy(
        s, dimension, before_sleep, trigger_variable_name)
    for counter in collect_counters:
        sources.append({'app': 'nebula', 'name': counter.name})

    conditions = (variables_conditions or list()) + (counter_conditions
                                                     or list())

    remark = 'collector for strategy {}'.format(utf8(s.name))
    total_filter = {}
    if conditions:
        conditions = [_.get_dict() for _ in conditions]
        total_filter = Filter('', '', '', '', '', '', 'and', '',
                              conditions).get_dict()

    dimension_field = get_field_from_dimension(dimension)
    if is_delay:
        variable_type = 'delaycollector'
    else:
        variable_type = 'collector'

    collector_function = {
        'method': 'setblacklist',
        'param': s.name,
        'config': {
            'trigger': trigger_variable_name
        }
    }
    if is_delay:
        sleep_terms = [_ for _ in s.terms if _.left.subtype == 'sleep']
        if not sleep_terms:
            raise RuntimeError('sleep配置出错')
        duration = int(sleep_terms[0].left.duration)
        unit = sleep_terms[0].left.unit
        if unit == 'm':
            duration *= 60
        elif unit == 'h':
            duration *= 3600
        collector_function['config']['sleep'] = duration

    variable = VariableModel('realtime', 'nebula', collect_variable_name,
                             remark, remark, '', 'enable', variable_type, '',
                             '', '', sources, total_filter, {},
                             collector_function, [dimension_field])
    add_variable_to_registry(variable)
    return counters, variable