Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
prepare new release
  • Loading branch information
lesovsky committed Oct 3, 2019
2 parents c333d5a + 5276228 commit e555ab8
Show file tree
Hide file tree
Showing 20 changed files with 438 additions and 131 deletions.
7 changes: 5 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@ SHAREDIR = ${PREFIX}/share
MANDIR = ${SHAREDIR}/man/man1

SOURCE = ${PROGRAM_NAME}.go
COMMIT=$(shell git rev-parse HEAD)
COMMIT=$(shell git rev-parse --short HEAD)
BRANCH=$(shell git rev-parse --abbrev-ref HEAD)
TAG=$(shell git describe --tags |cut -d- -f1)

LDFLAGS = -ldflags "-X main.COMMIT=${COMMIT} -X main.BRANCH=${BRANCH}"
LDFLAGS = -ldflags "-X github.com/lesovsky/pgcenter/cmd.GitTag=${TAG} \
-X github.com/lesovsky/pgcenter/cmd.GitCommit=${COMMIT} \
-X github.com/lesovsky/pgcenter/cmd.GitBranch=${BRANCH}"

DESTDIR ?=

Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ pgCenter is a command-line admin tool for observing and troubleshooting Postgres
Postgres provides various activity statistics that include detailed information about its behaviour: connections, statements, database operations, replication, resources usage and more. General purpose of the statistics is to help DBAs to monitor and troubleshoot Postgres. However, these statistics provided in textual form retrieved from SQL functions and views, and Postgres doesn't provide any tools for working with them.
pgCenter's main goal is to help Postgres DBA manage statistics that theу have in their databases and see all the necessary data in convenient format based on builtin stats views and functions.

![](doc/images/pgcenter-demo.gif)

#### Key features
- Top-like interface that allows you to monitor stats changes as you go. See details [here](doc/pgcenter-top-readme.md).
- Configuration management function allows viewing and editing of current configuration files and reloading the service, if needed.
Expand All @@ -45,7 +47,9 @@ pgCenter supports majority of statistics views available in Postgres, and at the
- [pg_stat_user_functions](https://www.postgresql.org/docs/current/static/monitoring-stats.html#PG-STAT-USER-FUNCTIONS-VIEW) - statistics on execution of functions.
- [pg_stat_statements](https://www.postgresql.org/docs/current/static/pgstatstatements.html) - statistics on SQL statements executed including time and resources usage.
- statistics on tables sizes based on `pg_relation_size()` and `pg_total_relation_size()` functions;
- [pg_stat_progress_vacuum](https://www.postgresql.org/docs/current/static/progress-reporting.html#VACUUM-PROGRESS-REPORTING) - information about (auto)vacuums status.
- [pg_stat_progress_vacuum](https://www.postgresql.org/docs/current/progress-reporting.html#VACUUM-PROGRESS-REPORTING) - information about progress of (auto)vacuums status.
- [pg_stat_progress_cluster](https://www.postgresql.org/docs/current/progress-reporting.html#CLUSTER-PROGRESS-REPORTING) - information about progress of CLUSTER and VACUUM FULL operations.
- [pg_stat_progress_create_index](https://www.postgresql.org/docs/current/progress-reporting.html#CREATE-INDEX-PROGRESS-REPORTING) - information about progress of CREATE INDEX and REINDEX operations.

##### System statistics
`pgcenter top` also provides system usage information based on statistics from `procfs` filesystem:
Expand Down
3 changes: 2 additions & 1 deletion cmd/help.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,8 @@ Report options:
-R, --replication show pg_stat_replication statistics
-T, --tables show pg_stat_user_tables statistics
-I, --indexes show pg_stat_user_indexes and pg_statio_user_indexes statistics
-V, --vacuum show pg_stat_progress_vacuum statistics
-P, --progress [X] show pg_stat_progress_* statistics, use additional selector to choose stats.
'v' - vacuum; 'c' - cluster; 'i' - create index.
-X, --statements [X] show pg_stat_statements statistics, use additional selector to choose stats.
'm' - timings; 'g' - general; 'i' - io; 't' - temp files io; 'l' - local files io.
Expand Down
51 changes: 34 additions & 17 deletions cmd/report/report.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ var (
showReplication bool // Show stats from pg_stat_replication
showTables bool // Show stats from pg_stat_user_tables, pg_statio_user_tables
showIndexes bool // Show stats from pg_stat_user_indexes, pg_statio_user_indexes
showVacuum bool // Show stats from pg_stat_progress_vacuum
showProgress string // Show stats from pg_stat_progress_* stats
showStatements string // Show stats from pg_stat_statements
showSizes bool // Show tables sizes
describe bool // Show description of requested stats view
Expand All @@ -60,7 +60,7 @@ var (
"replication": {view: stat.ReplicationView, ctx: stat.PgStatReplicationUnit},
"tables": {view: stat.TablesView, ctx: stat.PgStatTablesUnit},
"indexes": {view: stat.IndexesView, ctx: stat.PgStatIndexesUnit},
"vacuum": {view: stat.VacuumView, ctx: stat.PgStatVacuumUnit},
"progress": {view: "_PROGRESS_"},
"statements": {view: "_STATEMENTS_"},
}
// statementsReports is the statements reports available for user's choice
Expand All @@ -74,6 +74,14 @@ var (
"t": {view: stat.StatementsTempView, ctx: stat.PgSSTempUnit},
"l": {view: stat.StatementsLocalView, ctx: stat.PgSSLocalUnit},
}
progressReports = map[string]struct {
view string
ctx stat.ContextUnit
}{
"v": {view: stat.ProgressVacuumView, ctx: stat.PgStatProgressVacuumUnit},
"c": {view: stat.ProgressClusterView, ctx: stat.PgStatProgressClusterUnit},
"i": {view: stat.ProgressCreateIndexView, ctx: stat.PgStatProgressCreateIndexUnit},
}
)

func init() {
Expand All @@ -85,7 +93,7 @@ func init() {
CommandDefinition.Flags().BoolVarP(&showReplication, "replication", "R", false, "show pg_stat_replication stats")
CommandDefinition.Flags().BoolVarP(&showTables, "tables", "T", false, "show pg_stat_user_tables and pg_statio_user_tables stats")
CommandDefinition.Flags().BoolVarP(&showIndexes, "indexes", "I", false, "show pg_stat_user_indexes and pg_statio_user_indexes stats")
CommandDefinition.Flags().BoolVarP(&showVacuum, "vacuum", "V", false, "show pg_stat_progress_vacuum stats")
CommandDefinition.Flags().StringVarP(&showProgress, "progress", "P", "", "show pg_stat_progress_* stats")
CommandDefinition.Flags().StringVarP(&showStatements, "statements", "X", "", "show pg_stat_statements stats")
CommandDefinition.Flags().StringVarP(&tsStart, "start", "s", "", "starting time of the report")
CommandDefinition.Flags().StringVarP(&tsEnd, "end", "e", "", "ending time of the report")
Expand Down Expand Up @@ -126,12 +134,19 @@ func preFlightSetup(c *cobra.Command, _ []string) {
// selectReport selects appropriate type of the report depending on user's choice
func selectReport(f *pflag.Flag) {
if b, ok := basicReports[f.Name]; ok {
if b.view == "_STATEMENTS_" {
switch b.view {
case "_STATEMENTS_":
if s, ok := statementsReports[f.Value.String()]; ok {
opts.ReportType = s.view
opts.Context = s.ctx
return
}
case "_PROGRESS_":
if s, ok := progressReports[f.Value.String()]; ok {
opts.ReportType = s.view
opts.Context = s.ctx
return
}
}
opts.ReportType = b.view
opts.Context = b.ctx
Expand Down Expand Up @@ -216,19 +231,21 @@ func parseFilterString() {
// doDescribe shows detailed description of the requested stats
func doDescribe() {
var m = map[string]string{
stat.DatabaseView: stat.PgStatDatabaseDescription,
stat.ActivityView: stat.PgStatActivityDescription,
stat.ReplicationView: stat.PgStatReplicationDescription,
stat.TablesView: stat.PgStatTablesDescription,
stat.IndexesView: stat.PgStatIndexesDescription,
stat.FunctionsView: stat.PgStatFunctionsDescription,
stat.SizesView: stat.PgStatSizesDescription,
stat.VacuumView: stat.PgStatVacuumDescription,
stat.StatementsTimingView: stat.PgStatStatementsTimingDescription,
stat.StatementsGeneralView: stat.PgStatStatementsGeneralDescription,
stat.StatementsIOView: stat.PgStatStatementsIODescription,
stat.StatementsTempView: stat.PgStatStatementsTempDescription,
stat.StatementsLocalView: stat.PgStatStatementsLocalDescription,
stat.DatabaseView: stat.PgStatDatabaseDescription,
stat.ActivityView: stat.PgStatActivityDescription,
stat.ReplicationView: stat.PgStatReplicationDescription,
stat.TablesView: stat.PgStatTablesDescription,
stat.IndexesView: stat.PgStatIndexesDescription,
stat.FunctionsView: stat.PgStatFunctionsDescription,
stat.SizesView: stat.PgStatSizesDescription,
stat.ProgressVacuumView: stat.PgStatProgressVacuumDescription,
stat.ProgressClusterView: stat.PgStatProgressClusterDescription,
stat.ProgressCreateIndexView: stat.PgStatProgressCreateIndexDescription,
stat.StatementsTimingView: stat.PgStatStatementsTimingDescription,
stat.StatementsGeneralView: stat.PgStatStatementsGeneralDescription,
stat.StatementsIOView: stat.PgStatStatementsIODescription,
stat.StatementsTempView: stat.PgStatStatementsTempDescription,
stat.StatementsLocalView: stat.PgStatStatementsLocalDescription,
}

if description, ok := m[opts.ReportType]; ok {
Expand Down
10 changes: 5 additions & 5 deletions cmd/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ import (
const (
// ProgramName is the name of this program
ProgramName = "pgcenter"
// ProgramVersion is the version of this program
ProgramVersion = "0.6"
// ProgramRelease is release number of this program
ProgramRelease = "2"
// ProgramIssuesUrl is the public URL for posting issues, bug reports and asking questions
ProgramIssuesUrl = "https://github.com/lesovsky/pgcenter/issues"
)

var (
GitTag, GitCommit, GitBranch string
)

// PrintVersion prints the name and version of this program
func PrintVersion() string {
return fmt.Sprintf("%s %s.%s\n", ProgramName, ProgramVersion, ProgramRelease)
return fmt.Sprintf("%s %s %s-%s\n", ProgramName, GitTag, GitCommit, GitBranch)
}
20 changes: 15 additions & 5 deletions doc/Changelog
Original file line number Diff line number Diff line change
@@ -1,20 +1,30 @@
pgcenter (0.6.2) unstable; urgency=low
* report: print header at the beginning of the output
* top/report: refactoring aligning
* adjust header's styles of iostat/nicstat tabs in top utility
* added support for pg_stat_database.checksum_failures (pg-12)
* added support of pg_stat_progress_cluster and pg_stat_progress_create_index views
* inject program version info from git at build time
* fix #66, pgcenter crashes when no running postgres
* avoid rude disconnection from postgres at top-program exit

pgcenter (0.6.1) unstable; urgency=low
* improved aligning and query truncation
- record: records complete length of pg_stat_statements.query (be careful, it might produce high-volume stats file)
- record: add startup paramter for configuring truncation
- report: can use '--truncate 0', for disabling trucation only for pg_stat_statements.query (might produce an "eyes-bleeding" output)
- record: add startup parameter for configuring truncation
- report: can use '--truncate 0', for disabling truncation only for pg_stat_statements.query (might produce an "eyes-bleeding" output)
* reworked pg_stat_statements queries:
- remove unnecessary GROUP BY, ORDER BY and aggregations
- simplify usage of regexp_replace()
- use pg_get_userbyid() instead of joining pg_roles view
- use configurable limit for truncating length of queries
* top: read remote stats only if pgcenter schma is available
* top: read remote stats only if pgcenter schema is available
* top: do polling pg_stat_statements only if it's available (issue #59)
* top: fixed handling of libpq errors during connection establishment (issue #58)
* top: fix srong assebling of path to logfile (issue #55)
* top: fix strong assembling of path to logfile (issue #55)

pgcenter (0.6.0) unstable; urgency=low
* added goreleser support
* added goreleaser support
* top: fix wrong handling of group cancel/terminate mask
* implemented GoReport recommendations
* profile: emit error if '-P' is not specified
Expand Down
Binary file added doc/images/pgcenter-demo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
62 changes: 51 additions & 11 deletions doc/pgcenter-config-readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,26 +19,66 @@ Installing and removing functions is possible with `pgcenter config`, however, w
- `plperlu` (which means *untrusted plperl*) procedural language must be installed manually in the database you want to connect pgCenter to (see details [here](https://www.postgresql.org/docs/current/static/plperl.html)).
- perl module `Linux::Ethtool::Settings` should be installed in the system, it's used to get speed and duplex of network interfaces and properly calculate some metrics.

Of course, `pgcenter top` can also work with remote Postgres which don't have these SQL functions installed. In this case zeroes will be shown in the system stats interface (load average, cpu, memory, swap, io, network) and multiple errors will  appear in Postgres log. For easier distribution, SQL functions and views used by pgCenter are hard-coded into the source code, but their usage is not limited, so feel free to use it.

Another limitation is related to `procfs` filesystem, which is Linux-specific file system, hence there might be problematic to run pgCenter on operation systems other than Linux. But you can still run pgCenter in Docker.

#### Main functions
- installing and removing SQL functions and views in desired database.

#### Usage
In general, a prefered way is installing dependencies using distro’s default package manager, but it might happen that `Linux::Ethtool::Settings` will not be available in the official package repo. In this case, you can install perl module using CPAN, but extra dependencies would have to be resolved, such as `make` and `gcc`. Below is an example for Ubuntu Linux.

Run `config` command and install stats schema into a database:
```
apt install gcc make perl
cpan Linux::Ethtool::Settings
pgcenter config --install -h 1.2.3.4 -U postgres db_production
```

Perhaps it’s possible to use the same approach in other distros, because of perl module name is the same.
If `Linux::Ethtool::Settings` module is not installed in the system, `pgcenter config -i` will fail with the following error:

Run `config` command and install stats schema into a database:
```
pgcenter config --install -h 1.2.3.4 -U postgres db_production
# pgcenter config -i
ERROR: Can't locate Linux/Ethtool/Settings.pm in @INC (@INC contains: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at line 2.
BEGIN failed--compilation aborted at line 2.
DETAIL:
HINT:
STATEMENT: CREATE FUNCTION pgcenter.get_netdev_link_settings(INOUT iface CHARACTER VARYING, OUT speed BIGINT, OUT duplex INTEGER) RETURNS RECORD
LANGUAGE plperlu
AS $$
use Linux::Ethtool::Settings;
if (my $settings = Linux::Ethtool::Settings->new($_[0])) {
my $if_speed = $settings->speed();
my $if_duplex = $settings->duplex() ? 1 : 0;
return {iface => $_[0], speed => $if_speed, duplex => $if_duplex};
} else {
return {iface => $_[0], speed => 0, duplex => -1};
}
$$;
```

See other usage examples [here](examples.md).
As you can see the problem is related to `pgcenter.get_netdev_link_settings()` function which depends on `Linux::Ethtool::Settings` module. To fix the issue you need to install the module into your system.

In general, a preferred way is installing dependencies using distro's default package manager, but it might happen that `Linux::Ethtool::Settings` will not be available in the official package repo. In this case, you can install perl module using CPAN, but extra dependencies would have to be resolved, such as `make`,`gcc` and others.

Here is a complete example reproduced in Docker environment using using [official docker image for postgresql](https://hub.docker.com/r/centos/postgresql).

```
# yum install -y postgresql-plperl
# yum install -y gcc make perl cpan
# cpan Module::Build
# cpan Linux::Ethtool::Settings
# psql -U postgres -c 'CREATE LANGUAGE plperlu'
# pgcenter config -i -U postgres
# psql -U postgres -c "select * from pgcenter.get_netdev_link_settings('eth0')"
iface | speed | duplex
-------+-------+--------
eth0 | 10000 | 1
(1 row)
```
As you can see, finally function `pgcenter.get_netdev_link_settings()` works well.

Perhaps it’s possible to use the same approach in other distros, because of perl module name is the same, but names of other packages may vary (eg. `postgresql-10-plperl` instead of `postgresql-plperl`).

#### Other notes

Of course, `pgcenter top` can also work with remote Postgres which don't have these SQL functions installed. In this case zeroes will be shown in the system stats interface (load average, cpu, memory, swap, io, network) and multiple errors will  appear in Postgres log. For easier distribution, SQL functions and views used by pgCenter are hard-coded into the source code, but their usage is not limited, so feel free to use it.

Another limitation is related to `procfs` filesystem, which is Linux-specific file system, hence there might be problematic to run pgCenter on operation systems other than Linux. But you can still run pgCenter in Docker.


See other usage examples [here](examples.md).
46 changes: 39 additions & 7 deletions lib/stat/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ var (
PgStatDatabaseUnit = ContextUnit{
Name: DatabaseView,
Query: PgStatDatabaseQueryDefault,
DiffIntvl: [2]int{1, 15},
Ncols: 17,
DiffIntvl: [2]int{1, 16},
Ncols: 18,
OrderKey: 0,
OrderDesc: true,
ColsWidth: map[int]int{},
Expand Down Expand Up @@ -104,16 +104,40 @@ var (
Filters: map[int]*regexp.Regexp{},
}
// PgStatVacuumUnit describes how to handle pg_stat_progress_vacuum view
PgStatVacuumUnit = ContextUnit{
Name: VacuumView,
Query: PgStatVacuumQueryDefault,
PgStatProgressVacuumUnit = ContextUnit{
Name: ProgressVacuumView,
Query: PgStatProgressVacuumQueryDefault,
//DiffIntvl: NoDiff,
DiffIntvl: [2]int{9, 10},
DiffIntvl: [2]int{10, 11},
Ncols: 13,
OrderKey: 0,
OrderDesc: true,
ColsWidth: map[int]int{},
Msg: "Show vacuum progress statistics",
Filters: map[int]*regexp.Regexp{},
}
// PgStatProgressClusterUnit describes how to handle pg_stat_progress_cluster view
PgStatProgressClusterUnit = ContextUnit{
Name: ProgressClusterView,
Query: PgStatProgressClusterQueryDefault,
//DiffIntvl: NoDiff,
DiffIntvl: [2]int{10, 11},
Ncols: 13,
OrderKey: 0,
OrderDesc: true,
ColsWidth: map[int]int{},
Msg: "Show cluster/vacuum full progress statistics",
Filters: map[int]*regexp.Regexp{},
}
PgStatProgressCreateIndexUnit = ContextUnit{
Name: ProgressCreateIndexView,
Query: PgStatProgressCreateIndexQueryDefault,
DiffIntvl: NoDiff,
Ncols: 14,
OrderKey: 0,
OrderDesc: true,
ColsWidth: map[int]int{},
Msg: "Show vacuum statistics",
Msg: "Show create index/reindex progress statistics",
Filters: map[int]*regexp.Regexp{},
}
// PgStatActivityUnit describes how to handle pg_stat_activity view
Expand Down Expand Up @@ -232,6 +256,14 @@ func (cl ContextList) AdjustQueries(pi PgInfo) {
// use defaults assigned in context unit
}
}
case DatabaseView:
switch {
// versions prior 12 don't have checksum_failures column
case pi.PgVersionNum < 120000:
cl[c].Query = PgStatDatabaseQuery11
cl[c].Ncols = 17
cl[c].DiffIntvl = [2]int{1, 15}
}
}
}
}
Loading

0 comments on commit e555ab8

Please sign in to comment.