Esempio n. 1
0
 def test_quoted_raw_search_anywhere(self):
     assert parse_search_query('"hello there" user.email:[email protected] "general kenobi"') == [
         SearchFilter(
             key=SearchKey(name='message'),
             operator='=',
             value=SearchValue(raw_value='hello there'),
         ),
         SearchFilter(
             key=SearchKey(name='user.email'),
             operator="=",
             value=SearchValue(raw_value='*****@*****.**'),
         ),
         SearchFilter(
             key=SearchKey(name='message'),
             operator='=',
             value=SearchValue(raw_value='general kenobi'),
         ),
     ]
     assert parse_search_query(' " hello " ') == [
         SearchFilter(
             key=SearchKey(name='message'),
             operator='=',
             value=SearchValue(raw_value=' hello '),
         ),
     ]
     assert parse_search_query(' " he\\"llo " ') == [
         SearchFilter(
             key=SearchKey(name='message'),
             operator='=',
             value=SearchValue(raw_value=' he"llo '),
         ),
     ]
Esempio n. 2
0
    def test_parse_search_query(self):
        # test with raw search query at the end
        assert parse_search_query('user.email:[email protected] release:1.2.1 hello') == [
            SearchFilter(
                key=SearchKey(name='user.email'),
                operator="=",
                value=SearchValue(raw_value='*****@*****.**'),
            ),
            SearchFilter(
                key=SearchKey(name='release'),
                operator="=",
                value=SearchValue(raw_value='1.2.1'),
            ),
            SearchFilter(
                key=SearchKey(name='message'),
                operator='=',
                value=SearchValue(raw_value='hello'),
            )
        ]

        # if the search query starts with the raw query, assume the whole thing is a raw string
        assert parse_search_query('hello user.email:[email protected] release:1.2.1') == [
            SearchFilter(
                key=SearchKey(name='message'),
                operator='=',
                value=SearchValue(raw_value='hello user.email:[email protected] release:1.2.1'),
            ),
        ]
Esempio n. 3
0
 def test_rel_time_filter(self):
     now = timezone.now()
     with freeze_time(now):
         assert parse_search_query('first_seen:+7d') == [
             SearchFilter(
                 key=SearchKey(name='first_seen'),
                 operator="<=",
                 value=SearchValue(
                     raw_value=now - timedelta(days=7),
                 ),
             ),
         ]
         assert parse_search_query('first_seen:-2w') == [
             SearchFilter(
                 key=SearchKey(name='first_seen'),
                 operator=">=",
                 value=SearchValue(
                     raw_value=now - timedelta(days=14),
                 ),
             ),
         ]
         assert parse_search_query('random:-2w') == [
             SearchFilter(
                 key=SearchKey(name='random'),
                 operator="=",
                 value=SearchValue('-2w'),
             ),
         ]
Esempio n. 4
0
    def test_multiple_quotes(self):
        assert parse_search_query('device.family:"" browser.name:"Chrome"') == [
            SearchFilter(
                key=SearchKey(name='device.family'),
                operator='=',
                value=SearchValue(raw_value=''),
            ),
            SearchFilter(
                key=SearchKey(name='browser.name'),
                operator='=',
                value=SearchValue(raw_value='Chrome'),
            ),
        ]

        assert parse_search_query('device.family:"\\"" browser.name:"Chrome"') == [
            SearchFilter(
                key=SearchKey(name='device.family'),
                operator='=',
                value=SearchValue(raw_value='"'),
            ),
            SearchFilter(
                key=SearchKey(name='browser.name'),
                operator='=',
                value=SearchValue(raw_value='Chrome'),
            ),
        ]
Esempio n. 5
0
    def test_simple(self):
        assert parse_search_query(
            'user.email:[email protected] OR user.email:[email protected]'
        ) == [SearchBoolean(left_term=self.term1, operator="OR", right_term=self.term2)]

        assert parse_search_query(
            'user.email:[email protected] AND user.email:[email protected]'
        ) == [SearchBoolean(left_term=self.term1, operator="AND", right_term=self.term2)]
Esempio n. 6
0
    def test_parse_search_query_timestamp(self):
        # test date format
        assert parse_search_query('timestamp>2015-05-18') == [
            SearchFilter(
                key=SearchKey(name='timestamp'),
                operator=">",
                value=SearchValue(
                    raw_value=datetime.datetime(
                        2015,
                        5,
                        18,
                        0,
                        0,
                        tzinfo=timezone.utc),
                ),
            ),
        ]
        # test date time format
        assert parse_search_query('timestamp>2015-05-18T10:15:01') == [
            SearchFilter(
                key=SearchKey(name='timestamp'),
                operator=">",
                value=SearchValue(
                    raw_value=datetime.datetime(
                        2015,
                        5,
                        18,
                        10,
                        15,
                        1,
                        tzinfo=timezone.utc),
                ),
            ),
        ]

        # test date time format w microseconds
        assert parse_search_query('timestamp>2015-05-18T10:15:01.103') == [
            SearchFilter(
                key=SearchKey(name='timestamp'),
                operator=">",
                value=SearchValue(
                    raw_value=datetime.datetime(
                        2015,
                        5,
                        18,
                        10,
                        15,
                        1,
                        103000,
                        tzinfo=timezone.utc),
                ),
            ),
        ]
Esempio n. 7
0
 def test_invalid_date_formats(self):
     invalid_queries = [
         'first_seen:hello',
         'first_seen:123',
         'first_seen:2018-01-01T00:01ZZ'
     ]
     for invalid_query in invalid_queries:
         with self.assertRaises(
             InvalidSearchQuery,
             expected_regex='Invalid format for numeric search',
         ):
             parse_search_query(invalid_query)
Esempio n. 8
0
 def test_quoted_val(self):
     assert parse_search_query('release:"a release"') == [
         SearchFilter(
             key=SearchKey(name='release'),
             operator='=',
             value=SearchValue(raw_value='a release'),
         ),
     ]
     assert parse_search_query('!release:"a release"') == [
         SearchFilter(
             key=SearchKey(name='release'),
             operator='!=',
             value=SearchValue('a release'),
         ),
     ]
Esempio n. 9
0
 def test_quoted_key(self):
     assert parse_search_query('"hi:there":value') == [
         SearchFilter(
             key=SearchKey(name='hi:there'),
             operator='=',
             value=SearchValue(raw_value='value'),
         ),
     ]
     assert parse_search_query('!"hi:there":value') == [
         SearchFilter(
             key=SearchKey(name='hi:there'),
             operator='!=',
             value=SearchValue(raw_value='value'),
         ),
     ]
Esempio n. 10
0
 def test_escaped_quotes(self):
     assert parse_search_query('release:"a\\"thing\\""') == [
         SearchFilter(
             key=SearchKey(name='release'),
             operator='=',
             value=SearchValue(raw_value='a"thing"')
         ),
     ]
     assert parse_search_query('release:"a\\"\\"release"') == [
         SearchFilter(
             key=SearchKey(name='release'),
             operator='=',
             value=SearchValue(raw_value='a""release')
         ),
     ]
Esempio n. 11
0
 def test_empty_filter_value(self):
     assert parse_search_query('device.family:""') == [
         SearchFilter(
             key=SearchKey(name='device.family'),
             operator='=',
             value=SearchValue(raw_value=''),
         ),
     ]
Esempio n. 12
0
 def test_tab_within_quote(self):
     assert parse_search_query('release:"a\trelease"') == [
         SearchFilter(
             key=SearchKey(name='release'),
             operator='=',
             value=SearchValue(raw_value='a\trelease')
         ),
     ]
Esempio n. 13
0
 def test_sooo_many_quotes(self):
     assert parse_search_query('device.family:"\\"\\"\\"\\"\\"\\"\\"\\"\\"\\""') == [
         SearchFilter(
             key=SearchKey(name='device.family'),
             operator='=',
             value=SearchValue(raw_value='""""""""""'),
         ),
     ]
Esempio n. 14
0
 def test_numeric_filter(self):
     # Numeric format should still return a string if field isn't whitelisted
     assert parse_search_query('random_field:>500') == [
         SearchFilter(
             key=SearchKey(name='random_field'),
             operator="=",
             value=SearchValue(raw_value='>500'),
         ),
     ]
Esempio n. 15
0
    def test_not_has_tag(self):
        # unquoted key
        assert parse_search_query('!has:release') == [
            SearchFilter(
                key=SearchKey(name='release'),
                operator='=',
                value=SearchValue(''),
            ),
        ]

        # quoted key
        assert parse_search_query('!has:"hi:there"') == [
            SearchFilter(
                key=SearchKey(name='hi:there'),
                operator='=',
                value=SearchValue(''),
            ),
        ]
Esempio n. 16
0
    def test_other_dates(self):
        # test date format with other name
        assert parse_search_query('first_seen>2015-05-18') == [
            SearchFilter(
                key=SearchKey(name='first_seen'),
                operator=">",
                value=SearchValue(
                    raw_value=datetime.datetime(
                        2015,
                        5,
                        18,
                        0,
                        0,
                        tzinfo=timezone.utc,
                    ),
                ),
            ),
        ]

        # test colon format
        assert parse_search_query('first_seen:>2015-05-18') == [
            SearchFilter(
                key=SearchKey(name='first_seen'),
                operator=">",
                value=SearchValue(
                    raw_value=datetime.datetime(
                        2015,
                        5,
                        18,
                        0,
                        0,
                        tzinfo=timezone.utc,
                    ),
                ),
            ),
        ]

        assert parse_search_query('random:>2015-05-18') == [
            SearchFilter(
                key=SearchKey(name='random'),
                operator="=",
                value=SearchValue('>2015-05-18'),
            ),
        ]
Esempio n. 17
0
    def test_specific_time_filter(self):
        assert parse_search_query('first_seen:2018-01-01') == [
            SearchFilter(
                key=SearchKey(name='first_seen'),
                operator=">=",
                value=SearchValue(
                    raw_value=datetime.datetime(2018, 1, 1, tzinfo=timezone.utc),
                ),
            ),
            SearchFilter(
                key=SearchKey(name='first_seen'),
                operator="<",
                value=SearchValue(
                    raw_value=datetime.datetime(2018, 1, 2, tzinfo=timezone.utc),
                ),
            ),
        ]

        assert parse_search_query('first_seen:2018-01-01T05:06:07') == [
            SearchFilter(
                key=SearchKey(name='first_seen'),
                operator=">=",
                value=SearchValue(
                    raw_value=datetime.datetime(2018, 1, 1, 5, 1, 7, tzinfo=timezone.utc),
                ),
            ),
            SearchFilter(
                key=SearchKey(name='first_seen'),
                operator="<",
                value=SearchValue(
                    raw_value=datetime.datetime(2018, 1, 1, 5, 12, 7, tzinfo=timezone.utc),
                ),
            ),
        ]

        assert parse_search_query('random:2018-01-01T05:06:07') == [
            SearchFilter(
                key=SearchKey(name='random'),
                operator="=",
                value=SearchValue(raw_value='2018-01-01T05:06:07'),
            ),
        ]
Esempio n. 18
0
    def test_has_tag(self):
        # unquoted key
        assert parse_search_query('has:release') == [
            SearchFilter(
                key=SearchKey(name='release'),
                operator='!=',
                value=SearchValue(raw_value=''),
            ),
        ]

        # quoted key
        assert parse_search_query('has:"hi:there"') == [
            SearchFilter(
                key=SearchKey(name='hi:there'),
                operator='!=',
                value=SearchValue(raw_value=''),
            ),
        ]

        # malformed key
        with self.assertRaises(InvalidSearchQuery):
            parse_search_query('has:"hi there"')
Esempio n. 19
0
 def test_custom_tag(self):
     assert parse_search_query('fruit:apple release:1.2.1') == [
         SearchFilter(
             key=SearchKey(name='fruit'),
             operator='=',
             value=SearchValue(raw_value='apple'),
         ),
         SearchFilter(
             key=SearchKey(name='release'),
             operator='=',
             value=SearchValue(raw_value='1.2.1'),
         ),
     ]
Esempio n. 20
0
 def test_order_of_operations(self):
     assert parse_search_query(
         'user.email:[email protected] OR user.email:[email protected] AND user.email:[email protected]'
     ) == [SearchBoolean(
         left_term=self.term1,
         operator='OR',
         right_term=SearchBoolean(
             left_term=self.term2,
             operator='AND',
             right_term=self.term3
         )
     )]
     assert parse_search_query(
         'user.email:[email protected] AND user.email:[email protected] OR user.email:[email protected]'
     ) == [SearchBoolean(
         left_term=SearchBoolean(
             left_term=self.term1,
             operator='AND',
             right_term=self.term2,
         ),
         operator='OR',
         right_term=self.term3
     )]
Esempio n. 21
0
 def test_tab_outside_quote(self):
     # tab outside quote
     assert parse_search_query('release:a\trelease') == [
         SearchFilter(
             key=SearchKey(name='release'),
             operator='=',
             value=SearchValue(raw_value='a'),
         ),
         SearchFilter(
             key=SearchKey(name='message'),
             operator='=',
             value=SearchValue(raw_value='\trelease')
         ),
     ]
Esempio n. 22
0
    def get(self, request, organization):
        try:
            params = self.get_filter_params(request, organization)
        except OrganizationEventsError as e:
            return Response({"detail": six.text_type(e)}, status=400)
        except NoProjects:
            return Response([])

        possible_keys = ["transaction"]
        lookup_keys = {key: request.query_params.get(key) for key in possible_keys}

        if not any(lookup_keys.values()):
            return Response(
                {
                    "detail": "Must provide one of {} in order to find related events".format(
                        possible_keys
                    )
                },
                status=400,
            )

        try:
            projects = self.get_projects(request, organization)
            query_kwargs = build_query_params_from_request(
                request, organization, projects, params.get("environment")
            )
            query_kwargs["limit"] = 5
            try:
                # Need to escape quotes in case some "joker" has a transaction with quotes
                transaction_name = UNESCAPED_QUOTE_RE.sub('\\"', lookup_keys["transaction"])
                parsed_terms = parse_search_query('transaction:"{}"'.format(transaction_name))
            except ParseError:
                return Response({"detail": "Invalid transaction search"}, status=400)

            if query_kwargs.get("search_filters"):
                query_kwargs["search_filters"].extend(parsed_terms)
            else:
                query_kwargs["search_filters"] = parsed_terms

            results = search.query(**query_kwargs)
        except discover.InvalidSearchQuery as err:
            raise ParseError(detail=six.text_type(err))

        context = serialize(
            list(results),
            request.user,
            GroupSerializer(environment_func=self._get_environment_func(request, organization.id)),
        )

        return Response(context)
Esempio n. 23
0
 def test_tab_outside_quote(self):
     # tab outside quote
     assert parse_search_query('release:a\trelease') == [
         SearchFilter(
             key=SearchKey(name='release'),
             operator='=',
             value=SearchValue(raw_value='a'),
         ),
         SearchFilter(
             key=SearchKey(name='message'),
             operator='=',
             value=SearchValue(raw_value='\trelease')
         ),
     ]
Esempio n. 24
0
 def test_order_of_operations(self):
     assert parse_search_query(
         'user.email:[email protected] OR user.email:[email protected] AND user.email:[email protected]'
     ) == [SearchBoolean(
         left_term=self.term1,
         operator='OR',
         right_term=SearchBoolean(
             left_term=self.term2,
             operator='AND',
             right_term=self.term3
         )
     )]
     assert parse_search_query(
         'user.email:[email protected] AND user.email:[email protected] OR user.email:[email protected]'
     ) == [SearchBoolean(
         left_term=SearchBoolean(
             left_term=self.term1,
             operator='AND',
             right_term=self.term2,
         ),
         operator='OR',
         right_term=self.term3
     )]
Esempio n. 25
0
    def test_simple(self):
        # test with raw search query at the end
        assert parse_search_query('user.email:[email protected] release:1.2.1 hello') == [
            SearchFilter(
                key=SearchKey(name='user.email'),
                operator="=",
                value=SearchValue(raw_value='*****@*****.**'),
            ),
            SearchFilter(
                key=SearchKey(name='release'),
                operator="=",
                value=SearchValue(raw_value='1.2.1'),
            ),
            SearchFilter(
                key=SearchKey(name='message'),
                operator='=',
                value=SearchValue(raw_value='hello'),
            )
        ]

        assert parse_search_query('hello user.email:[email protected] release:1.2.1') == [
            SearchFilter(
                key=SearchKey(name='message'),
                operator='=',
                value=SearchValue(raw_value='hello'),
            ),
            SearchFilter(
                key=SearchKey(name='user.email'),
                operator="=",
                value=SearchValue(raw_value='*****@*****.**'),
            ),
            SearchFilter(
                key=SearchKey(name='release'),
                operator="=",
                value=SearchValue(raw_value='1.2.1'),
            ),
        ]
Esempio n. 26
0
    def test_simple(self):
        # test with raw search query at the end
        assert parse_search_query('user.email:[email protected] release:1.2.1 hello') == [
            SearchFilter(
                key=SearchKey(name='user.email'),
                operator="=",
                value=SearchValue(raw_value='*****@*****.**'),
            ),
            SearchFilter(
                key=SearchKey(name='release'),
                operator="=",
                value=SearchValue(raw_value='1.2.1'),
            ),
            SearchFilter(
                key=SearchKey(name='message'),
                operator='=',
                value=SearchValue(raw_value='hello'),
            )
        ]

        assert parse_search_query('hello user.email:[email protected] release:1.2.1') == [
            SearchFilter(
                key=SearchKey(name='message'),
                operator='=',
                value=SearchValue(raw_value='hello'),
            ),
            SearchFilter(
                key=SearchKey(name='user.email'),
                operator="=",
                value=SearchValue(raw_value='*****@*****.**'),
            ),
            SearchFilter(
                key=SearchKey(name='release'),
                operator="=",
                value=SearchValue(raw_value='1.2.1'),
            ),
        ]
Esempio n. 27
0
 def test_basic_fallthrough(self):
     # These should all fall through to basic equal searches, even though they
     # look like numeric, date, etc.
     queries = [
         ('random:<hello', self._build_search_filter('random', '=', '<hello')),
         ('random:<512.1.0', self._build_search_filter('random', '=', '<512.1.0')),
         ('random:2018-01-01', self._build_search_filter('random', '=', '2018-01-01')),
         ('random:+7d', self._build_search_filter('random', '=', '+7d')),
         ('random:>2018-01-01', self._build_search_filter('random', '=', '>2018-01-01')),
         ('random:2018-01-01', self._build_search_filter('random', '=', '2018-01-01')),
         ('random:hello', self._build_search_filter('random', '=', 'hello')),
         ('random:123', self._build_search_filter('random', '=', '123')),
     ]
     for query, expected in queries:
         assert parse_search_query(query) == [expected]
Esempio n. 28
0
    def test_duration_op_breakdowns_filter(self):
        assert parse_search_query("spans.browser:1.5s") == [
            SearchFilter(
                key=SearchKey(name="spans.browser"),
                operator="=",
                value=SearchValue(raw_value=1500),
            )
        ]

        assert parse_search_query("spans.browser:>1.5s") == [
            SearchFilter(
                key=SearchKey(name="spans.browser"),
                operator=">",
                value=SearchValue(raw_value=1500),
            )
        ]

        assert parse_search_query("spans.browser:<1.5s") == [
            SearchFilter(
                key=SearchKey(name="spans.browser"),
                operator="<",
                value=SearchValue(raw_value=1500),
            )
        ]
Esempio n. 29
0
    def test_duration_aggregate_measurements_filter(self):
        assert parse_search_query("percentile(measurements.fp, 0.5):3.3s") == [
            SearchFilter(
                key=SearchKey(name="percentile(measurements.fp, 0.5)"),
                operator="=",
                value=SearchValue(raw_value=3300),
            )
        ]

        assert parse_search_query("percentile(measurements.fp, 0.5):>3.3s") == [
            SearchFilter(
                key=SearchKey(name="percentile(measurements.fp, 0.5)"),
                operator=">",
                value=SearchValue(raw_value=3300),
            )
        ]

        assert parse_search_query("percentile(measurements.fp, 0.5):<3.3s") == [
            SearchFilter(
                key=SearchKey(name="percentile(measurements.fp, 0.5)"),
                operator="<",
                value=SearchValue(raw_value=3300),
            )
        ]
Esempio n. 30
0
    def test_duration_aggregate_op_breakdowns_filter(self):
        assert parse_search_query("percentile(spans.browser, 0.5):3.3s") == [
            SearchFilter(
                key=SearchKey(name="percentile(spans.browser, 0.5)"),
                operator="=",
                value=SearchValue(raw_value=3300),
            )
        ]

        assert parse_search_query("percentile(spans.browser, 0.5):>3.3s") == [
            SearchFilter(
                key=SearchKey(name="percentile(spans.browser, 0.5)"),
                operator=">",
                value=SearchValue(raw_value=3300),
            )
        ]

        assert parse_search_query("percentile(spans.browser, 0.5):<3.3s") == [
            SearchFilter(
                key=SearchKey(name="percentile(spans.browser, 0.5)"),
                operator="<",
                value=SearchValue(raw_value=3300),
            )
        ]
Esempio n. 31
0
 def test_rel_time_filter(self):
     now = timezone.now()
     with freeze_time(now):
         assert parse_search_query('first_seen:+7d') == [
             SearchFilter(
                 key=SearchKey(name='first_seen'),
                 operator="<=",
                 value=SearchValue(raw_value=now - timedelta(days=7), ),
             ),
         ]
         assert parse_search_query('first_seen:-2w') == [
             SearchFilter(
                 key=SearchKey(name='first_seen'),
                 operator=">=",
                 value=SearchValue(raw_value=now - timedelta(days=14), ),
             ),
         ]
         assert parse_search_query('random:-2w') == [
             SearchFilter(
                 key=SearchKey(name='random'),
                 operator="=",
                 value=SearchValue('-2w'),
             ),
         ]
Esempio n. 32
0
 def test_basic_fallthrough(self):
     # These should all fall through to basic equal searches, even though they
     # look like numeric, date, etc.
     queries = [
         ('random:<hello', self._build_search_filter('random', '=', '<hello')),
         ('random:<512.1.0', self._build_search_filter('random', '=', '<512.1.0')),
         ('random:2018-01-01', self._build_search_filter('random', '=', '2018-01-01')),
         ('random:+7d', self._build_search_filter('random', '=', '+7d')),
         ('random:>2018-01-01', self._build_search_filter('random', '=', '>2018-01-01')),
         ('random:2018-01-01', self._build_search_filter('random', '=', '2018-01-01')),
         ('random:hello', self._build_search_filter('random', '=', 'hello')),
         ('random:123', self._build_search_filter('random', '=', '123')),
     ]
     for query, expected in queries:
         assert parse_search_query(query) == [expected]
Esempio n. 33
0
    def test_duration_measurements_filter(self):
        assert parse_search_query("measurements.fp:1.5s") == [
            SearchFilter(
                key=SearchKey(name="measurements.fp"),
                operator="=",
                value=SearchValue(raw_value=1500),
            )
        ]

        assert parse_search_query("measurements.fp:>1.5s") == [
            SearchFilter(
                key=SearchKey(name="measurements.fp"),
                operator=">",
                value=SearchValue(raw_value=1500),
            )
        ]

        assert parse_search_query("measurements.fp:<1.5s") == [
            SearchFilter(
                key=SearchKey(name="measurements.fp"),
                operator="<",
                value=SearchValue(raw_value=1500),
            )
        ]
Esempio n. 34
0
 def test_empty_spaces_stripped_correctly(self):
     assert parse_search_query(
         "event.type:transaction   transaction:/organizations/:orgId/discover/results/"
     ) == [
         SearchFilter(
             key=SearchKey(name="event.type"),
             operator="=",
             value=SearchValue(raw_value="transaction"),
         ),
         SearchFilter(
             key=SearchKey(name="transaction"),
             operator="=",
             value=SearchValue(raw_value="/organizations/:orgId/discover/results/"),
         ),
     ]
Esempio n. 35
0
    def test_multiple_quotes(self):
        assert parse_search_query(
            'device.family:"" browser.name:"Chrome"') == [
                SearchFilter(key=SearchKey(name="device.family"),
                             operator="=",
                             value=SearchValue(raw_value="")),
                SearchFilter(
                    key=SearchKey(name="browser.name"),
                    operator="=",
                    value=SearchValue(raw_value="Chrome"),
                ),
            ]

        assert parse_search_query(
            'device.family:"\\"" browser.name:"Chrome"') == [
                SearchFilter(key=SearchKey(name="device.family"),
                             operator="=",
                             value=SearchValue(raw_value='"')),
                SearchFilter(
                    key=SearchKey(name="browser.name"),
                    operator="=",
                    value=SearchValue(raw_value="Chrome"),
                ),
            ]
Esempio n. 36
0
 def test_numeric_filter(self):
     # test numeric format
     assert parse_search_query('some_number:>500') == [
         SearchFilter(
             key=SearchKey(name='some_number'),
             operator=">",
             value=SearchValue(raw_value=500),
         ),
     ]
     assert parse_search_query('some_number:<500') == [
         SearchFilter(
             key=SearchKey(name='some_number'),
             operator="<",
             value=SearchValue(raw_value=500),
         ),
     ]
     # Non numeric shouldn't match
     assert parse_search_query('some_number:<hello') == [
         SearchFilter(
             key=SearchKey(name='some_number'),
             operator="=",
             value=SearchValue(raw_value="<hello"),
         ),
     ]
Esempio n. 37
0
 def test_basic_fallthrough(self):
     # These should all fall through to basic equal searches, even though they
     # look like numeric, date, etc.
     queries = [
         ("random:<hello", self._build_search_filter("random", "=", "<hello")),
         ("random:<512.1.0", self._build_search_filter("random", "=", "<512.1.0")),
         ("random:2018-01-01", self._build_search_filter("random", "=", "2018-01-01")),
         ("random:+7d", self._build_search_filter("random", "=", "+7d")),
         ("random:>2018-01-01", self._build_search_filter("random", "=", ">2018-01-01")),
         ("random:2018-01-01", self._build_search_filter("random", "=", "2018-01-01")),
         ("random:hello", self._build_search_filter("random", "=", "hello")),
         ("random:123", self._build_search_filter("random", "=", "123")),
     ]
     for query, expected in queries:
         assert parse_search_query(query) == [expected]
    def test_key_remapping(self):
        config = SearchConfig(key_mappings={"target_value": ["someValue", "legacy-value"]})

        assert parse_search_query(
            "someValue:123 legacy-value:456 normal_value:hello", config=config
        ) == [
            SearchFilter(
                key=SearchKey(name="target_value"), operator="=", value=SearchValue("123")
            ),
            SearchFilter(
                key=SearchKey(name="target_value"), operator="=", value=SearchValue("456")
            ),
            SearchFilter(
                key=SearchKey(name="normal_value"), operator="=", value=SearchValue("hello")
            ),
        ]
Esempio n. 39
0
 def test_custom_explicit_tag(self):
     assert parse_search_query("tags[fruit]:apple release:1.2.1 tags[project_id]:123") == [
         SearchFilter(
             key=SearchKey(name="tags[fruit]"),
             operator="=",
             value=SearchValue(raw_value="apple"),
         ),
         SearchFilter(
             key=SearchKey(name="release"), operator="=", value=SearchValue(raw_value="1.2.1")
         ),
         SearchFilter(
             key=SearchKey(name="tags[project_id]"),
             operator="=",
             value=SearchValue(raw_value="123"),
         ),
     ]
Esempio n. 40
0
 def test_timestamp_rollup(self):
     assert parse_search_query(
         "timestamp.to_hour:2018-01-01T05:06:07+00:00") == [
             SearchFilter(
                 key=SearchKey(name="timestamp.to_hour"),
                 operator=">=",
                 value=SearchValue(raw_value=datetime.datetime(
                     2018, 1, 1, 5, 1, 7, tzinfo=timezone.utc)),
             ),
             SearchFilter(
                 key=SearchKey(name="timestamp.to_hour"),
                 operator="<",
                 value=SearchValue(raw_value=datetime.datetime(
                     2018, 1, 1, 5, 12, 7, tzinfo=timezone.utc)),
             ),
         ]
Esempio n. 41
0
 def test_malformed_groups(self):
     error_text = "Rule 'search' matched in its entirety, but it didn't consume all the text. The non-matching portion of the text begins with"
     with pytest.raises(IncompleteParseError) as error:
         parse_search_query(
             '(user.email:[email protected] OR user.email:[email protected]')
     assert six.text_type(error.value) == '%s %s' % (
         error_text, "'(user.email:foo@exam' (line 1, column 1).")
     with pytest.raises(IncompleteParseError) as error:
         parse_search_query(
             '((user.email:[email protected] OR user.email:[email protected] AND  user.email:[email protected])'
         )
     assert six.text_type(error.value) == '%s %s' % (
         error_text, "'((user.email:foo@exa' (line 1, column 1).")
     with pytest.raises(IncompleteParseError) as error:
         parse_search_query(
             'user.email:[email protected] OR user.email:[email protected])')
     assert six.text_type(
         error.value) == '%s %s' % (error_text, "')' (line 1, column 57).")
     with pytest.raises(IncompleteParseError) as error:
         parse_search_query(
             '(user.email:[email protected] OR user.email:[email protected] AND  user.email:[email protected]))'
         )
     assert six.text_type(
         error.value) == '%s %s' % (error_text, "')' (line 1, column 91).")
Esempio n. 42
0
    def test_multiple_statements(self):
        assert parse_search_query(
            'user.email:[email protected] OR user.email:[email protected] OR user.email:[email protected]'
        ) == [
            SearchBoolean(left_term=self.term1,
                          operator='OR',
                          right_term=SearchBoolean(left_term=self.term2,
                                                   operator='OR',
                                                   right_term=self.term3))
        ]

        assert parse_search_query(
            'user.email:[email protected] AND user.email:[email protected] AND user.email:[email protected]'
        ) == [
            SearchBoolean(left_term=self.term1,
                          operator='AND',
                          right_term=SearchBoolean(left_term=self.term2,
                                                   operator='AND',
                                                   right_term=self.term3))
        ]

        # longer even number of terms
        assert parse_search_query(
            'user.email:[email protected] AND user.email:[email protected] OR user.email:[email protected] AND user.email:[email protected]'
        ) == [
            SearchBoolean(left_term=SearchBoolean(left_term=self.term1,
                                                  operator='AND',
                                                  right_term=self.term2),
                          operator='OR',
                          right_term=SearchBoolean(left_term=self.term3,
                                                   operator='AND',
                                                   right_term=self.term4))
        ]

        # longer odd number of terms
        assert parse_search_query(
            'user.email:[email protected] AND user.email:[email protected] OR user.email:[email protected] AND user.email:[email protected] AND user.email:[email protected]'
        ) == [
            SearchBoolean(left_term=SearchBoolean(left_term=self.term1,
                                                  operator='AND',
                                                  right_term=self.term2),
                          operator='OR',
                          right_term=SearchBoolean(left_term=self.term3,
                                                   operator='AND',
                                                   right_term=SearchBoolean(
                                                       left_term=self.term4,
                                                       operator='AND',
                                                       right_term=self.term5)))
        ]

        # absurdly long
        assert parse_search_query(
            'user.email:[email protected] AND user.email:[email protected] OR user.email:[email protected] AND user.email:[email protected] AND user.email:[email protected] OR user.email:[email protected] AND user.email:[email protected] OR user.email:[email protected] AND user.email:[email protected] AND user.email:[email protected]'
        ) == [
            SearchBoolean(
                left_term=SearchBoolean(left_term=self.term1,
                                        operator='AND',
                                        right_term=self.term2),
                operator='OR',
                right_term=SearchBoolean(
                    left_term=SearchBoolean(left_term=self.term3,
                                            operator='AND',
                                            right_term=SearchBoolean(
                                                left_term=self.term4,
                                                operator='AND',
                                                right_term=self.term5)),
                    operator='OR',
                    right_term=SearchBoolean(
                        left_term=SearchBoolean(left_term=self.term1,
                                                operator='AND',
                                                right_term=self.term2),
                        operator='OR',
                        right_term=SearchBoolean(left_term=self.term3,
                                                 operator='AND',
                                                 right_term=SearchBoolean(
                                                     left_term=self.term4,
                                                     operator='AND',
                                                     right_term=self.term5)))))
        ]
Esempio n. 43
0
 def test_single_term(self):
     assert parse_search_query('user.email:[email protected]') == [self.term1]
Esempio n. 44
0
    def test_raw_search_anywhere(self):
        assert parse_search_query(
            'hello what user.email:[email protected] where release:1.2.1 when'
        ) == [
            SearchFilter(
                key=SearchKey(name='message'),
                operator='=',
                value=SearchValue(raw_value='hello what'),
            ),
            SearchFilter(
                key=SearchKey(name='user.email'),
                operator="=",
                value=SearchValue(raw_value='*****@*****.**'),
            ),
            SearchFilter(
                key=SearchKey(name='message'),
                operator='=',
                value=SearchValue(raw_value='where'),
            ),
            SearchFilter(
                key=SearchKey(name='release'),
                operator="=",
                value=SearchValue(raw_value='1.2.1'),
            ),
            SearchFilter(
                key=SearchKey(name='message'),
                operator='=',
                value=SearchValue(raw_value='when'),
            ),
        ]

        assert parse_search_query('hello') == [
            SearchFilter(
                key=SearchKey(name='message'),
                operator='=',
                value=SearchValue(raw_value='hello'),
            ),
        ]

        assert parse_search_query('  hello  ') == [
            SearchFilter(
                key=SearchKey(name='message'),
                operator='=',
                value=SearchValue(raw_value='hello'),
            ),
        ]

        assert parse_search_query('  hello   there') == [
            SearchFilter(
                key=SearchKey(name='message'),
                operator='=',
                value=SearchValue(raw_value='hello   there'),
            ),
        ]

        assert parse_search_query('  hello   there:bye') == [
            SearchFilter(
                key=SearchKey(name='message'),
                operator='=',
                value=SearchValue(raw_value='hello'),
            ),
            SearchFilter(
                key=SearchKey(name='there'),
                operator='=',
                value=SearchValue(raw_value='bye'),
            ),
        ]
Esempio n. 45
0
 def test_empty_string(self):
     # Empty quotations become a dropped term
     assert parse_search_query('') == []
    def get(self, request, organization):
        try:
            # events-meta is still used by events v1 which doesn't require global views
            params = self.get_snuba_params(request,
                                           organization,
                                           check_global_views=False)
        except NoProjects:
            return Response([])

        with sentry_sdk.start_span(op="discover.endpoint",
                                   description="find_lookup_keys") as span:
            possible_keys = ["transaction"]
            lookup_keys = {
                key: request.query_params.get(key)
                for key in possible_keys
            }

            if not any(lookup_keys.values()):
                return Response(
                    {
                        "detail":
                        f"Must provide one of {possible_keys} in order to find related events"
                    },
                    status=400,
                )

        with self.handle_query_errors():
            with sentry_sdk.start_span(op="discover.endpoint",
                                       description="filter_creation"):
                projects = self.get_projects(request, organization)
                query_kwargs = build_query_params_from_request(
                    request, organization, projects, params.get("environment"))
                query_kwargs["limit"] = 5
                try:
                    # Need to escape quotes in case some "joker" has a transaction with quotes
                    transaction_name = UNESCAPED_QUOTE_RE.sub(
                        '\\"', lookup_keys["transaction"])
                    parsed_terms = parse_search_query(
                        f'transaction:"{transaction_name}"')
                except ParseError:
                    return Response({"detail": "Invalid transaction search"},
                                    status=400)

                if query_kwargs.get("search_filters"):
                    query_kwargs["search_filters"].extend(parsed_terms)
                else:
                    query_kwargs["search_filters"] = parsed_terms

            with sentry_sdk.start_span(op="discover.endpoint",
                                       description="issue_search"):
                results = search.query(**query_kwargs)

        with sentry_sdk.start_span(op="discover.endpoint",
                                   description="serialize_results") as span:
            results = list(results)
            span.set_data("result_length", len(results))
            context = serialize(
                results,
                request.user,
                GroupSerializer(environment_func=self._get_environment_func(
                    request, organization.id)),
            )

        return Response(context)
Esempio n. 47
0
 def test_invalid_aggregate_column_with_duration_filter(self):
     with self.assertRaises(InvalidSearchQuery, regex="not a duration column"):
         parse_search_query("avg(stack.colno):>500s")
Esempio n. 48
0
    def test_quotes_filtered_on_raw(self):
        # Enclose the full raw query? Strip it.
        assert parse_search_query('thinger:unknown "what is this?"') == [
            SearchFilter(
                key=SearchKey(name='thinger'),
                operator='=',
                value=SearchValue(raw_value='unknown'),
            ),
            SearchFilter(
                key=SearchKey(name='message'),
                operator='=',
                value=SearchValue(raw_value='what is this?'),
            ),
        ]

        # Enclose the full query? Strip it and the whole query is raw.
        assert parse_search_query('"thinger:unknown what is this?"') == [
            SearchFilter(
                key=SearchKey(name='message'),
                operator='=',
                value=SearchValue(raw_value='thinger:unknown what is this?'),
            ),
        ]

        # Allow a single quotation at end
        assert parse_search_query('end"') == [
            SearchFilter(
                key=SearchKey(name='message'),
                operator='=',
                value=SearchValue(raw_value='end"'),
            ),
        ]

        # Allow a single quotation at beginning
        assert parse_search_query('"beginning') == [
            SearchFilter(
                key=SearchKey(name='message'),
                operator='=',
                value=SearchValue(raw_value='"beginning'),
            ),
        ]

        # Allow a single quotation
        assert parse_search_query('"') == [
            SearchFilter(
                key=SearchKey(name='message'),
                operator='=',
                value=SearchValue(raw_value='"'),
            ),
        ]

        # Empty quotations become a dropped term
        assert parse_search_query('""') == []

        # Allow a search for space
        assert parse_search_query('" "') == [
            SearchFilter(
                key=SearchKey(name='message'),
                operator='=',
                value=SearchValue(raw_value=' '),
            ),
        ]

        # Strip in a balanced manner
        assert parse_search_query('""woof"') == [
            SearchFilter(
                key=SearchKey(name='message'),
                operator='=',
                value=SearchValue(raw_value='woof"'),
            ),
        ]

        # Don't try this at home kids
        assert parse_search_query('"""""""""') == [
            SearchFilter(
                key=SearchKey(name='message'),
                operator='=',
                value=SearchValue(raw_value='"'),
            ),
        ]
Esempio n. 49
0
 def test_invalid_aggregate_duration_filter(self):
     with self.assertRaises(InvalidSearchQuery, expected_regex="not a valid duration value"):
         parse_search_query("avg(transaction.duration):>..500s")
Esempio n. 50
0
 def test_empty_string(self):
     # Empty quotations become a dropped term
     assert parse_search_query('') == []
Esempio n. 51
0
 def test_newline_outside_quote(self):
     with self.assertRaises(IncompleteParseError):
         parse_search_query('release:a\nrelease')
Esempio n. 52
0
    def test_raw_search_anywhere(self):
        assert parse_search_query('hello what user.email:[email protected] where release:1.2.1 when') == [
            SearchFilter(
                key=SearchKey(name='message'),
                operator='=',
                value=SearchValue(raw_value='hello what'),
            ),
            SearchFilter(
                key=SearchKey(name='user.email'),
                operator="=",
                value=SearchValue(raw_value='*****@*****.**'),
            ),
            SearchFilter(
                key=SearchKey(name='message'),
                operator='=',
                value=SearchValue(raw_value='where'),
            ),
            SearchFilter(
                key=SearchKey(name='release'),
                operator="=",
                value=SearchValue(raw_value='1.2.1'),
            ),
            SearchFilter(
                key=SearchKey(name='message'),
                operator='=',
                value=SearchValue(raw_value='when'),
            ),
        ]

        assert parse_search_query('hello') == [
            SearchFilter(
                key=SearchKey(name='message'),
                operator='=',
                value=SearchValue(raw_value='hello'),
            ),
        ]

        assert parse_search_query('  hello  ') == [
            SearchFilter(
                key=SearchKey(name='message'),
                operator='=',
                value=SearchValue(raw_value='hello'),
            ),
        ]

        assert parse_search_query('  hello   there') == [
            SearchFilter(
                key=SearchKey(name='message'),
                operator='=',
                value=SearchValue(raw_value='hello   there'),
            ),
        ]

        assert parse_search_query('  hello   there:bye') == [
            SearchFilter(
                key=SearchKey(name='message'),
                operator='=',
                value=SearchValue(raw_value='hello'),
            ),
            SearchFilter(
                key=SearchKey(name='there'),
                operator='=',
                value=SearchValue(raw_value='bye'),
            ),
        ]
Esempio n. 53
0
 def test_is_query_unsupported(self):
     with self.assertRaises(InvalidSearchQuery):
         parse_search_query('is:unassigned')
Esempio n. 54
0
 def test_invalid_aggregate_percentage_filter(self):
     with self.assertRaises(InvalidSearchQuery, expected_regex="not a valid percentage value"):
         parse_search_query("percentage(transaction.duration, transaction.duration):>..500%")
Esempio n. 55
0
    def test_multiple_statements(self):
        assert parse_search_query(
            'user.email:[email protected] OR user.email:[email protected] OR user.email:[email protected]'
        ) == [SearchBoolean(
            left_term=self.term1,
            operator='OR',
            right_term=SearchBoolean(
                left_term=self.term2,
                operator='OR',
                right_term=self.term3
            )
        )]

        assert parse_search_query(
            'user.email:[email protected] AND user.email:[email protected] AND user.email:[email protected]'
        ) == [SearchBoolean(
            left_term=self.term1,
            operator='AND',
            right_term=SearchBoolean(
                left_term=self.term2,
                operator='AND',
                right_term=self.term3
            )
        )]

        term4 = SearchFilter(
            key=SearchKey(name='user.email'),
            operator="=",
            value=SearchValue(raw_value='*****@*****.**'),
        )

        # longer even number of terms
        assert parse_search_query(
            'user.email:[email protected] AND user.email:[email protected] OR user.email:[email protected] AND user.email:[email protected]'
        ) == [SearchBoolean(
            left_term=SearchBoolean(
                left_term=self.term1,
                operator='AND',
                right_term=self.term2
            ),
            operator='OR',
            right_term=SearchBoolean(
                left_term=self.term3,
                operator='AND',
                right_term=term4
            )
        )]

        term5 = SearchFilter(
            key=SearchKey(name='user.email'),
            operator="=",
            value=SearchValue(raw_value='*****@*****.**'),
        )

        # longer odd number of terms
        assert parse_search_query(
            'user.email:[email protected] AND user.email:[email protected] OR user.email:[email protected] AND user.email:[email protected] AND user.email:[email protected]'
        ) == [
            SearchBoolean(
                left_term=SearchBoolean(
                    left_term=self.term1,
                    operator='AND',
                    right_term=self.term2
                ),
                operator='OR',
                right_term=SearchBoolean(
                    left_term=self.term3,
                    operator='AND',
                    right_term=SearchBoolean(
                        left_term=term4,
                        operator='AND',
                        right_term=term5
                    )
                )
            )]

        # absurdly long
        assert parse_search_query(
            'user.email:[email protected] AND user.email:[email protected] OR user.email:[email protected] AND user.email:[email protected] AND user.email:[email protected] OR user.email:[email protected] AND user.email:[email protected] OR user.email:[email protected] AND user.email:[email protected] AND user.email:[email protected]'
        ) == [SearchBoolean(
            left_term=SearchBoolean(
                left_term=self.term1,
                operator='AND',
                right_term=self.term2),
            operator='OR',
            right_term=SearchBoolean(
                left_term=SearchBoolean(
                    left_term=self.term3,
                    operator='AND',
                    right_term=SearchBoolean(
                        left_term=term4,
                        operator='AND',
                        right_term=term5)),
                operator='OR',
                right_term=SearchBoolean(
                    left_term=SearchBoolean(
                        left_term=self.term1,
                        operator='AND',
                        right_term=self.term2),
                    operator='OR',
                    right_term=SearchBoolean(
                        left_term=self.term3,
                        operator='AND',
                        right_term=SearchBoolean(
                            left_term=term4,
                            operator='AND',
                            right_term=term5
                        )
                    )
                )
            )
        )]
Esempio n. 56
0
 def test_newline_outside_quote(self):
     with self.assertRaises(IncompleteParseError):
         parse_search_query('release:a\nrelease')
Esempio n. 57
0
 def test_tab_within_quote(self):
     assert parse_search_query('release:"a\trelease"') == [
         SearchFilter(key=SearchKey(name='release'),
                      operator='=',
                      value=SearchValue(raw_value='a\trelease')),
     ]
Esempio n. 58
0
 def test_single_term(self):
     assert parse_search_query('user.email:[email protected]') == [self.term1]
Esempio n. 59
0
    def test_quotes_filtered_on_raw(self):
        # Enclose the full raw query? Strip it.
        assert parse_search_query('thinger:unknown "what is this?"') == [
            SearchFilter(
                key=SearchKey(name='thinger'),
                operator='=',
                value=SearchValue(raw_value='unknown'),
            ),
            SearchFilter(
                key=SearchKey(name='message'),
                operator='=',
                value=SearchValue(raw_value='what is this?'),
            ),
        ]

        # Enclose the full query? Strip it and the whole query is raw.
        assert parse_search_query('"thinger:unknown what is this?"') == [
            SearchFilter(
                key=SearchKey(name='message'),
                operator='=',
                value=SearchValue(raw_value='thinger:unknown what is this?'),
            ),
        ]

        # Allow a single quotation at end
        assert parse_search_query('end"') == [
            SearchFilter(
                key=SearchKey(name='message'),
                operator='=',
                value=SearchValue(raw_value='end"'),
            ),
        ]

        # Allow a single quotation at beginning
        assert parse_search_query('"beginning') == [
            SearchFilter(
                key=SearchKey(name='message'),
                operator='=',
                value=SearchValue(raw_value='"beginning'),
            ),
        ]

        # Allow a single quotation
        assert parse_search_query('"') == [
            SearchFilter(
                key=SearchKey(name='message'),
                operator='=',
                value=SearchValue(raw_value='"'),
            ),
        ]

        # Empty quotations become a dropped term
        assert parse_search_query('""') == []

        # Allow a search for space
        assert parse_search_query('" "') == [
            SearchFilter(
                key=SearchKey(name='message'),
                operator='=',
                value=SearchValue(raw_value=' '),
            ),
        ]

        # Strip in a balanced manner
        assert parse_search_query('""woof"') == [
            SearchFilter(
                key=SearchKey(name='message'),
                operator='=',
                value=SearchValue(raw_value='"woof'),
            ),
        ]

        # Don't try this at home kids
        assert parse_search_query('"""""""""') == [
            SearchFilter(
                key=SearchKey(name='message'),
                operator='=',
                value=SearchValue(raw_value='"'),
            ),
        ]
Esempio n. 60
0
 def test_is_query_unsupported(self):
     with self.assertRaises(InvalidSearchQuery):
         parse_search_query('is:unassigned')