disnake SDK
pip install mochi-analytics mochi-analytics-disnakeRequires Python 3.10+.
Quick start
import os
import disnake
from mochi_analytics import MochiClient
from mochi_analytics_disnake import attach_mochi
mochi = MochiClient(
url="https://mochi.example.com", # your Mochi instance
api_key=os.environ["MOCHI_API_KEY"], # from the bot's settings page
)
intents = disnake.Intents.default()
client = disnake.Client(intents=intents)
attach_mochi(client, mochi)
client.run(os.environ["DISCORD_TOKEN"])That’s it. Mochi now records slash/context-menu command usage, guild joins and leaves, and an hourly server-count snapshot.
attach_mochi works with disnake.Client, disnake.AutoShardedClient, and
disnake.ext.commands.Bot / InteractionBot. An AutoShardedClient sends one
snapshot per shard, each carrying that shard’s own guild count.
Options
attach_mochi(
client,
mochi,
include_guild_names=True, # put guild names in join/leave metadata
ignore_commands=["ping"], # skip noisy commands
snapshot_interval=30 * 60, # seconds; default 1 hour
auto_track_commands=False, # see "accurate timings" below
)Accurate duration & success
Auto-tracking records commands the moment the interaction arrives — it can’t see whether your handler succeeded or how long it took. For that, disable auto-tracking and wrap your handlers:
from disnake.ext import commands
from mochi_analytics_disnake import wrap_command
bot = commands.InteractionBot()
attach_mochi(bot, mochi, auto_track_commands=False)
@bot.slash_command()
@wrap_command(mochi)
async def play(inter: disnake.ApplicationCommandInteraction):
... # duration and raised exceptions are recordedCommand names
disnake exposes qualified_name only on prefix commands, so the adapter rebuilds
the full application-command name — for example config channel set — by walking
the option tree the gateway sent. Value options never extend the name.
Custom events
from mochi_analytics import MochiEvent
mochi.track(MochiEvent(
type="custom",
name="premium_purchased",
user_id=str(inter.author.id),
guild_id=str(inter.guild_id) if inter.guild_id else None,
meta={"tier": "gold"},
))Design guarantees
- Events are batched (flushed every 5 s or 100 events) and sent in the
background —
track()never blocks or raises. - Transient failures retry with backoff; the queue is bounded (oldest dropped first), so a dead Mochi instance can never leak memory or crash the bot.
- Raw user ids are hashed server-side with a per-bot salt and never stored.
Everything above is a thin wrapper over two HTTP endpoints — see the Ingest API to integrate from any other framework.