Skip to content
Merged
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
35 changes: 33 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -212,9 +212,40 @@ EMAIL_TEMPLATE_TICKET_BOTTOM_GRAPHIC=https://spaces.fnvirtual.app/emails/REGISTR
EMAIL_TEMPLATE_PRIMARY_COLOR="#000000"
EMAIL_TEMPLATE_SECONDARY_COLOR="#808080"

#Open Telemetry vars
OTEL_EXPORTER_OTLP_ENDPOINT=
#Open Telemetry
OTEL_SERVICE_ENABLED=true
OTEL_SERVICE_NAME=summit-api
OTEL_PROPAGATORS=tracecontext,baggage
OTEL_EXPORTER_OTLP_PROTOCOL=http/json # Supported values: "grpc", "http/protobuf", "http/json"
OTEL_EXPORTER_OTLP_MAX_RETRIES=3
OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4318
TRACE_SPAN_PREFIX=SPAN
OTEL_TRACES_SAMPLER_PARENT=false
# OTEL_TRACES_SAMPLER_TYPE=always_on # Supported values: "always_on", "always_off", "traceidratio"
# OTEL_TRACES_SAMPLER_TRACEIDRATIO_RATIO=0.05
# OTEL_METRICS_EXPORTER=otlp
# OTEL_TRACES_EXPORTER=otlp
# OTEL_LOGS_EXPORTER=otlp
# OTEL_EXPORTER_OTLP_TIMEOUT=10000
# OTEL_EXPORTER_OTLP_HEADERS=
# OTEL_EXPORTER_OTLP_TRACES_TIMEOUT=10000
# OTEL_EXPORTER_OTLP_TRACES_HEADERS=
# OTEL_EXPORTER_OTLP_METRICS_TIMEOUT=10000
# OTEL_EXPORTER_OTLP_METRICS_HEADERS=
# OTEL_EXPORTER_OTLP_LOGS_TIMEOUT=10000
# OTEL_EXPORTER_OTLP_LOGS_HEADERS=
# OTEL_EXPORTER_ZIPKIN_ENDPOINT=http://localhost:9411
# OTEL_EXPORTER_ZIPKIN_TIMEOUT=10000
# OTEL_EXPORTER_ZIPKIN_MAX_RETRIES=3
# OTEL_INSTRUMENTATION_HTTP_SERVER=true
# OTEL_INSTRUMENTATION_HTTP_CLIENT=true
# OTEL_INSTRUMENTATION_QUERY=true
# OTEL_INSTRUMENTATION_REDIS=true
# OTEL_INSTRUMENTATION_QUEUE=true
# OTEL_INSTRUMENTATION_CACHE=true
# OTEL_INSTRUMENTATION_VIEW=true
# OTEL_INSTRUMENTATION_LIVEWIRE=true
# OTEL_INSTRUMENTATION_CONSOLE=true

# SWAGGER CONFIG

Expand Down
110 changes: 48 additions & 62 deletions app/Http/Middleware/TrackRequestMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,99 +2,85 @@

namespace App\Http\Middleware;

use Illuminate\Http\Request;
use Closure;
use Illuminate\Support\Str;
use \OpenTelemetry\API\Trace\SpanInterface;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
use Illuminate\Log\LogManager;
use Keepsuit\LaravelOpenTelemetry\Facades\Tracer;

use Illuminate\Log\LogManager;
use OpenTelemetry\API\Baggage\Baggage;
use OpenTelemetry\Context\ScopeInterface;

class TrackRequestMiddleware
{
/**
* @var LogManager
*/
protected LogManager $logger;
private const ATTRIBUTE_START_TIME = '_start_time';
private const EVENT_REQUEST_STARTED = 'request.started';
private const EVENT_REQUEST_FINISHED = 'request.finished';

/**
* @var float
*/
protected float $startTime = 0;

/**
* @var SpanInterface
*/
protected SpanInterface $span;
protected LogManager $logger;
private ?ScopeInterface $baggageScope = null;
private bool $shouldTrack;

/**
* Constructor del middleware.
* Laravel inyectará el LogManager aquí.
*
* @param LogManager $logger
*/
public function __construct(LogManager $logger)
{
$this->logger = $logger;
$this->shouldTrack = env('OTEL_SERVICE_ENABLED', false);
}

/**
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
if(env('APP_ENV') === 'testing') {
// Skip tracking in testing environment
if (!$this->shouldTrack) {
return $next($request);
}

try {
// generating dynamic id for span with configurable prefix
$spanId = env('TRACE_SPAN_PREFIX', 'SPAN') . '_' . Str::uuid();
$this->startTime = microtime(true);
$this->span = Tracer::newSpan($spanId)->start();
$request->attributes->set(self::ATTRIBUTE_START_TIME, microtime(true));
if ($span = Tracer::activeSpan()) {
if ($ray = $request->header('cf-ray')) {
$span->setAttribute('cloudflare.cf-ray', $ray);

$baggage = Baggage::getCurrent()
->toBuilder()
->set('cf-ray', $ray)
->set('user_agent', substr($request->userAgent() ?? 'unknown', 0, 100))
->build();

$this->logger->channel('otlp')->info('Request started.', [
'endpoint' => $request->url(),
'method' => $request->method(),
'timestamp_utc' => now()->toIso8601String(),
]);
$this->baggageScope = $baggage->activate();
}

$span->addEvent(self::EVENT_REQUEST_STARTED, [
'method' => $request->method(),
'url' => $request->fullUrl(),
]);
}
} catch (\Throwable $e) {
// forcing 'single' channel in case otlp log fails
$this->logger->channel('single')->error("Error on request tracking" . $e->getMessage());
$this->logger->channel('daily')->error("Error on request tracking: " . $e->getMessage());
}

$response = $next($request);
return $response;
return $next($request);
}

/**
* @param Request $request
* @param Response $response
* @return void
*/
public function terminate(Request $request, Response $response): void
{
if(env('APP_ENV') === 'testing') {
// Skip tracking in testing environment
if (!$this->shouldTrack) {
return;
}

try {
$endTime = microtime(true);
$responseTime = intval(($endTime - $this->startTime) * 1000);
$this->logger->channel('otlp')->info('Request finished.', [
'response_time' => $responseTime,
]);
$start = (float) $request->attributes->get(self::ATTRIBUTE_START_TIME, microtime(true));
$ms = (int) ((microtime(true) - $start) * 1000);

if (isset($this->span)) {
$this->span->end();
if ($span = Tracer::activeSpan()) {
$span->setAttribute('app.response_ms', $ms);
$span->setAttribute('http.status_code', $response->getStatusCode());
$span->addEvent(self::EVENT_REQUEST_FINISHED, ['response_ms' => $ms]);
}

} catch (\Throwable $e) {
// forcing 'single' channel in case otlp log fails
$this->logger->channel('single')->error("Error on request tracking: " . $e->getMessage());
$this->logger->channel('daily')->error("Error on request tracking: " . $e->getMessage());
} finally {
if ($this->baggageScope) {
$this->baggageScope->detach();
$this->baggageScope = null;
}
}
}
}
}
2 changes: 2 additions & 0 deletions app/Services/Apis/MailApi.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use GuzzleHttp\RequestOptions;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Log;
use Keepsuit\LaravelOpenTelemetry\Support\HttpClient\GuzzleTraceMiddleware;
use libs\utils\ICacheService;
use models\exceptions\ValidationException;
/**
Expand Down Expand Up @@ -58,6 +59,7 @@ public function __construct(ICacheService $cacheService)
parent::__construct($cacheService);
$stack = HandlerStack::create();
$stack->push(GuzzleRetryMiddleware::factory());
$stack->push(GuzzleTraceMiddleware::make());

$this->client = new Client([
'handler' => $stack,
Expand Down
28 changes: 17 additions & 11 deletions app/Services/Utils/RedisCacheService.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,19 +64,25 @@ public function __destruct()
if (is_resource($res)) $metadata = @stream_get_meta_data($res);
}
} catch (\Throwable $ignored) {}
Log::error
(
sprintf
// Check if Laravel app is still available before logging
if (app()->bound('config')) {
Log::error
(
"RedisCacheService::__destruct %s %s %s",
$ex->getCode(),
$ex->getMessage(),
var_export($metadata, true)
)
);
sprintf
(
"RedisCacheService::__destruct %s %s %s",
$ex->getCode(),
$ex->getMessage(),
var_export($metadata, true)
)
);
}
}
catch(\Exception $ex){
Log::warning($ex);
// Check if Laravel app is still available before logging
if (app()->bound('config')) {
Log::warning($ex);
}
}
}

Expand Down Expand Up @@ -325,7 +331,7 @@ public function ttl($key)
return (int)$conn->ttl($key);
}, 0);
}

/**
* @param string $cache_region_key
* @return void
Expand Down
20 changes: 13 additions & 7 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"google/apiclient": "^2.2",
"guzzlehttp/guzzle": "7.8.2",
"guzzlehttp/uri-template": "^1.0",
"keepsuit/laravel-opentelemetry": "^1.6",
"keepsuit/laravel-opentelemetry": "^1.11.0",
"laminas/laminas-math": "^3.7",
"laravel-doctrine/extensions": "2.0.1",
"laravel-doctrine/migrations": "3.4.0",
Expand Down Expand Up @@ -66,10 +66,10 @@
"rector/rector": "*",
"spatie/laravel-ignition": "^2.8.0"
},
"suggest":{
"suggest": {
"lib-openssl": "Required to use AES algorithms (except AES GCM)",
"ext-json":"Required to use json algorithms",
"ext-gd":"Required to use json algorithms"
"ext-json": "Required to use json algorithms",
"ext-gd": "Required to use json algorithms"
},
"autoload": {
"classmap": [
Expand All @@ -82,9 +82,15 @@
"vendor/affinipay/chargeio-php/lib"
],
"psr-4": {
"App\\": "app/"
"App\\": "app/",
"OpenTelemetry\\SemConv\\Unstable\\Metrics\\": "vendor/open-telemetry/sem-conv/Incubating/Metrics/",
"OpenTelemetry\\" : "vendor/open-telemetry/",
"OpenTelemetry\\API\\": "vendor/open-telemetry/api/"

},
"files": ["app/Utils/helpers.php"]
"files": [
"app/Utils/helpers.php"
]
},
"autoload-dev": {
"psr-4": {
Expand Down Expand Up @@ -128,4 +134,4 @@
},
"minimum-stability": "dev",
"prefer-stable": true
}
}
Loading