Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add daily active users license model documentation #3658

Open
wants to merge 23 commits into
base: latest
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
6c5d789
feat: add DAU documentation
mcollovati Sep 4, 2024
cc05be7
feat: document DAUCustomizer interface (#3648)
mcollovati Sep 9, 2024
622cb43
feat: Add DAU general description (#3653)
mshabarov Sep 12, 2024
ca0f85d
Merge branch 'latest' into feat/dau
mshabarov Sep 12, 2024
e647583
add since label
mshabarov Sep 13, 2024
7c1f525
Merge branch 'latest' into feat/dau
mshabarov Sep 13, 2024
59dcbad
correct the runtime licenses note
mshabarov Sep 13, 2024
1c7bbde
Merge branch 'latest' into feat/dau
mshabarov Sep 13, 2024
4ed0b45
Update articles/flow/configuration/licenses/index.adoc
mshabarov Sep 13, 2024
3ca021f
Merge branch 'latest' into feat/dau
mshabarov Sep 13, 2024
6b9e4f0
fix review comments
mshabarov Sep 18, 2024
fc1784c
Merge remote-tracking branch 'refs/remotes/origin/latest' into feat/dau
mshabarov Sep 18, 2024
30e8fab
fix lint comments
mshabarov Sep 18, 2024
58d9f7b
add a better explanation for active users
mshabarov Sep 19, 2024
5469992
Merge branch 'latest' into feat/dau
mshabarov Sep 19, 2024
881bf68
add a note about sub key in runtime
mshabarov Sep 23, 2024
2c60250
added a note about dev mode
mshabarov Sep 23, 2024
5cdc60d
Merge branch 'latest' into feat/dau
mshabarov Sep 23, 2024
7f8172f
Merge branch 'latest' into feat/dau
mshabarov Sep 24, 2024
c63a34e
add license-checker
mshabarov Sep 26, 2024
57f99c1
Merge branch 'latest' into feat/dau
mshabarov Sep 26, 2024
032fd2b
runtime only
mshabarov Sep 26, 2024
68f8fc5
Merge remote-tracking branch 'origin/feat/dau' into feat/dau
mshabarov Sep 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/styles/Vaadin/Abbr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ exceptions:
- CSS
- CSV
- CVSS
- DAU
- DNS
- DOM
- DPI
Expand Down
259 changes: 259 additions & 0 deletions articles/flow/configuration/licenses/daily-active-users.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,259 @@
---
title: Daily Active Users
layout: tabbed-page
description: Short description
order: 10
---

[role="since:com.vaadin:vaadin@v24.5"]
= Daily Active Users

Daily Active User (DAU) represents a *human end-user* using one application, that customer builds with Vaadin, during a 24 hours period.
Vaadin limits the DAU number in some subscription plans and doesn't for other plans, see https://vaadin.com/pricing[Pricing] page for more information.
DAU license model is only supported by Vaadin versions starting from 24.5.

This article describes the DAU license model and how to customise it for project's specifics.

== How Are End-Users Counted

DAU counting is made per Vaadin application or a group of applications sharing the same subscription.
End-users do not need to log in the application to be counted as DAU, *anonymous* users are counted as well.
Vaadin uses a persistent technical cookie with expiration time *24 hours* as a main method for end-users counting.
This ensures that the same user is counted only once between his sessions during the day.

End-users, who use the application with two or more different browsers or devices, are counted twice or more by default.
Vaadin provides an API to configure application *user identity* (e.g. use an email of the logged-in user), this ensures the same logged-in end-user to be counted as a single user, no matter from what browser or device an application is used.

See <<{articles}/flow/configuration/licenses/daily-active-users#customizing-user-identity-supplier, User Identity Supplier>> for more information and examples.

An end-user needs to interact with the application to be counted - merely opening the application in a browser and closing it immediately does not count as DAU. The threshold of activity for DAU is *1 minute*.

== Where And How The DAU Information Is Stored

Check warning on line 31 in articles/flow/configuration/licenses/daily-active-users.adoc

View workflow job for this annotation

GitHub Actions / lint

[vale] reported by reviewdog 🐶 [Vaadin.HeadingCase] 'Where And How The DAU Information Is Stored' should be in title case. Raw Output: {"message": "[Vaadin.HeadingCase] 'Where And How The DAU Information Is Stored' should be in title case.", "location": {"path": "articles/flow/configuration/licenses/daily-active-users.adoc", "range": {"start": {"line": 31, "column": 4}}}, "severity": "WARNING"}

Vaadin doesn't collect or store any end-users personal data, but only a number of end-users.
If an application provides a user identity function, this identity is hashed immediately and published to Vaadin’s license server as a hash value that cannot tell anything about the end-users.
Vaadin license server only stores the hashes generated this way and counts unique number of hashes per day, i.e. DAU number.
Vaadin application stores these hashes in memory and doesn't persist it anywhere, rather than publishing to Vaadin’s license server once a day.

== What Happens When DAU Exceeds The Limit

Vaadin follows the soft DAU limit rules.
DAU limit is enforced, but the enforcement is done in a way that minimizes the risk of disruption to customer’s production applications.
Vaadin allows a limit to be exceeded temporarily - every time limit is exceeded, a *30-day grace period* starts.
Customer’s administrators are alerted by email, when DAU exceeds the limit.
The email notification informs the customer that the grace period has started and provides guidelines on why it occurred and how to resolve the issue.

After half of the grace period has passed (*15 days*), if the limit is still exceeded for at least past *5 consecutive days*, then:

- Customer is alerted that limit enforcement may start soon
- Vaadin team is alerted to allow them to contact Customer for solving the issue by offering an increased DAU limit.

After the grace period has ended, if the limit hasn't been increased:

- if DAU limit is reached on *3 consecutive days*, the DAU limit is enforced and application responds with `Service Unavailable` error - not allowing additional end-users that day, but remaining fully functional for users that were counted before the limit was reached;
- Every time limit is exceeded, Customer is alerted and explained that continuing to ignore the issue results in application’s usage being restricted.

After the limit has been updated, the grace period and enforcement are deactivated.
After this, a new grace period is started in case of another DAU limit overrun.

Emails for notifications can be added on the "Subscriptions" page of your account at https://vaadin.com/myaccount/subscriptions[vaadin.com] web-site, see <<{articles}/flow/configuration/licenses/daily-active-users#what-is-available-in-my-account-page, What information is available on personal account page>>.

== DAU Is Only Calculated For Production Environments

The DAU license model only counts the end-users, when the Vaadin application runs in production mode.

Testing environments, such as staging or performance tests environments, may use production mode as well.
Vaadin provides a way to avoid DAU counting for these environments:

- set a unique string name to `vaadin.applicationIdentifier` property for each Vaadin application that runs on test environment;
- add these application names on the "Subscriptions" page at https://vaadin.com/myaccount/subscriptions[vaadin.com] web-site.

Vaadin uses a hash string by default (if this property in not defined) as application name that is based on project's unique parameters (`groupId` and `artifactId` for Maven, `projectName` for Gradle).
To distinguish default and custom application names, it adds also the `app-` prefix.
Thus, it is recommended to not use `app-` prefix for your custom application names.

See <<{articles}/flow/configuration/licenses/daily-active-users#what-is-available-in-my-account-page, What information is available on personal account page>> for more information.

== How To Build And Run Applications

Check warning on line 77 in articles/flow/configuration/licenses/daily-active-users.adoc

View workflow job for this annotation

GitHub Actions / lint

[vale] reported by reviewdog 🐶 [Vaadin.HeadingCase] 'How To Build And Run Applications' should be in title case. Raw Output: {"message": "[Vaadin.HeadingCase] 'How To Build And Run Applications' should be in title case.", "location": {"path": "articles/flow/configuration/licenses/daily-active-users.adoc", "range": {"start": {"line": 77, "column": 4}}}, "severity": "WARNING"}
paulroemer marked this conversation as resolved.
Show resolved Hide resolved

To build Vaadin applications for production under a subscription plan with DAU license model, you need to use the server license key, as described in <<{articles}/flow/configuration/licenses#server-license-key, License Validation on a CI/CD or Build Server>> article.
paulroemer marked this conversation as resolved.
Show resolved Hide resolved
Then you need to obtain the subscription key from the "Licenses" -> "DAU" page of your personal account in https://vaadin.com/myaccount/licenses[vaadin.com] web-site:
paulroemer marked this conversation as resolved.
Show resolved Hide resolved

image::images/subscription-key.png[]

Figure 1 - Subscription Key page

Finally, you *must* configure this subscription key for each application that runs within the same subscription.
It can be set in the following ways:

- as a `vaadin.subscriptionKey` system property;
- as a `VAADIN_SUBSCRIPTION_KEY` environment variable;
- in a file with name `subscriptionKey` in Vaadin home directory - `%userprofile%\.vaadin\` for Windows, `~/.vaadin/` for macOS/Linux;
- use a server license key (or offline key) file that was used to build the application.

If Vaadin does not find the subscription key in any of the sources above, it fails fast the application’s startup with the corresponding message.

If you use subscription plan with DAU license model and want to build your application for production by not using the server license key (e.g. if you want to build from a local machine with internet access), you *must* set the subscription key.
See the instructions above where to find it and how to set this key.

[[what-is-available-in-my-account-page]]
Legioth marked this conversation as resolved.
Show resolved Hide resolved
== What Information Is Available On Personal Account Page

Below you can see an example of a "Subscription" page in https://vaadin.com/myaccount/subscriptions[vaadin.com] personal account:

*Customer account number and Subscriptions*
Select an account number from the select drop-down and subscriptions of this account that you’d like to browse.

*DAU chart*
You can browse visually the DAU distribution over the time, as well as the current DAU limit and maximum DAU number for the past 28 days.
paulroemer marked this conversation as resolved.
Show resolved Hide resolved
Use time interval selectors for filtering by date.

*Subscribe to alerts*
Add a new email address to which Vaadin sends DAU-related alerts by entering it into the text field.
Use "X" to remove an email address and "Subscribe to alerts" button to save it.

*Add test application names*
Specify identifiers for your application(s) running on testing environments by entering them into a text field.

Check warning on line 116 in articles/flow/configuration/licenses/daily-active-users.adoc

View workflow job for this annotation

GitHub Actions / lint

[vale] reported by reviewdog 🐶 [Vaadin.OptionalPlurals] Avoid using plurals in parentheses such as in 'application(s)'. Raw Output: {"message": "[Vaadin.OptionalPlurals] Avoid using plurals in parentheses such as in 'application(s)'.", "location": {"path": "articles/flow/configuration/licenses/daily-active-users.adoc", "range": {"start": {"line": 116, "column": 30}}}, "severity": "WARNING"}
Use "X" to remove an application name and "Add application name" button to save it.

image::images/subscriptions-view.png[]

Figure 2 - Subscriptions page

== Customizations

You can customize the Daily Active Users feature in your Vaadin application using the [interfacename]`DAUCustomizer` interface. This customization is crucial for tracking unique users across multiple devices and tailoring the enforcement notification messages displayed to them.

The [interfacename]`DAUCustomizer` interface allows you to implement two key customizations:

* User Identity Supplier: This allows the system to identify and count a user as a single entity, even when they access the application from multiple devices.
* Enforcement Notification Messages: This allows you to provide custom messages and, optionally, a landing page for the enforcement notification popup that users might encounter.

=== Implementing DAU Customization

To apply the available customizations, you need to create a class that implements the [interfacename]`DAUCustomizer` interface.
Only one implementation of this interface is permitted per application, and it is discovered through the Vaadin [interfacename]`Instantiator`.
Making the [interfacename]`DAUCustomizer` implementation available to your application depends on the architecture you are using.
For a plain Java servlet application, you need to register the implementation using the Java ServiceLoader mechanism. To do this, create a [filename]`META-INF/services/com.vaadin.flow.server.dau.DAUCustomizer` file that lists the fully qualified name of your custom class.
For Spring, CDI, and Quarkus applications, it is sufficient to expose your [interfacename]`DAUCustomizer` implementation as a [annotationname]`@Singleton` or [annotationname]`@ApplicationScoped` bean, which is picked up automatically by the framework.
Quarkus developers should also add the [annotationname]`@Unremovable` annotation to the implementation class, to prevent Quarkus to consider the bean unused and therefore removed at build time.


*Example*: Registering DAU customization for Spring, CDI, and Quarkus

[.example]
--
[source,java]
.`Spring`
----
package com.yourpackage;

@Component
public class MyDAUCustomizer implements DAUCustomizer {
// Implementation omitted for brevity
}
----

[source,java]
.`CDI`
----
package com.yourpackage;

@Singleton
public class MyDAUCustomizer implements DAUCustomizer {
// Implementation omitted for brevity
}
----

[source,java]
.`Quarkus`
----
package com.yourpackage;

@Singleton
@Unremovable
public class MyDAUCustomizer implements DAUCustomizer {
// Implementation omitted for brevity
}
----

--

*Example*: Registering DAU customization for Plain Java Servlet Application

[source,java]
----
package com.yourpackage;

public class MyDAUCustomizer implements DAUCustomizer {
// Implementation omitted for brevity
}
----
[source,text]
.`META-INF/services/com.vaadin.flow.server.dau.DAUCustomizer`
----
com.yourpackage.MyDAUCustomizer
----

[[customizing-user-identity-supplier]]
=== Customizing User Identity Supplier

The user identity supplier is a function that defines how the system identifies a unique user. By default, this feature is not enabled. However, you can provide a custom implementation to count a user only once, regardless of how many different devices or browser applications on a single device they use to access your application.
The function must always return the same value for a given user of the application, or an empty [classname]`Optional` if it is not possible to determine the user identity for the current request.

*Example*: Customize DAU User Identity Supplier.

[source,java]
----
@Singleton
public class MyDAUCustomizer implements DAUCustomizer {

@Override
public UserIdentitySupplier getUserIdentitySupplier() {
return userIdentityContext -> Optional.ofNullable(
// In this example a session attribute is supposed to be saved
// upon authentication and then used to provide the user identity
(String) userIdentityContext.session().getAttribute("userId")
);
}
}
----

=== Customizing Enforcement Notification Messages

The enforcement notification messages are used to notify users about application usage restrictions caused by exceeding the DAU limit.
An enforcement message object has four properties: a short caption, a message, an optional detailed text such as technical details or further explanation, and a URL to where to redirect after displaying the notification to the user. If the URL is not specified, the current page is reloaded.

The [methodname]`getEnforcementNotificationMessages()` method receives a [classname]`SystemMessagesInfo` parameter to allows access to the UI locale, so that messages can be translated in the current user language.

The default values of the properties are shown below:

* `caption`: Service Unavailable
* `message`: Please notify the administrator. Take note of any unsaved data, and click here or press ESC to continue.

Check warning on line 232 in articles/flow/configuration/licenses/daily-active-users.adoc

View workflow job for this annotation

GitHub Actions / lint

[vale] reported by reviewdog 🐶 [Vaadin.Abbr] 'ESC' has no definition. Raw Output: {"message": "[Vaadin.Abbr] 'ESC' has no definition.", "location": {"path": "articles/flow/configuration/licenses/daily-active-users.adoc", "range": {"start": {"line": 232, "column": 102}}}, "severity": "WARNING"}
* `details`: null
* `url`: null

*Example*: Customize enforcemente notification messages.

[source,java]
----
public class MyDAUCustomizer implements DAUCustomizer {

@Override
public EnforcementNotificationMessages getEnforcementNotificationMessages(SystemMessagesInfo systemMessagesInfo) {
return new EnforcementNotificationMessages(
"DAU Limit Reached", // caption
"The allowed number of users has been exceeded.", // message
"Please contact customer service.", // details
"/device-management" // url
);
}
}
----

[NOTE]
====
The URL parameter should reference either a static page or a dynamic page that is not built with Vaadin.
A Vaadin view would not be shown because of DAU restriction.
====

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, outdated. Maybe we can update it once more when the stuff is released on (likely) Monday.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, let's update it next week.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,13 @@
You need a commercial license only if you use one of the commercial components (such as, Vaadin Charts) or tools (such as, Vaadin TestBench).
If your project includes such components or tools, a commercial license is needed for development and to build the production application.

In general, you don't need a license after deploying an application to production.
The only exception is Collaboration Kit, which requires a license for production use, and it's priced per end user.
See <<{articles}/tools/collaboration/developing-with-ce#,Collaboration Kit documentation>> for details.
Vaadin requires production runtime license only for the following cases:

- Premium subscription that counts <<{articles}/flow/configuration/licenses/daily-active-users#, Daily Active Users>>;
- Collaboration Kit for Vaadin versions before 24.5 is priced per end user, see <<{articles}/tools/collaboration/developing-with-ce#,Collaboration Kit documentation>> for details.
Collaboration Kit is free from Vaadin 24.5 onwards.

Check warning on line 21 in articles/flow/configuration/licenses/index.adoc

View workflow job for this annotation

GitHub Actions / lint

[vale] reported by reviewdog 🐶 [Vaadin.Versions] Don't refer to a specific Vaadin version. Raw Output: {"message": "[Vaadin.Versions] Don't refer to a specific Vaadin version.", "location": {"path": "articles/flow/configuration/licenses/index.adoc", "range": {"start": {"line": 21, "column": 32}}}, "severity": "WARNING"}

Check failure on line 21 in articles/flow/configuration/licenses/index.adoc

View workflow job for this annotation

GitHub Actions / lint

[vale] reported by reviewdog 🐶 [Vale.Spelling] Did you really mean 'onwards'? Raw Output: {"message": "[Vale.Spelling] Did you really mean 'onwards'?", "location": {"path": "articles/flow/configuration/licenses/index.adoc", "range": {"start": {"line": 21, "column": 44}}}, "severity": "ERROR"}

For other use cases, you don't need a license after deploying an application to production.

[[online-license-key]]
== License Validation on a Local Machine
Expand Down
Loading