예제 #1
0
 def testAlternateDatabase(self):
     settings.DATABASE_USING = 'default'
     
     try:
         Message.objects.get(id=999999979)
     except Message.DoesNotExist, exc:
         SentryClient.create_from_exception(exc)
예제 #2
0
def sentry_exception_handler(sender, request=None, **kwargs):
    try:
        exc_type, exc_value, exc_traceback = sys.exc_info()

        if not settings.CATCH_404_ERRORS \
                and issubclass(exc_type, Http404):
            return

        if dj_settings.DEBUG or getattr(exc_type, 'skip_sentry', False):
            return

        if transaction.is_dirty():
            transaction.rollback()

        # kudos to Tapz for this idea
        modules = get_installed_apps()

        # only retrive last 10 lines
        tb = traceback.extract_tb(exc_traceback)

        # retrive final file and line number where the exception occured
        file, line_number = tb[-1][:2]

        # tiny hack to get the python path from filename
        for (filename, line, function, text) in reversed(tb):
            for path in sys.path:
                if filename.startswith(path):
                    view = '%s.%s' % (filename[len(path)+1:].replace('/', '.').replace('.py', ''), function)
                    break
            if view.split('.')[0] in modules:
                break
            else:
                view = '%s.%s' % (exc_traceback.tb_frame.f_globals['__name__'], tb[-1][2]) 

        if request:
            data = dict(
                META=request.META,
                POST=request.POST,
                GET=request.GET,
                COOKIES=request.COOKIES,
            )
        else:
            data = dict()

        extra = dict(
            url=request and request.build_absolute_uri() or None,
            data=data,
            view=view,
        )

        if settings.USE_LOGGING:
            logger.critical(exc_value, exc_info=sys.exc_info(), extra=extra)
        else:
            SentryClient.create_from_exception(**extra)
    except Exception, exc:
        try:
            logger.exception(u'Unable to process log entry: %s' % (exc,))
        except Exception, exc:
            warnings.warn(u'Unable to process log entry: %s' % (exc,))
예제 #3
0
 def testThrashing(self):
     settings.THRASHING_LIMIT = 10
     settings.THRASHING_TIMEOUT = 60
     
     Message.objects.all().delete()
     GroupedMessage.objects.all().delete()
     
     for i in range(0, 50):
         SentryClient.create_from_text('hi')
     
     self.assertEquals(Message.objects.count(), settings.THRASHING_LIMIT)
예제 #4
0
    def testNoThrashing(self):
        prev = settings.THRASHING_LIMIT
        settings.THRASHING_LIMIT = 0
        
        Message.objects.all().delete()
        GroupedMessage.objects.all().delete()
        
        for i in range(0, 50):
            SentryClient.create_from_text('hi')
        
        self.assertEquals(Message.objects.count(), 50)

        settings.THRASHING_LIMIT = prev
예제 #5
0
 def testProcess(self):
     self.start_test_server()
     message_id = SentryClient().process(message='hello')
     self.assertTrue(message_id)
     instance = Message.objects.all().order_by('-id')[0]
     self.assertEquals(instance.message, 'hello')
     self.stop_test_server()
예제 #6
0
    def fetch_new_content(self, **options):
        update_horizon = datetime.utcnow() - timedelta(minutes=15)
        last_viewed_horizon = datetime.utcnow() - timedelta(days=5)

        users = User.objects.all()
        for user in users:
            try:
                person = user.person
            except Person.DoesNotExist:
                continue

            # Don't update accounts if someone hasn't viewed the site in some days.
            if person.last_viewed_home < last_viewed_horizon:
                logging.getLogger(__name__).debug(
                    "User %s hasn't viewed the site in a while; skipping",
                    user.username)
                continue

            for account in person.accounts.all():
                log = logging.getLogger('%s.%s' % (__name__, account.service))

                try:
                    poller = pollers[account.service]
                except KeyError:
                    log.debug("Account service %s has no poller, skipping",
                              account.service)
                    continue

                if options['service'] and account.service != options['service']:
                    log.debug(
                        "Account is for service %s but we're only polling %s, skipping",
                        account.service, options['service'])
                    continue

                if not options[
                        'force'] and account.last_updated > update_horizon:
                    log.debug(
                        "Account %s %s was updated fewer than 15 minutes ago, skipping",
                        account.service, account.display_name)
                    continue

                # Mark the account as updated even if the update fails later.
                log.debug("Polling account %s %s", account.service,
                          account.display_name)
                account.last_updated = datetime.utcnow()
                account.save()

                try:
                    poller(account)
                except Exception, exc:
                    log.exception(exc)
                    SentryClient().create_from_exception(
                        view='%s.%s' % (__name__, account.service))
                else:
                    account.last_success = datetime.utcnow()
                    account.save()
예제 #7
0
    def testTimestamp(self):
        timestamp = datetime.datetime.now() - datetime.timedelta(hours=1)

        self.start_test_server()
        message_id = SentryClient().process(message='hello', timestamp=timestamp)
        self.stop_test_server()

        self.assertTrue(message_id)
        instance = Message.objects.all().order_by('-id')[0]
        self.assertEquals(instance.message, 'hello')
        self.assertEquals(instance.datetime, timestamp)
        group = instance.group
        self.assertEquals(group.first_seen, timestamp)
        self.assertEquals(group.last_seen, timestamp)
예제 #8
0
    def testCorrectUnicode(self):
        self.setUpHandler()
        
        cnt = Message.objects.count()
        value = 'רונית מגן'.decode('utf-8')

        error = SentryClient.create_from_text(value)
        self.assertEquals(Message.objects.count(), cnt+1)
        self.assertEquals(error.message, value)

        logging.info(value)
        self.assertEquals(Message.objects.count(), cnt+2)

        x = TestModel.objects.create(data={'value': value})
        logging.warn(x)
        self.assertEquals(Message.objects.count(), cnt+3)

        try:
            raise SyntaxMessage(value)
        except Exception, exc:
            logging.exception(exc)
            logging.info('test', exc_info=sys.exc_info())
예제 #9
0
 def testLongURLs(self):
     # Fix: #6 solves URLs > 200 characters
     error = SentryClient.create_from_text('hello world', url='a'*210)
     self.assertEquals(error.url, 'a'*200)
     self.assertEquals(error.data['url'], 'a'*210)
예제 #10
0
 def testAPI(self):
     try:
         Message.objects.get(id=999999989)
     except Message.DoesNotExist, exc:
         SentryClient.create_from_exception(exc)
예제 #11
0
        self.assertEquals(last.class_name, 'DoesNotExist')
        self.assertEquals(last.level, logging.ERROR)
        self.assertEquals(last.message, smart_unicode(exc))
        
    def testAPI(self):
        try:
            Message.objects.get(id=999999989)
        except Message.DoesNotExist, exc:
            SentryClient.create_from_exception(exc)
        else:
            self.fail('Unable to create `Message` entry.')

        try:
            Message.objects.get(id=999999989)
        except Message.DoesNotExist, exc:
            error = SentryClient.create_from_exception()
            self.assertTrue(error.data.get('__sentry__', {}).get('exc'))
        else:
            self.fail('Unable to create `Message` entry.')

        
        cur = (Message.objects.count(), GroupedMessage.objects.count())
        self.assertEquals(cur, (2, 2), 'Assumed logs failed to save. %s' % (cur,))
        last = Message.objects.all().order_by('-id')[0:1].get()
        self.assertEquals(last.logger, 'root')
        self.assertEquals(last.class_name, 'DoesNotExist')
        self.assertEquals(last.level, logging.ERROR)
        self.assertEquals(last.message, smart_unicode(exc))
        
        SentryClient.create_from_text('This is an error', level=logging.DEBUG)
        
예제 #12
0
파일: tasks.py 프로젝트: dcramer/sentry-old
def send(data):
    return SentryClient().send(**data)
예제 #13
0
 def handle_noargs(self, **options):
     try:
         self.fetch_new_content(**options)
     except Exception, exc:
         logging.exception(exc)
         SentryClient().create_from_exception(view=__name__)
예제 #14
0
            log.debug("Creating a UserStream row for object %r which is a %s by %r", obj, why_verb, actor)
            streamitem, created = UserStream.objects.get_or_create(user=user, obj=obj,
                defaults={'why_account': actor, 'why_verb': why_verb, 'time': orig_obj.time})

            # Now walk up again creating UserReplyStream rows as necessary
            reply_obj = orig_obj
            while reply_obj.in_reply_to is not None:
                UserReplyStream.objects.get_or_create(user=user, root=obj, reply=reply_obj,
                    defaults={'root_time': streamitem.time, 'reply_time': reply_obj.time})
                reply_obj = reply_obj.in_reply_to


        except Exception, exc:
            from sentry.client.base import SentryClient
            SentryClient().create_from_exception(view=__name__)


def account_for_facebook_user(fb_user, person=None):
    try:
        account = Account.objects.get(service='facebook.com', ident=fb_user["id"])
    except Account.DoesNotExist:
        if person is None:
            avatar = Media(
                width=50,
                height=50,
                image_url='http://graph.facebook.com/%s/picture' % fb_user["id"]
            )
            avatar.save()
            person = Person(
                display_name=fb_user["name"],
예제 #15
0
    def emit(self, record):
        from sentry.client.base import SentryClient

        SentryClient.create_from_record(record)
예제 #16
0
def poll_twitter(account):
    user = account.person.user
    if user is None:
        return

    authtoken = account.authinfo
    if not authtoken:
        return

    # Get that twitter user's home timeline.
    csr = oauth.Consumer(*settings.TWITTER_CONSUMER)
    token = oauth.Token(*authtoken.split(':', 1))
    client = oauth.Client(csr, token)
    try:
        resp, content = client.request(
            'http://api.twitter.com/1/statuses/home_timeline.json?include_entities=true&count=50',
            'GET')
    except httplib.IncompleteRead:
        log.info(
            "Twitter returned an incomplete response asking for %s's feed",
            account.ident)
        return
    if resp.status in (500, 502, 503):
        # Can't get Twitter results right now. Let's try again later.
        log.info(
            "Twitter returned a server error status %d asking for %s's feed (Twitter's down?)",
            resp.status, account.ident)
        return
    if resp.status == 401:
        # The token may be invalid. Have we successfully scanned this account recently?
        if account.last_success > datetime.utcnow() - timedelta(days=2):
            raise ValueError(
                "Token for Twitter user %s came back as invalid (possibly temporary)"
                % account.ident)
        # The token is now invalid (maybe they revoked the app). Stop updating this account.
        account.authinfo = ''
        account.save()
        raise ValueError(
            "Token for Twitter user %s came back as invalid (probably permanent, so deleted authinfo)"
            % account.ident)
    if resp.status != 200:
        raise ValueError(
            "Unexpected %d %s response fetching %s's twitter timeline" %
            (resp.status, resp.reason, account.ident))

    tl = json.loads(content)

    for orig_tweetdata in reversed(tl):
        try:
            # TODO: filter based on source?

            tweetdata = orig_tweetdata
            why_verb = 'post'
            try:
                tweetdata = orig_tweetdata['retweeted_status']
            except KeyError:
                pass
            else:
                why_verb = 'share'

            really_a_share, tweet = raw_object_for_tweet(tweetdata, client)
            if tweet is None:
                continue

            if really_a_share:
                why_verb = 'share'

            if why_verb == 'share':
                why_account = account_for_twitter_user(orig_tweetdata['user'])
            else:
                why_account = tweet.author

            # CASES:
            # real reply to...
            # real retweet of...
            # tweet with just a link
            # tweet with a link and custom text
            # tweet with a link and the link's target page title (found how?)

            if why_verb == 'post' and tweet.in_reply_to is not None:
                why_verb = 'reply'

            root = tweet
            while root.in_reply_to is not None:
                log.debug('Walking up from %r to %r', root, root.in_reply_to)
                root = root.in_reply_to

            streamitem, created = UserStream.objects.get_or_create(
                user=user,
                obj=root,
                # TODO: is tweet.time the right time here or do we need the "why time" from orig_tweetdata?
                defaults={
                    'why_account': why_account,
                    'why_verb': why_verb,
                    'time': tweet.time
                })

            # Now add a reply for each tweet in the thread along the way.
            supertweet = tweet
            while supertweet.in_reply_to is not None:
                UserReplyStream.objects.get_or_create(user=user,
                                                      root=root,
                                                      reply=supertweet,
                                                      defaults={
                                                          'root_time':
                                                          streamitem.time,
                                                          'reply_time':
                                                          supertweet.time
                                                      })
                supertweet = supertweet.in_reply_to

        except Exception, exc:
            from sentry.client.base import SentryClient
            SentryClient().create_from_exception(view=__name__)