Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
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 composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
},
"extra": {
"branch-alias": {
"dev-master": "2.12-dev"
"dev-master": "3.0-dev"
}
},
"config": {
Expand Down
8 changes: 6 additions & 2 deletions src/Bridges/Nette/MailSender.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public function __construct(
}


public function send(mixed $message, string $email): void
public function send(mixed $message, string $email, ?string $exceptionFile = null): void
{
$host = preg_replace('#[^\w.-]+#', '', $this->host ?? $_SERVER['SERVER_NAME'] ?? php_uname('n'));

Expand All @@ -41,7 +41,11 @@ public function send(mixed $message, string $email): void
}

$mail->setSubject('PHP: An error occurred on the server ' . $host);
$mail->setBody(Tracy\Logger::formatMessage($message) . "\n\nsource: " . Tracy\Helpers::getSource());
$mail->setBody(
Tracy\Logger::formatMessage($message)
. "\n\nsource: " . Tracy\Helpers::getSource()
. ($exceptionFile ? "\nreport: " . basename($exceptionFile) : ''),
);

$this->mailer->send($mail);
}
Expand Down
4 changes: 2 additions & 2 deletions src/Bridges/Nette/TracyExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -156,14 +156,14 @@ public function afterCompile(Nette\PhpGenerator\ClassType $class): void
}

$initialize->addBody($builder->formatPhp('if ($logger instanceof Tracy\Logger) $logger->mailer = ?;', [
[new Statement(Tracy\Bridges\Nette\MailSender::class, $params), 'send'],
[new Statement(Tracy\Bridges\Nette\MailSender::class, $params), 'send'], // TODO: nette/di must be able to create closures
]));
}

if ($this->debugMode) {
foreach ($config->bar as $item) {
if (is_string($item) && str_starts_with($item, '@')) {
$item = new Statement(['@' . $builder::THIS_CONTAINER, 'getService'], [substr($item, 1)]);
$item = new Statement(['@' . $builder::ThisContainer, 'getService'], [substr($item, 1)]);
} elseif (is_string($item)) {
$item = new Statement($item);
}
Expand Down
20 changes: 20 additions & 0 deletions src/Tracy/Bar/AgentPanel.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php declare(strict_types=1);

/**
* This file is part of the Tracy (https://tracy.nette.org)
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
*/

namespace Tracy;


/**
* Tracy Bar panel providing a plain-text (markdown) summary for AI agents.
*/
interface AgentPanel
{
/**
* Returns markdown summary for AI agents, or null when there is nothing to report.
*/
function getAgentInfo(): ?string;
}
16 changes: 13 additions & 3 deletions src/Tracy/Bar/Bar.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ public function render(DeferredContent $defer): void
foreach (array_reverse($redirectQueue) as $item) {
$content['bar'] .= $item['content']['bar'];
$content['panels'] .= $item['content']['panels'];
}

foreach ($redirectQueue as $item) { // chronological order for the console log
$contentAgent[] = $item['agent'];
}

Expand Down Expand Up @@ -186,9 +189,16 @@ public function renderAgent(): string
$time = number_format((microtime(true) - Debugger::$time) * 1000, 1);
$memory = number_format(memory_get_peak_usage() / 1_000_000, 2);
$parts = ["Tracy Bar | $time ms | $memory MB"];
foreach ($this->panels as $panel) {
if (method_exists($panel, 'getAgentInfo') && ($text = $panel->getAgentInfo()) !== null) {
$parts[] = $text;
foreach ($this->panels as $id => $panel) {
try {
if (
($panel instanceof AgentPanel || method_exists($panel, 'getAgentInfo'))
&& ($text = $panel->getAgentInfo()) !== null
) {
$parts[] = $text;
}
} catch (\Throwable $e) { // a broken panel must not kill the whole bar render
$parts[] = "Error in panel $id: {$e->getMessage()}";
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/Tracy/Bar/DefaultBarPanel.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* @internal
*/
#[\AllowDynamicProperties]
class DefaultBarPanel implements IBarPanel
class DefaultBarPanel implements IBarPanel, AgentPanel
{
public mixed $data = null;

Expand Down
2 changes: 1 addition & 1 deletion src/Tracy/Bar/IBarPanel.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

/**
* Tracy Bar panel providing a tab label and optional panel content.
* @method ?string getAgentInfo() Returns markdown summary for AI agents.
* @method ?string getAgentInfo() Returns markdown summary for AI agents, see also the AgentPanel interface.
*/
interface IBarPanel
{
Expand Down
112 changes: 64 additions & 48 deletions src/Tracy/Bar/assets/bar.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,54 @@
* This file is part of the Tracy (https://tracy.nette.org)
*/

/* common styles */
#tracy-debug {
@layer tracy-components {

/* shadow DOM host */
:host {
--tracy-space: 10px;
display: none;
direction: ltr;
display: none;
}

body#tracy-debug { /* in popup window */
display: block;
/* host is shown as a manual popover in the top layer, undo UA popover geometry */
:host([popover]) {
position: static;
inset: auto;
width: auto;
height: auto;
margin: 0;
border: none;
padding: 0;
background: none;
overflow: visible;
color: inherit;
}

#tracy-debug:not(body) {
position: absolute;
left: 0;
top: 0;
body#tracy-debug { /* in popup window, the sheet is adopted by the document */
--tracy-space: 10px;
direction: ltr;
display: block;
}

#tracy-debug a {
/* common styles */
a {
color: #125EAE;
text-decoration: none;
}

#tracy-debug a:hover,
#tracy-debug a:focus {
a:hover,
a:focus {
background-color: #125EAE;
color: white;
}

#tracy-debug h2,
#tracy-debug h3 {
h2,
h3 {
font-size: inherit;
font-weight: bold;
}

#tracy-debug :where(:is(
:where(:is(
h1, h2, h3, h4, h5, h6,
p,
ol, ul, dl,
Expand All @@ -47,44 +61,44 @@ body#tracy-debug { /* in popup window */
margin-top: var(--tracy-space);
}

#tracy-debug table {
table {
background: #FDF5CE;
width: 100%;
}

#tracy-debug tr:nth-child(2n) td {
tr:nth-child(2n) td {
background: rgba(0, 0, 0, 0.02);
}

#tracy-debug td,
#tracy-debug th {
td,
th {
border: 1px solid #E6DFBF;
padding: 2px 5px;
vertical-align: top;
text-align: left;
}

#tracy-debug th {
th {
background: #F4F3F1;
color: #655E5E;
font-size: 90%;
font-weight: bold;
}

#tracy-debug pre,
#tracy-debug code {
pre,
code {
font: 9pt/1.5 Consolas, monospace;
}

#tracy-debug table .tracy-right {
table .tracy-right {
text-align: right;
}

#tracy-debug svg {
svg {
display: inline;
}

#tracy-debug .tracy-dump {
.tracy-dump {
margin: 0;
padding: 2px 5px;
}
Expand Down Expand Up @@ -182,7 +196,7 @@ body#tracy-debug { /* in popup window */


/* panels */
#tracy-debug .tracy-panel {
.tracy-panel {
display: none;
font: normal normal 12px/1.5 sans-serif;
background: white;
Expand All @@ -194,37 +208,37 @@ body#tracy-debug .tracy-panel { /* in popup window */
display: block;
}

#tracy-debug h1 {
h1 {
font: normal normal 23px/1.4 Tahoma, sans-serif;
line-height: 1;
color: #575753;
margin: 0;
word-wrap: break-word;
}

#tracy-debug .tracy-inner {
.tracy-inner {
overflow: auto;
flex: 1;
}

#tracy-debug .tracy-panel .tracy-icons {
.tracy-panel .tracy-icons {
display: none;
}

#tracy-debug .tracy-panel-ajax h1::after,
#tracy-debug .tracy-panel-redirect h1::after {
.tracy-panel-ajax h1::after,
.tracy-panel-redirect h1::after {
content: 'ajax';
float: right;
font-size: 65%;
margin: 0 .3em;
}

#tracy-debug .tracy-panel-redirect h1::after {
.tracy-panel-redirect h1::after {
content: 'redirect';
}

#tracy-debug .tracy-mode-peek,
#tracy-debug .tracy-mode-float {
.tracy-mode-peek,
.tracy-mode-float {
position: fixed;
flex-direction: column;
padding: var(--tracy-space);
Expand All @@ -235,24 +249,24 @@ body#tracy-debug .tracy-panel { /* in popup window */
border: 1px solid rgba(0, 0, 0, 0.1);
}

#tracy-debug .tracy-mode-peek,
#tracy-debug .tracy-mode-float:not(.tracy-panel-resized) {
.tracy-mode-peek,
.tracy-mode-float:not(.tracy-panel-resized) {
max-width: 700px;
max-height: 500px;
}

@media (max-height: 555px) {
#tracy-debug .tracy-mode-peek,
#tracy-debug .tracy-mode-float:not(.tracy-panel-resized) {
.tracy-mode-peek,
.tracy-mode-float:not(.tracy-panel-resized) {
max-height: 100vh;
}
}

#tracy-debug .tracy-mode-peek h1 {
.tracy-mode-peek h1 {
cursor: move;
}

#tracy-debug .tracy-mode-float {
.tracy-mode-float {
display: flex;
opacity: .95;
transition: opacity 0.2s;
Expand All @@ -261,44 +275,46 @@ body#tracy-debug .tracy-panel { /* in popup window */
resize: both;
}

#tracy-debug .tracy-focused {
.tracy-focused {
display: flex;
opacity: 1;
transition: opacity 0.1s;
}

#tracy-debug .tracy-mode-float h1 {
.tracy-mode-float h1 {
cursor: move;
padding-right: 25px;
}

#tracy-debug .tracy-mode-float .tracy-icons {
.tracy-mode-float .tracy-icons {
display: block;
position: absolute;
top: 0;
right: 5px;
font-size: 18px;
}

#tracy-debug .tracy-mode-window {
.tracy-mode-window {
padding: var(--tracy-space);
}

#tracy-debug .tracy-icons a {
.tracy-icons a {
color: #575753;
}

#tracy-debug .tracy-icons a:hover {
.tracy-icons a:hover {
color: white;
}


#tracy-debug .tracy-inner-container {
.tracy-inner-container {
min-width: fit-content;
}

@media print {
#tracy-debug * {
* {
display: none;
}
}

}
Loading
Loading