コード例 #1
0
        private void processLogEntry(LogEntry entry)
        {
            if (entry.Level < LogLevel.Verbose)
            {
                return;
            }

            var exception = entry.Exception;

            if (exception != null)
            {
                if (!shouldSubmitException(exception))
                {
                    return;
                }

                // since we let unhandled exceptions go ignored at times, we want to ensure they don't get submitted on subsequent reports.
                if (lastException != null && lastException.Message == exception.Message && exception.StackTrace.StartsWith(lastException.StackTrace, StringComparison.Ordinal))
                {
                    return;
                }

                lastException = exception;
                sentry.CaptureEvent(new SentryEvent(exception)
                {
                    Message = entry.Message
                }, sentryScope);
            }
            else
            {
                sentryScope.AddBreadcrumb(DateTimeOffset.Now, entry.Message, entry.Target.ToString(), "navigation");
            }
        }
コード例 #2
0
        // TODO: should this class take the Scope by dependency injection instead?
        // Would allow us to create a centralized "chain of handlers" where this class could just be registered as an entry in
        
        public void Enrich(Scope scope, DiscordClient shard, MessageCreateEventArgs evt)
        {
            scope.AddBreadcrumb(evt.Message.Content, "event.message", data: new Dictionary<string, string>
            {
                {"user", evt.Author.Id.ToString()},
                {"channel", evt.Channel.Id.ToString()},
                {"guild", evt.Channel.GuildId.ToString()},
                {"message", evt.Message.Id.ToString()},
            });
            scope.SetTag("shard", shard.ShardId.ToString());

            // Also report information about the bot's permissions in the channel
            // We get a lot of permission errors so this'll be useful for determining problems
            var perms = evt.Channel.BotPermissions();
            scope.AddBreadcrumb(perms.ToPermissionString(), "permissions");
        }
コード例 #3
0
 public static void AddMessageBreadcrumb(this Scope scope, SocketMessage msg)
 {
     scope.AddBreadcrumb(msg.Content, "event.message", data: new Dictionary <string, string>()
     {
         { "user", msg.Author.Id.ToString() },
         { "channel", msg.Channel.Id.ToString() },
         { "guild", ((msg.Channel as IGuildChannel)?.GuildId ?? 0).ToString() },
         { "message", msg.Id.ToString() },
     });
 }
コード例 #4
0
 public static void AddMessageBulkDeleteBreadcrumb(this Scope scope, IReadOnlyCollection <Cacheable <IMessage, ulong> > messages,
                                                   ISocketMessageChannel channel)
 {
     scope.AddBreadcrumb("", "event.messageDelete", data: new Dictionary <string, string>()
     {
         { "channel", channel.Id.ToString() },
         { "guild", ((channel as IGuildChannel)?.GuildId ?? 0).ToString() },
         { "messages", string.Join(",", messages.Select(m => m.Id)) },
     });
 }
コード例 #5
0
 public static void AddMessageDeleteBreadcrumb(this Scope scope, Cacheable <IMessage, ulong> message,
                                               ISocketMessageChannel channel)
 {
     scope.AddBreadcrumb("", "event.messageDelete", data: new Dictionary <string, string>()
     {
         { "channel", channel.Id.ToString() },
         { "guild", ((channel as IGuildChannel)?.GuildId ?? 0).ToString() },
         { "message", message.Id.ToString() },
     });
 }
コード例 #6
0
 public void Enrich(Scope scope, MessageBulkDeleteEventArgs evt)
 {
     scope.AddBreadcrumb("", "event.messageDelete",
                         data: new Dictionary <string, string>()
     {
         { "channel", evt.Channel.Id.ToString() },
         { "guild", evt.Channel.Id.ToString() },
         { "messages", string.Join(",", evt.Messages.Select(m => m.Id)) },
     });
     scope.SetTag("shard", evt.Client.ShardId.ToString());
 }
コード例 #7
0
 public void Enrich(Scope scope, DiscordClient shard, MessageDeleteEventArgs evt)
 {
     scope.AddBreadcrumb("", "event.messageDelete",
         data: new Dictionary<string, string>()
         {
             {"channel", evt.Channel.Id.ToString()},
             {"guild", evt.Channel.GuildId.ToString()},
             {"message", evt.Message.Id.ToString()},
         });
     scope.SetTag("shard", shard.ShardId.ToString());
 }
コード例 #8
0
        public void Apply_Breadcrumbs_NotOnSource_TargetUnmodified()
        {
            var target = new Scope();

            target.AddBreadcrumb("test target");
            var expected = target.InternalBreadcrumbs;

            _sut.Apply(target);

            Assert.Same(expected, target.InternalBreadcrumbs);
        }
コード例 #9
0
        public void Apply_Breadcrumbs_OnTarget_MergedWithSource()
        {
            _sut.AddBreadcrumb("test sut");
            var target = new Scope();

            target.AddBreadcrumb("test target");

            _sut.Apply(target);

            Assert.Equal(2, target.InternalBreadcrumbs.Count);
        }
コード例 #10
0
        public void AddBreadcrumb_WithoutOptions_NoMoreThanDefaultMaxBreadcrumbs()
        {
            var scope = new Scope();

            for (var i = 0; i < Constants.DefaultMaxBreadcrumbs + 1; i++)
            {
                scope.AddBreadcrumb(i.ToString());
            }

            Assert.Equal(Constants.DefaultMaxBreadcrumbs, scope.InternalBreadcrumbs.Count);
        }
コード例 #11
0
ファイル: SentryUtils.cs プロジェクト: xSke/PluralKit
 public void Enrich(Scope scope, int shardId, MessageDeleteEvent evt)
 {
     scope.AddBreadcrumb("", "event.messageDelete",
                         data: new Dictionary <string, string>
     {
         { "channel", evt.ChannelId.ToString() },
         { "guild", evt.GuildId.ToString() },
         { "message", evt.Id.ToString() }
     });
     scope.SetTag("shard", shardId.ToString());
 }
コード例 #12
0
ファイル: SentryUtils.cs プロジェクト: xSke/PluralKit
 public void Enrich(Scope scope, int shardId, MessageUpdateEvent evt)
 {
     scope.AddBreadcrumb(evt.Content.Value ?? "<unknown>", "event.messageEdit",
                         data: new Dictionary <string, string>
     {
         { "channel", evt.ChannelId.ToString() },
         { "guild", evt.GuildId.Value.ToString() },
         { "message", evt.Id.ToString() }
     });
     scope.SetTag("shard", shardId.ToString());
 }
コード例 #13
0
 public void Enrich(Scope scope, MessageUpdateEventArgs evt)
 {
     scope.AddBreadcrumb(evt.Message.Content ?? "<unknown>", "event.messageEdit",
                         data: new Dictionary <string, string>()
     {
         { "channel", evt.Channel.Id.ToString() },
         { "guild", evt.Channel.GuildId.ToString() },
         { "message", evt.Message.Id.ToString() }
     });
     scope.SetTag("shard", evt.Client.ShardId.ToString());
 }
コード例 #14
0
 public void Enrich(Scope scope, Shard shard, MessageDeleteBulkEvent evt)
 {
     scope.AddBreadcrumb("", "event.messageDelete",
                         data: new Dictionary <string, string>()
     {
         { "channel", evt.ChannelId.ToString() },
         { "guild", evt.GuildId.ToString() },
         { "messages", string.Join(",", evt.Ids) },
     });
     scope.SetTag("shard", shard.ShardInfo.ShardId.ToString());
 }
コード例 #15
0
        public SentryLogger(OsuGame game)
        {
            if (!game.IsDeployedBuild)
            {
                return;
            }

            var options = new SentryOptions
            {
                Dsn     = new Dsn("https://[email protected]/1255255"),
                Release = game.Version
            };

            sentry      = new SentryClient(options);
            sentryScope = new Scope(options);

            Exception lastException = null;

            Logger.NewEntry += entry =>
            {
                if (entry.Level < LogLevel.Verbose)
                {
                    return;
                }

                var exception = entry.Exception;

                if (exception != null)
                {
                    if (!shouldSubmitException(exception))
                    {
                        return;
                    }

                    // since we let unhandled exceptions go ignored at times, we want to ensure they don't get submitted on subsequent reports.
                    if (lastException != null &&
                        lastException.Message == exception.Message && exception.StackTrace.StartsWith(lastException.StackTrace, StringComparison.Ordinal))
                    {
                        return;
                    }

                    lastException = exception;
                    sentry.CaptureEvent(new SentryEvent(exception)
                    {
                        Message = entry.Message
                    }, sentryScope);
                }
                else
                {
                    sentryScope.AddBreadcrumb(DateTimeOffset.Now, entry.Message, entry.Target.ToString(), "navigation");
                }
            };
        }
コード例 #16
0
 public static void AddReactionAddedBreadcrumb(this Scope scope, Cacheable <IUserMessage, ulong> message,
                                               ISocketMessageChannel channel, SocketReaction reaction)
 {
     scope.AddBreadcrumb("", "event.reaction", data: new Dictionary <string, string>()
     {
         { "user", reaction.UserId.ToString() },
         { "channel", channel.Id.ToString() },
         { "guild", ((channel as IGuildChannel)?.GuildId ?? 0).ToString() },
         { "message", message.Id.ToString() },
         { "reaction", reaction.Emote.Name }
     });
 }
コード例 #17
0
 public void Enrich(Scope scope, MessageReactionAddEventArgs evt)
 {
     scope.AddBreadcrumb("", "event.reaction",
                         data: new Dictionary <string, string>()
     {
         { "user", evt.User.Id.ToString() },
         { "channel", (evt.Channel?.Id ?? 0).ToString() },
         { "guild", (evt.Channel?.GuildId ?? 0).ToString() },
         { "message", evt.Message.Id.ToString() },
         { "reaction", evt.Emoji.Name }
     });
     scope.SetTag("shard", evt.Client.ShardId.ToString());
 }
コード例 #18
0
        public void AddBreadcrumb_WithOptions_BoundOptionsLimit(int limit)
        {
            var options = Substitute.For <IScopeOptions>();

            options.MaxBreadcrumbs.Returns(limit);

            var scope = new Scope(options);

            for (var i = 0; i < limit + 1; i++)
            {
                scope.AddBreadcrumb(i.ToString());
            }

            Assert.Equal(limit, scope.InternalBreadcrumbs.Count);
        }
コード例 #19
0
        public SentryLogger(QsorBaseGame game)
        {
            if (DebugUtils.IsDebugBuild)
            {
                return;
            }

            var sentryOptions = new SentryOptions
            {
                Dsn     = new Dsn("https://[email protected]/5193034"),
                Release = QsorBaseGame.Version
            };

            _sentry = new SentryClient(sentryOptions);
            var sentryScope = new Scope(sentryOptions);

            Exception lastException = null;

            Logger.NewEntry += async entry =>
            {
                if (entry.Level < LogLevel.Verbose)
                {
                    return;
                }

                var exception = entry.Exception;

                if (exception != null)
                {
                    if (lastException != null && // We shouldn't resubmit the same exception
                        lastException.Message == exception.Message &&
                        exception.StackTrace?.StartsWith(lastException.StackTrace ?? string.Empty) == true)
                    {
                        return;
                    }

                    _sentry.CaptureEvent(new SentryEvent(exception)
                    {
                        Message = entry.Message
                    }, sentryScope);
                    lastException = exception;
                }
                else
                {
                    sentryScope.AddBreadcrumb(DateTimeOffset.Now, entry.Message, entry.Target.ToString(), "qsor-logger");
                }
            };
        }
コード例 #20
0
ファイル: ScopeTests.cs プロジェクト: robopsi/sentry-dotnet
        public void AddBreadcrumb()
        {
            const int limit   = 5;
            var       options = Substitute.For <IScopeOptions>();

            options.MaxBreadcrumbs.Returns(limit);

            var scope = new Scope(options);

            for (var i = 0; i < limit + 1; i++)
            {
                scope.AddBreadcrumb(i.ToString(), "test");
            }

            // Breadcrumb 0 is dropped
            Assert.Equal("1", scope.Breadcrumbs[0].Message);
            Assert.Equal("5", scope.Breadcrumbs[4].Message);
        }
コード例 #21
0
ファイル: SentryUtils.cs プロジェクト: xSke/PluralKit
    // TODO: should this class take the Scope by dependency injection instead?
    // Would allow us to create a centralized "chain of handlers" where this class could just be registered as an entry in

    public void Enrich(Scope scope, int shardId, MessageCreateEvent evt)
    {
        scope.AddBreadcrumb(evt.Content, "event.message",
                            data: new Dictionary <string, string>
        {
            { "user", evt.Author.Id.ToString() },
            { "channel", evt.ChannelId.ToString() },
            { "guild", evt.GuildId.ToString() },
            { "message", evt.Id.ToString() }
        });
        scope.SetTag("shard", shardId.ToString());

        // Also report information about the bot's permissions in the channel
        // We get a lot of permission errors so this'll be useful for determining problems

        // todo: re-add this
        // var perms = _bot.PermissionsIn(evt.ChannelId);
        // scope.AddBreadcrumb(perms.ToPermissionString(), "permissions");
    }
コード例 #22
0
        public void AddBreadcrumb_ValueTuple_AllArgumentsMatch()
        {
            const string          expectedMessage  = "original Message";
            const string          expectedCategory = "original Category";
            const string          expectedType     = "original Type";
            var                   expectedData     = (key : "key", value : "value");
            const BreadcrumbLevel expectedLevel    = BreadcrumbLevel.Critical;

            _sut.AddBreadcrumb(
                expectedMessage,
                expectedCategory,
                expectedType,
                expectedData,
                expectedLevel);

            var actual = Assert.Single(_sut.InternalBreadcrumbs);

            Assert.Equal(expectedMessage, actual.Message);
            Assert.Equal(expectedCategory, actual.Category);
            Assert.Equal(expectedType, actual.Type);
            Assert.Equal(expectedData.key, actual.Data.Single().Key);
            Assert.Equal(expectedData.value, actual.Data.Single().Value);
            Assert.Equal(expectedLevel, actual.Level);
        }
コード例 #23
0
        public async Task HandleMessage(SocketMessage arg)
        {
            if (_client.GetShardFor((arg.Channel as IGuildChannel)?.Guild).ConnectionState != ConnectionState.Connected)
            {
                return; // Discard messages while the bot "catches up" to avoid unnecessary CPU pressure causing timeouts
            }
            RegisterMessageMetrics(arg);

            // Ignore system messages (member joined, message pinned, etc)
            var msg = arg as SocketUserMessage;

            if (msg == null)
            {
                return;
            }

            // Ignore bot messages
            if (msg.Author.IsBot || msg.Author.IsWebhook)
            {
                return;
            }

            // Add message info as Sentry breadcrumb
            _msg = msg;
            _sentryScope.AddBreadcrumb(msg.Content, "event.message", data: new Dictionary <string, string>
            {
                { "user", msg.Author.Id.ToString() },
                { "channel", msg.Channel.Id.ToString() },
                { "guild", ((msg.Channel as IGuildChannel)?.GuildId ?? 0).ToString() },
                { "message", msg.Id.ToString() },
            });

            // We fetch information about the sending account *and* guild from the cache
            GuildConfig cachedGuild = default; // todo: is this default correct?

            if (msg.Channel is ITextChannel textChannel)
            {
                cachedGuild = await _cache.GetGuildDataCached(textChannel.GuildId);
            }
            var cachedAccount = await _cache.GetAccountDataCached(msg.Author.Id);

            // this ^ may be null, do remember that down the line

            int argPos = -1;

            // Check if message starts with the command prefix
            if (msg.Content.StartsWith("pk;", StringComparison.InvariantCultureIgnoreCase))
            {
                argPos = 3;
            }
            else if (msg.Content.StartsWith("pk!", StringComparison.InvariantCultureIgnoreCase))
            {
                argPos = 3;
            }
            else if (msg.Content != null && Utils.HasMentionPrefix(msg.Content, ref argPos, out var id)) // Set argPos to the proper value
            {
                if (id != _client.CurrentUser.Id)                                                        // But undo it if it's someone else's ping
                {
                    argPos = -1;
                }
            }

            // If it does, try executing a command
            if (argPos > -1)
            {
                _logger.Verbose("Parsing command {Command} from message {Channel}-{Message}", msg.Content, msg.Channel.Id, msg.Id);

                // Essentially move the argPos pointer by however much whitespace is at the start of the post-argPos string
                var trimStartLengthDiff = msg.Content.Substring(argPos).Length -
                                          msg.Content.Substring(argPos).TrimStart().Length;
                argPos += trimStartLengthDiff;

                await _tree.ExecuteCommand(new Context(_services, msg, argPos, cachedAccount?.System));
            }
            else if (cachedAccount != null)
            {
                // If not, try proxying anyway
                // but only if the account data we got before is present
                // no data = no account = no system = no proxy!
                try
                {
                    await _proxy.HandleMessageAsync(cachedGuild, cachedAccount, msg);
                }
                catch (PKError e)
                {
                    await arg.Channel.SendMessageAsync($"{Emojis.Error} {e.Message}");
                }
            }
        }
コード例 #24
0
 public static void AddPeriodicBreadcrumb(this Scope scope) => scope.AddBreadcrumb("", "periodic");