Mark Bergsma has uploaded a new change for review.
https://gerrit.wikimedia.org/r/179954
Change subject: Revert "Add 'xenon' module for aggregating ext_xenon-produced
traces".
......................................................................
Revert "Add 'xenon' module for aggregating ext_xenon-produced traces".
Let's review such changes first.
This reverts commit 793c30b11d4801abf3249cc2cbe2b09908a64b26.
Change-Id: I4b7a2c91b964a0f4fab27dba50da547661b6b44a
---
M manifests/role/performance.pp
D manifests/role/xenon.pp
D modules/xenon/files/flamegraph.pl
D modules/xenon/files/xenon-generate-svgs
D modules/xenon/files/xenon-log
D modules/xenon/files/xenon-log.conf
D modules/xenon/manifests/init.pp
M templates/apache/sites/performance.wikimedia.org.erb
D templates/apache/sites/xenon.erb
9 files changed, 0 insertions(+), 1,137 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/operations/puppet
refs/changes/54/179954/1
diff --git a/manifests/role/performance.pp b/manifests/role/performance.pp
index 14e2da2..226a957 100644
--- a/manifests/role/performance.pp
+++ b/manifests/role/performance.pp
@@ -5,7 +5,6 @@
#
class role::performance {
include ::apache
- include ::apache::mod::proxy
package { 'reporter/reporter':
provider => 'trebuchet',
diff --git a/manifests/role/xenon.pp b/manifests/role/xenon.pp
deleted file mode 100644
index 138d350..0000000
--- a/manifests/role/xenon.pp
+++ /dev/null
@@ -1,25 +0,0 @@
-# == Class: role::xenon
-#
-# Aggregates and graphs stack trace snapshots from MediaWiki
-# application servers, showing where time is spent.
-#
-class role::xenon {
- include ::xenon
-
- class { '::redis':
- maxmemory => '1Mb',
- persist => undef,
- redis_replication => undef,
- }
-
- Service['redis'] ~> Service['xenon']
-
- apache::site { 'xenon':
- content => template('apache/sites/xenon.erb'),
- }
-
- ferm::service { 'xenon_http':
- proto => 'tcp',
- port => '80',
- }
-}
diff --git a/modules/xenon/files/flamegraph.pl
b/modules/xenon/files/flamegraph.pl
deleted file mode 100755
index def5ed0..0000000
--- a/modules/xenon/files/flamegraph.pl
+++ /dev/null
@@ -1,846 +0,0 @@
-#!/usr/bin/perl -w
-#
-# flamegraph.pl flame stack grapher.
-#
-# This takes stack samples and renders a call graph, allowing hot functions
-# and codepaths to be quickly identified. Stack samples can be generated using
-# tools such as DTrace, perf, SystemTap, and Instruments.
-#
-# USAGE: ./flamegraph.pl [options] input.txt > graph.svg
-#
-# grep funcA input.txt | ./flamegraph.pl [options] > graph.svg
-#
-# Options are listed in the usage message (--help).
-#
-# The input is stack frames and sample counts formatted as single lines. Each
-# frame in the stack is semicolon separated, with a space and count at the end
-# of the line. These can be generated using DTrace with stackcollapse.pl,
-# and other tools using the stackcollapse variants.
-#
-# An optional extra column of counts can be provided to generate a differential
-# flame graph of the counts, colored red for more, and blue for less. This
-# can be useful when using flame graphs for non-regression testing.
-# See the header comment in the difffolded.pl program for instructions.
-#
-# The output graph shows relative presence of functions in stack samples. The
-# ordering on the x-axis has no meaning; since the data is samples, time order
-# of events is not known. The order used sorts function names alphabetically.
-#
-# While intended to process stack samples, this can also process stack traces.
-# For example, tracing stacks for memory allocation, or resource usage. You
-# can use --title to set the title to reflect the content, and --countname
-# to change "samples" to "bytes" etc.
-#
-# There are a few different palettes, selectable using --color. By default,
-# the colors are selected at random (except for differentials). Functions
-# called "-" will be printed gray, which can be used for stack separators (eg,
-# between user and kernel stacks).
-#
-# HISTORY
-#
-# This was inspired by Neelakanth Nadgir's excellent function_call_graph.rb
-# program, which visualized function entry and return trace events. As Neel
-# wrote: "The output displayed is inspired by Roch's CallStackAnalyzer which
-# was in turn inspired by the work on vftrace by Jan Boerhout". See:
-# https://blogs.oracle.com/realneel/entry/visualizing_callstacks_via_dtrace_and
-#
-# Copyright 2011 Joyent, Inc. All rights reserved.
-# Copyright 2011 Brendan Gregg. All rights reserved.
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at docs/cddl1.txt or
-# http://opensource.org/licenses/CDDL-1.0.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at docs/cddl1.txt.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-# 21-Nov-2013 Shawn Sterling Added consistent palette file option
-# 17-Mar-2013 Tim Bunce Added options and more tunables.
-# 15-Dec-2011 Dave Pacheco Support for frames with whitespace.
-# 10-Sep-2011 Brendan Gregg Created this.
-
-use strict;
-
-use Getopt::Long;
-
-# tunables
-my $encoding;
-my $fonttype = "Verdana";
-my $imagewidth = 1200; # max width, pixels
-my $frameheight = 16; # max height is dynamic
-my $fontsize = 12; # base text size
-my $fontwidth = 0.59; # avg width relative to fontsize
-my $minwidth = 0.1; # min function width, pixels
-my $nametype = "Function:"; # what are the names in the data?
-my $countname = "samples"; # what are the counts in the data?
-my $colors = "hot"; # color theme
-my $bgcolor1 = "#eeeeee"; # background color gradient start
-my $bgcolor2 = "#eeeeb0"; # background color gradient stop
-my $nameattrfile; # file holding function attributes
-my $timemax; # (override the) sum of the counts
-my $factor = 1; # factor to scale counts by
-my $hash = 0; # color by function name
-my $palette = 0; # if we use consistent palettes (default off)
-my %palette_map; # palette map hash
-my $pal_file = "palette.map"; # palette map file name
-my $stackreverse = 0; # reverse stack order, switching merge end
-my $inverted = 0; # icicle graph
-my $negate = 0; # switch differential hues
-my $titletext = ""; # centered heading
-my $titledefault = "Flame Graph"; # overwritten by --title
-my $titleinverted = "Icicle Graph"; # " "
-
-GetOptions(
- 'fonttype=s' => \$fonttype,
- 'width=i' => \$imagewidth,
- 'height=i' => \$frameheight,
- 'encoding=s' => \$encoding,
- 'fontsize=f' => \$fontsize,
- 'fontwidth=f' => \$fontwidth,
- 'minwidth=f' => \$minwidth,
- 'title=s' => \$titletext,
- 'nametype=s' => \$nametype,
- 'countname=s' => \$countname,
- 'nameattr=s' => \$nameattrfile,
- 'total=s' => \$timemax,
- 'factor=f' => \$factor,
- 'colors=s' => \$colors,
- 'hash' => \$hash,
- 'cp' => \$palette,
- 'reverse' => \$stackreverse,
- 'inverted' => \$inverted,
- 'negate' => \$negate,
-) or die <<USAGE_END;
-USAGE: $0 [options] infile > outfile.svg\n
- --title # change title text
- --width # width of image (default 1200)
- --height # height of each frame (default 16)
- --minwidth # omit smaller functions (default 0.1 pixels)
- --fonttype # font type (default "Verdana")
- --fontsize # font size (default 12)
- --countname # count type label (default "samples")
- --nametype # name type label (default "Function:")
- --colors # set color palette. choices are: hot (default), mem, io,
- # java, js, red, green, blue, yellow, purple, orange
- --hash # colors are keyed by function name hash
- --cp # use consistent palette (palette.map)
- --reverse # generate stack-reversed flame graph
- --inverted # icicle graph
- --negate # switch differential hues (blue<->red)
-
- eg,
- $0 --title="Flame Graph: malloc()" trace.txt > graph.svg
-USAGE_END
-
-# internals
-my $ypad1 = $fontsize * 4; # pad top, include title
-my $ypad2 = $fontsize * 2 + 10; # pad bottom, include labels
-my $xpad = 10; # pad lefm and right
-my $framepad = 1; # vertical padding for frames
-my $depthmax = 0;
-my %Events;
-my %nameattr;
-
-if ($titletext eq "") {
- unless ($inverted) {
- $titletext = $titledefault;
- } else {
- $titletext = $titleinverted;
- }
-}
-
-if ($nameattrfile) {
- # The name-attribute file format is a function name followed by a tab
then
- # a sequence of tab separated name=value pairs.
- open my $attrfh, $nameattrfile or die "Can't read $nameattrfile: $!\n";
- while (<$attrfh>) {
- chomp;
- my ($funcname, $attrstr) = split /\t/, $_, 2;
- die "Invalid format in $nameattrfile" unless defined $attrstr;
- $nameattr{$funcname} = { map { split /=/, $_, 2 } split /\t/,
$attrstr };
- }
-}
-
-if ($colors eq "mem") { $bgcolor1 = "#eeeeee"; $bgcolor2 = "#e0e0ff"; }
-if ($colors eq "io") { $bgcolor1 = "#f8f8f8"; $bgcolor2 = "#e8e8e8"; }
-
-# SVG functions
-{ package SVG;
- sub new {
- my $class = shift;
- my $self = {};
- bless ($self, $class);
- return $self;
- }
-
- sub header {
- my ($self, $w, $h) = @_;
- my $enc_attr = '';
- if (defined $encoding) {
- $enc_attr = qq{ encoding="$encoding"};
- }
- $self->{svg} .= <<SVG;
-<?xml version="1.0"$enc_attr standalone="no"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" width="$w" height="$h" onload="init(evt)" viewBox="0 0 $w
$h" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
-SVG
- }
-
- sub include {
- my ($self, $content) = @_;
- $self->{svg} .= $content;
- }
-
- sub colorAllocate {
- my ($self, $r, $g, $b) = @_;
- return "rgb($r,$g,$b)";
- }
-
- sub group_start {
- my ($self, $attr) = @_;
-
- my @g_attr = map {
- exists $attr->{$_} ? sprintf(qq/$_="%s"/, $attr->{$_})
: ()
- } qw(class style onmouseover onmouseout onclick);
- push @g_attr, $attr->{g_extra} if $attr->{g_extra};
- $self->{svg} .= sprintf qq/<g %s>\n/, join(' ', @g_attr);
-
- $self->{svg} .= sprintf qq/<title>%s<\/title>/, $attr->{title}
- if $attr->{title}; # should be first element within g
container
-
- if ($attr->{href}) {
- my @a_attr;
- push @a_attr, sprintf qq/xlink:href="%s"/,
$attr->{href} if $attr->{href};
- # default target=_top else links will open within SVG
<object>
- push @a_attr, sprintf qq/target="%s"/, $attr->{target}
|| "_top";
- push @a_attr, $attr->{a_extra}
if $attr->{a_extra};
- $self->{svg} .= sprintf qq/<a %s>/, join(' ', @a_attr);
- }
- }
-
- sub group_end {
- my ($self, $attr) = @_;
- $self->{svg} .= qq/<\/a>\n/ if $attr->{href};
- $self->{svg} .= qq/<\/g>\n/;
- }
-
- sub filledRectangle {
- my ($self, $x1, $y1, $x2, $y2, $fill, $extra) = @_;
- $x1 = sprintf "%0.1f", $x1;
- $x2 = sprintf "%0.1f", $x2;
- my $w = sprintf "%0.1f", $x2 - $x1;
- my $h = sprintf "%0.1f", $y2 - $y1;
- $extra = defined $extra ? $extra : "";
- $self->{svg} .= qq/<rect x="$x1" y="$y1" width="$w" height="$h"
fill="$fill" $extra \/>\n/;
- }
-
- sub stringTTF {
- my ($self, $color, $font, $size, $angle, $x, $y, $str, $loc,
$extra) = @_;
- $x = sprintf "%0.2f", $x;
- $loc = defined $loc ? $loc : "left";
- $extra = defined $extra ? $extra : "";
- $self->{svg} .= qq/<text text-anchor="$loc" x="$x" y="$y"
font-size="$size" font-family="$font" fill="$color" $extra >$str<\/text>\n/;
- }
-
- sub svg {
- my $self = shift;
- return "$self->{svg}</svg>\n";
- }
- 1;
-}
-
-sub namehash {
- # Generate a vector hash for the name string, weighting early over
- # later characters. We want to pick the same colors for function
- # names across different flame graphs.
- my $name = shift;
- my $vector = 0;
- my $weight = 1;
- my $max = 1;
- my $mod = 10;
- # if module name present, trunc to 1st char
- $name =~ s/.(.*?)`//;
- foreach my $c (split //, $name) {
- my $i = (ord $c) % $mod;
- $vector += ($i / ($mod++ - 1)) * $weight;
- $max += 1 * $weight;
- $weight *= 0.70;
- last if $mod > 12;
- }
- return (1 - $vector / $max)
-}
-
-sub color {
- my ($type, $hash, $name) = @_;
- my ($v1, $v2, $v3);
-
- if ($hash) {
- $v1 = namehash($name);
- $v2 = $v3 = namehash(scalar reverse $name);
- } else {
- $v1 = rand(1);
- $v2 = rand(1);
- $v3 = rand(1);
- }
-
- # theme palettes
- if (defined $type and $type eq "hot") {
- my $r = 205 + int(50 * $v3);
- my $g = 0 + int(230 * $v1);
- my $b = 0 + int(55 * $v2);
- return "rgb($r,$g,$b)";
- }
- if (defined $type and $type eq "mem") {
- my $r = 0;
- my $g = 190 + int(50 * $v2);
- my $b = 0 + int(210 * $v1);
- return "rgb($r,$g,$b)";
- }
- if (defined $type and $type eq "io") {
- my $r = 80 + int(60 * $v1);
- my $g = $r;
- my $b = 190 + int(55 * $v2);
- return "rgb($r,$g,$b)";
- }
-
- # multi palettes
- if (defined $type and $type eq "java") {
- if ($name =~ /::/) { # C++
- $type = "yellow";
- } elsif ($name =~ m:/:) { # Java (match "/" in path)
- $type = "green"
- } else { # system
- $type = "red";
- }
- # fall-through to color palettes
- }
- if (defined $type and $type eq "js") {
- if ($name =~ /::/) { # C++
- $type = "yellow";
- } elsif ($name =~ m:/:) { # JavaScript (match "/" in path)
- $type = "green"
- } elsif ($name =~ m/:/) { # JavaScript (match ":" in
builtin)
- $type = "aqua"
- } elsif ($name =~ m/^ $/) { # Missing symbol
- $type = "green"
- } else { # system
- $type = "red";
- }
- # fall-through to color palettes
- }
-
- # color palettes
- if (defined $type and $type eq "red") {
- my $r = 200 + int(55 * $v1);
- my $x = 50 + int(80 * $v1);
- return "rgb($r,$x,$x)";
- }
- if (defined $type and $type eq "green") {
- my $g = 200 + int(55 * $v1);
- my $x = 50 + int(60 * $v1);
- return "rgb($x,$g,$x)";
- }
- if (defined $type and $type eq "blue") {
- my $b = 205 + int(50 * $v1);
- my $x = 80 + int(60 * $v1);
- return "rgb($x,$x,$b)";
- }
- if (defined $type and $type eq "yellow") {
- my $x = 175 + int(55 * $v1);
- my $b = 50 + int(20 * $v1);
- return "rgb($x,$x,$b)";
- }
- if (defined $type and $type eq "purple") {
- my $x = 190 + int(65 * $v1);
- my $g = 80 + int(60 * $v1);
- return "rgb($x,$g,$x)";
- }
- if (defined $type and $type eq "aqua") {
- my $r = 50 + int(60 * $v1);
- my $g = 165 + int(55 * $v1);
- my $b = 165 + int(55 * $v1);
- return "rgb($r,$g,$b)";
- }
- if (defined $type and $type eq "orange") {
- my $r = 190 + int(65 * $v1);
- my $g = 90 + int(65 * $v1);
- return "rgb($r,$g,0)";
- }
-
- return "rgb(0,0,0)";
-}
-
-sub color_scale {
- my ($value, $max) = @_;
- my ($r, $g, $b) = (255, 255, 255);
- $value = -$value if $negate;
- if ($value > 0) {
- $g = $b = int(210 * ($max - $value) / $max);
- } elsif ($value < 0) {
- $r = $g = int(210 * ($max + $value) / $max);
- }
- return "rgb($r,$g,$b)";
-}
-
-sub color_map {
- my ($colors, $func) = @_;
- if (exists $palette_map{$func}) {
- return $palette_map{$func};
- } else {
- $palette_map{$func} = color($colors);
- return $palette_map{$func};
- }
-}
-
-sub write_palette {
- open(FILE, ">$pal_file");
- foreach my $key (sort keys %palette_map) {
- print FILE $key."->".$palette_map{$key}."\n";
- }
- close(FILE);
-}
-
-sub read_palette {
- if (-e $pal_file) {
- open(FILE, $pal_file) or die "can't open file $pal_file: $!";
- while ( my $line = <FILE>) {
- chomp($line);
- (my $key, my $value) = split("->",$line);
- $palette_map{$key}=$value;
- }
- close(FILE)
- }
-}
-
-my %Node; # Hash of merged frame data
-my %Tmp;
-
-# flow() merges two stacks, storing the merged frames and value data in %Node.
-sub flow {
- my ($last, $this, $v, $d) = @_;
-
- my $len_a = @$last - 1;
- my $len_b = @$this - 1;
-
- my $i = 0;
- my $len_same;
- for (; $i <= $len_a; $i++) {
- last if $i > $len_b;
- last if $last->[$i] ne $this->[$i];
- }
- $len_same = $i;
-
- for ($i = $len_a; $i >= $len_same; $i--) {
- my $k = "$last->[$i];$i";
- # a unique ID is constructed from "func;depth;etime";
- # func-depth isn't unique, it may be repeated later.
- $Node{"$k;$v"}->{stime} = delete $Tmp{$k}->{stime};
- if (defined $Tmp{$k}->{delta}) {
- $Node{"$k;$v"}->{delta} = delete $Tmp{$k}->{delta};
- }
- delete $Tmp{$k};
- }
-
- for ($i = $len_same; $i <= $len_b; $i++) {
- my $k = "$this->[$i];$i";
- $Tmp{$k}->{stime} = $v;
- if (defined $d) {
- $Tmp{$k}->{delta} += $i == $len_b ? $d : 0;
- }
- }
-
- return $this;
-}
-
-# parse input
-my @Data;
-my $last = [];
-my $time = 0;
-my $delta = undef;
-my $ignored = 0;
-my $line;
-my $maxdelta = 1;
-
-# reverse if needed
-foreach (<>) {
- chomp;
- $line = $_;
- if ($stackreverse) {
- # there may be an extra samples column for differentials
- # XXX todo: redo these REs as one. It's repeated below.
- my ($stack, $samples) = (/^(.*)\s+?(\d+(?:\.\d*)?)$/);
- my $samples2 = undef;
- if ($stack =~ /^(.*)\s+?(\d+(?:\.\d*)?)$/) {
- $samples2 = $samples;
- ($stack, $samples) = $stack =~
(/^(.*)\s+?(\d+(?:\.\d*)?)$/);
- unshift @Data, join(";", reverse split(";", $stack)) .
" $samples $samples2";
- } else {
- unshift @Data, join(";", reverse split(";", $stack)) .
" $samples";
- }
- } else {
- unshift @Data, $line;
- }
-}
-
-# process and merge frames
-foreach (sort @Data) {
- chomp;
- # process: folded_stack count
- # eg: func_a;func_b;func_c 31
- my ($stack, $samples) = (/^(.*)\s+?(\d+(?:\.\d*)?)$/);
- unless (defined $samples and defined $stack) {
- ++$ignored;
- next;
- }
-
- # there may be an extra samples column for differentials:
- my $samples2 = undef;
- if ($stack =~ /^(.*)\s+?(\d+(?:\.\d*)?)$/) {
- $samples2 = $samples;
- ($stack, $samples) = $stack =~ (/^(.*)\s+?(\d+(?:\.\d*)?)$/);
- }
- $delta = undef;
- if (defined $samples2) {
- $delta = $samples2 - $samples;
- $maxdelta = abs($delta) if abs($delta) > $maxdelta;
- }
-
- $stack =~ tr/<>/()/;
-
- # merge frames and populate %Node:
- $last = flow($last, [ '', split ";", $stack ], $time, $delta);
-
- if (defined $samples2) {
- $time += $samples2;
- } else {
- $time += $samples;
- }
-}
-flow($last, [], $time, $delta);
-
-warn "Ignored $ignored lines with invalid format\n" if $ignored;
-unless ($time) {
- warn "ERROR: No stack counts found\n";
- my $im = SVG->new();
- # emit an error message SVG, for tools automating flamegraph use
- my $imageheight = $fontsize * 5;
- $im->header($imagewidth, $imageheight);
- $im->stringTTF($im->colorAllocate(0, 0, 0), $fonttype, $fontsize + 2,
- 0.0, int($imagewidth / 2), $fontsize * 2,
- "ERROR: No valid input provided to flamegraph.pl.", "middle");
- print $im->svg;
- exit 2;
-}
-if ($timemax and $timemax < $time) {
- warn "Specified --total $timemax is less than actual total $time, so
ignored\n"
- if $timemax/$time > 0.02; # only warn is significant (e.g., not
rounding etc)
- undef $timemax;
-}
-$timemax ||= $time;
-
-my $widthpertime = ($imagewidth - 2 * $xpad) / $timemax;
-my $minwidth_time = $minwidth / $widthpertime;
-
-# prune blocks that are too narrow and determine max depth
-while (my ($id, $node) = each %Node) {
- my ($func, $depth, $etime) = split ";", $id;
- my $stime = $node->{stime};
- die "missing start for $id" if not defined $stime;
-
- if (($etime-$stime) < $minwidth_time) {
- delete $Node{$id};
- next;
- }
- $depthmax = $depth if $depth > $depthmax;
-}
-
-# draw canvas, and embed interactive JavaScript program
-my $imageheight = ($depthmax * $frameheight) + $ypad1 + $ypad2;
-my $im = SVG->new();
-$im->header($imagewidth, $imageheight);
-my $inc = <<INC;
-<defs >
- <linearGradient id="background" y1="0" y2="1" x1="0" x2="0" >
- <stop stop-color="$bgcolor1" offset="5%" />
- <stop stop-color="$bgcolor2" offset="95%" />
- </linearGradient>
-</defs>
-<style type="text/css">
- .func_g:hover { stroke:black; stroke-width:0.5; cursor:pointer; }
-</style>
-<script type="text/ecmascript">
-<![CDATA[
- var details, svg;
- function init(evt) {
- details = document.getElementById("details").firstChild;
- svg = document.getElementsByTagName("svg")[0];
- }
- function s(info) { details.nodeValue = "$nametype " + info; }
- function c() { details.nodeValue = ' '; }
- function find_child(parent, name, attr) {
- var children = parent.childNodes;
- for (var i=0; i<children.length;i++) {
- if (children[i].tagName == name)
- return (attr != undefined) ?
children[i].attributes[attr].value : children[i];
- }
- return;
- }
- function orig_save(e, attr, val) {
- if (e.attributes["_orig_"+attr] != undefined) return;
- if (e.attributes[attr] == undefined) return;
- if (val == undefined) val = e.attributes[attr].value;
- e.setAttribute("_orig_"+attr, val);
- }
- function orig_load(e, attr) {
- if (e.attributes["_orig_"+attr] == undefined) return;
- e.attributes[attr].value = e.attributes["_orig_"+attr].value;
- e.removeAttribute("_orig_"+attr);
- }
- function update_text(e) {
- var r = find_child(e, "rect");
- var t = find_child(e, "text");
- var w = parseFloat(r.attributes["width"].value) -3;
- var txt = find_child(e,
"title").textContent.replace(/\\([^(]*\\)/,"");
- t.attributes["x"].value = parseFloat(r.attributes["x"].value)
+3;
-
- // Smaller than this size won't fit anything
- if (w < 2*$fontsize*$fontwidth) {
- t.textContent = "";
- return;
- }
-
- t.textContent = txt;
- // Fit in full text width
- if (/^ *\$/.test(txt) || t.getSubStringLength(0, txt.length) <
w)
- return;
-
- for (var x=txt.length-2; x>0; x--) {
- if (t.getSubStringLength(0, x+2) <= w) {
- t.textContent = txt.substring(0,x) + "..";
- return;
- }
- }
- t.textContent = "";
- }
- function zoom_reset(e) {
- if (e.attributes != undefined) {
- orig_load(e, "x");
- orig_load(e, "width");
- }
- if (e.childNodes == undefined) return;
- for(var i=0, c=e.childNodes; i<c.length; i++) {
- zoom_reset(c[i]);
- }
- }
- function zoom_child(e, x, ratio) {
- if (e.attributes != undefined) {
- if (e.attributes["x"] != undefined) {
- orig_save(e, "x");
- e.attributes["x"].value =
(parseFloat(e.attributes["x"].value) - x - $xpad) * ratio + $xpad;
- if(e.tagName == "text") e.attributes["x"].value
= find_child(e.parentNode, "rect", "x") + 3;
- }
- if (e.attributes["width"] != undefined) {
- orig_save(e, "width");
- e.attributes["width"].value =
parseFloat(e.attributes["width"].value) * ratio;
- }
- }
-
- if (e.childNodes == undefined) return;
- for(var i=0, c=e.childNodes; i<c.length; i++) {
- zoom_child(c[i], x-$xpad, ratio);
- }
- }
- function zoom_parent(e) {
- if (e.attributes) {
- if (e.attributes["x"] != undefined) {
- orig_save(e, "x");
- e.attributes["x"].value = $xpad;
- }
- if (e.attributes["width"] != undefined) {
- orig_save(e, "width");
- e.attributes["width"].value =
parseInt(svg.width.baseVal.value) - ($xpad*2);
- }
- }
- if (e.childNodes == undefined) return;
- for(var i=0, c=e.childNodes; i<c.length; i++) {
- zoom_parent(c[i]);
- }
- }
- function zoom(node) {
- var attr = find_child(node, "rect").attributes;
- var width = parseFloat(attr["width"].value);
- var xmin = parseFloat(attr["x"].value);
- var xmax = parseFloat(xmin + width);
- var ymin = parseFloat(attr["y"].value);
- var ratio = (svg.width.baseVal.value - 2*$xpad) / width;
-
- // XXX: Workaround for JavaScript float issues (fix me)
- var fudge = 0.0001;
-
- var unzoombtn = document.getElementById("unzoom");
- unzoombtn.style["opacity"] = "1.0";
-
- var el = document.getElementsByTagName("g");
- for(var i=0;i<el.length;i++){
- var e = el[i];
- var a = find_child(e, "rect").attributes;
- var ex = parseFloat(a["x"].value);
- var ew = parseFloat(a["width"].value);
- // Is it an ancestor
- if ($inverted == 0) {
- var upstack = parseFloat(a["y"].value) > ymin;
- } else {
- var upstack = parseFloat(a["y"].value) < ymin;
- }
- if (upstack) {
- // Direct ancestor
- if (ex <= xmin && (ex+ew+fudge) >= xmax) {
- e.style["opacity"] = "0.5";
- zoom_parent(e);
- e.onclick = function(e){unzoom();
zoom(this);};
- update_text(e);
- }
- // not in current path
- else
- e.style["display"] = "none";
- }
- // Children maybe
- else {
- // no common path
- if (ex < xmin || ex + fudge >= xmax) {
- e.style["display"] = "none";
- }
- else {
- zoom_child(e, xmin, ratio);
- e.onclick = function(e){zoom(this);};
- update_text(e);
- }
- }
- }
- }
- function unzoom() {
- var unzoombtn = document.getElementById("unzoom");
- unzoombtn.style["opacity"] = "0.0";
-
- var el = document.getElementsByTagName("g");
- for(i=0;i<el.length;i++) {
- el[i].style["display"] = "block";
- el[i].style["opacity"] = "1";
- zoom_reset(el[i]);
- update_text(el[i]);
- }
- }
-]]>
-</script>
-INC
-$im->include($inc);
-$im->filledRectangle(0, 0, $imagewidth, $imageheight, 'url(#background)');
-my ($white, $black, $vvdgrey, $vdgrey) = (
- $im->colorAllocate(255, 255, 255),
- $im->colorAllocate(0, 0, 0),
- $im->colorAllocate(40, 40, 40),
- $im->colorAllocate(160, 160, 160),
- );
-$im->stringTTF($black, $fonttype, $fontsize + 5, 0.0, int($imagewidth / 2),
$fontsize * 2, $titletext, "middle");
-$im->stringTTF($black, $fonttype, $fontsize, 0.0, $xpad, $imageheight -
($ypad2 / 2), " ", "", 'id="details"');
-$im->stringTTF($black, $fonttype, $fontsize, 0.0, $xpad, $fontsize * 2,
- "Reset Zoom", "", 'id="unzoom" onclick="unzoom()"
style="opacity:0.0;cursor:pointer"');
-
-if ($palette) {
- read_palette();
-}
-
-# draw frames
-while (my ($id, $node) = each %Node) {
- my ($func, $depth, $etime) = split ";", $id;
- my $stime = $node->{stime};
- my $delta = $node->{delta};
-
- $etime = $timemax if $func eq "" and $depth == 0;
-
- my $x1 = $xpad + $stime * $widthpertime;
- my $x2 = $xpad + $etime * $widthpertime;
- my ($y1, $y2);
- unless ($inverted) {
- $y1 = $imageheight - $ypad2 - ($depth + 1) * $frameheight +
$framepad;
- $y2 = $imageheight - $ypad2 - $depth * $frameheight;
- } else {
- $y1 = $ypad1 + $depth * $frameheight;
- $y2 = $ypad1 + ($depth + 1) * $frameheight - $framepad;
- }
-
- my $samples = sprintf "%.0f", ($etime - $stime) * $factor;
- (my $samples_txt = $samples) # add commas per perlfaq5
- =~ s/(^[-+]?\d+?(?=(?>(?:\d{3})+)(?!\d))|\G\d{3}(?=\d))/$1,/g;
-
- my $info;
- if ($func eq "" and $depth == 0) {
- $info = "all ($samples_txt $countname, 100%)";
- } else {
- my $pct = sprintf "%.2f", ((100 * $samples) / ($timemax *
$factor));
- my $escaped_func = $func;
- $escaped_func =~ s/&/&/g;
- $escaped_func =~ s/</</g;
- $escaped_func =~ s/>/>/g;
- unless (defined $delta) {
- $info = "$escaped_func ($samples_txt $countname,
$pct%)";
- } else {
- my $deltapct = sprintf "%.2f", ((100 * $delta) /
($timemax * $factor));
- $deltapct = $delta > 0 ? "+$deltapct" : $deltapct;
- $info = "$escaped_func ($samples_txt $countname, $pct%;
$deltapct%)";
- }
- }
-
- my $nameattr = { %{ $nameattr{$func}||{} } }; # shallow clone
- $nameattr->{class} ||= "func_g";
- $nameattr->{onmouseover} ||= "s('".$info."')";
- $nameattr->{onmouseout} ||= "c()";
- $nameattr->{onclick} ||= "zoom(this)";
- $nameattr->{title} ||= $info;
- $im->group_start($nameattr);
-
- my $color;
- if ($func eq "-") {
- $color = $vdgrey;
- } elsif (defined $delta) {
- $color = color_scale($delta, $maxdelta);
- } elsif ($palette) {
- $color = color_map($colors, $func);
- } else {
- $color = color($colors, $hash, $func);
- }
- $im->filledRectangle($x1, $y1, $x2, $y2, $color, 'rx="2" ry="2"');
-
- my $chars = int( ($x2 - $x1) / ($fontsize * $fontwidth));
- my $text = "";
- if ($chars >= 3) { # room for one char plus two dots
- $text = substr $func, 0, $chars;
- substr($text, -2, 2) = ".." if $chars < length $func;
- $text =~ s/&/&/g;
- $text =~ s/</</g;
- $text =~ s/>/>/g;
- }
- $im->stringTTF($black, $fonttype, $fontsize, 0.0, $x1 + 3, 3 + ($y1 +
$y2) / 2, $text, "");
-
- $im->group_end($nameattr);
-}
-
-print $im->svg;
-
-if ($palette) {
- write_palette();
-}
-
-# vim: ts=8 sts=8 sw=8 noexpandtab
diff --git a/modules/xenon/files/xenon-generate-svgs
b/modules/xenon/files/xenon-generate-svgs
deleted file mode 100755
index d9c958b..0000000
--- a/modules/xenon/files/xenon-generate-svgs
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/bash
-set +C # OK to clobber out-of-date SVGs
-for log in "/srv/xenon/logs/*/*.log"; do
- svg="${log//log/svg}"
- mkdir -m0755 -p "$(dirname $svg)"
- [ ! -f "$svg" -o "$svg" -ot "$log" ] && {
- /usr/local/bin/flamegraph.pl --minwidth=1 "$log" > "$svg"
- }
-done
diff --git a/modules/xenon/files/xenon-log b/modules/xenon/files/xenon-log
deleted file mode 100755
index 73cb3c3..0000000
--- a/modules/xenon/files/xenon-log
+++ /dev/null
@@ -1,91 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-"""
- xenon-log
- ~~~~~~~~~
-
- `xenon` is a built-in HHVM extension that periodically captures
- stacktraces of running PHP code. This tool reads xenon-generated
- traces via redis and logs them to disk.
-
-"""
-from __future__ import print_function
-
-import sys
-reload(sys)
-sys.setdefaultencoding('utf-8')
-
-import argparse
-import datetime
-import errno
-import logging
-import os
-import os.path
-
-import redis
-import yaml
-
-
-parser = argparse.ArgumentParser()
-parser.add_argument('config', nargs='?', default='/etc/xenon/config.yaml',
- type=argparse.FileType('r'))
-args = parser.parse_args()
-
-with args.config as f:
- config = yaml.load(f)
-
-
-class TimeLog(object):
-
- base_path = config.get('base_path', '/srv/xenon/logs')
-
- def __init__(self, period, format, retain):
- self.period = period
- self.format = format
- self.retain = retain
- self.path = os.path.join(self.base_path, period)
- try:
- os.makedirs(self.path, 0755)
- except OSError as exc:
- if exc.errno != errno.EEXIST: raise
-
- def get_time_from_file(self, file_name):
- return datetime.datetime.strptime(file_name, self.format + '.log')
-
- def get_file_from_time(self, time=None):
- time = datetime.datetime.utcnow() if time is None else time
- return time.strftime(self.format) + '.log'
-
- def write(self, message, time=None):
- file = os.path.join(self.path, self.get_file_from_time(time))
- if not os.path.isfile(file):
- self.prune_files()
- with open(file, 'a') as f:
- print(message, file=f)
-
- def prune_files(self):
- files = {}
- for file in os.listdir(self.path):
- try:
- files[file] = self.get_time_from_file(file)
- except ValueError:
- continue
- files = list(sorted(files, key=files.get, reverse=True))
- for file in files[self.retain:]:
- try:
- os.remove(os.path.join(path, file))
- except OSError:
- continue
-
-
-
-logs = [TimeLog(**log) for log in config['logs']]
-conn = redis.Redis(config['redis'])
-pubsub = conn.pubsub()
-pubsub.subscribe('xenon')
-
-for message in pubsub.listen():
- data = message['data']
- time = datetime.datetime.utcnow()
- for log in logs:
- log.write(data, time)
diff --git a/modules/xenon/files/xenon-log.conf
b/modules/xenon/files/xenon-log.conf
deleted file mode 100644
index 1858e81..0000000
--- a/modules/xenon/files/xenon-log.conf
+++ /dev/null
@@ -1,13 +0,0 @@
-# xenon-log - Log Xenon traces to disk.
-
-description "Xenon trace logger"
-
-start on (local-filesystems and net-device-up IFACE!=lo)
-
-setuid www-data
-setgid www-data
-
-respawn
-respawn limit unlimited
-
-exec /usr/bin/python /usr/local/bin/xenon-log /etc/xenon-log.yaml
diff --git a/modules/xenon/manifests/init.pp b/modules/xenon/manifests/init.pp
deleted file mode 100644
index ba7b3ca..0000000
--- a/modules/xenon/manifests/init.pp
+++ /dev/null
@@ -1,133 +0,0 @@
-# == Class: xenon
-#
-# Xenon is an HHVM extension that periodically captures a stack trace of
-# PHP code. MediaWiki servers send the captured trace via Redis pub/sub.
-# This class implements an aggregator that stores captured traces to disk
-# and generates SVG flame graphs from them.
-#
-# === Parameters
-#
-# [*ensure*]
-# Description
-#
-# [*redis_host*]
-# Address of Redis server that is publishing Xenon traces.
-# Default: '127.0.0.1'.
-#
-# [*redis_port*]
-# Port of Redis server that is publishing Xenon traces.
-# Default: 6379.
-#
-# === Examples
-#
-# class { 'xenon':
-# ensure => present,
-# redis_host => 'fluorine.eqiad.wmnet',
-# redis_port => 6379,
-# }
-#
-class xenon(
- $ensure = present,
- $redis_host = '127.0.0.1',
- $redis_port = 6379,
-) {
- require_package('python-redis')
- require_package('python-yaml')
-
- $config = {
- base_path => '/srv/xenon/logs',
- redis => {
- host => $redis_host,
- port => $redis_port,
- },
- logs => [
- { period => 'hourly', format => '%Y-%m-%d_%H', retain => 24 },
- { period => 'daily', format => '%Y-%m-%d', retain => 30 },
- { period => 'weekly', format => '%Y-%W', retain => 52 },
- { period => 'monthly', format => '%Y-%m', retain => 12 },
- ],
- }
-
- group { 'xenon':
- ensure => $ensure,
- }
-
- user { 'xenon':
- ensure => $ensure,
- gid => 'xenon',
- shell => '/bin/false',
- home => '/nonexistent',
- system => true,
- managehome => false,
- }
-
- file { '/srv/xenon':
- ensure => ensure_directory($ensure),
- owner => 'xenon',
- group => 'xenon',
- mode => '0755',
- before => Service['xenon-log'],
- }
-
- file { '/etc/xenon-log.yaml':
- ensure => $ensure,
- content => ordered_yaml($config),
- owner => 'root',
- group => 'root',
- mode => '0444',
- notify => Service['xenon-log'],
- }
-
- file { '/usr/local/bin/xenon-log':
- ensure => $ensure,
- source => 'puppet:///modules/xenon/xenon-log',
- owner => 'root',
- group => 'root',
- mode => '0555',
- notify => Service['xenon-log'],
- }
-
- file { '/etc/init/xenon-log.conf':
- ensure => $ensure,
- source => 'puppet:///modules/xenon/xenon-log.conf',
- notify => Service['xenon-log'],
- }
-
- service { 'xenon-log':
- ensure => ensure_service($ensure),
- provider => 'upstart',
- }
-
-
- # This is the Perl script that generates flame graphs.
- # It comes from <https://github.com/brendangregg/FlameGraph>.
-
- file { '/usr/local/bin/flamegraph.pl':
- ensure => $ensure,
- source => 'puppet:///modules/xenon/flamegraph.pl',
- owner => 'root',
- group => 'root',
- mode => '0555',
- notify => Service['xenon-log'],
- }
-
-
- # Walks /srv/xenon/logs looking for log files which do not have a
- # corresponding SVG file and calls flamegraph.pl on each of them.
-
- file { '/usr/local/bin/xenon-generate-svgs':
- ensure => $ensure,
- source => 'puppet:///modules/xenon/xenon-generate-svgs',
- owner => 'root',
- group => 'root',
- mode => '0555',
- before => Cron['xenon_generate_svgs'],
- }
-
- cron { 'xenon_generate_svgs':
- ensure => $ensure,
- command => '/usr/local/bin/xenon-generate-svgs',
- user => 'xenon',
- minute => '*/15',
- }
-}
diff --git a/templates/apache/sites/performance.wikimedia.org.erb
b/templates/apache/sites/performance.wikimedia.org.erb
index 00838f6..8d27032 100644
--- a/templates/apache/sites/performance.wikimedia.org.erb
+++ b/templates/apache/sites/performance.wikimedia.org.erb
@@ -14,7 +14,4 @@
Order allow,deny
allow from all
</Directory>
-
- ProxyPass /xenon http://fluorine.eqiad.wmnet
- ProxyPassReverse /xenon http://fluorine.eqiad.wmnet
</VirtualHost>
diff --git a/templates/apache/sites/xenon.erb b/templates/apache/sites/xenon.erb
deleted file mode 100644
index 9ea2909..0000000
--- a/templates/apache/sites/xenon.erb
+++ /dev/null
@@ -1,16 +0,0 @@
-# Apache configuration for xenon SVG hosting.
-# This file is managed by Puppet.
-<VirtualHost *:80>
- DocumentRoot /srv/xenon/svgs
-
- <Directory />
- AllowOverride None
- </Directory>
-
- <Directory /srv/xenon/svgs>
- Options Indexes
- AllowOverride None
- Order allow,deny
- allow from all
- </Directory>
-</VirtualHost>
--
To view, visit https://gerrit.wikimedia.org/r/179954
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I4b7a2c91b964a0f4fab27dba50da547661b6b44a
Gerrit-PatchSet: 1
Gerrit-Project: operations/puppet
Gerrit-Branch: production
Gerrit-Owner: Mark Bergsma <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits