Skip to content

Commit

Permalink
add tor python module (netdata#4546)
Browse files Browse the repository at this point in the history
* tor: python tor module init version

* tor: minor

* tor: minor

* tor: minor

* tor: user super in __init__

* tor: do not suggest to use password by default

* tor: add module to python.d.conf
  • Loading branch information
ilyam8 authored Nov 5, 2018
1 parent a9869d2 commit bc91d16
Show file tree
Hide file tree
Showing 6 changed files with 248 additions and 0 deletions.
1 change: 1 addition & 0 deletions collectors/python.d.plugin/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ include spigotmc/Makefile.inc
include springboot/Makefile.inc
include squid/Makefile.inc
include tomcat/Makefile.inc
include tor/Makefile.inc
include traefik/Makefile.inc
include unbound/Makefile.inc
include uwsgi/Makefile.inc
Expand Down
1 change: 1 addition & 0 deletions collectors/python.d.plugin/python.d.conf
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ nginx_log: no
# springboot: yes
# squid: yes
# tomcat: yes
# tor: yes
unbound: no
# uwsgi: yes
# varnish: yes
Expand Down
13 changes: 13 additions & 0 deletions collectors/python.d.plugin/tor/Makefile.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# SPDX-License-Identifier: GPL-3.0-or-later

# THIS IS NOT A COMPLETE Makefile
# IT IS INCLUDED BY ITS PARENT'S Makefile.am
# IT IS REQUIRED TO REFERENCE ALL FILES RELATIVE TO THE PARENT

# install these files
dist_python_DATA += tor/tor.chart.py
dist_pythonconfig_DATA += tor/tor.conf

# do not install these files, but include them in the distribution
dist_noinst_DATA += tor/README.md tor/Makefile.inc

46 changes: 46 additions & 0 deletions collectors/python.d.plugin/tor/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# tor

Module connects to tor control port to collect traffic statistics.

**Requirements:**
* `tor` program
* `stem` python package

It produces only one chart:

1. **Traffic**
* read
* write

### configuration

Needs only `control_port`

Here is an example for local server:

```yaml
update_every : 1
priority : 60000

local_tcp:
name: 'local'
control_port: 9051

local_socket:
name: 'local'
control_port: '/var/run/tor/control'
```
### prerequisite
Add to `/etc/tor/torrc`:

```
ControlPort 9051
```
For more options please read the manual.
Without configuration, module attempts to connect to `127.0.0.1:9051`.
---
108 changes: 108 additions & 0 deletions collectors/python.d.plugin/tor/tor.chart.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# -*- coding: utf-8 -*-
# Description: adaptec_raid netdata python.d module
# Author: Federico Ceratto <[email protected]>
# Author: Ilya Mashchenko (l2isbad)
# SPDX-License-Identifier: GPL-3.0-or-later


from bases.FrameworkServices.SimpleService import SimpleService

try:
import stem
import stem.connection
import stem.control
STEM_AVAILABLE = True
except ImportError:
STEM_AVAILABLE = False


DEF_PORT = 'default'

ORDER = [
'traffic',
]

CHARTS = {
'traffic': {
'options': [None, 'Tor Traffic', 'KB/s', 'traffic', 'tor.traffic', 'area'],
'lines': [
['read', 'read', 'incremental', 1, 1024],
['write', 'write', 'incremental', 1, -1024],
]
}
}


class Service(SimpleService):
"""Provide netdata service for Tor"""
def __init__(self, configuration=None, name=None):
super(Service, self).__init__(configuration=configuration, name=name)
self.order = ORDER
self.definitions = CHARTS

self.port = self.configuration.get('control_port', DEF_PORT)
self.password = self.configuration.get('password')

self.use_socket = isinstance(self.port, str) and self.port != DEF_PORT and not self.port.isdigit()
self.conn = None
self.alive = False

def check(self):
if not STEM_AVAILABLE:
self.error('the stem library is missing')
return False

return self.connect()

def get_data(self):
if not self.alive and not self.reconnect():
return None

data = dict()

try:
data['read'] = self.conn.get_info('traffic/read')
data['write'] = self.conn.get_info('traffic/written')
except stem.ControllerError as error:
self.debug(error)
self.alive = False

return data or None

def authenticate(self):
try:
self.conn.authenticate(password=self.password)
except stem.connection.AuthenticationFailure as error:
self.error('authentication error: {0}'.format(error))
return False
return True

def connect_via_port(self):
try:
self.conn = stem.control.Controller.from_port(port=self.port)
except (stem.SocketError, ValueError) as error:
self.error(error)

def connect_via_socket(self):
try:
self.conn = stem.control.Controller.from_socket_file(path=self.port)
except (stem.SocketError, ValueError) as error:
self.error(error)

def connect(self):
if self.conn:
self.conn.close()
self.conn = None

if self.use_socket:
self.connect_via_socket()
else:
self.connect_via_port()

if self.conn and self.authenticate():
self.alive = True

return self.alive

def reconnect(self):
return self.connect()
79 changes: 79 additions & 0 deletions collectors/python.d.plugin/tor/tor.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# netdata python.d.plugin configuration for tor
#
# This file is in YaML format. Generally the format is:
#
# name: value
#
# There are 2 sections:
# - global variables
# - one or more JOBS
#
# JOBS allow you to collect values from multiple sources.
# Each source will have its own set of charts.
#
# JOB parameters have to be indented (using spaces only, example below).

# ----------------------------------------------------------------------
# Global Variables
# These variables set the defaults for all JOBs, however each JOB
# may define its own, overriding the defaults.

# update_every sets the default data collection frequency.
# If unset, the python.d.plugin default is used.
# update_every: 1

# priority controls the order of charts at the netdata dashboard.
# Lower numbers move the charts towards the top of the page.
# If unset, the default for python.d.plugin is used.
# priority: 60000

# retries sets the number of retries to be made in case of failures.
# If unset, the default for python.d.plugin is used.
# Attempts to restore the service are made once every update_every
# and only if the module has collected values in the past.
# retries: 60

# autodetection_retry sets the job re-check interval in seconds.
# The job is not deleted if check fails.
# Attempts to start the job are made once every autodetection_retry.
# This feature is disabled by default.
# autodetection_retry: 0

# ----------------------------------------------------------------------
# JOBS (data collection sources)
#
# The default JOBS share the same *name*. JOBS with the same name
# are mutually exclusive. Only one of them will be allowed running at
# any time. This allows autodetection to try several alternatives and
# pick the one that works.
#
# Any number of jobs is supported.
#
# All python.d.plugin JOBS (for all its modules) support a set of
# predefined parameters. These are:
#
# job_name:
# name: myname # the JOB's name as it will appear at the
# # dashboard (by default is the job_name)
# # JOBs sharing a name are mutually exclusive
# update_every: 1 # the JOB's data collection frequency
# priority: 60000 # the JOB's order on the dashboard
# retries: 10 # the JOB's number of restoration attempts
# autodetection_retry: 0 # the JOB's re-check interval in seconds
#
# Additionally to the above, tor plugin also supports the following:
#
# control_port: 'port' # tor control port
# password: 'password' # tor control password
#
# ----------------------------------------------------------------------
# AUTO-DETECTION JOBS
# only one of them will run (they have the same name)
#
# local_tcp:
# name: 'local'
# control_port: 9051
#
# local_socket:
# name: 'local'
# control_port: '/var/run/tor/control'

0 comments on commit bc91d16

Please sign in to comment.