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

Build time analytics #33555

Merged
merged 1 commit into from Jun 20, 2023
Merged

Build time analytics #33555

merged 1 commit into from Jun 20, 2023

Conversation

brunobat
Copy link
Contributor

@brunobat brunobat commented May 23, 2023

This PR enables an opt-in feature to allow gathering of build time analytics to get info/insights about how Quarkus is being used during development/builds (only build time NOT runtime).

TO TEST THIS

build the PR first using mvn -Dquickly, then create a project using latest snapshot and with a non quarkus grouped, for example: quarkus create app -P io.quarkus:quarkus-bom:999-SNAPSHOT something.random:myapp.

Please try and use your own groupid/name so we get more diverse reports.

Then run quarkus dev in the project and say y to report data.
Running in dev mode and mvn quarkus:dev, and gradle quarkusDev should report then submit data on each run.

Check target/build-analytics-event.json for content of what was sent.

Implementation

It is implemented using Segment which is used by other Red Hat projects to gather anonymous usage data.

Intent is that on first quarkus dev mode user will be asked if they wish to share anonymously build time info to Quarkus team.

If answer is no, marker file is created in ~/.redhat and no recording/analytics is made before that markerfile is removed.

If answer is yes, markerfile is made + ~/.redhat/anonymousId is created which is just to be able to group data per installation without any identifiable info in them. From that point on when ever quarkus build plugin runs it will send a json packet with info. This is sent async and non-blocking. Meaning build won't block because of this.

  • One-way SHA-265 hashes representing the application:
    • groupId+artifactId
    • artifactId+version
  • Name/Version info for Java, GraalVM, Operating System, Build system
  • Whether or not Kubernetes is used on the build
  • Known Extensions enabled
    i.e. group-ids "io.quarkus", "io.quarkiverse", “org.apache.camel.quarkus” or listed in Quarkus platform.
  • The IP is set to 0.0.0.0 on purpose to disable any possible inference, if not present.

An example of data collected is shown below - all non-identifiable info.

{
  "context": {
    "app": {
      "name": "ZzOlt3q0VgNK0oyUd6NDAhPqJjTSxNOAnqHb5dHfS7M=",
      "version": "FUDdh16tTKtuJkcoY2Wp57IKKwxZ/Hx42tTvi3Izpmc="
    },
    "build": {
      "gradle_version": "N/A",
      "maven_version": "3.8.7"
    },
    "ci": {
      "name": "unknown"
    },
    "graalvm": {
      "java_version": "N/A",
      "vendor": "N/A",
      "version": "N/A"
    },
    "ip": "0.0.0.0",
    "java": {
      "vendor": "Eclipse Adoptium",
      "version": "17.0.4.1"
    },
    "kubernetes": {
      "detected": "false"
    },
    "location": {
      "country": "PT"
    },
    "os": {
      "name": "Mac OS X",
      "os_arch": "aarch64",
      "version": "13.3.1"
    },
    "quarkus": {
      "version": "999-SNAPSHOT"
    },
    "timezone": "Europe/Lisbon"
  },
  "event": "PROD_BUILD",
  "integrations": {},
  "messageId": "api-2QCEFlcxqJeuKjX4Uf0m1aWoKED",
  "originalTimestamp": "2023-05-23T13:37:39.913591Z",
  "properties": {
    "app_extensions": [
      {
        "artifact_id": "quarkus-resteasy-jackson",
        "group_id": "io.quarkus",
        "version": "999-SNAPSHOT"
      },
      {
        "artifact_id": "quarkus-smallrye-openapi",
        "group_id": "io.quarkus",
        "version": "999-SNAPSHOT"
      },
      {
        "artifact_id": "quarkus-hibernate-orm",
        "group_id": "io.quarkus",
        "version": "999-SNAPSHOT"
      },
      {
        "artifact_id": "quarkus-opentelemetry",
        "group_id": "io.quarkus",
        "version": "999-SNAPSHOT"
      },
      {
        "artifact_id": "quarkus-jdbc-postgresql",
        "group_id": "io.quarkus",
        "version": "999-SNAPSHOT"
      },
      {
        "artifact_id": "quarkus-arc",
        "group_id": "io.quarkus",
        "version": "999-SNAPSHOT"
      }
    ]
  },
  "receivedAt": "2023-05-23T13:37:40.856Z",
  "timestamp": "2023-05-23T13:37:39.913Z",
  "type": "track",
  "userId": "58991333-5f25-4401-ae5b-e3eb09ceb4de"
}

@quarkus-bot quarkus-bot bot added area/core area/dependencies Pull requests that update a dependency file area/devtools Issues/PR related to maven, gradle, platform and cli tooling/plugins area/documentation area/gradle Gradle area/maven area/platform Issues related to definition and interaction with Quarkus Platform labels May 23, 2023
@quarkus-bot quarkus-bot bot added this to To do in Quarkus Documentation May 23, 2023
@quarkus-bot

This comment has been minimized.

@github-actions
Copy link

github-actions bot commented May 24, 2023

🙈 The PR is closed and the preview is expired.

@brunobat brunobat marked this pull request as ready for review May 25, 2023 13:19
@quarkus-bot

This comment has been minimized.

@brunobat
Copy link
Contributor Author

@snazy would you be able to double check my changes to the gradle plugin?

@quarkus-bot

This comment has been minimized.

@snazy
Copy link
Contributor

snazy commented May 26, 2023

@snazy would you be able to double check my changes to the gradle plugin?

Sure thing.

Copy link
Contributor

@snazy snazy left a comment

Choose a reason for hiding this comment

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

Took a look, mostly from the Gradle plugin. I recommend to call the AnalyticsService directly from the BuildWorker, which should have everything that's needed. Doing so would also remove the need for the added tasks and the new extension. Having some Gradle IT(s) would be nice.

@brunobat
Copy link
Contributor Author

Thanks @snazy. The review was much appreciated.

Copy link
Contributor

@maxandersen maxandersen left a comment

Choose a reason for hiding this comment

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

logs when they show up in mvn/gradle output does not tell what is making the log/error - ie. quarkus usage analytics.

Quarkus Documentation automation moved this from To do to Review pending Jun 3, 2023
@rsvoboda rsvoboda added the triage/qe? Issue could use a quality focused review to further harden it label Jun 5, 2023
@quarkus-bot
Copy link

quarkus-bot bot commented Jun 5, 2023

/cc @mjurc (qe)

@brunobat
Copy link
Contributor Author

Updated the prompt and it's text and added a section to the documentation about How to disable analytics @rolfedh.

@brunobat
Copy link
Contributor Author

rsvobodawould you also be able to test in gradle and also behind a proxy?

@quarkus-bot

This comment has been minimized.

Copy link
Contributor

@snazy snazy left a comment

Choose a reason for hiding this comment

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

Looked through the Gradle changes and some related pieces of the code. The Gradle changes mostly LGTM, a couple mostly minor comments, except that there's no unit/integration test for Gradle.

One concern about the use of the fork-join-common-pool in ConfigService.

Also added some suggestions (maybe not doable at this stage?) about the contents of the analytics data.

.pair(PROP_OS_ARCH, getProperty("os.arch", "N/A"))
.build()
.mapPair(PROP_CI)
.pair(PROP_CI_NAME, getBuildSystemName())
Copy link
Contributor

Choose a reason for hiding this comment

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

Does it make sense to have a property that tells whether the CI environment is set to indicate that it's running in CI (in case getBuildSystemName returns unknown for some exotic CI)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There are a limited number of CIs we can detect. It returns unknown when he couldn't detect any CI.

.pair(PROP_VERSION, getProperty("java.version", "N/A"))
.build()
.mapPair(PROP_GRAALVM)
.pair(PROP_VENDOR, ofNullable(buildInfo.get(GRAALVM_VERSION_DISTRIBUTION)).orElse("N/A"))
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: wonder why not just Map.getOrDefault?

Copy link
Contributor Author

@brunobat brunobat Jun 19, 2023

Choose a reason for hiding this comment

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

It would be less verbose but I'll not change that now to reduce the amount of changes.

@snazy
Copy link
Contributor

snazy commented Jun 19, 2023

Forgot to mention: the Gradle changes look MUCH simpler now - thanks for that!

@brunobat
Copy link
Contributor Author

Forgot to mention: the Gradle changes look MUCH simpler now - thanks for that!

Thanks for your guidance @snazy!
Still working on an IT test... The setup is tricky.

@brunobat
Copy link
Contributor Author

Updated a field name on the remote payload

@quarkus-bot

This comment has been minimized.

@quarkus-bot
Copy link

quarkus-bot bot commented Jun 20, 2023

Failing Jobs - Building 9061f37

Status Name Step Failures Logs Raw logs
✔️ JVM Tests - JDK 11
✔️ JVM Tests - JDK 17
JVM Tests - JDK 17 Windows Build Failures Logs Raw logs
✔️ JVM Tests - JDK 19
Native Tests - Windows - RESTEasy Jackson Setup GraalVM ⚠️ Check → Logs Raw logs

Full information is available in the Build summary check run.

Failures

⚙️ JVM Tests - JDK 17 Windows #

- Failing: integration-tests/smallrye-context-propagation 

📦 integration-tests/smallrye-context-propagation

io.quarkus.context.test.SimpleContextPropagationTest.testArcTCContextPropagationDisabled line 92 - More details - Source on GitHub

org.opentest4j.AssertionFailedError: expected: <2> but was: <3>
	at org.junit.jupiter.api.AssertionFailureBuilder.build(AssertionFailureBuilder.java:151)
	at org.junit.jupiter.api.AssertionFailureBuilder.buildAndThrow(AssertionFailureBuilder.java:132)

@brunobat
Copy link
Contributor Author

@paulrobinson @maxandersen @rolfedh @rsvoboda @snazy @jsmrcka Do you have any concerns with the PR? If not, can you please approve?

@rsvoboda
Copy link
Member

would you also be able to test in gradle and also behind a proxy?

Sorry, was on pto. I don't capacity to look into this today. Not aware of any proxy I could use right now.

Copy link
Member

@gsmet gsmet left a comment

Choose a reason for hiding this comment

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

I added a few comments and questions but I see nothing blocking.

Let's make sure we fix these issues (when they are actually issues) before the Final though.

Let me test it locally again and I'll give my approval.

Comment on lines +48 to +49
@Component
BuildAnalyticsProvider analyticsProvider;
Copy link
Member

Choose a reason for hiding this comment

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

The component is automatically closed? I'm surprised it is given it doesn't implement any marker interface.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Closing is performed in the BootstrapSessionListener

docs/src/main/asciidoc/build-analytics.adoc Show resolved Hide resolved
* Build system details, such as Maven, Gradle, and so on.
* If a CI system was detected
* Country and timezone
* Extensions enabled. Only extensions whose `groupIds` start with `io.quarkus`, `io.quarkiverse` or are included in the quarkus platform are collected.
Copy link
Member

Choose a reason for hiding this comment

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

or?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

will rephrase to:
Only extensions whose groupIds start with io.quarkus, io.quarkiverse and others included in the quarkus platform are collected.

docs/src/main/asciidoc/build-analytics.adoc Show resolved Hide resolved
} else {
try {
CompletableFuture<String> userInputFuture = CompletableFuture
.supplyAsync(() -> analyticsEnabledSupplier.apply(ACCEPTANCE_PROMPT));
Copy link
Member

Choose a reason for hiding this comment

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

@geoand @cescoffier could you have a look at this?

Comment on lines +9 to +17
"io.quarkus",
"io.quarkiverse",
"org.apache.camel.quarkus",
"io.debezium",
"org.drools",
"org.optaplanner",
"org.amqphub.quarkus",
"com.hazelcast",
"com.datastax.oss.quarkus");
Copy link
Member

Choose a reason for hiding this comment

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

OK, so you need to clarify the list in the documentation because we are not doing what we documented.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

These are group Ids of extensions bundled on the platform.

@brunobat
Copy link
Contributor Author

brunobat commented Jun 20, 2023

On a follow up PR:

  • The config files namespace will change to io.quarkus.analytics.*
  • Support environment properties
  • localconfig should have disabled:true
  • Improve maven logging

@rsvoboda
Copy link
Member

I don't capacity to look into this today.

I managed to shift some stuff to Wed and Thu so I have a bit of time to look into this.

Windows
There are no dev mode logs once y is answered to sharing build time analytics

See bottom left green icon that indicates the app is running, but there are no logs from the app boot
Capture

Proxy
We do not really have a proper production proxy setup in RH that would simulate restrictions some companies introduce on their employees.

I tried company internal squid instance and configured it in macOS network settings for http and https. No warnings in the application logs, even if I used bad port number.

I checked the code and it uses

    private HttpClient createHttpClient() {
        return HttpClient.newBuilder()
                .followRedirects(HttpClient.Redirect.ALWAYS)
                .connectTimeout(Duration.ofMillis(timeoutMs))
                .build();
    }

I don't think the client is checking or setting anything for proxy
To use proxy there is this construct for HttpClient

    HttpClient.newBuilder()
        .proxy(ProxySelector.of(new InetSocketAddress(...)))

@brunobat
Copy link
Contributor Author

@rsvoboda Thanks very much.

Will debug and fix the windows issue in a new PR.

In relation to the proxy. My main concern was if it would hang the build or blow up in some unforeseen way. Proxy handling should be a concern for later.

@rsvoboda
Copy link
Member

I tried the builds with disconnected network, nothing was delayed or hanging.

Copy link
Member

@gsmet gsmet left a comment

Choose a reason for hiding this comment

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

Let's merge and iterate from there.

@gsmet gsmet dismissed maxandersen’s stale review June 20, 2023 16:00

We decided to merge it.

Quarkus Documentation automation moved this from Review pending to Reviewer approved Jun 20, 2023
@gsmet gsmet merged commit df7445d into quarkusio:main Jun 20, 2023
47 of 49 checks passed
Quarkus Documentation automation moved this from Reviewer approved to Done Jun 20, 2023
@quarkus-bot quarkus-bot bot added this to the 3.2 - main milestone Jun 20, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/core area/dependencies Pull requests that update a dependency file area/devtools Issues/PR related to maven, gradle, platform and cli tooling/plugins area/documentation area/gradle Gradle area/maven area/platform Issues related to definition and interaction with Quarkus Platform area/testing triage/qe? Issue could use a quality focused review to further harden it
Development

Successfully merging this pull request may close these issues.

None yet

8 participants