.NET SDK — report usage and meter consumption
Oclavex distinguishes two kinds of usage. Reporting is telling the platform what happened (a feature was used, a session started) for analytics and utilization. Metering is drawing down a quota or credit balance, where the answer “is there room?” must be authoritative. The SDK exposes both off the session. Some reporting happens on its own: feature adoption is counted from the license checks your application already makes.
Feature adoption is counted for you
Section titled “Feature adoption is counted for you”Every license check your application already makes is a record that someone reached for that feature, so adoption needs no reporting calls of its own:
if (!license.FeatureValidation.IsValidFeature("reports.export")) return Forbid(); // counted as a refused check// ... the feature runs ... counted as a granted checkRefused checks are counted separately from granted ones, and that separation is what makes them worth having: a feature customers are repeatedly refused is one they would pay for.
Gating is counted, reading is not. IsValidFeature and ValidateUsageQuota decide whether
a user may do something, so they count. GetLicenseFeature and LicensedFeatures only read
the license, so a pricing table or feature matrix that renders every capability does not
inflate the usage of every feature on it. If your code gates by fetching a feature and
inspecting it, switch it to IsValidFeature(code) so the check is counted here.
Set Usage.AutoReportFeatureChecks to false to turn this off. Nothing else you report is
affected.
Report activity
Section titled “Report activity”session.UsageReporter records activity. Reports are buffered and flushed on the
UsageReportingIntervalSeconds interval you configure, so calls are cheap and don’t block
your request:
await session.UsageReporter.ReportStartFeatureUseAsync(feature);// ... feature runs ...await session.UsageReporter.ReportEndFeatureUsageAsync(feature);Use that pair when you want to know how long a feature was open and how activities nested. Which features are used at all is already counted from your license checks, so you do not need it for adoption.
Other reports on the same reporter cover session lifecycle
(ReportSessionStartedAsync / ReportSessionEndedAsync), a raw asset amount
(ReportAssetUsageAsync), application events (ReportAppEventAsync), and feedback
(ReportProductFeedbackAsync, ReportFeatureRatingAsync). The background reporter flushes
buffered usage on shutdown within ShutdownFlushTimeoutSeconds.
Transactions queue locally — on disk with FileTransactionStore, or the in-memory
default — and upload in the background, so reporting keeps working through network
drops. In a hosted app, register your own ITransactionStore (for example a
FileTransactionStore) before AddMonetizeItLicenseConsumer to make the buffer durable
across restarts. On the fluent-builder path,
use UseFileTransactionStore(path) or UseTransactionProcessorBuilder(...), and call
client.FlushAsync() to drain the queue on demand.
Meter a monitored asset
Section titled “Meter a monitored asset”When a metric has to enforce a limit — API calls, credits, seats-worth of a resource —
use session.AssetConsumption. TryConsumeAsync draws down the amount and returns the
resulting status; the server settles concurrent draw-down so two callers can’t both spend
the last unit:
var status = await session.AssetConsumption.TryConsumeAsync( license.LicenseValidation.CurrentSession, "api-calls.total", amount: 1);
if (status is null || status.QuotaUsagePolicy is TierUsagePolicy.Deny or TierUsagePolicy.SuspendUsage){ return Results.StatusCode(429); // limit reached — stop the action}The returned status carries the enforcement decision, not just a number.
QuotaUsagePolicy ranges from None/NotifyOnly/AllowWithOverage/AllowWithGrace
(proceed) through RateLimit (throttle) to Deny/SuspendUsage (hard stop) — so a plan
that permits billed overage and one that blocks outright are both expressible without
your code special-casing them. CurrentValue, Limit, UsagePercentage, and
PeriodResetAt describe where the meter stands and when it rolls over.
To show remaining allowance without consuming, use GetUsageStatusAsync, or
GetUsageWithBalanceAsync when you want the full picture including any prepaid credit
balance. Pass the session id from license.LicenseValidation.CurrentSession.
Before starting work that is expensive to throw away, ask first. TryPreAllocateAsync
answers the question TryConsumeAsync would answer — allowed or refused, and what it
costs — without changing anything: nothing is metered, nothing is charged, and nothing is
held. Do the work, then commit it:
var check = await session.AssetConsumption.TryPreAllocateAsync(sessionId, "video.seconds", amount: 6);
if (check?.QuotaUsagePolicy is TierUsagePolicy.Deny or TierUsagePolicy.SuspendUsage){ // check.Reason says whether it is the plan limit or the credits: NoCredit, // SpendingDisabled, BalanceExpired, BalanceSuspended — None means the quota itself. return Results.StatusCode(429);}
// ... render the six seconds ...
var status = await session.AssetConsumption.TryConsumeAsync( sessionId, "video.seconds", amount: 6, idempotentKey: renderId);Pass an idempotentKey on the commit so a retry after a dropped response returns the
original decision instead of metering the work twice.
Because nothing is reserved between the two calls, a concurrent commit can still take the capacity the projection saw — the commit is the decision that binds, and it can still refuse. Check its answer, not only the projection’s.
When the quota’s overage tier is funded by a credit balance, a successful commit says what
it cost: CreditsCharged and FundedUnits — the part of your amount that fell past the
included quota. Six seconds committed with one funded unit is “five seconds included, one
second from your credits”.
Reporting vs. metering — which to use
Section titled “Reporting vs. metering — which to use”- For adoption — which features are reached for, and which are refused — call nothing. Your license checks are already counted.
- Use
UsageReporterfor activity you want to see later: how long a feature was open, session counts, application events. It is fire-and-then-flush; a dropped report costs a data point, not correctness. - Use
AssetConsumption.TryConsumeAsyncwhen the number governs behavior — when exceeding it must stop the action. The server answers before the action proceeds and settles concurrent draw-down.
One overlap is worth knowing. ReportAssetUsageAsync names a monitored asset, so when that
asset carries quota tiers or a credit balance, the queued readings are priced and charged on
arrival exactly as a commit would be — consumption costs the same whether the network was
there or not. What an upload cannot do is be refused: the work has already happened. Reach for
TryConsumeAsync when you need the answer before it runs.
Feedback prompts
Section titled “Feedback prompts”GetFeatureRatingPromptAsync asks the platform which feature (if any) the current user
should be prompted to rate — targeted, not random. Render your own prompt when it returns
a target, then submit with ReportFeatureRatingAsync. It returns null when nothing is
targeted.