diff options
Diffstat (limited to 'app/components')
-rw-r--r-- | app/components/about/about.html | 41 | ||||
-rw-r--r-- | app/components/about/about.ts | 7 | ||||
-rw-r--r-- | app/components/app/app.html | 3 | ||||
-rw-r--r-- | app/components/app/app.ts | 4 | ||||
-rw-r--r-- | app/components/plan-new/plan-new.html | 2 | ||||
-rw-r--r-- | app/components/plan-node/plan-node.html | 13 | ||||
-rw-r--r-- | app/components/plan-node/plan-node.ts | 2 | ||||
-rw-r--r-- | app/components/plan-view/plan-view.html | 1 |
8 files changed, 63 insertions, 10 deletions
diff --git a/app/components/about/about.html b/app/components/about/about.html new file mode 100644 index 0000000..08c913b --- /dev/null +++ b/app/components/about/about.html @@ -0,0 +1,41 @@ +<div class="page page-content"> + <h2>Postgres EXPLAIN Visualizer (Pev)</h2> + <p> + Pev is designed to make <a href="http://www.postgresql.org/docs/current/static/sql-explain.html"> + Postgres query plans</a> easier to grok. It displays a plan as a tree, with each node representing a step that takes in a row set + and produces another. Pev can show you a number of useful things:</p> + <ul> + <li>overall plan stats</li> + <li>individual node stats (duration, row size, cost)</li> + <li>explanation of what each node does</li> + <li>outlier nodes</li> + <li>graph of a specific metric (like cost) for all nodes</li> + <li>for some nodes, highlighted part of the query which corresponds to the node</li> + </ul> + + <p>You can tweak display options using the menu on the right.</p> + + <h3>Usage tips</h3> + <p>Pev currently accepts only JSON formatted plans. In fact, the get the most out of it, + I recommend generating a query plan using the following line: + <code>EXPLAIN (ANALYZE, COSTS, VERBOSE, BUFFERS, FORMAT JSON)</code>. I also recommend submitting a (decently formatted) + SQL query that generated the plan. Doing so will make Pev more useful. + </p> + + <p>Pev will remember the plans you analyzed. They are stored locally and are not submitted to me. This is good + because no one but you will see your queries. It's also bad because you can't share them with others.</p> + + <h3>Acknowledgements</h3> + <p>Pev was inspired and heavily influenced by the excellent <a href="http://explain.depesz.com/">explain.depesz.com</a>. Both the + tool and the corresponding help files are a great resource to learn about Postgres and its planner. + </p> + + <h3>Help me improve Pev</h3> + <p>If you want to help, there are multiple ways to contribute:</p> + <ul> + <li>give me your plans - I need more test cases for the layout</li> + <li>add descriptions for missing node types (especially ones from newer versions of Postgres)</li> + <li>contribute to the code on <a href="https://github.com/AlexTatiyants/pev">github</a></li> + </ul> + +</div> diff --git a/app/components/about/about.ts b/app/components/about/about.ts new file mode 100644 index 0000000..64777fc --- /dev/null +++ b/app/components/about/about.ts @@ -0,0 +1,7 @@ +import {Component} from 'angular2/core'; + +@Component({ + selector: 'about', + templateUrl: './components/about/about.html' +}) +export class About {} diff --git a/app/components/app/app.html b/app/components/app/app.html index b87937f..8d5072b 100644 --- a/app/components/app/app.html +++ b/app/components/app/app.html @@ -1,6 +1,7 @@ <nav> <div class="nav-container"> - <a class="btn btn-primary btn-lg pull-right" [routerLink]="['/PlanNew']">new plan</a> + <a class="about"[routerLink]="['About']">about</a> + <a class="btn btn-primary btn-lg pull-right" [routerLink]="['PlanNew']">new plan</a> <a [routerLink]="['PlanList']">plans</a> </div> </nav> diff --git a/app/components/app/app.ts b/app/components/app/app.ts index f9c83e0..1b78861 100644 --- a/app/components/app/app.ts +++ b/app/components/app/app.ts @@ -4,6 +4,7 @@ import {RouteConfig, ROUTER_DIRECTIVES} from 'angular2/router'; import {PlanView} from '../plan-view/plan-view'; import {PlanList} from '../plan-list/plan-list'; import {PlanNew} from '../plan-new/plan-new'; +import {About} from '../about/about'; @Component({ selector: 'app', @@ -16,7 +17,8 @@ import {PlanNew} from '../plan-new/plan-new'; { path: '/', redirectTo: ['/PlanList'] }, { path: '/plans', component: PlanList, name: 'PlanList' }, { path: '/plans/new', component: PlanNew, name: 'PlanNew' }, - { path: '/plans/:id', component: PlanView, name: 'PlanView' } + { path: '/plans/:id', component: PlanView, name: 'PlanView' }, + { path: '/about', component: About, name: 'About'} ]) export class App { } diff --git a/app/components/plan-new/plan-new.html b/app/components/plan-new/plan-new.html index ba65d99..ee2565e 100644 --- a/app/components/plan-new/plan-new.html +++ b/app/components/plan-new/plan-new.html @@ -2,7 +2,7 @@ <span class="text-muted">For best results, use EXPLAIN (ANALYZE, COSTS, VERBOSE, BUFFERS, FORMAT JSON)</span> <div> <input placeholder="name (optional)" class="input-box input-box-main" type="text" [(ngModel)]="newPlanName"> - <button class="btn btn-primary btn-lg pull-right" (click)="submitPlan()">submit</button> + <button class="btn btn-default btn-lg pad-top pull-right" (click)="submitPlan()">submit</button> </div> <textarea placeholder="paste execution plan" class="input-box input-box-lg" [(ngModel)]="newPlanContent"></textarea> diff --git a/app/components/plan-node/plan-node.html b/app/components/plan-node/plan-node.html index 08a7a96..fdc2c89 100644 --- a/app/components/plan-node/plan-node.html +++ b/app/components/plan-node/plan-node.html @@ -1,5 +1,5 @@ <div class="plan-node" [class.expanded]="showDetails"> - <header (click)="showDetails = !showDetails"> + <header (click)="showDetails = !showDetails" tooltip="view node details"> <h4>{{node[_planService.NODE_TYPE_PROP] | uppercase}} </h4> <span class="node-duration">{{duration}}<span class="text-muted">{{durationUnit}} | </span> @@ -7,11 +7,12 @@ </span> </header> - <div class="relation-name" *ngIf="node[_planService.RELATION_NAME_PROP]"> - <button *ngIf="plan.formattedQuery" class="btn btn-sm btn-default btn-slim pull-right" (click)="showQuery = !showQuery"> - <i class="fa fa-database"></i> - </button> + <button *ngIf="plan.formattedQuery" tooltip="view corresponding query" + class="btn btn-sm btn-default btn-slim pull-right" (click)="showQuery = !showQuery"> + <i class="fa fa-database"></i> + </button> + <div class="relation-name" *ngIf="node[_planService.RELATION_NAME_PROP]"> <span class="text-muted">on </span> <span *ngIf="node[_planService.SCHEMA_PROP]">{{node[_planService.SCHEMA_PROP]}}.</span>{{node[_planService.RELATION_NAME_PROP]}} <span *ngIf="node[_planService.ALIAS_PROP]"> ({{node[_planService.ALIAS_PROP]}})</span> @@ -31,7 +32,7 @@ </div> <div *ngIf="currentHighlightType !== highlightTypes.NONE"> - <div class="node-bar-container" [style.width]="(MAX_WIDTH+3)+'px'"> + <div class="node-bar-container" [style.width]="(MAX_WIDTH)+'px'"> <span class="node-bar" [style.width]="width+'px'" [style.backgroundColor]="backgroundColor"></span> </div> <span class="node-bar-label"> diff --git a/app/components/plan-node/plan-node.ts b/app/components/plan-node/plan-node.ts index fc865b8..2f3164e 100644 --- a/app/components/plan-node/plan-node.ts +++ b/app/components/plan-node/plan-node.ts @@ -66,7 +66,6 @@ export class PlanNode { } ngDoCheck() { - // console.log("check", this.currentHighlightType, this.viewOptions.highlightType); if (this.currentHighlightType !== this.viewOptions.highlightType) { this.currentHighlightType = this.viewOptions.highlightType; this.calculateBar(); @@ -78,6 +77,7 @@ export class PlanNode { keyItems.push(this.node[this._planService.SCHEMA_PROP] + '.' + this.node[this._planService.RELATION_NAME_PROP]); keyItems.push(' ' + this.node[this._planService.RELATION_NAME_PROP] + ' '); keyItems.push(' ' + this.node[this._planService.ALIAS_PROP] + ' '); + keyItems.push(this.node[this._planService.GROUP_KEY_PROP]); return this._syntaxHighlightService.highlightKeyItems(this.plan.formattedQuery, keyItems); } diff --git a/app/components/plan-view/plan-view.html b/app/components/plan-view/plan-view.html index c63c4d1..268bdac 100644 --- a/app/components/plan-view/plan-view.html +++ b/app/components/plan-view/plan-view.html @@ -55,6 +55,7 @@ <span class="stat-value">{{plan.planStats.maxCost | number:'.0-2'}}</span> <span class="stat-label">costliest node</span> </div> + <div class="btn-close" (click)="viewOptions.showPlanStats = false"><i class="fa fa-close"></i></div> </div> <div class="plan"> |