Exemple #1
0
def write_to_influxdb(_url, _token, _org, _bucket, _host, _seconds):
    """
    Write the response time to Influxdb
    :param _url: Influxdb server URL as string
    :param _token: Influxdb auth token as string
    :param _org: Influxdb organization as string
    :param _bucket: Influxdb bucket as string
    :param _host: Name of the host being as string
    :param _seconds: Response time in seconds as float
    :return: None
    """
    point = Point("response_time").tag("host",
                                       _host).field("seconds", _seconds)

    try:
        client = InfluxDBClient(url=_url,
                                token=_token,
                                org=_org,
                                verify_ssl=False)
        write_api = client.write_api(write_options=SYNCHRONOUS)
        write_api.write(bucket=_bucket, record=point)
        client.close()
    except Exception as e:
        print("CRITICAL - Failed to write to influxdb: %s" % e)
        sys.exit(2)

    return None
def main():
    parse_row.progress = 0

    url = "https://github.com/influxdata/influxdb-client-python/wiki/data/stock-prices-example.csv"
    response = requests.get(url, stream=True)
    data = rx \
        .from_iterable(DictReader(response.iter_lines(decode_unicode=True))) \
        .pipe(ops.map(lambda row: parse_row(row)))

    client = InfluxDBClient(url="http://localhost:8086",
                            token="my-token",
                            org="my-org",
                            debug=False)
    write_api = client.write_api(
        write_options=WriteOptions(batch_size=50_000, flush_interval=10_000))

    write_api.write(bucket="my-bucket", record=data)
    write_api.close()

    query = '''
    from(bucket:"my-bucket")
            |> range(start: 0, stop: now())
            |> filter(fn: (r) => r._measurement == "financial-analysis")
            |> filter(fn: (r) => r.symbol == "AAPL")
            |> filter(fn: (r) => r._field == "close")
            |> drop(columns: ["_start", "_stop", "table", "_field","_measurement"])
    '''

    result = client.query_api().query_data_frame(query=query)
    print(result.head(100))
    """
    Close client
    """
    client.close()
Exemple #3
0
class InfluxDBDataWriter(CovidDataWriter):
    def __init__(self, url: str, token: str, org: str, bucket: str):
        self._org = org
        self._bucket = bucket
        self._client = InfluxDBClient(url=url, token=token)
        self._write_api = self._client.write_api()

    def write_data(self, data_point: CovidDataPoint) -> None:
        self._write_api.write(
            bucket=self._bucket,
            org=self._org,
            record=self._convert_datapoint(data_point=data_point),
        )

    @staticmethod
    def _convert_datapoint(data_point: CovidDataPoint) -> Point:
        point = (Point(data_point.measurement.value).tag(
            "iso3", data_point.iso_3).tag("country", data_point.country).tag(
                "state_province", data_point.state_province).tag(
                    "county",
                    data_point.county).tag("lat", data_point.lat).tag(
                        "long",
                        data_point.long).field("count", data_point.value).time(
                            data_point.timestamp))
        return point

    def __del__(self):
        self._client.close()
class InfluxDBWriter(multiprocessing.Process):
    """
    Writer that writes data in batches with 50_000 items.
    """
    def __init__(self, queue):
        multiprocessing.Process.__init__(self)
        self.queue = queue
        self.client = InfluxDBClient(url="http://localhost:8086",
                                     token="my-token",
                                     org="my-org",
                                     debug=False)
        self.write_api = self.client.write_api(
            write_options=WriteOptions(write_type=WriteType.batching,
                                       batch_size=50_000,
                                       flush_interval=10_000))

    def run(self):
        while True:
            next_task = self.queue.get()
            if next_task is None:
                # Poison pill means terminate
                self.terminate()
                self.queue.task_done()
                break
            self.write_api.write(bucket="my-bucket", record=next_task)
            self.queue.task_done()

    def terminate(self) -> None:
        proc_name = self.name
        print()
        print('Writer: flushing data...')
        self.write_api.close()
        self.client.close()
        print('Writer: closed'.format(proc_name))
Exemple #5
0
def send_data(what, value):
    """ 
    this function sends the data as json, and checks if it was succesfull 
    """
    client = InfluxDBClient(url=influx_cloud_url, token=influx_cloud_token)
    try:
        point = Point("measurement").field(what,
                                           value).time(time=datetime.utcnow())

        # if data is incorrect, don't send anything
        if point is None:
            return -1
        """
        Write data by Point structure
        """

        print(f'Writing to InfluxDB cloud: {point.to_line_protocol()} ...')

        write_api = client.write_api(write_options=SYNCHRONOUS)
        write_api.write(bucket=bucket, org=org, record=point)

        print()
        print('success')
        print()
        print()

    except Exception as e:
        print(e)
    finally:
        client.close()
Exemple #6
0
class TestHealthMock(unittest.TestCase):
    def setUp(self) -> None:
        httpretty.enable()
        httpretty.reset()

        self.influxdb_client = InfluxDBClient(url="http://localhost",
                                              token="my-token")

    def tearDown(self) -> None:
        self.influxdb_client.close()
        httpretty.disable()

    def test_without_retry(self):
        httpretty.register_uri(httpretty.GET,
                               uri="http://localhost/health",
                               status=429,
                               adding_headers={
                                   'Retry-After': '5',
                                   'Content-Type': 'application/json'
                               },
                               body="{\"message\":\"Health is not working\"}")

        check = self.influxdb_client.health()
        self.assertTrue("Health is not working" in check.message,
                        msg=check.message)
        self.assertEqual(check.status, "fail")
        self.assertEqual(check.name, "influxdb")

        self.assertEqual(1, len(httpretty.httpretty.latest_requests))

    def test_with_retry(self):

        self.influxdb_client.close()
        self.influxdb_client = InfluxDBClient(url="http://localhost",
                                              token="my-token",
                                              retries=Retry())

        httpretty.register_uri(
            httpretty.GET,
            uri="http://localhost/health",
            status=200,
            adding_headers={'Content-Type': 'application/json'},
            body=
            "{\"message\":\"ready for queries and writes\", \"name\":\"influxdb\", \"status\":\"pass\"}"
        )
        httpretty.register_uri(httpretty.GET,
                               uri="http://localhost/health",
                               status=429,
                               adding_headers={
                                   'Retry-After': '1',
                                   'Content-Type': 'application/json'
                               },
                               body="{\"message\":\"Health is not working\"}")

        health = self.influxdb_client.health()
        self.assertEqual(health.message, 'ready for queries and writes')
        self.assertEqual(health.status, "pass")
        self.assertEqual(health.name, "influxdb")

        self.assertEqual(2, len(httpretty.httpretty.latest_requests))
Exemple #7
0
class BaseTest(unittest.TestCase):
    def setUp(self) -> None:
        self.conf = influxdb_client.configuration.Configuration()

        self.host = os.getenv('INFLUXDB_V2_URL', "http://localhost:8086")
        self.debug = False
        self.auth_token = os.getenv('INFLUXDB_V2_TOKEN', "my-token")
        self.org = os.getenv('INFLUXDB_V2_ORG', "my-org")

        self.client = InfluxDBClient(url=self.host,
                                     token=self.auth_token,
                                     debug=self.debug,
                                     org=self.org)
        self.api_client = self.client.api_client

        self.query_api = self.client.query_api()
        self.buckets_api = self.client.buckets_api()
        self.users_api = self.client.users_api()
        self.organizations_api = self.client.organizations_api()
        self.authorizations_api = self.client.authorizations_api()
        self.labels_api = self.client.labels_api()

        self.my_organization = self.find_my_org()

    def tearDown(self) -> None:
        self.client.close()

    def create_test_bucket(self):
        bucket_name = generate_bucket_name()
        bucket = self.buckets_api.create_bucket(bucket_name=bucket_name,
                                                org=self.my_organization,
                                                description=bucket_name +
                                                "description")
        return bucket

    def delete_test_bucket(self, bucket):
        return self.buckets_api.delete_bucket(bucket)

    def find_my_org(self) -> Organization:
        return self.client.organizations_api().find_organizations(
            org=self.org)[0]

    @staticmethod
    def log(args):
        print(">>>", args)

    @staticmethod
    def generate_name(prefix):
        assert prefix != "" or prefix is not None
        return prefix + str(datetime.datetime.now().timestamp()) + "-IT"

    @classmethod
    def retention_rule(cls) -> BucketRetentionRules:
        return BucketRetentionRules(type='expire', every_seconds=3600)

    def assertEqualIgnoringWhitespace(self, first, second, msg=None) -> None:
        whitespace_pattern = re.compile(r"\s+")
        self.assertEqual(whitespace_pattern.sub("", first),
                         whitespace_pattern.sub("", second),
                         msg=msg)
 def test_ping_not_running_instance(self):
     client_not_running = InfluxDBClient("http://localhost:8099",
                                         token="my-token",
                                         debug=True)
     ping = client_not_running.ping()
     self.assertFalse(ping)
     client_not_running.close()
    def test_version_not_running_instance(self):
        client_not_running = InfluxDBClient("http://localhost:8099",
                                            token="my-token",
                                            debug=True)
        with self.assertRaises(NewConnectionError):
            client_not_running.version()

        client_not_running.close()
 def write_data(self, data: [Point], bucket):
     client = InfluxDBClient(url="http://%s:%s" % (self.host, self.port),
                             token=self.token,
                             org=self.org,
                             timeout=1000)
     _write_client = client.write_api(write_options=SYNCHRONOUS)
     _write_client.write(bucket=bucket, org=self.org, record=data)
     _write_client.close()
     client.close()
def on_exit(db_client: InfluxDBClient, write_api: WriteApi):
    """Close clients after terminate a script.

    :param db_client: InfluxDB client
    :param write_api: WriteApi
    :return: nothing
    """
    write_api.close()
    db_client.close()
Exemple #12
0
def send_to_influxdb():
    client = InfluxDBClient(
        url="https://eu-central-1-1.aws.cloud2.influxdata.com", token=my_token)
    try:
        kind = 'temperature'
        device = 'opt-123'
        """
		Get sensor data
		"""
        # pressure = sense.get_pressure()
        pressure = 339.3
        # pressure = round(pressure, 1)
        temp = 12.0
        # temp = sense.get_temperature()
        # temp = round(temp, 1)
        # humid = sense.get_humidity()
        humid = 99
        """
		Write data by Point structure
		"""
        point = Point(kind).tag('owner', owner).tag('device', device).field(
            'value', round(outside_temp(), 2)).time(time=datetime.utcnow())
        print(f'Writing to InfluxDB cloud: {point.to_line_protocol()} ...')

        write_api = client.write_api(write_options=SYNCHRONOUS)
        write_api.write(bucket=bucket, org=org, record=point)

        print()
        print('success')
        print()
        print()

        if False:
            """
			Query written data
			"""
            query = f'from(bucket: "{bucket}") |> range(start: -1d) |> filter(fn: (r) => r._measurement == "{kind}")'
            print(f'Querying from InfluxDB cloud: "{query}" ...')
            print()

            query_api = client.query_api()
            tables = query_api.query(query=query, org=org)

            for table in tables:
                for row in table.records:
                    print(
                        f'{row.values["_time"]}: owner={row.values["owner"]},device={row.values["device"]} '
                        f'{row.values["_value"]} °C')

            print()
            print('success')
    except Exception as e:
        print(e)
    finally:
        client.close()
    return
Exemple #13
0
class HelpersTest(BaseTest):
    def test_is_id(self):
        self.assertTrue(_is_id("ffffffffffffffff"))
        self.assertTrue(_is_id("020f755c3c082000"))
        self.assertTrue(_is_id("ca55e77eca55e77e"))
        self.assertTrue(_is_id("02def021097c6000"))
        self.assertFalse(_is_id("gggggggggggggggg"))
        self.assertFalse(_is_id("abc"))
        self.assertFalse(_is_id("abcdabcdabcdabcd0"))
        self.assertFalse(_is_id("020f75"))
        self.assertFalse(_is_id("020f755c3c082000aaa"))
        self.assertFalse(_is_id(None))

    def test_organization_as_query_param(self):
        organization = Organization(id="org-id", name="org-name")
        org = get_org_query_param(organization, self.client)
        self.assertEqual("org-id", org)

    def test_required_id(self):
        org = get_org_query_param(None, self.client, required_id=True)
        self.assertEqual(self.my_organization.id, org)

    def test_required_id_not_exist(self):
        with pytest.raises(InfluxDBError) as e:
            get_org_query_param("not_exist_name",
                                self.client,
                                required_id=True)
        assert "The client cannot find organization with name: 'not_exist_name' to determine their ID." in f"{e.value} "

    def test_both_none(self):
        self.client.close()
        self.client = InfluxDBClient(url=self.client.url, token="my-token")
        org = get_org_query_param(None, self.client)
        self.assertIsNone(org)

    def test_not_permission_to_read_org(self):
        # Create Token without permission to read Organizations
        resource = PermissionResource(type="buckets",
                                      org_id=self.find_my_org().id)
        authorization = self.client \
            .authorizations_api() \
            .create_authorization(org_id=self.find_my_org().id,
                                  permissions=[Permission(resource=resource, action="read"),
                                               Permission(resource=resource, action="write")])
        self.client.close()

        # Initialize client without permission to read Organizations
        self.client = InfluxDBClient(url=self.client.url,
                                     token=authorization.token)

        with pytest.raises(InfluxDBError) as e:
            get_org_query_param("my-org", self.client, required_id=True)
        assert "The client cannot find organization with name: 'my-org' to determine their ID. Are you using token " \
               "with sufficient permission?" in f"{e.value} "
Exemple #14
0
    def test_check_write_permission_by_empty_data(self):
        client = InfluxDBClient(url="http://localhost:8086", token="my-token-wrong", org="my-org")
        write_api = client.write_api(write_options=SYNCHRONOUS)

        with self.assertRaises(ApiException) as cm:
            write_api.write("my-bucket", self.org, b'')
        exception = cm.exception

        self.assertEqual(401, exception.status)
        self.assertEqual("Unauthorized", exception.reason)

        client.close()
Exemple #15
0
def main():
    # Main logic resides here.

    # Connect to local influx db container.
    config_json = load_config()
    client = InfluxDBClient(url='http://localhost:8086',
                            token=config_json['token'],
                            org=config_json['org'])

    try:
        while True:
            is_chrome_open = False
            list_procs = ""
            output = subprocess.Popen(["ps", "aux"], stdout=subprocess.PIPE)
            list_procs = output.stdout.read()
            if 'Google Chrome'.encode('utf-8') in list_procs:
                is_chrome_open = True

            if is_chrome_open:
                all_tabs = subprocess.Popen(
                    ["osascript", "show_tabs_chrome.scpt"],
                    stdout=subprocess.PIPE)
                all_tabs = all_tabs.stdout.read()
                all_tabs = all_tabs.decode('utf-8').split('\n')

                parsed_links = set()
                parsed_active_link = ''
                for link in all_tabs:
                    if link:
                        string_form = link
                        if string_form.split()[0] != 'Active:':
                            parsed_url = parse_url(string_form.split()[0])
                            parsed_links.add(parsed_url)
                        elif string_form.split()[0] == 'Active:':
                            parsed_active_link = parse_url(
                                string_form.split()[1])

                write_api = client.write_api(write_options=SYNCHRONOUS)
                query_api = client.query_api()

                for link in parsed_links:
                    active_time = 0 if parsed_active_link != link else 1
                    inactive_time = 1 if parsed_active_link != link else 0
                    insert_link_query(write_api, link,
                                      config_json['bucket_name'], active_time,
                                      inactive_time)

            time.sleep(1)

    except Exception as e:
        client.close()
Exemple #16
0
    def test_query_without_credentials(self):
        _client = InfluxDBClient(url="http://localhost:9999", token="my-token-wrong-credentials", org="my-org")

        with self.assertRaises(ApiException) as ae:
            query = 'from(bucket: "my-bucket")' \
                    '|> range(start: 2020-02-19T23:30:00Z, stop: now())' \
                    f'|> filter(fn: (r) => r._measurement == "my-measurement")'
            _client.query_api().query_data_frame(query=query)

        exception = ae.exception
        self.assertEqual(401, exception.status)
        self.assertEqual("Unauthorized", exception.reason)

        _client.close()
Exemple #17
0
def refreshLatencyGraphs(secondsToRun):
	startTime = datetime.now()
	with open('statsByParentNode.json', 'r') as j:
		parentNodes = json.loads(j.read())
	
	with open('statsByDevice.json', 'r') as j:
		devices = json.loads(j.read())
	
	print("Retrieving device statistics")
	devices = getLatencies(devices, secondsToRun)
	
	print("Computing parent node statistics")
	parentNodes = getParentNodeStats(parentNodes, devices)
	
	print("Writing data to InfluxDB")
	bucket = influxDBBucket
	org = influxDBOrg
	token = influxDBtoken
	url="http://localhost:8086"
	client = InfluxDBClient(
		url=url,
		token=token,
		org=org
	)
	write_api = client.write_api(write_options=SYNCHRONOUS)
	
	queriesToSend = []
	for device in devices:
		if device['tcpLatency'] != None:
			p = Point('Latency').tag("Device", device['hostname']).tag("ParentNode", device['ParentNode']).tag("Type", "Device").field("TCP Latency", device['tcpLatency'])
			queriesToSend.append(p)

	for parentNode in parentNodes:
		if parentNode['tcpLatency'] != None:
			p = Point('Latency').tag("Device", parentNode['parentNodeName']).tag("ParentNode", parentNode['parentNodeName']).tag("Type", "Parent Node").field("TCP Latency", parentNode['tcpLatency'])
			queriesToSend.append(p)
			
	write_api.write(bucket=bucket, record=queriesToSend)
	print("Added " + str(len(queriesToSend)) + " points to InfluxDB.")
	client.close()
	
	#with open('statsByParentNode.json', 'w') as infile:
	#	json.dump(parentNodes, infile)
	
	#with open('statsByDevice.json', 'w') as infile:
	#	json.dump(devices, infile)
	
	endTime = datetime.now()
	durationSeconds = round((endTime - startTime).total_seconds())
	print("Graphs updated within " + str(durationSeconds) + " seconds.")
Exemple #18
0
class InfluxDBWriterToPickle:
    def __init__(self):
        self.client = InfluxDBClient(url="http://localhost:8086",
                                     token="my-token",
                                     org="my-org",
                                     debug=False)
        self.write_api = self.client.write_api(
            write_options=WriteOptions(write_type=WriteType.batching,
                                       batch_size=50_000,
                                       flush_interval=10_000))

    def write(self, record):
        self.write_api.write(bucket="my-bucket", record=record)

    def terminate(self) -> None:
        self.write_api.close()
        self.client.close()
class WriteApiTestMock(BaseTest):
    def setUp(self) -> None:
        httpretty.enable()
        httpretty.reset()

        conf = influxdb_client.configuration.Configuration()
        conf.host = "http://localhost"
        conf.debug = False

        self.influxdb_client = InfluxDBClient(url=conf.host, token="my-token")

    def tearDown(self) -> None:
        self.influxdb_client.close()
        httpretty.disable()

    def test_writes_synchronous_without_retry(self):
        httpretty.register_uri(httpretty.POST,
                               uri="http://localhost/api/v2/write",
                               status=503)

        self.write_client = self.influxdb_client.write_api(
            write_options=SYNCHRONOUS)
        with self.assertRaises(ApiException) as cm:
            self.write_client.write(
                "my-bucket", "my-org",
                "h2o_feet,location=coyote_creek water_level=1 1")
        exception = cm.exception

        self.assertEqual("Service Unavailable", exception.reason)
        self.assertEqual(1, len(httpretty.httpretty.latest_requests))

    def test_writes_asynchronous_without_retry(self):
        httpretty.register_uri(httpretty.POST,
                               uri="http://localhost/api/v2/write",
                               status=503)

        self.write_client = self.influxdb_client.write_api(
            write_options=ASYNCHRONOUS)
        with self.assertRaises(ApiException) as cm:
            self.write_client.write(
                "my-bucket", "my-org",
                "h2o_feet,location=coyote_creek water_level=1 1").get()
        exception = cm.exception

        self.assertEqual("Service Unavailable", exception.reason)
        self.assertEqual(1, len(httpretty.httpretty.latest_requests))
class InfluxDBClientAuthorization(unittest.TestCase):
    def setUp(self) -> None:
        httpretty.enable()
        httpretty.reset()

    def tearDown(self) -> None:
        if self.influxdb_client:
            self.influxdb_client.close()
        httpretty.disable()

    def test_session_request(self):
        httpretty.reset()
        self.influxdb_client = InfluxDBClient(url="http://localhost",
                                              token="my-token",
                                              username="******",
                                              password="******")

        # create user session
        httpretty.register_uri(httpretty.POST,
                               uri="http://localhost/api/v2/signin",
                               adding_headers={'Set-Cookie': 'session=xyz'})
        # authorized request
        httpretty.register_uri(httpretty.GET, uri="http://localhost/ping")
        # expires current session
        httpretty.register_uri(httpretty.POST,
                               uri="http://localhost/api/v2/signout")

        ping = self.influxdb_client.ping()
        self.assertTrue(ping)

        self.assertEqual(2, len(httpretty.httpretty.latest_requests))
        # basic auth header
        self.assertEqual(
            'Basic bXktdXNlcm5hbWU6bXktcGFzc3dvcmQ=',
            httpretty.httpretty.latest_requests[0].headers['Authorization'])
        # cookie header
        self.assertEqual(
            'session=xyz',
            httpretty.httpretty.latest_requests[1].headers['Cookie'])
        self.assertIsNotNone(self.influxdb_client.api_client.cookie)

        # signout
        self.influxdb_client.close()

        self.assertEqual(3, len(httpretty.httpretty.latest_requests))
    def send(self, vals, batteryAPI):
        client = InfluxDBClient(url=self.influx_url,
                                token=f'{self.influx_user}:{self.influx_pass}',
                                org='-')
        bucket = f'{self.influx_database}/{self.influx_retention_policy}'
        write_api = client.write_api()

        inverterDetails = vals.copy()
        inverterDetails.pop('Serial', None)

        point = Point("solax").tag("inverter", vals['name'])
        for x, y in inverterDetails.items():
            point.field(x, y)
        #        print(point.to_line_protocol())
        #        print(inverterDetails)

        write_api.write(bucket=bucket, record=point)
        write_api.__del__()

        client.close()
Exemple #22
0
def ingest_dataframe(df, measurement_name, tag_columns):
    """Write data"""

    point_settings = PointSettings()
    point_settings.add_default_tag("units", "Wh")
    point_settings.add_default_tag("source", "enphase")

    points = data_frame_to_list_of_points(
        data_frame=df,
        point_settings=point_settings,
        data_frame_measurement_name=measurement_name,
        data_frame_tag_columns=tag_columns)

    client = InfluxDBClient(url=url, token=token, org=org)
    write_api = client.write_api()

    # line protocol: measurementName,tagKey=tagValue fieldKey="fieldValue" timestamp
    # write_api.write(bucket=bucket, org=org, record=df,
    #                 data_frame_measurement_name=measurement_name,
    #                 data_frame_tag_columns=tag_columns)
    write_api.write(bucket=bucket, org=org, record=points)

    write_api.close()
    client.close()
Exemple #23
0
class InfluxDB:
    def __init__(self, config):
        self._config = config
        self._client = None
        self._write_api = None
        self._query_api = None
        self._delete_api = None
        self._tasks_api = None
        self._organizations_api = None
        self._token = None
        self._org = None
        self._url = None
        self._bucket = None

    def start(self) -> bool:
        """Initialize the InfluxDB client."""
        try:
            influxdb_options = retrieve_options(self._config, 'influxdb2', _INFLUXDB2_OPTIONS)
            debug_options = retrieve_options(self._config, 'debug', _DEBUG_OPTIONS)
        except FailedInitialization as e:
            _LOGGER.error(f"{e}")
            return False

        if not influxdb_options.get('enable', None):
            _LOGGER.warning("InfluxDB support is disabled in the YAML configuration file")
            return True

        result = False
        try:
            self._bucket = influxdb_options.get('bucket', None)
            self._url = influxdb_options.get('url', None)
            self._token = influxdb_options.get('token', None)
            self._org = influxdb_options.get('org', None)
            self._client = InfluxDBClient(url=self._url, token=self._token, org=self._org, enable_gzip=True)
            if not self._client:
                raise FailedInitialization(
                    f"failed to get InfluxDBClient from '{self._url}' (check url, token, and/or organization)")
            self._write_api = self._client.write_api(write_options=SYNCHRONOUS)
            self._query_api = self._client.query_api()
            self._delete_api = self._client.delete_api()
            self._tasks_api = self._client.tasks_api()
            self._organizations_api = self._client.organizations_api()

            multisma2_debug = os.getenv(_DEBUG_ENV_VAR, 'False').lower() in ('true', '1', 't')
            try:
                if multisma2_debug and debug_options.get('delete_bucket', False):
                    self.delete_bucket()
                    _LOGGER.info(f"Deleted bucket '{self._bucket}' at '{self._url}'")
            except InfluxDBBucketError as e:
                raise FailedInitialization(f"{e}")

            try:
                if not self.connect_bucket(multisma2_debug and debug_options.get('create_bucket', False)):
                    raise FailedInitialization(f"Unable to access (or create) bucket '{self._bucket}' at '{self._url}'")
            except InfluxDBBucketError as e:
                raise FailedInitialization(f"{e}")

            _LOGGER.info(f"Connected to InfluxDB: '{self._url}', bucket '{self._bucket}'")
            result = True

        except FailedInitialization as e:
            _LOGGER.error(f"{e}")
        except NewConnectionError:
            _LOGGER.error(f"InfluxDB client unable to connect to host at {self._url}")
        except ApiException as e:
            _LOGGER.error(f"InfluxDB client unable to access bucket '{self._bucket}' at {self._url}: {e.reason}")
        except Exception as e:
            _LOGGER.error(f"Unexpected exception: {e}")
        finally:
            return result

    def stop(self):
        if self._write_api:
            self._write_api.close()
            self._write_api = None
        if self._client:
            self._client.close()
            self._client = None

    def bucket(self):
        return self._bucket

    def org(self):
        return self._org

    def write_api(self):
        return self._write_api

    def query_api(self):
        return self._query_api

    def delete_api(self):
        return self._delete_api

    def tasks_api(self):
        return self._tasks_api

    def organizations_api(self):
        return self._organizations_api

    def write_points(self, points):
        if not self._write_api:
            return False
        try:
            self._write_api.write(bucket=self._bucket, record=points, write_precision=WritePrecision.S)
            return True
        except ApiException as e:
            raise InfluxDBWriteError(f"InfluxDB client unable to write to '{self._bucket}' at {self._url}: {e.reason}")
        except Exception as e:
            raise InfluxDBWriteError(f"Unexpected failure in write_points(): {e}")

    def write_history(self, site, topic):
        if not self._write_api:
            return False

        lookup = LP_LOOKUP.get(topic, None)
        if not lookup:
            _LOGGER.error(f"write_history(): unknown topic '{topic}'")
            return False

        measurement = lookup.get('measurement')
        tags = lookup.get('tags', None)
        field = lookup.get('field', None)
        lps = []
        for inverter in site:
            inverter_name = inverter.pop(0)
            name = inverter_name.get('inverter', 'sunnyboy')
            for history in inverter:
                t = history['t']
                v = history['v']
                if v is None:
                    continue
                lp = f"{measurement}"
                if tags and len(tags):
                    lp += f",{tags[0]}={name}"
                if isinstance(v, int):
                    lp += f" {field}={v}i {t}"
                    lps.append(lp)
                else:
                    _LOGGER.error(
                        f"write_history(): unanticipated type '{type(v)}' in measurement '{measurement}/{field}'")
                    continue

        try:
            self._write_api.write(bucket=self._bucket, record=lps, write_precision=WritePrecision.S)
            _LOGGER.debug(f"write_history({site}, {topic}): {lps}")
            return True
        except ApiException as e:
            raise InfluxDBWriteError(f"InfluxDB client unable to write to '{self._bucket}' at {self._url}: {e.reason}")
        except Exception as e:
            raise InfluxDBWriteError(f"Unexpected failure in write_history(): {e}")

    def write_sma_sensors(self, sensor, timestamp=None):
        if not self._client:
            return False

        ts = timestamp if timestamp is not None else int(time.time())
        lps = []
        for old_point in sensor:
            point = old_point.copy()
            topic = point.pop('topic', None)
            point.pop('precision', None)
            if topic:
                lookup = LP_LOOKUP.get(topic, None)
                if not lookup:
                    _LOGGER.error(f"write_sma_sensors(): unknown topic '{topic}'")
                    continue

                if not lookup.get('output', False):
                    continue

                if topic == 'production/today':
                    day = datetime.datetime.fromtimestamp(ts).date()
                    dt = datetime.datetime.combine(day, datetime.time(0, 0))
                    ts = int(dt.timestamp())
                elif topic == 'production/month':
                    month = datetime.date.fromtimestamp(ts).replace(day=1)
                    dt = datetime.datetime.combine(month, datetime.time(0, 0))
                    ts = int(dt.timestamp())
                elif topic == 'production/year':
                    year = datetime.date.fromtimestamp(ts).replace(month=1, day=1)
                    dt = datetime.datetime.combine(year, datetime.time(0, 0))
                    ts = int(dt.timestamp())

                measurement = lookup.get('measurement')
                tags = lookup.get('tags', None)
                for k, v in point.items():
                    field = lookup.get('field')
                    # sample: dc_measurements
                    lp = f'{measurement}'
                    if tags and len(tags):
                        # sample: dc_measurements,_inverter=sb71
                        lp += f',{tags[0]}={k}'
                    if not field:
                        field = k
                    if isinstance(v, int):
                        # sample: ac_measurements,_inverter=sb71 power=0.23 1556813561098
                        lp += f' {field}={v}i {ts}'
                        lps.append(lp)
                    elif isinstance(v, float):
                        # sample: ac_measurements,_inverter=sb71 power=0.23 1556813561098
                        lp += f' {field}={v} {ts}'
                        lps.append(lp)
                    elif isinstance(v, dict):
                        lp_prefix = f'{lp}'
                        for k1, v1 in v.items():
                            # sample: dc_measurements,_inverter=sb71
                            lp = f'{lp_prefix}'
                            if tags and len(tags) > 1:
                                # sample: dc_measurements,_inverter=sb71,_string=a
                                lp += f',{tags[1]}={k1}'
                            if isinstance(v1, int):
                                # sample: dc_measurements,_inverter=sb71,_string=a power=1000 1556813561098
                                lp += f' {field}={v1}i {ts}'
                                lps.append(lp)
                            elif isinstance(v1, float):
                                # sample: dc_measurements,_inverter=sb71,_string=a current=0.23 1556813561098
                                lp += f' {field}={v1} {ts}'
                                lps.append(lp)
                            else:
                                _LOGGER.error(
                                    f"write_sma_sensors(): unanticipated dictionary type '{type(v1)}' in measurement '{measurement}/{field}'")
                    else:
                        _LOGGER.error(
                            f"write_sma_sensors(): unanticipated type '{type(v)}' in measurement '{measurement}/{field}'")
                        continue

        try:
            self._write_api.write(bucket=self._bucket, record=lps, write_precision=WritePrecision.S)
            return True
        except ApiException as e:
            raise InfluxDBWriteError(f"InfluxDB client unable to write to '{self._bucket}' at {self._url}: {e.reason}")
        except Exception as e:
            raise InfluxDBWriteError(f"Unexpected failure in write_sma_sensors(): {e}")

    def delete_bucket(self):
        if not self._client:
            return False
        try:
            buckets_api = self._client.buckets_api()
            found_bucket = buckets_api.find_bucket_by_name(self._bucket)
            if found_bucket:
                buckets_api.delete_bucket(found_bucket)
                bucket = buckets_api.find_bucket_by_name(self._bucket)
                if not bucket:
                    return True
            return False
        except ApiException as e:
            raise InfluxDBBucketError(
                f"InfluxDB client unable to delete bucket '{self._bucket}' at {self._url}: {e.reason}")
        except Exception as e:
            raise InfluxDBBucketError(f"Unexpected exception in delete_bucket(): {e}")

    def connect_bucket(self, create_bucket=False):
        if not self._client:
            return False
        try:
            buckets_api = self._client.buckets_api()
            bucket = buckets_api.find_bucket_by_name(self._bucket)
            if bucket:
                return True
            if create_bucket:
                bucket = buckets_api.create_bucket(
                    bucket_name=self._bucket, org_id=self._org, retention_rules=None, org=None)
                if bucket:
                    _LOGGER.info(f"Created bucket '{self._bucket}' at {self._url}")
                    return True
            return False
        except ApiException as e:
            raise InfluxDBBucketError(
                f"InfluxDB client unable to create bucket '{self._bucket}' at {self._url}: {e.reason}")
        except NewConnectionError:
            raise
        except Exception as e:
            raise InfluxDBBucketError(f"Unexpected exception in connect_bucket(): {e}")
Exemple #24
0
class InfluxOutput(Output):
    ip: str
    port: str
    token: str
    org: str
    bucket: str
    measurement: str
    url: str
    tags: Dict
    output_timestamp_name: str
    influx_writer: Any

    def __init__(self, conf: Dict[Any, Any] = None) -> None:
        super().__init__()
        if (conf is not None):
            self.configure(conf=conf)

    def configure(self, conf: Dict[Any, Any] = None) -> None:
        super().configure(conf=conf)

        # Configura writer
        self.ip = conf["ip"]
        self.port = conf["port"]
        self.token = conf["token"]
        self.org = conf["org"]
        self.url = "http://" + self.ip + ":" + self.port

        self.bucket = conf["bucket"]
        self.measurement = conf["measurement"]
        self.tags = eval(conf["tags"])
        self.output_timestamp_name = conf["output_timestamp_name"]

        self.influx_writer = InfluxDBClient(
            url=self.url, token=self.token,
            org=self.org).write_api(write_options=ASYNCHRONOUS)

    def send_out(self, output_dict: Dict[str, Any],
                 datetime_timestamp: Any) -> None:
        # Remove timestamp from output dictionary
        # NOTE: timestamp MUST be in nanoseconds
        timestamp = int(output_dict[self.output_timestamp_name] * 1000000000)
        only_values = output_dict
        del only_values[self.output_timestamp_name]

        # Delete strings that cannot be written to influxdb
        to_delete = []
        for value in only_values:
            if (isinstance(only_values[value], str)
                    or isinstance(only_values[value], bool)
                    or isinstance(only_values[value], dict)):
                to_delete.append(value)

        for v_d in to_delete:
            del only_values[v_d]

        try:
            # Write to database
            #print(only_values, flush=True)
            self.influx_writer.write(self.bucket, self.org,
                                     [{
                                         "measurement": self.measurement,
                                         "tags": self.tags,
                                         "fields": only_values,
                                         "time": timestamp
                                     }])

            self.influx_writer.close()
        except OSError:
            # If too many opened files wait one second and try again.
            time.sleep(100)
            print("{}: Too many opened files. Retrying now.".format(
                datetime.datetime.now()),
                  flush=True)
            self.send_out(output_dict=output_dict)
Exemple #25
0
Create client that writes data in batches with 50_000 items.
"""
write_api = client.write_api(
    write_options=WriteOptions(batch_size=50_000, flush_interval=10_000))
"""
Write data into InfluxDB
"""
write_api.write(bucket="my-bucket", record=data)
write_api.close()
"""
Querying max value of CBOE Volatility Index
"""
query = 'from(bucket:"my-bucket")' \
        ' |> range(start: 0, stop: now())' \
        ' |> filter(fn: (r) => r._measurement == "financial-analysis")' \
        ' |> max()'
result = client.query_api().query(query=query)
"""
Processing results
"""
print()
print("=== results ===")
print()
for table in result:
    for record in table.records:
        print('max {0:5} = {1}'.format(record.get_field(), record.get_value()))
"""
Close client
"""
client.close()
Exemple #26
0
def refreshBandwidthGraphs():
    startTime = datetime.now()
    with open('statsByParentNode.json', 'r') as j:
        parentNodes = json.loads(j.read())

    with open('statsByDevice.json', 'r') as j:
        devices = json.loads(j.read())

    parentNodeNameDict = parentNodeNameDictPull()

    print("Retrieving device statistics")
    devices = getDeviceStats(devices)
    print("Computing parent node statistics")
    parentNodes = getParentNodeStats(parentNodes, devices)
    print("Writing data to InfluxDB")
    bucket = influxDBBucket
    org = influxDBOrg
    token = influxDBtoken
    url = influxDBurl
    client = InfluxDBClient(url=url, token=token, org=org)
    write_api = client.write_api(write_options=SYNCHRONOUS)

    queriesToSend = []
    for device in devices:
        bitsDownload = int(device['bitsDownloadSinceLastQuery'])
        bitsUpload = int(device['bitsUploadSinceLastQuery'])
        if (bitsDownload > 0) and (bitsUpload > 0):
            percentUtilizationDownload = round(
                (bitsDownload / round(device['downloadMax'] * 1000000)), 4)
            percentUtilizationUpload = round(
                (bitsUpload / round(device['uploadMax'] * 1000000)), 4)

            p = Point('Bandwidth').tag("Device", device['hostname']).tag(
                "ParentNode",
                device['ParentNode']).tag("Type", "Device").field(
                    "Download", bitsDownload)
            queriesToSend.append(p)
            p = Point('Bandwidth').tag("Device", device['hostname']).tag(
                "ParentNode",
                device['ParentNode']).tag("Type", "Device").field(
                    "Upload", bitsUpload)
            queriesToSend.append(p)
            p = Point('Utilization').tag("Device", device['hostname']).tag(
                "ParentNode",
                device['ParentNode']).tag("Type", "Device").field(
                    "Download", percentUtilizationDownload)
            queriesToSend.append(p)
            p = Point('Utilization').tag("Device", device['hostname']).tag(
                "ParentNode",
                device['ParentNode']).tag("Type", "Device").field(
                    "Upload", percentUtilizationUpload)
            queriesToSend.append(p)

    for parentNode in parentNodes:
        bitsDownload = int(parentNode['bitsDownloadSinceLastQuery'])
        bitsUpload = int(parentNode['bitsUploadSinceLastQuery'])
        if (bitsDownload > 0) and (bitsUpload > 0):
            percentUtilizationDownload = round(
                (bitsDownload / round(parentNode['downloadMax'] * 1000000)), 4)
            percentUtilizationUpload = round(
                (bitsUpload / round(parentNode['uploadMax'] * 1000000)), 4)

            p = Point('Bandwidth').tag(
                "Device", parentNode['parentNodeName']).tag(
                    "ParentNode", parentNode['parentNodeName']).tag(
                        "Type", "Parent Node").field("Download", bitsDownload)
            queriesToSend.append(p)
            p = Point('Bandwidth').tag(
                "Device", parentNode['parentNodeName']).tag(
                    "ParentNode", parentNode['parentNodeName']).tag(
                        "Type", "Parent Node").field("Upload", bitsUpload)
            queriesToSend.append(p)
            p = Point('Utilization').tag(
                "Device", parentNode['parentNodeName']).tag(
                    "ParentNode", parentNode['parentNodeName']).tag(
                        "Type",
                        "Parent Node").field("Download",
                                             percentUtilizationDownload)
            queriesToSend.append(p)
            p = Point('Utilization').tag(
                "Device", parentNode['parentNodeName']).tag(
                    "ParentNode", parentNode['parentNodeName']).tag(
                        "Type", "Parent Node").field("Upload",
                                                     percentUtilizationUpload)
            queriesToSend.append(p)

    write_api.write(bucket=bucket, record=queriesToSend)
    print("Added " + str(len(queriesToSend)) + " points to InfluxDB.")
    client.close()

    with open('statsByParentNode.json', 'w') as infile:
        json.dump(parentNodes, infile)

    with open('statsByDevice.json', 'w') as infile:
        json.dump(devices, infile)
    endTime = datetime.now()
    durationSeconds = round((endTime - startTime).total_seconds(), 2)
    print("Graphs updated within " + str(durationSeconds) + " seconds.")
Exemple #27
0
class WriteApiTestMock(BaseTest):

    def setUp(self) -> None:
        httpretty.enable()
        httpretty.reset()

        conf = influxdb_client.configuration.Configuration()
        conf.host = "http://localhost"
        conf.debug = False

        self.influxdb_client = InfluxDBClient(url=conf.host, token="my-token")

    def tearDown(self) -> None:
        self.influxdb_client.close()
        httpretty.disable()

    def test_writes_synchronous_without_retry(self):
        httpretty.register_uri(httpretty.POST, uri="http://localhost/api/v2/write", status=503)

        self.write_client = self.influxdb_client.write_api(write_options=SYNCHRONOUS)
        with self.assertRaises(ApiException) as cm:
            self.write_client.write("my-bucket", "my-org", "h2o_feet,location=coyote_creek water_level=1 1")
        exception = cm.exception

        self.assertEqual("Service Unavailable", exception.reason)
        self.assertEqual(1, len(httpretty.httpretty.latest_requests))

    def test_writes_asynchronous_without_retry(self):
        httpretty.register_uri(httpretty.POST, uri="http://localhost/api/v2/write", status=503)

        self.write_client = self.influxdb_client.write_api(write_options=ASYNCHRONOUS)
        with self.assertRaises(ApiException) as cm:
            self.write_client.write("my-bucket", "my-org", "h2o_feet,location=coyote_creek water_level=1 1").get()
        exception = cm.exception

        self.assertEqual("Service Unavailable", exception.reason)
        self.assertEqual(1, len(httpretty.httpretty.latest_requests))

    def test_writes_default_tags_dict_without_tag(self):
        httpretty.register_uri(httpretty.POST, uri="http://localhost/api/v2/write", status=204)

        point_settings = PointSettings(**{"id": "132-987-655", "customer": "California Miner"})
        self.write_client = self.influxdb_client.write_api(write_options=SYNCHRONOUS,
                                                           point_settings=point_settings)

        self.write_client.write("my-bucket", "my-org", {"measurement": "h2o", "fields": {"level": 1.0}, "time": 1})

        requests = httpretty.httpretty.latest_requests
        self.assertEqual(1, len(requests))
        self.assertEqual("h2o,customer=California\\ Miner,id=132-987-655 level=1 1", requests[0].parsed_body)

    def test_redirect(self):
        from urllib3 import Retry
        Retry.DEFAULT_REMOVE_HEADERS_ON_REDIRECT = frozenset()
        Retry.DEFAULT.remove_headers_on_redirect = Retry.DEFAULT_REMOVE_HEADERS_ON_REDIRECT
        self.influxdb_client.close()

        self.influxdb_client = InfluxDBClient(url="http://localhost", token="my-token", org="my-org")

        httpretty.register_uri(httpretty.POST, uri="http://localhost2/api/v2/write", status=204)
        httpretty.register_uri(httpretty.POST, uri="http://localhost/api/v2/write", status=301,
                               adding_headers={'Location': 'http://localhost2/api/v2/write'})

        self.write_client = self.influxdb_client.write_api(write_options=SYNCHRONOUS)

        self.write_client.write("my-bucket", "my-org", {"measurement": "h2o", "fields": {"level": 1.0}, "time": 1})

        requests = httpretty.httpretty.latest_requests
        self.assertEqual(2, len(requests))
        self.assertEqual('Token my-token', requests[0].headers['Authorization'])
        self.assertEqual('Token my-token', requests[1].headers['Authorization'])

        from urllib3 import Retry
        Retry.DEFAULT.remove_headers_on_redirect = Retry.DEFAULT_REMOVE_HEADERS_ON_REDIRECT

    def test_named_tuple(self):
        httpretty.register_uri(httpretty.POST, uri="http://localhost/api/v2/write", status=204)

        self.write_client = self.influxdb_client.write_api(write_options=SYNCHRONOUS)

        Factory = namedtuple('Factory', ['measurement', 'position', 'customers'])
        factory = Factory(measurement='factory', position="central europe", customers=123456)

        self.write_client.write("my-bucket", "my-org", factory,
                                record_measurement_key="measurement",
                                record_tag_keys=["position"],
                                record_field_keys=["customers"])

        requests = httpretty.httpretty.latest_requests
        self.assertEqual(1, len(requests))
        self.assertEqual("factory,position=central\\ europe customers=123456i", requests[0].parsed_body)

    @pytest.mark.skipif(sys.version_info < (3, 8), reason="requires python3.8 or higher")
    def test_data_class(self):
        httpretty.register_uri(httpretty.POST, uri="http://localhost/api/v2/write", status=204)

        self.write_client = self.influxdb_client.write_api(write_options=SYNCHRONOUS)

        from dataclasses import dataclass

        @dataclass
        class Car:
            engine: str
            type: str
            speed: float

        car = Car('12V-BT', 'sport-cars', 125.25)
        self.write_client.write("my-bucket", "my-org",
                                record=car,
                                record_measurement_name="performance",
                                record_tag_keys=["engine", "type"],
                                record_field_keys=["speed"])

        requests = httpretty.httpretty.latest_requests
        self.assertEqual(1, len(requests))
        self.assertEqual("performance,engine=12V-BT,type=sport-cars speed=125.25", requests[0].parsed_body)
Exemple #28
0
class InfluxDB:
    def __init__(self, config):
        self._config = config
        self._client = None
        self._write_api = None
        self._query_api = None
        self._delete_api = None
        self._tasks_api = None
        self._organizations_api = None
        self._token = None
        self._org = None
        self._url = None
        self._bucket = None

    def start(self):
        """Initialize the InfluxDB client."""
        try:
            influxdb_options = retrieve_options(self._config, 'influxdb2',
                                                _INFLUXDB2_OPTIONS)
            debug_options = retrieve_options(self._config, 'debug',
                                             _DEBUG_OPTIONS)
        except FailedInitialization as e:
            _LOGGER.error(f"{e}")
            return False

        if len(influxdb_options.keys()) == 0:
            raise FailedInitialization("missing 'influxdb2' options")

        result = False
        try:
            self._bucket = influxdb_options.get('bucket', None)
            self._url = influxdb_options.get('url', None)
            self._token = influxdb_options.get('token', None)
            self._org = influxdb_options.get('org', None)
            self._client = InfluxDBClient(url=self._url,
                                          token=self._token,
                                          org=self._org,
                                          enable_gzip=True)
            if not self._client:
                raise FailedInitialization(
                    f"failed to get InfluxDBClient from '{self._url}' (check url, token, and/or organization)"
                )
            self._write_api = self._client.write_api(write_options=SYNCHRONOUS)
            self._query_api = self._client.query_api()
            self._delete_api = self._client.delete_api()
            self._tasks_api = self._client.tasks_api()
            self._organizations_api = self._client.organizations_api()

            cs_esphome_debug = os.getenv(_DEBUG_ENV_VAR,
                                         'False').lower() in ('true', '1', 't')
            try:
                if cs_esphome_debug and debug_options.get(
                        'delete_bucket', False):
                    self.delete_bucket()
                    _LOGGER.info(
                        f"Deleted bucket '{self._bucket}' at '{self._url}'")
            except InfluxDBBucketError as e:
                raise FailedInitialization(f"{e}")

            try:
                if not self.connect_bucket(
                        cs_esphome_debug
                        and debug_options.get('create_bucket', False)):
                    raise FailedInitialization(
                        f"Unable to access (or create) bucket '{self._bucket}' at '{self._url}'"
                    )
            except InfluxDBBucketError as e:
                raise FailedInitialization(f"{e}")

            _LOGGER.info(
                f"Connected to InfluxDB: '{self._url}', bucket '{self._bucket}'"
            )
            result = True

        except FailedInitialization as e:
            _LOGGER.error(f" client {e}")
            self._client = None
        except NewConnectionError:
            _LOGGER.error(
                f"InfluxDB client unable to connect to host at {self._url}")
        except ApiException as e:
            _LOGGER.error(
                f"InfluxDB client unable to access bucket '{self._bucket}' at {self._url}: {e.reason}"
            )
        except Exception as e:
            _LOGGER.error(f"Unexpected exception: {e}")
        finally:
            return result

    def stop(self):
        if self._write_api:
            self._write_api.close()
            self._write_api = None
        if self._client:
            self._client.close()
            self._client = None

    def bucket(self):
        return self._bucket

    def org(self):
        return self._org

    def write_api(self):
        return self._write_api

    def query_api(self):
        return self._query_api

    def delete_api(self):
        return self._delete_api

    def tasks_api(self):
        return self._tasks_api

    def organizations_api(self):
        return self._organizations_api

    def write_point(self, measurement, tags, field, value, timestamp=None):
        """Write a single sensor to the database."""
        timestamp = timestamp if timestamp is not None else int(time.time())
        lp_tags = ''
        separator = ''
        for tag in tags:
            lp_tags += f"{separator}{tag.get('t')}={tag.get('v')}"
            separator = ','
        lp = f"{measurement}," + lp_tags + f" {field}={value} {timestamp}"

        try:
            self._write_api.write(bucket=self._bucket,
                                  record=lp,
                                  write_precision=WritePrecision.S)
        except ApiException as e:
            raise InfluxDBWriteError(
                f"InfluxDB client unable to write to '{self._bucket}' at {self._url}: {e.reason}"
            )
        except Exception as e:
            raise InfluxDBWriteError(
                f"Unexpected failure in write_point(): {e}")

    def write_points(self, points):
        """Write a list of points to the database."""
        try:
            self._write_api.write(bucket=self._bucket,
                                  record=points,
                                  write_precision=WritePrecision.S)
        except ApiException as e:
            raise InfluxDBWriteError(
                f"InfluxDB client unable to write to '{self._bucket}' at {self._url}: {e.reason}"
            )
        except Exception as e:
            raise InfluxDBWriteError(
                f"Unexpected failure in write_points(): {e}")

    def write_batch_sensors(self, batch_sensors, timestamp=None):
        """Write a batch of sensors to the database."""

        if len(batch_sensors) == 0:
            return

        timestamp = timestamp if timestamp is not None else int(time.time())

        batch = []
        for record in batch_sensors:
            sensor = record.get('sensor', None)
            state = record.get('state', None)
            measurement = sensor.get('measurement', None)
            device = sensor.get('device', None)
            location = sensor.get('location', None)
            precision = sensor.get('precision', None)
            if measurement is None or device is None:
                raise InfluxDBFormatError(
                    "'measurement' and/or 'device' are required")

            location_tag = '' if not location or not len(
                location) else f',_location={location}'
            device_tag = f',_device={device}'
            value = round(
                state, precision) if ((precision is not None)
                                      and isinstance(state, float)) else state
            lp = f'{measurement}{device_tag}{location_tag} sample={value} {timestamp}'
            batch.append(lp)

        try:
            self._write_api.write(bucket=self._bucket,
                                  record=batch,
                                  write_precision=WritePrecision.S)
        except ApiException as e:
            raise InfluxDBWriteError(
                f"InfluxDB client unable to write to '{self._bucket}' at {self._url}: {e.reason}"
            )
        except Exception as e:
            raise InfluxDBWriteError(
                f"Unexpected failure in write_batch_sensors(): {e}")

    def delete_bucket(self):
        try:
            buckets_api = self._client.buckets_api()
            found_bucket = buckets_api.find_bucket_by_name(self._bucket)
            if found_bucket:
                buckets_api.delete_bucket(found_bucket)
                bucket = buckets_api.find_bucket_by_name(self._bucket)
                if not bucket:
                    return True
            return False
        except ApiException as e:
            raise InfluxDBBucketError(
                f"InfluxDB client unable to delete bucket '{self._bucket}' at {self._url}: {e.reason}"
            )
        except Exception as e:
            raise InfluxDBBucketError(
                f"Unexpected exception in delete_bucket(): {e}")

    def connect_bucket(self, create_bucket=False):
        try:
            buckets_api = self._client.buckets_api()
            bucket = buckets_api.find_bucket_by_name(self._bucket)
            if bucket:
                return True
            if create_bucket:
                bucket = buckets_api.create_bucket(bucket_name=self._bucket,
                                                   org_id=self._org,
                                                   retention_rules=None,
                                                   org=None)
                if bucket:
                    _LOGGER.info(
                        f"Created bucket '{self._bucket}' at {self._url}")
                    return True
            return False
        except ApiException as e:
            raise InfluxDBBucketError(
                f"InfluxDB client unable to create bucket '{self._bucket}' at {self._url}: {e.reason}"
            )
        except Exception as e:
            raise InfluxDBBucketError(
                f"Unexpected exception in connect_bucket(): {e}")
class InfluxLoggingHandler(logging.Handler):
    """
    InfluxLoggingHandler instances dispatch logging events to influx.

    There is no need to set a Formatter.
    The raw input will be passed on to the influx write api.
    """

    DEFAULT_LOG_RECORD_KEYS = list(logging.makeLogRecord(
        {}).__dict__.keys()) + ['message']

    def __init__(self,
                 *,
                 url,
                 token,
                 org,
                 bucket,
                 client_args=None,
                 write_api_args=None):
        """
        Initialize defaults.

        The arguments `client_args` and `write_api_args` can be dicts of kwargs.
        They are passed on to the InfluxDBClient and write_api calls respectively.
        """
        super().__init__()

        self.bucket = bucket

        client_args = {} if client_args is None else client_args
        self.client = InfluxDBClient(url=url,
                                     token=token,
                                     org=org,
                                     **client_args)

        write_api_args = {} if write_api_args is None else write_api_args
        self.write_api = self.client.write_api(**write_api_args)

    def __del__(self):
        """Make sure all resources are closed."""
        self.close()

    def close(self) -> None:
        """Close the write_api, client and logger."""
        self.write_api.close()
        self.client.close()
        super().close()

    def emit(self, record: logging.LogRecord) -> None:
        """Emit a record via the influxDB WriteApi."""
        try:
            message = self.format(record)
            extra = self._get_extra_values(record)
            return self.write_api.write(record=message, **extra)
        except (KeyboardInterrupt, SystemExit):
            raise
        except (Exception, ):
            self.handleError(record)

    def _get_extra_values(self, record: logging.LogRecord) -> dict:
        """
        Extract all items from the record that were injected via extra.

        Example: `logging.debug(msg, extra={key: value, ...})`.
        """
        extra = {'bucket': self.bucket}
        extra.update({
            key: value
            for key, value in record.__dict__.items()
            if key not in self.DEFAULT_LOG_RECORD_KEYS
        })
        return extra
class InfluxDBClientTestIT(BaseTest):
    httpRequest = []

    def tearDown(self) -> None:
        super(InfluxDBClientTestIT, self).tearDown()
        if hasattr(self, 'httpd'):
            self.httpd.shutdown()
        if hasattr(self, 'httpd_thread'):
            self.httpd_thread.join()
        InfluxDBClientTestIT.httpRequest = []

    def test_proxy(self):
        self._start_proxy_server()

        self.client.close()
        self.client = InfluxDBClient(
            url=self.host,
            token=self.auth_token,
            proxy=f"http://localhost:{self.httpd.server_address[1]}",
            proxy_headers={'ProxyHeader': 'Val'})
        ready = self.client.ready()
        self.assertEqual(ready.status, "ready")
        self.assertEqual(1, len(InfluxDBClientTestIT.httpRequest))
        self.assertEqual(
            'Val',
            InfluxDBClientTestIT.httpRequest[0].headers.get('ProxyHeader'))

    def test_ping(self):
        ping = self.client.ping()
        self.assertTrue(ping)

    def test_ping_not_running_instance(self):
        client_not_running = InfluxDBClient("http://localhost:8099",
                                            token="my-token",
                                            debug=True)
        ping = client_not_running.ping()
        self.assertFalse(ping)
        client_not_running.close()

    def test_version(self):
        version = self.client.version()
        self.assertTrue(len(version) > 0)

    def test_version_not_running_instance(self):
        client_not_running = InfluxDBClient("http://localhost:8099",
                                            token="my-token",
                                            debug=True)
        with self.assertRaises(NewConnectionError):
            client_not_running.version()

        client_not_running.close()

    def test_username_password_authorization(self):
        self.client.close()
        self.client = InfluxDBClient(url=self.host,
                                     username="******",
                                     password="******",
                                     debug=True)
        self.client.query_api().query("buckets()", "my-org")

    def test_query_and_debug(self):
        self.client.close()
        self.client = InfluxDBClient(url=self.host,
                                     token="my-token",
                                     debug=True)
        # Query
        results = self.client.query_api().query("buckets()", "my-org")
        self.assertIn(
            "my-bucket",
            list(map(lambda record: record["name"], results[0].records)))
        # Query RAW
        results = self.client.query_api().query_raw("buckets()", "my-org")
        self.assertIn("my-bucket", codecs.decode(results.data))
        # Bucket API
        results = self.client.buckets_api().find_buckets()
        self.assertIn("my-bucket",
                      list(map(lambda bucket: bucket.name, results.buckets)))

    def _start_proxy_server(self):
        import http.server
        import urllib.request

        class ProxyHTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
            def do_GET(self):
                InfluxDBClientTestIT.httpRequest.append(self)
                self.send_response(200)
                self.send_header('Content-type', 'application/json')
                self.end_headers()
                self.copyfile(urllib.request.urlopen(self.path), self.wfile)

        self.httpd = http.server.HTTPServer(('localhost', 0),
                                            ProxyHTTPRequestHandler)
        self.httpd_thread = threading.Thread(target=self.httpd.serve_forever)
        self.httpd_thread.start()