public void writeTelemetryData(JsonWriter json, TelemetryData telemetryData) {
    json.beginObject();
    json.prop("id", telemetryData.getServerId());
    json.prop(VERSION, telemetryData.getVersion());
    json.prop("messageSequenceNumber", telemetryData.getMessageSequenceNumber());
    json.prop("localTimestamp", toUtc(system2.now()));
    json.prop(NCD_ID, telemetryData.getNcdId());
    telemetryData.getEdition().ifPresent(e -> json.prop("edition", e.name().toLowerCase(Locale.ENGLISH)));
    json.prop("defaultQualityGate", telemetryData.getDefaultQualityGate());
    json.prop("sonarway_quality_gate_uuid", telemetryData.getSonarWayQualityGate());
    json.name("database");
    json.beginObject();
    json.prop("name", telemetryData.getDatabase().name());
    json.prop(VERSION, telemetryData.getDatabase().version());
    json.endObject();
    json.name("plugins");
    json.beginArray();
    telemetryData.getPlugins().forEach((plugin, version) -> {
      json.beginObject();
      json.prop("name", plugin);
      json.prop(VERSION, version);
      json.endObject();
    });
    json.endArray();

    if (!telemetryData.getCustomSecurityConfigs().isEmpty()) {
      json.name("customSecurityConfig");
      json.beginArray();
      json.values(telemetryData.getCustomSecurityConfigs());
      json.endArray();
    }

    telemetryData.hasUnanalyzedC().ifPresent(hasUnanalyzedC -> json.prop("hasUnanalyzedC", hasUnanalyzedC));
    telemetryData.hasUnanalyzedCpp().ifPresent(hasUnanalyzedCpp -> json.prop("hasUnanalyzedCpp", hasUnanalyzedCpp));

    if (telemetryData.getInstallationDate() != null) {
      json.prop("installationDate", toUtc(telemetryData.getInstallationDate()));
    }
    if (telemetryData.getInstallationVersion() != null) {
      json.prop("installationVersion", telemetryData.getInstallationVersion());
    }
    json.prop("container", telemetryData.isInContainer());

    writeUserData(json, telemetryData);
    writeProjectData(json, telemetryData);
    writeProjectStatsData(json, telemetryData);
    writeBranches(json, telemetryData);
    writeNewCodeDefinitions(json, telemetryData);
    writeQualityGates(json, telemetryData);
    writeQualityProfiles(json, telemetryData);
    writeManagedInstanceInformation(json, telemetryData.getManagedInstanceInformation());
    writeCloudUsage(json, telemetryData.getCloudUsage());
    extensions.forEach(e -> e.write(json));

    json.endObject();
  }
@Test
  void write_server_id_version_and_sequence() {
    TelemetryData data = telemetryBuilder().build();

    String json = writeTelemetryData(data);
    assertJson(json).isSimilarTo("""
      {
        "id": "%s",
        "version": "%s",
        "messageSequenceNumber": %s
      }
      """.formatted(data.getServerId(), data.getVersion(), data.getMessageSequenceNumber()));
  }

  @Test
  void does_not_write_edition_if_null() {
    TelemetryData data = telemetryBuilder().build();

    String json = writeTelemetryData(data);

    assertThat(json).doesNotContain("edition");
  }