Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion includes/API/MetaLog/Request.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
defined( 'ABSPATH' ) || exit;

/**
* Request object for MetaLog > Error Graph Api.
* Request object for MetaLog Graph Api.
*/
class Request extends ApiRequest {

Expand Down
2 changes: 1 addition & 1 deletion includes/API/MetaLog/Response.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
defined( 'ABSPATH' ) || exit;

/**
* Response object for MetaLog > Error Graph Api.
* Response object for MetaLog Graph Api.
*/
class Response extends ApiResponse {}
52 changes: 46 additions & 6 deletions includes/Framework/BatchLogHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
*
* @since 3.5.0
*/
class BatchLogHandler {
class BatchLogHandler extends LogHandlerBase {

/**
* Constructs a new BatchLog handler.
Expand All @@ -33,18 +33,58 @@ public function __construct() {
}

/**
* Function that runs every minute.
* Function that runs every five minutes.
*
* @internal
*
* @since 3.5.0
*/
public function process_telemetry_logs_batch() {
if ( get_transient( 'global_telemetry_message_queue' ) !== false ) {
$logs = get_transient( 'global_telemetry_message_queue' );
if ( get_transient( 'global_telemetry_message_queue' ) !== false && ! empty( get_transient( 'global_telemetry_message_queue' ) ) ) {
$logs = get_transient( 'global_telemetry_message_queue' );
$chunked_logs = array_chunk( $logs, 20 );

// TODO: Replace with send batch logging request to Meta function.
WC_Facebookcommerce_Utils::log( wp_json_encode( $logs ) );
$chunked_failed_logs = array_map(
function ( $logs_chunk ) {
$logs_chunk_with_core_context = array_map(
function ( $log ) {
return self::set_core_log_context( $log );
},
$logs_chunk
);

$context = [
'event' => 'persist_meta_telemetry_logs',
'extra_data' => [ 'telemetry_logs' => wp_json_encode( $logs_chunk_with_core_context ) ],
];

try {
$response = facebook_for_woocommerce()->get_api()->log_to_meta( $context );
if ( $response->success ) {
WC_Facebookcommerce_Utils::logWithDebugModeEnabled( 'Telemetry logs: ' . wp_json_encode( $context ) );
return [];
} else {
WC_Facebookcommerce_Utils::logWithDebugModeEnabled( 'Bad response from log_to_meta request' );
return $logs_chunk;
}
} catch ( \Exception $e ) {
WC_Facebookcommerce_Utils::logWithDebugModeEnabled( 'Error persisting telemetry logs: ' . $e->getMessage() );
return $logs_chunk;
}
},
$chunked_logs
);

$failed_logs = array_merge( ...$chunked_failed_logs );
// Only keep the latest 100 failed logs, in case too much memory got eaten up on the host
if ( count( $failed_logs ) > 100 ) {
$failed_logs = array_slice( $failed_logs, -100 );
}

if ( ! empty( $failed_logs ) ) {
set_transient( 'global_telemetry_message_queue', $failed_logs, HOUR_IN_SECONDS );
return;
}
}

set_transient( 'global_telemetry_message_queue', [], HOUR_IN_SECONDS );
Expand Down
49 changes: 46 additions & 3 deletions includes/Framework/ErrorLogHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@

namespace WooCommerce\Facebook\Framework;

use WC_Facebookcommerce_Utils;
use Throwable;

defined( 'ABSPATH' ) || exit;


Expand All @@ -18,7 +21,7 @@
*
* @since 3.5.0
*/
class ErrorLogHandler {
class ErrorLogHandler extends LogHandlerBase {

/**
* Hook name for Meta Log API.
Expand All @@ -39,10 +42,50 @@ public function __construct() {
*
* @internal
*
* @param array $context log context
* @param array $raw_context log context
* @since 3.5.0
*/
public function process_error_log( $context ) {
public function process_error_log( $raw_context ) {
$context = self::set_core_log_context( $raw_context );
facebook_for_woocommerce()->get_api()->log_to_meta( $context );
WC_Facebookcommerce_Utils::logWithDebugModeEnabled( 'Error log: ' . wp_json_encode( $context ) );
}

/**
* Utility function for sending exception logs to Meta.
*
* @since 3.5.0
*
* @param Throwable $error error object
* @param array $context context example: ['catalog_id' => '1234567890', 'order_id' => '1234567890',
* 'promotion_id' => '1234567890', 'flow_name' => 'checkout', 'flow_step' => 'verification',
* 'extra_data' => ['dictionary type' => 'any data that is not fall into our pre-defined format.']
*/
public static function log_exception_to_meta( Throwable $error, array $context = [] ) {
$extra_data = WC_Facebookcommerce_Utils::getContextData( $context, 'extra_data', [] );
$extra_data['php_version'] = phpversion();

$request_data = [
'event' => 'error_log',
'event_type' => WC_Facebookcommerce_Utils::getContextData( $context, 'event_type' ),
'exception_message' => $error->getMessage(),
'exception_trace' => $error->getTraceAsString(),
'exception_code' => $error->getCode(),
'exception_class' => get_class( $error ),
'order_id' => WC_Facebookcommerce_Utils::getContextData( $context, 'order_id' ),
'promotion_id' => WC_Facebookcommerce_Utils::getContextData( $context, 'promotion_id' ),
'flow_name' => WC_Facebookcommerce_Utils::getContextData( $context, 'flow_name' ),
'flow_step' => WC_Facebookcommerce_Utils::getContextData( $context, 'flow_step' ),
'incoming_params' => WC_Facebookcommerce_Utils::getContextData( $context, 'incoming_params' ),
'extra_data' => $extra_data,
];

// Check if Action Scheduler is available
if ( function_exists( 'as_enqueue_async_action' ) ) {
as_enqueue_async_action( 'facebook_for_woocommerce_log_api', array( $request_data ) );
} else {
// Handle the absence of the Action Scheduler
WC_Facebookcommerce_Utils::logWithDebugModeEnabled( 'Action Scheduler is not available.' );
}
}
}
48 changes: 48 additions & 0 deletions includes/Framework/LogHandlerBase.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*
* This source code is licensed under the license found in the
* LICENSE file in the root directory of this source tree.
*
* @package FacebookCommerce
*/

namespace WooCommerce\Facebook\Framework;

defined( 'ABSPATH' ) || exit;


/**
* Log handler Base class
*
* @since 3.5.0
*/
class LogHandlerBase {

/**
* Plugin version.
*/
const PLUGIN_VERSION = \WC_Facebookcommerce::VERSION;

/**
* Prefill the log context with basic information.
*
* @since 3.5.0
*
* @param array $context log context
*/
public static function set_core_log_context( array $context ) {
$request_data = [
'commerce_merchant_settings_id' => facebook_for_woocommerce()->get_connection_handler()->get_commerce_merchant_settings_id(),
'commerce_partner_integration_id' => facebook_for_woocommerce()->get_connection_handler()->get_commerce_partner_integration_id(),
'external_business_id' => facebook_for_woocommerce()->get_connection_handler()->get_external_business_id(),
'catalog_id' => facebook_for_woocommerce()->get_integration()->get_product_catalog_id(),
'page_id' => facebook_for_woocommerce()->get_integration()->get_facebook_page_id(),
'pixel_id' => facebook_for_woocommerce()->get_integration()->get_facebook_pixel_id(),
'seller_platform_app_version' => self::PLUGIN_VERSION,
];

return array_merge( $request_data, $context );
}
}
15 changes: 15 additions & 0 deletions includes/Handlers/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ class Connection {
/** @var string the Commerce merchant settings ID option name */
const OPTION_COMMERCE_MERCHANT_SETTINGS_ID = 'wc_facebook_commerce_merchant_settings_id';

/** @var string the Commerce Partner Integration ID option name */
const OPTION_COMMERCE_PARTNER_INTEGRATION_ID = 'wc_facebook_commerce_partner_integration_id';

/** @var string|null the generated external merchant settings ID */
private $external_business_id;

Expand Down Expand Up @@ -794,6 +797,18 @@ public function get_commerce_merchant_settings_id() {
}


/**
* Gets Commerce Partner Integration ID value.
*
* @since 3.5.0
*
* @return string
*/
public function get_commerce_partner_integration_id() {
return get_option( self::OPTION_COMMERCE_PARTNER_INTEGRATION_ID, '' );
}


/**
* Gets the proxy URL.
*
Expand Down
48 changes: 7 additions & 41 deletions includes/fbutils.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use WooCommerce\Facebook\Events\AAMSettings;
use WooCommerce\Facebook\Events\Normalizer;
use WooCommerce\Facebook\Framework\Api\Exception as ApiException;
use WooCommerce\Facebook\Framework\ErrorLogHandler;
use WooCommerce\Facebook\Products\Sync;

if ( ! class_exists( 'WC_Facebookcommerce_Utils' ) ) :
Expand Down Expand Up @@ -868,54 +869,19 @@ public static function prepare_product_variation_data_items_batch( $product ) {
* 'extra_data' => ['dictionary type' => 'any data that is not fall into our pre-defined format.']
*/
public static function logExceptionImmediatelyToMeta(Throwable $error, array $context = []) {
$extra_data = self::getContextData($context, 'extra_data', []);
$extra_data['php_version'] = phpversion();

$request_data = [
'event' => 'error_log',
'event_type' => self::getContextData($context, 'event_type'),
'commerce_merchant_settings_id' => self::getContextData($context, 'commerce_merchant_settings_id', self::$ems),
'commerce_partner_integration_id' => self::getContextData($context, 'commerce_partner_integration_id'),
'exception_message' => $error->getMessage(),
'exception_trace' => $error->getTraceAsString(),
'exception_code' => $error->getCode(),
'exception_class' => get_class($error),
'external_business_id' => self::getContextData($context, 'external_business_id'),
'catalog_id' => self::getContextData($context, 'catalog_id'),
'order_id' => self::getContextData($context, 'order_id'),
'page_id' => self::getContextData($context, 'page_id'),
'promotion_id' => self::getContextData($context, 'promotion_id'),
'flow_name' => self::getContextData($context, 'flow_name'),
'flow_step' => self::getContextData($context, 'flow_step'),
'incoming_params' => self::getContextData($context, 'incoming_params'),
'seller_platform_app_version' => self::PLUGIN_VERSION,
'extra_data' => $extra_data,
];

// Check if Action Scheduler is available
if ( function_exists( 'as_enqueue_async_action' ) ) {
as_enqueue_async_action( 'facebook_for_woocommerce_log_api', array( $request_data ) );
} else {
// Handle the absence of the Action Scheduler
self::logWithDebugModeEnabled( 'Action Scheduler is not available.' );
}

self::logWithDebugModeEnabled( 'Request data: ' . json_encode( $request_data ) );
ErrorLogHandler::log_exception_to_meta($error, $context);
}

/**
* Utility function for sending telemetry logs to Meta.
* @since 3.5.0
*/
public static function logTelemetryToMeta(string $message, array $context = []) {
/**
* WIP: This is a dummy function to send telemetry logs to Meta.
* $context is an array of data that will be sent to Meta, includes commerce_merchant_settings_id,
* catalog_id, order_id, promotion_id, flow_name, flow_step, extra_data and etc.
*/

$extra_data = self::getContextData( $context, 'extra_data', [] );
$extra_data['message'] = $message;
$context['extra_data'] = $extra_data;

// Push logging request to global message queue function.
$context['extra_data'] = ['message' => $message];
$logs = get_transient( 'global_telemetry_message_queue' );
$logs[] = $context;
set_transient( 'global_telemetry_message_queue', $logs, HOUR_IN_SECONDS );
Expand Down Expand Up @@ -949,7 +915,7 @@ public static function is_fpassthru_disabled(): bool {
* @param mixed $default
* @return mixed
*/
private static function getContextData(array $context, string $key, $default = null)
public static function getContextData(array $context, string $key, $default = null)
{
return $context[$key] ?? $default;
}
Expand Down