Skip to content

Commit 7a2bb07

Browse files
sakshamg1304rohitesh-wingify
authored andcommitted
feat: advanced debugging
1 parent 51861ab commit 7a2bb07

39 files changed

+1281
-388
lines changed

CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [1.20.0] - 2026-02-18
9+
10+
### Added
11+
12+
- Enhanced Logging capabilities at VWO by sending `vwo_sdkDebug` event with additional debug properties.
13+
814
## [1.19.0] - 2026-02-11
915

1016
### Added
@@ -370,4 +376,4 @@ $vwoClient->setAlias('userId', 'aliasId');
370376
// set Attribute
371377
$setAttribute = $vwoClient->setAttribute('attribute-name', 'attribute-value', $userContext);
372378

373-
```
379+
```

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,7 @@ To customize the SDK further, additional parameters can be passed to the `init()
6161
| **Parameter** | **Description** | **Required** | **Type** | **Example** |
6262
| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | --------- | ------------------------------- |
6363
| `sdkKey` | SDK key corresponding to the specific environment to initialize the VWO SDK Client. You can get this key from VWO Application. | Yes | string | `'32-alpha-numeric-sdk-key'` |
64-
| `accountId` | VWO Account ID for authentication. | Yes | string | `'123456'` |
65-
| `pollInterval` | Time interval for fetching updates from VWO servers (in milliseconds). | No | integer | `60000` |
64+
| `accountId` | VWO Account ID for authentication. | Yes | string | `'123456'` | |
6665
| `gatewayService` | An object representing configuration for integrating VWO Gateway Service. | No | array | see [Gateway](#gateway) section |
6766
| `proxy` | An object representing configuration for routing all SDK network requests through a custom proxy server. | No | array | See [Proxy](#proxy) section |
6867
| `storage` | Custom storage connector for persisting user decisions and campaign data. | No | array | See [Storage](#storage) section |

composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "vwo/vwo-fme-php-sdk",
33

4-
"version": "1.19.0",
4+
"version": "1.20.0",
55
"keywords": ["vwo", "fme", "sdk"],
66
"license": "Apache-2.0",
77
"authors": [{
@@ -16,7 +16,7 @@
1616
"ramsey/uuid": "^3.0 || ^4.2",
1717
"lastguest/murmurhash": "^2.1.1",
1818
"vwo/vwo-fme-sdk-e2e-test-settings-n-cases": "^1.2.4",
19-
"vwo/vwo-fme-sdk-log-messages": "^1.0.0"
19+
"vwo/vwo-fme-sdk-log-messages": "^1.4.0"
2020
},
2121
"autoload": {
2222
"psr-4": {

phpunit.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,7 @@
99
<directory>./src</directory>
1010
</whitelist>
1111
</filter>
12+
<php>
13+
<env name="APP_ENV" value="test"/>
14+
</php>
1215
</phpunit>

src/Api/GetFlag.php

Lines changed: 65 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@
4040
use vwo\Utils\NetworkUtil;
4141
use vwo\Enums\EventEnum;
4242
use vwo\Services\SettingsService;
43+
use vwo\Utils\DebuggerServiceUtil;
44+
use vwo\Enums\DebuggerCategoryEnum;
45+
use vwo\Services\LoggerService;
46+
use vwo\Packages\Logger\Enums\LogLevelEnum;
47+
use vwo\Constants\Constants;
4348

4449
class GetFlag
4550
{
@@ -64,6 +69,7 @@ public function get(
6469

6570
$hooksService = $serviceContainer->getHooksService();
6671
$logManager = $serviceContainer->getLogManager();
72+
$loggerService = $serviceContainer->getLoggerService();
6773

6874
// Get feature object from feature key
6975
$feature = FunctionUtil::getFeatureFromKey($serviceContainer->getSettings(), $featureKey);
@@ -75,6 +81,14 @@ public function get(
7581
'api' => ApiEnum::GET_FLAG,
7682
];
7783

84+
// create debug event props
85+
$debugEventProps = [
86+
'an' => ApiEnum::GET_FLAG,
87+
'uuid' => $context ? $context->getVwoUuid() : null,
88+
'fk' => $feature ? $feature->getKey() : null,
89+
'sId' => $context ? $context->getSessionId() : null,
90+
];
91+
7892
// Retrieve stored data
7993
$storedData = (new StorageDecorator())->getFeatureFromStorage(
8094
$featureKey,
@@ -134,10 +148,10 @@ public function get(
134148
}
135149

136150
if (!DataTypeUtil::isObject($feature)) {
137-
$logManager->error(sprintf(
138-
"Feature not found for the key: %s",
139-
$featureKey
140-
));
151+
$loggerService->error('FEATURE_NOT_FOUND',
152+
array_merge([
153+
'featureKey' => $featureKey,
154+
], $debugEventProps));
141155

142156
return new GetFlagResultUtil(false, [], $ruleStatus);
143157
}
@@ -172,7 +186,7 @@ public function get(
172186

173187
if(!$isDebuggerUsed) {
174188
if(($serviceContainer->getSettingsService()->isGatewayServiceProvided || $serviceContainer->getSettingsService()->isProxyUrlProvided) && $payload !== null) {
175-
ImpressionUtil::SendImpressionForVariationShown($serviceContainer, $payload, $context);
189+
ImpressionUtil::SendImpressionForVariationShown($serviceContainer, $payload, $context, $featureKey);
176190
} else {
177191
if($payload !== null) {
178192
$batchPayload[] = $payload;
@@ -216,7 +230,7 @@ public function get(
216230
);
217231

218232
if(($serviceContainer->getSettingsService()->isGatewayServiceProvided || $serviceContainer->getSettingsService()->isProxyUrlProvided) && $payload !== null) {
219-
ImpressionUtil::SendImpressionForVariationShown($serviceContainer, $payload, $context);
233+
ImpressionUtil::SendImpressionForVariationShown($serviceContainer, $payload, $context, $featureKey);
220234
} else {
221235
//push this payload to the batch payload
222236
if($payload !== null) {
@@ -257,7 +271,7 @@ public function get(
257271
$isEnabled = true;
258272
$payload = $evaluateRuleResult['payload'];
259273
if(($serviceContainer->getSettingsService()->isGatewayServiceProvided || $serviceContainer->getSettingsService()->isProxyUrlProvided) && $payload !== null) {
260-
ImpressionUtil::SendImpressionForVariationShown($serviceContainer, $payload, $context);
274+
ImpressionUtil::SendImpressionForVariationShown($serviceContainer, $payload, $context, $featureKey);
261275
} else {
262276
if($payload !== null) {
263277
$batchPayload[] = $payload;
@@ -301,7 +315,7 @@ public function get(
301315
);
302316

303317
if(($serviceContainer->getSettingsService()->isGatewayServiceProvided || $serviceContainer->getSettingsService()->isProxyUrlProvided) && $payload !== null) {
304-
ImpressionUtil::SendImpressionForVariationShown($serviceContainer, $payload, $context);
318+
ImpressionUtil::SendImpressionForVariationShown($serviceContainer, $payload, $context, $featureKey);
305319
} else {
306320
//push this payload to the batch payload
307321
if($payload !== null) {
@@ -330,6 +344,22 @@ public function get(
330344
$hooksService->set($decision);
331345
$hooksService->execute($hooksService->get());
332346

347+
// send debug event, if debugger is enabled
348+
if ($feature->getIsDebuggerEnabled()) {
349+
350+
$debugEventProps['cg'] = DebuggerCategoryEnum::DECISION;
351+
// debugEventProps.msg_t = Constants.FLAG_DECISION;
352+
$debugEventProps['msg_t'] = Constants::FLAG_DECISION_GIVEN;
353+
354+
$debugEventProps['lt'] = LogLevelEnum::INFO;
355+
356+
// Update debug event props with decision keys
357+
$this->updateDebugEventPropsWithDecisionKeys($debugEventProps, $decision);
358+
359+
// Send debug event
360+
DebuggerServiceUtil::sendDebugEventToVWO($debugEventProps);
361+
}
362+
333363
// Send data for Impact Campaign, if defined
334364
if ($feature->getImpactCampaign()->getCampaignId()) {
335365
$status = $isEnabled ? 'enabled' : 'disabled';
@@ -352,7 +382,7 @@ public function get(
352382
);
353383

354384
if(($serviceContainer->getSettingsService()->isGatewayServiceProvided || $serviceContainer->getSettingsService()->isProxyUrlProvided) && $payload !== null) {
355-
ImpressionUtil::SendImpressionForVariationShown($serviceContainer, $payload, $context);
385+
ImpressionUtil::SendImpressionForVariationShown($serviceContainer, $payload, $context, $featureKey);
356386
} else {
357387
//push this payload to the batch payload
358388
if($payload !== null) {
@@ -395,4 +425,30 @@ private function updateIntegrationsDecisionObject(CampaignModel $campaign, Varia
395425

396426
$decision = array_merge($decision, $passedRulesInformation);
397427
}
428+
429+
/**
430+
* Update debug event props with decision keys.
431+
*
432+
* @param array &$debugEventProps Debug event props (passed by reference)
433+
* @param array $decision Decision array
434+
* @return void
435+
*/
436+
private function updateDebugEventPropsWithDecisionKeys(array &$debugEventProps, array $decision)
437+
{
438+
$decisionKeys = DebuggerServiceUtil::extractDecisionKeys($decision);
439+
$message = "Flag decision given for feature:{$decision['featureKey']}.";
440+
441+
if (isset($decision['rolloutKey']) && isset($decision['rolloutVariationId'])) {
442+
$rolloutKeySuffix = substr($decision['rolloutKey'], strlen($decision['featureKey'] . '_'));
443+
$message .= " Got rollout:{$rolloutKeySuffix} with variation:{$decision['rolloutVariationId']}";
444+
}
445+
446+
if (isset($decision['experimentKey']) && isset($decision['experimentVariationId'])) {
447+
$experimentKeySuffix = substr($decision['experimentKey'], strlen($decision['featureKey'] . '_'));
448+
$message .= " and experiment:{$experimentKeySuffix} with variation:{$decision['experimentVariationId']}";
449+
}
450+
451+
$debugEventProps['msg'] = $message;
452+
$debugEventProps = array_merge($debugEventProps, $decisionKeys);
453+
}
398454
}

src/Api/SetAttribute.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ private function createImpressionForAttributes(SettingsModel $settings, array $a
6565
$properties = $networkUtil->getEventsBaseProperties(
6666
EventEnum::VWO_SYNC_VISITOR_PROP,
6767
$context->getUserAgent(),
68-
$context->getIpAddress()
68+
$context->getIpAddress(),
69+
$context->getSessionId()
6970
);
7071

7172
// Construct payload data for multiple attributes
@@ -77,6 +78,6 @@ private function createImpressionForAttributes(SettingsModel $settings, array $a
7778
);
7879

7980
// Send the constructed payload via POST request
80-
$networkUtil->sendPostApiRequest($properties, $payload);
81+
$networkUtil->sendPostApiRequest($properties, $payload, $context->getId());
8182
}
8283
}

src/Api/TrackEvent.php

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
namespace vwo\Api;
2020

2121
use vwo\Enums\ApiEnum;
22-
use vwo\Enums\ErrorLogMessagesEnum;
2322
use vwo\Models\SettingsModel;
2423
use vwo\Models\User\ContextModel;
2524
use vwo\Services\HooksService;
@@ -65,16 +64,20 @@ public function track(SettingsModel $settings, string $eventName, ContextModel $
6564
}
6665

6766
// Set and execute integration callback for the track event
68-
$hooksService->set(['eventName' => $eventName, 'api' => ApiEnum::TRACK]);
67+
$hooksService->set(['eventName' => $eventName, 'api' => ApiEnum::TRACK_EVENT]);
6968
$hooksService->execute($hooksService->get());
7069

7170
return [$eventName => true];
7271
}
7372

7473
// Log an error if the event does not exist
75-
$logManager = $serviceContainer->getLogManager();
76-
$logManager->error("Event '$eventName' not found in any of the features");
77-
74+
$loggerService = $serviceContainer->getLoggerService();
75+
$loggerService->error('EVENT_NOT_FOUND',[
76+
'eventName' => $eventName,
77+
'an' => ApiEnum::TRACK_EVENT,
78+
'uuid' => $context->getVwoUuid(),
79+
'sId' => $context->getSessionId(),
80+
]);
7881

7982
return [$eventName => false];
8083
}
@@ -92,7 +95,7 @@ private function createImpressionForTrack(SettingsModel $settings, string $event
9295
$networkUtil = new NetworkUtil($serviceContainer);
9396

9497
// Get base properties for the event
95-
$properties = $networkUtil->getEventsBaseProperties($eventName, $context->getUserAgent(), $context->getIpAddress());
98+
$properties = $networkUtil->getEventsBaseProperties($eventName, $context->getUserAgent(), $context->getIpAddress(), $context->getSessionId());
9699

97100
// Prepare the payload for the track goal
98101
$payload = $networkUtil->getTrackGoalPayloadData(
@@ -103,7 +106,7 @@ private function createImpressionForTrack(SettingsModel $settings, string $event
103106
);
104107

105108
// Send the prepared payload via POST API request
106-
$networkUtil->sendPostApiRequest($properties, $payload);
109+
$networkUtil->sendPostApiRequest($properties, $payload, $context->getId(), $eventProperties);
107110
}
108111
}
109112
?>

src/Constants/Constants.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class Constants {
4040
const DEFAULT_EVENTS_PER_REQUEST = 100;
4141
const SDK_NAME = 'vwo-fme-php-sdk';
4242

43-
const SDK_VERSION = '1.19.0';
43+
const SDK_VERSION = '1.20.0';
4444
const AP = 'server';
4545

4646
const SETTINGS = 'settings';
@@ -71,6 +71,18 @@ class Constants {
7171
self::RETRY_INITIAL_DELAY => 2,
7272
self::RETRY_BACKOFF_MULTIPLIER => 2,
7373
];
74+
75+
// Debugger constants
76+
const V2_SETTINGS = 'v2-settings';
77+
const POLLING = 'polling';
78+
const FLAG_DECISION_GIVEN = 'FLAG_DECISION_GIVEN';
79+
const NETWORK_CALL_FAILURE_AFTER_MAX_RETRIES = 'NETWORK_CALL_FAILURE_AFTER_MAX_RETRIES';
80+
const NETWORK_CALL_SUCCESS_WITH_RETRIES = 'NETWORK_CALL_SUCCESS_WITH_RETRIES';
81+
const IMPACT_ANALYSIS = "IMPACT_ANALYSIS";
82+
83+
const HTTP_SUCCESS_MIN = 200;
84+
const HTTP_SUCCESS_MAX = 299;
85+
const HTTP_SUCCESS_UPPER_BOUND = 300;
7486
}
7587

7688
?>

src/Decorators/StorageDecorator.php

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
use vwo\Models\VariationModel;
2525
use vwo\Models\User\ContextModel;
2626
use vwo\Services\ServiceContainer;
27+
use vwo\Services\LoggerService;
28+
use vwo\Packages\Logger\Enums\LogLevelEnum;
29+
use vwo\Enums\ApiEnum;
2730

2831
interface IStorageDecorator
2932
{
@@ -67,25 +70,25 @@ public function setDataInStorage($data, $storageService, ServiceContainer $servi
6770
$experimentKey = $data['experimentKey'] ?? null;
6871
$experimentVariationId = $data['experimentVariationId'] ?? null;
6972

70-
$logManager = $serviceContainer->getLogManager();
73+
$loggerService = $serviceContainer->getLoggerService();
7174

7275
if (!$featureKey) {
73-
$logManager->error("Error storing data: featureKey is invalid.");
76+
$loggerService->error("ERROR_STORING_DATA_IN_STORAGE", ["featureKey" => $featureKey, 'an' => ApiEnum::GET_FLAG, 'uuid' => $context->getVwoUuid(), 'sId' => $context->getSessionId()]);
7477
return false;
7578
}
7679

7780
if ($context->getId() == null) {
78-
$logManager->error("Error storing data: Context or Context.id is invalid.");
81+
$loggerService->error("ERROR_STORING_DATA_IN_STORAGE", ["context" => $context, 'an' => ApiEnum::GET_FLAG, 'uuid' => $context->getVwoUuid(), 'sId' => $context->getSessionId()]);
7982
return false;
8083
}
8184

8285
if ($rolloutKey && !$experimentKey && !$rolloutVariationId) {
83-
$logManager->error("Error storing data: Variation (rolloutKey, experimentKey or rolloutVariationId) is invalid.");
86+
$loggerService->error("ERROR_STORING_DATA_IN_STORAGE", ["rolloutKey" => $rolloutKey, "experimentKey" => $experimentKey, "rolloutVariationId" => $rolloutVariationId, 'an' => ApiEnum::GET_FLAG, 'uuid' => $context->getVwoUuid(), 'sId' => $context->getSessionId()]);
8487
return false;
8588
}
8689

8790
if ($experimentKey && !$experimentVariationId) {
88-
$logManager->error("Error storing data: Variation (experimentKey or experimentVariationId) is invalid.");
91+
$loggerService->error("ERROR_STORING_DATA_IN_STORAGE", ["experimentKey" => $experimentKey, "experimentVariationId" => $experimentVariationId, 'an' => ApiEnum::GET_FLAG, 'uuid' => $context->getVwoUuid(), 'sId' => $context->getSessionId()]);
8992
return false;
9093
}
9194

src/Enums/ApiEnum.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@
2020

2121
class ApiEnum {
2222
const GET_FLAG = 'getFlag';
23-
const TRACK = 'trackEvent';
23+
const TRACK_EVENT = 'trackEvent';
2424
const SET_ATTRIBUTE = 'setAttribute';
25+
const INIT = 'init';
2526
const SET_ALIAS = 'setAlias';
2627
}
2728
?>

0 commit comments

Comments
 (0)