Skip to content

Commit

Permalink
Refactor Tracks events props to util functions (#5966)
Browse files Browse the repository at this point in the history
- Refactor Tracks events props to util functions for easy use.
- Add following properties in each track event

```php
[
	'hosting_provider' => get_hosting_provider(),
	'is_vip_user'      => false,
	'is_multisite'     => is_multisite(),
	'wp_version'       => get_bloginfo( 'version' ),
]
```
  • Loading branch information
mehmoodak authored Nov 15, 2024
1 parent 61cb023 commit 05a72c5
Show file tree
Hide file tree
Showing 7 changed files with 236 additions and 53 deletions.
1 change: 1 addition & 0 deletions 000-vip-init.php
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@
__DIR__ . '/telemetry/tracks/class-tracks-event-dto.php',
__DIR__ . '/telemetry/tracks/class-tracks-event.php',
__DIR__ . '/telemetry/tracks/class-tracks-client.php',
__DIR__ . '/telemetry/tracks/tracks-utils.php',
];

// If there is a missing file, the loop will break and the telemetry files will not be loaded at all
Expand Down
4 changes: 0 additions & 4 deletions telemetry/tracks/class-tracks-event-dto.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,6 @@
namespace Automattic\VIP\Telemetry\Tracks;

use AllowDynamicProperties;
use stdClass;
use WP_Error;
use Automattic\VIP\Support_User\User as Support_User;
use function Automattic\VIP\Logstash\log2logstash;

/**
* Class that holds necessary properties of Tracks events.
Expand Down
62 changes: 14 additions & 48 deletions telemetry/tracks/class-tracks-event.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@

use Automattic\VIP\Telemetry\Telemetry_Event;
use WP_Error;
use Automattic\VIP\Support_User\User as Support_User;
use function Automattic\VIP\Logstash\log2logstash;

/**
Expand Down Expand Up @@ -153,24 +152,19 @@ protected function process_properties(
unset( $event->_via_ip );
}

// Set VIP environment if it exists.
if ( defined( 'VIP_GO_APP_ENVIRONMENT' ) ) {
$app_environment = constant( 'VIP_GO_APP_ENVIRONMENT' );
if ( is_string( $app_environment ) && '' !== $app_environment ) {
$event->vipgo_env = $app_environment;
}
$base_props = get_base_properties_of_track_event();

if ( isset( $base_props['vipgo_env'] ) ) {
$event->vipgo_env = $base_props['vipgo_env'];
}

// Set VIP organization if it exists.
if ( defined( 'VIP_ORG_ID' ) ) {
$org_id = constant( 'VIP_ORG_ID' );
if ( is_integer( $org_id ) && $org_id > 0 ) {
$event->vipgo_org = $org_id;
}
if ( isset( $base_props['vipgo_org'] ) ) {
$event->vipgo_org = $base_props['vipgo_org'];
}

// Check if the user is a VIP user.
$event->is_vip_user = Support_User::user_has_vip_support_role( get_current_user_id() );
if ( isset( $base_props['is_vip_user'] ) ) {
$event->is_vip_user = $base_props['is_vip_user'];
}

return $event;
}
Expand All @@ -183,44 +177,16 @@ protected function process_properties(
* @return Tracks_Event_DTO The new event object including identity information.
*/
protected static function set_user_properties( Tracks_Event_DTO $event ): Tracks_Event_DTO {
$wp_user = wp_get_current_user();

// Only track logged-in users.
if ( 0 === $wp_user->ID ) {
return $event;
}
$base_props = get_base_properties_of_track_user();

// Set anonymized event user ID; it should be consistent across environments.
// VIP_TELEMETRY_SALT is a private constant shared across the platform.
if ( defined( 'VIP_TELEMETRY_SALT' ) ) {
$salt = constant( 'VIP_TELEMETRY_SALT' );
$tracks_user_id = hash_hmac( 'sha256', $wp_user->user_email, $salt );

$event->_ui = $tracks_user_id;
$event->_ut = 'vip:user_email';

return $event;
if ( isset( $base_props['_ui'] ) ) {
$event->_ui = $base_props['_ui'];
}

// Users in the VIP environment.
if ( defined( 'VIP_GO_APP_ID' ) ) {
$app_id = constant( 'VIP_GO_APP_ID' );
if ( is_integer( $app_id ) && $app_id > 0 ) {
$event->_ui = sprintf( '%s_%s', $app_id, $wp_user->ID );
$event->_ut = 'vip_go_app_wp_user';

return $event;
}
if ( isset( $base_props['_ut'] ) ) {
$event->_ut = $base_props['_ut'];
}

// All other environments.
$event->_ui = wp_hash( sprintf( '%s|%s', get_option( 'home' ), $wp_user->ID ) );

/**
* @see \Automattic\VIP\Parsely\Telemetry\Tracks_Event::annotate_with_id_and_type()
*/
$event->_ut = 'anon'; // Same as the default value in the original code.

return $event;
}

Expand Down
128 changes: 128 additions & 0 deletions telemetry/tracks/tracks-utils.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
<?php
/**
* Telemetry: Tracks Utils
*
* @package Automattic\VIP\Telemetry\Tracks
*/

declare(strict_types=1);

namespace Automattic\VIP\Telemetry\Tracks;

use Automattic\VIP\Support_User\User as Support_User;

/**
* Returns the base properties for a track event.
*
* @return array<string, mixed> The base properties.
*/
function get_base_properties_of_track_event(): array {
$props = [
'hosting_provider' => get_hosting_provider(),
'is_vip_user' => Support_User::user_has_vip_support_role( get_current_user_id() ),
'is_multisite' => is_multisite(),
'wp_version' => get_bloginfo( 'version' ),
];

// Set VIP environment if it exists.
if ( defined( 'VIP_GO_APP_ENVIRONMENT' ) ) {
$app_environment = constant( 'VIP_GO_APP_ENVIRONMENT' );
if ( is_string( $app_environment ) && '' !== $app_environment ) {
$props['vipgo_env'] = $app_environment;
}
}

// Set VIP organization if it exists.
if ( defined( 'VIP_ORG_ID' ) ) {
$org_id = constant( 'VIP_ORG_ID' );
if ( is_integer( $org_id ) && $org_id > 0 ) {
$props['vipgo_org'] = $org_id;
}
}

return $props;
}

/**
* Check if the site is hosted on VIP.
*/
function is_wpvip_site(): bool {
if ( is_wpvip_sandbox() ) {
return false;
}

return defined( 'WPCOM_IS_VIP_ENV' ) && constant( 'WPCOM_IS_VIP_ENV' ) === true;
}

/**
* Check if the site is hosted on VIP sandbox.
*/
function is_wpvip_sandbox(): bool {
return defined( 'WPCOM_SANDBOXED' ) && constant( 'WPCOM_SANDBOXED' ) === true;
}

/**
* Get the hosting provider.
*/
function get_hosting_provider(): string {
if ( is_wpvip_sandbox() ) {
return 'wpvip_sandbox';
}

if ( is_wpvip_site() ) {
return 'wpvip';
}

return 'other';
}

/**
* Returns the base properties for a track user.
*
* @return array<string, mixed> The base properties.
*/
function get_base_properties_of_track_user(): array {
$props = [];

// Only track logged-in users.
$wp_user = wp_get_current_user();
if ( 0 === $wp_user->ID ) {
return $props;
}

// Set anonymized event user ID; it should be consistent across environments.
// VIP_TELEMETRY_SALT is a private constant shared across the platform.
if ( defined( 'VIP_TELEMETRY_SALT' ) ) {
$salt = constant( 'VIP_TELEMETRY_SALT' );
$tracks_user_id = hash_hmac( 'sha256', $wp_user->user_email, $salt );

$props['_ui'] = $tracks_user_id;
$props['_ut'] = 'vip:user_email';
} elseif ( defined( 'VIP_GO_APP_ID' ) ) {
// Users in the VIP environment.
$app_id = constant( 'VIP_GO_APP_ID' );
if ( is_integer( $app_id ) && $app_id > 0 ) {
$props['_ui'] = sprintf( '%s_%s', $app_id, $wp_user->ID );
$props['_ut'] = 'vip_go_app_wp_user';
}
} else {
// All other environments.
$props['_ui'] = wp_hash( sprintf( '%s|%s', get_option( 'home' ), $wp_user->ID ) );

/**
* @see \Automattic\VIP\Parsely\Telemetry\Tracks_Event::annotate_with_id_and_type()
*/
$props['_ut'] = 'anon'; // Same as the default value in the original code.
}

return $props;
}

/**
* Get the core properties for a Tracks event.
*
* @return array<string, mixed> The core properties.
*/
function get_tracks_core_properties(): array {
return array_merge( get_base_properties_of_track_event(), get_base_properties_of_track_user() );
}
3 changes: 3 additions & 0 deletions tests/telemetry/test-class-tracks.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
namespace Automattic\VIP\Telemetry;

use Automattic\VIP\Telemetry\Tracks\Tracks_Event;
use PHPUnit\Framework\MockObject\MockObject;
use WP_UnitTestCase;

class Tracks_Test extends WP_UnitTestCase {
public function test_event_queued() {
$user = $this->factory()->user->create_and_get();
wp_set_current_user( $user->ID );

/** @var MockObject|Telemetry_Event_Queue */
$queue = $this->getMockBuilder( Telemetry_Event_Queue::class )
->disableOriginalConstructor()
->getMock();
Expand All @@ -28,6 +30,7 @@ public function test_event_queued() {
->willReturn( true );

$tracks = new Tracks( 'test_', [], $queue );

$this->assertTrue( $tracks->record_event( 'cool_event', [ 'foo' => 'bar' ] ) );
}

Expand Down
84 changes: 84 additions & 0 deletions tests/telemetry/test-tracks-utils.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<?php

declare(strict_types=1);

namespace Automattic\VIP\Telemetry;

use Automattic\Test\Constant_Mocker;
use WP_UnitTestCase;

use function Automattic\VIP\Telemetry\Tracks\get_hosting_provider;
use function Automattic\VIP\Telemetry\Tracks\is_wpvip_site;
use function Automattic\VIP\Telemetry\Tracks\get_tracks_core_properties;
use function Automattic\VIP\Telemetry\Tracks\is_wpvip_sandbox;

class Tracks_Utils_Test extends WP_UnitTestCase {
public function tear_down() {
parent::tear_down();
Constant_Mocker::clear();
}

public function test_is_wpvip_site_returns_false_on_non_VIP_hosting(): void {
Constant_Mocker::define( 'WPCOM_IS_VIP_ENV', false );

$this->assertEquals( false, is_wpvip_site() );
}

public function test_is_wpvip_site_returns_false_on_sandbox(): void {
Constant_Mocker::define( 'WPCOM_IS_VIP_ENV', true );
Constant_Mocker::define( 'WPCOM_SANDBOXED', true );

$this->assertEquals( false, is_wpvip_site() );
}

public function test_is_wpvip_site_returns_true(): void {
Constant_Mocker::define( 'WPCOM_IS_VIP_ENV', true );
Constant_Mocker::define( 'WPCOM_SANDBOXED', false );

$this->assertEquals( true, is_wpvip_site() );
}

public function test_is_wpvip_sandbox_returns_true(): void {
Constant_Mocker::define( 'WPCOM_SANDBOXED', true );

$this->assertEquals( true, is_wpvip_sandbox() );
}

public function test_is_wpvip_sandbox_returns_false(): void {
Constant_Mocker::define( 'WPCOM_SANDBOXED', false );

$this->assertEquals( false, is_wpvip_sandbox() );
}

public function test_get_hosting_provider_returns_wpvip_on_VIP_hosting(): void {
Constant_Mocker::define( 'WPCOM_IS_VIP_ENV', true );
Constant_Mocker::define( 'WPCOM_SANDBOXED', false );

$this->assertEquals( 'wpvip', get_hosting_provider() );
}

public function test_get_hosting_provider_returns_wpvip_sandbox_on_sandbox(): void {
Constant_Mocker::define( 'WPCOM_SANDBOXED', true );

$this->assertEquals( 'wpvip_sandbox', get_hosting_provider() );
}

public function test_get_hosting_provider_returns_other_on_non_VIP_hosting(): void {
$this->assertEquals( 'other', get_hosting_provider() );
}

public function test_track_core_properties(): void {
wp_set_current_user( 1 );
$output = get_tracks_core_properties();

$props = [
'hosting_provider' => 'other',
'is_vip_user' => false,
'is_multisite' => is_multisite(),
'wp_version' => get_bloginfo( 'version' ),
'_ut' => 'anon',
'_ui' => wp_hash( sprintf( '%s|%s', get_option( 'home' ), 1 ) ),
];
$this->assertEquals( $props, $output );
}
}
7 changes: 6 additions & 1 deletion vip-support/class-vip-support-user.php
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,12 @@ public function __construct() {
* user edit and profile screens.
*/
public function action_admin_head() {
if ( in_array( get_current_screen()->base, array( 'user-edit', 'profile' ) ) ) {
$current_screen = get_current_screen();
if ( ! $current_screen ) {
return;
}

if ( in_array( $current_screen->base, array( 'user-edit', 'profile' ) ) ) {
?>
<style type="text/css">
.vip-support-email-status {
Expand Down

0 comments on commit 05a72c5

Please sign in to comment.