Giter VIP home page Giter VIP logo

grafana-gnocchi-datasource's People

Contributors

alexanderzobnin avatar ali5h avatar asu4ni avatar bobuhiro11 avatar bollig avatar christianchristensen avatar chupman avatar heinrichvk avatar jd avatar jsm222 avatar kylebrandt avatar mark-ezhkov avatar matschaffer avatar mtanda avatar pdf avatar prepor avatar siavashs avatar sileht avatar sorrison avatar tmonk42 avatar tobias-urdin avatar torkelo avatar waipeng avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

grafana-gnocchi-datasource's Issues

Invalid filter when selecting a single instance

When selecting a single instance, the query passed to gnocchi seems to be incorrect.

params: {filter: "instance_id in cb5f8625-155c-4528-a51e-
"Invalid input: expected a list for dictionary value @ data['in']['instance_id']”

We're using this dashboard: https://grafana.com/dashboards/4569. The plugin could probably ensure that this is actually handled as a list.

Problem when using keystone auth mode and server(proxy) access mode

When using token auth mode and server access mode, test operation will get gnocchi resources through grafana server normally.
However, if using keystone auth mode, test operation will get token through proxy but get gnocchi resource directly.
For example (in one test operation):
http://<grafana_ip>:<grafana_port>/api/datasources/proxy/5/v3/auth/tokens
http://<gnocchi_ip>:8041/v1/resource

Does grafana-gnocchi-datasource support Https ?

I have built a grafana server and could connected gnocchi datasource through Http. But after our OpenStack env. (include gnocchi) swift from Http to Https, it can not connected anymore.

Does grafana-gnocchi-datasource support Https ?

Feature Request: Group and sort functions for measures

Right now it's impossible to sort all obtained measures or show only part of them.

For example we need to get instances with top CPU utilization. That means that we want to get all metrics (cpu_util) for some resource type (instance), sort by value in descending order and show only some of them in Grafana.

We can use "resource search" query type, set resource type, metric name and some simple query string (say, started_at>='somedate'). After that we will receive some amount of metrics, maximum amount of those metrics will be equal to api.max_limit value in gnocchi.conf.
If we want to get all measures (to perform some kind of analysis) we have to set big value for api.max_limit option in gnocchi.conf. But in this case we will get thousands of metrics on one chart in Grafana.

What we need is some kind of functions to set them on all of our received values.
There are some example implementations:
Graphite datasource: http://docs.grafana.org/features/datasources/graphite/#functions
Zabbix datasource: http://docs.grafana-zabbix.org/reference/functions/

Issue Keystone Auth, forcing HTTPS

Using Auth Mode keystone, with all settings OK (URL endpoint http://controller:5000, domain, project, user and password) and CORS enabled.
Grafana gets the Keystone token and the Gnocchi endpoint, and goes to query it.
But, the connection is done via HTTPS automatically forced, not HTTP.
As HTTPS is not responding, data load fails.
This happens in some versions of Firefox and Chrome, Internet Explorer is not having this issue and gets the data OK.

Missing points from gnocchi drew as zeros

When there are missing points from gnocchi, e.g. there are no data with the granularity in the metric, the missing values are represented as 0 value. This makes the graphs awkward, e.g. when ceilometer samples the CPU usage in 10 minutes interval, but using the 5 minutes aggregation in Gnocchi, the graph looks like a sawtooth wave. I think missing values should be null and the null values can be interpolated then.

Issue: Unable to Query in Template

Hello,

i recently deployed grafana with gnocchi in an openstack kolla-ansible deployment.
Now I have the Problem that I am unable to query for instancesnames like it is shown in your documentation.
When I query for

resources(instance, id, host=COMP2)

i get a popup with:

Templating
Template variables could not be initialized: Unexpected token h in JSON at position 0

In the gnocchicli it looks like this:

gnocchi resource list --type instance -f json [ { "started_at": "2018-01-16T12:54:19.093064+00:00", "user_id": "399af2114fb043aab626b7c022e5cfaa", "revision_end": null, "creator": "6509a0fb8ecf40cf98b77ad311bad32d:c61f928dd839427bbde384ac8151ad8b", "revision_start": "2018-01-16T12:54:19.093084+00:00", "flavor_name": "m2.medium", "host": "COMP2", "image_ref": null, "flavor_id": "f8464ff2-f60d-45b9-8198-973cd0e11acb", "server_group": null, "original_resource_id": "08176e67-81ad-43ce-8a72-847849dfbbfc", "ended_at": null, "project_id": "0fbb5957dd564cb1928e2a64888c096e", "type": "instance", "id": "08176e67-81ad-43ce-8a72-847849dfbbfc", "display_name": "test" } ]

How to return one value for the result of a dynamic aggregate?

Hello,
we are using the current stable Gnocchi Grafana Datasource plugin in to query the metrics of an OpenStack cluster. At the moment, I am trying to use the dynamic aggregates query type to fill a Single Stats panel. However, the return value of the query is an array of items instead of a single value. What am I doing wrong?

The expected output of the query is the sum of the mean number of vcpus of all instances for a given search string in the given time period (I know I can do that via the resource search (aggregated measurements) but would like to apply some math to the result).

The operation I have defined is: (aggregate sum (metric vcpus mean))
and the response I can see in the Query Inspector looks like this:

...
response:Object
measures:Object
aggregated:Array[4]
0:Array[2018-03-13T13:25:00+00:00,300,16]
1:Array[2018-03-13T13:50:00+00:00,300,192]
2:Array[2018-03-13T13:55:00+00:00,300,48]
3:Array[2018-03-13T14:00:00+00:00,300,224]
references:Array[32]
0:Object
...

How do I aggregate the response array into a single value?

RFE: support "groupby" in queries

In order to produce graphs for things like "total allocated storage by project", it would be great to have support for the "groupby" operation in the gnocchi data source (for both dynamic aggregates and the older aggregate api).

JSON parsing issues

Some response jsons will include “Infinity”, which JSON.parse can’t handle.

E.g. "{"measures": {"aggregated": [["2018-10-10T13:10:00+00:00", 300.0, Infinity]]}}"

The plugin could probably replace those occurrences with 1e+99999, avoiding such parsing errors.

Gnocchi is unreachable or CORS is misconfigured

Hi,

The Gnocchi Grafana datasource is failing with Gnocchi is unreachable or CORS is misconfigured (detail: TypeError: NetworkError when attempting to fetch resource.) Grafana version is 8.2.1 and gnocchixyz-gnocchi-datasource has this fix applied.

Both Keystone and Gnocchi have this in their configs:

[cors]
allowed_origin = *
allow_methods = GET,POST,PUT,DELETE,OPTIONS,HEAD
allow_headers = X-Auth-Token,X-Openstack-Request-Id,X-Subject-Token,X-Project-Id,X-Project-Name,X-Project-Domain-Id,X-Project-Domain-Name,X-Domain-Id,X-Domain-Name

But somehow the integration keep failing.

How to write query to get gnocchi information at grafana

I am using gnocchi version 7.0.1 with OpenStack Queens.
Can anyone send any sample query to get the information from grafana with gnocchi plugin server?
I mean what are the information, I have to write for the following fields:
Resource Type: instance
Query: What should I write here?
Operations: What should I write here?

Kindly write a sample query to get the cpu utilization of an instance.

Connect Grafana to Gnocchi without modifying gnocchi.conf

Hi,

I'm trying to connect Grafana to Gnocchi data source with keystone authentication.
But I don't have permissions to modify the gnocchi.conf or keystone.conf for [cors] "allowed_origin".
Is there any way where I can access Gnocchi resources? e.g. Passing the required headers in HTTP request itself? Or extending the gnocchi.conf as we do it for apache conf.

Cannot use Grafana Gnocchi Datasource with Keystone auth mode

@sileht @jd I've read all docs, but couldn't I fix the issue.

Error :

Error

Gnocchi error: No response status code, is CORS correctly configured ?

Config files :

Gnocchi.conf ↴

[DEFAULT]
debug = true
verbose = true

[api]
workers = 4
middlewares = oslo_middleware.cors.CORS                   
middlewares = keystonemiddleware.auth_token.AuthProtocol  
paste_config = /usr/lib/python2.7/site-packages/gnocchi/rest/api-paste.ini
auth_mode = keystone


[archive_policy]

[cors]
allowed_origin = http://172.18.1.199:3000


Auth-Token,X-Subject-Token
allow_methods = GET,POST,PUT,DELETE,OPTIONS,HEAD
allow_headers = Content-Type,Cache-Control,Content-Language,Expires,Last-Modified,Pragma,X-Auth-Token,X-Subject-Token
expose_headers = Content-Type,Cache-Control,Content-Language,Expires,Last-Modified,Pragma

[cors.subdomain]

[database]
backend = sqlalchemy

[healthcheck]
[incoming]

[indexer]
url = "postgresql://gnocchi:[email protected]/gnocchi"

[metricd]
workers = 8

[oslo_middleware]
[oslo_policy]

[statsd]
host = 0.0.0.0
port = 8125

[storage]
coordination_url = file:///var/lib/gnocchi/locks
driver = file
file_basepath = /var/lib/gnocchi

[keystone_authtoken]
auth_type = password
auth_url = http://127.0.0.1:5000/v3
memcached_servers = localhost:11211
project_domain_name = default
user_domain_name = default
project_name = service
username = admin
password = ***************************************
region_name = Region_LAB

Keystone-paste.ini ↴

[filter:debug]
use = egg:oslo.middleware#debug

[filter:request_id]
use = egg:oslo.middleware#request_id

[filter:build_auth_context]
use = egg:keystone#build_auth_context

[filter:token_auth]
use = egg:keystone#token_auth

[filter:admin_token_auth]
use = egg:keystone#admin_token_auth

[filter:json_body]
use = egg:keystone#json_body

[filter:cors]
allowed_origin = http://172.18.1.199:3000
paste.filter_factory = oslo_middleware.cors:CORS.factory
oslo_config_project = keystone


[filter:http_proxy_to_wsgi]
use = egg:oslo.middleware#http_proxy_to_wsgi

[filter:healthcheck]
use = egg:oslo.middleware#healthcheck

[filter:ec2_extension]
use = egg:keystone#ec2_extension

[filter:ec2_extension_v3]
use = egg:keystone#ec2_extension_v3

[filter:s3_extension]
use = egg:keystone#s3_extension

[filter:url_normalize]
use = egg:keystone#url_normalize

[filter:sizelimit]
use = egg:oslo.middleware#sizelimit

[filter:osprofiler]
use = egg:osprofiler#osprofiler

[app:public_service]
use = egg:keystone#public_service

[app:service_v3]
use = egg:keystone#service_v3

[app:admin_service]
use = egg:keystone#admin_service

[pipeline:public_api]
pipeline = cors healthcheck sizelimit http_proxy_to_wsgi osprofiler url_normalize request_id admin_token_auth build_auth_context token_auth json_body ec2_extension public_service

[pipeline:admin_api]
pipeline = cors healthcheck sizelimit http_proxy_to_wsgi osprofiler url_normalize request_id admin_token_auth build_auth_context token_auth json_body ec2_extension s3_extension admin_service

[pipeline:api_v3]
pipeline = cors healthcheck sizelimit http_proxy_to_wsgi osprofiler url_normalize request_id admin_token_auth build_auth_context token_auth json_body ec2_extension_v3 s3_extension service_v3

[app:public_version_service]
use = egg:keystone#public_version_service

[app:admin_version_service]
use = egg:keystone#admin_version_service

[pipeline:public_version_api]
pipeline = cors healthcheck sizelimit osprofiler url_normalize public_version_service

[pipeline:admin_version_api]
pipeline = cors healthcheck sizelimit osprofiler url_normalize admin_version_service

[composite:main]
use = egg:Paste#urlmap
/v2.0 = public_api
/v3 = api_v3
/ = public_version_api

[composite:admin]
use = egg:Paste#urlmap
/v2.0 = admin_api
/v3 = api_v3
/ = admin_version_api

Keystone.conf ↴

[DEFAULT]
admin_token = c01f11a39faceecde032
[assignment]
[auth]
[cache]
[catalog]
driver = keystone.catalog.backends.sql.Catalog
[cors]
allowed_origin = http://172.18.1.199:3000
allow_methods = GET,POST,PUT,DELETE,OPTIONS
allow_headers = Content-Type,Cache-Control,Content-Language,Expires,Last-Modified,Pragma,X-Auth-Token,X-Subject-Token
expose_headers = Content-Type,Cache-Control,Content-Language,Expires,Last-Modified,Pragma,X-Auth-Token,X-Subject-Token
[cors.subdomain]
[credential]
[database]
connection = mysql+pymysql://keystone:***********************@127.0.0.1/keystone
[domain_config]
[endpoint_filter]
[endpoint_policy]
[eventlet_server]
bind_host = 172.19.1.11
public_bind_host = 172.19.1.11
admin_bind_host = 172.19.1.11
[federation]
[fernet_tokens]
[healthcheck]
[identity]
driver = keystone.identity.backends.sql.Identity
[identity_mapping]
[kvs]
[ldap]
[matchmaker_redis]
[memcache]
[oauth1]
[oslo_messaging_amqp]
[oslo_messaging_kafka]
[oslo_messaging_notifications]
[oslo_messaging_rabbit]
[oslo_messaging_zmq]
[oslo_middleware]
[oslo_policy]
[paste_deploy]
[policy]
[profiler]
[resource]
[revoke]
[role]
[saml]
[security_compliance]
[shadow_users]
[signing]
[token]
provider = fernet
[tokenless_auth]
[trust]

We are using Ocata versoin.

Would you please help??

plugin at risk of deprecation

Hi there from Grafana Labs 👋

Firstly, thank you for contributing to the Grafana plugin ecosystem.

I'm reaching out as this plugin is at risk of being deprecated from the Grafana plugin catalog as it depends on Angular (#83) and has not been updated in a number of years.

We recognise that priorities change and that it may no longer be possible to keep plugins up to date. For your awareness, deprecation has no impact on existing users of the plugin, but discourages further adoption to prevent users from starting to rely on a component which won't receive updates.

Please advise if you plan to migrate, or alternatively that you agree the plugin should be deprecated. In the case of the latter, if there is any specific guidance you would like to offer users of the plugin - please let me know and we can include this in the deprecation notice.

Feel free to email me at [email protected] if preferred; apologies, we don't have an email address associated with this plugin so I had to raise an issue.

If we don't hear from you within 30 days, I'll go ahead and deprecate the plugin.

Thank you again
David

Angular is deprecated - please migrate to React

Hello 👋 from Grafana Labs

We have detected that your plugin might still be using AngularJS and recommend migrating it to React, so that it may continue to operate successfully in future versions of Grafana.

You can read more on why and how by visiting our documentation: https://grafana.com/docs/grafana/latest/developers/angular_deprecation/

You can reach out to us with any questions via slack: slack.grafana.com - channel #plugins or our plugin development community forum

Gnocchi datasource via keystone not working after upgrade to Grafana 7

Hi,

Didn't change the settings, but after upgrade to grafana 7, the datasource just seems not to be working. It was working previously with keystone credentials set.

When I hit "Save and test" the blue bar shows "Testing" forever.

image

in the grafana logs, I just see a 200..

t=2020-06-09T16:52:40+0200 lvl=info msg="Request Completed" logger=context userId=67 orgId=1 uname=<email> method=GET path=/api/frontend/settings status=200 remote_addr=123.123.123.123 time_ms=5 size=21483 referer=https://grafana-url.url/datasources/edit/19/

any advise or hints to track it down?

Missing Template Variables for Grafana

The metrics() and resources() variables do not appear in the Templating Variables list. They do not function in the queries.

Your plugin documentation:

Templated queries
Gnocchi Datasource Plugin provides following functions in Variables values query field in Templating Editor.

Name Description
metrics(resource_id) Returns a list of metrics avialable for the resource identified by ‘resource_id’
resources(resource_type,attribute, query) Returns a list of resource attribute matching query.
For details of query format, please refer to the Gnocchi documentations.

If I have the wrong expectations for these to appear automatically, can you provide an example of how to properly use these? I'd like a template variable for all resources that are active in gnocchi within the specified time frame.

Keystone returning an HTML 404 error when attemting to aquire token

Problem Statement

Getting an error when selecting Save & Test Gnocchi data source stating: Keystone failure: (404 Not Found).

The associated error was found on the openstack controller in /var/log/keystone/keystone_access.log:

<ip redacted> - - [27/Nov/2018:14:21:58 +0000] "POST /v3/v3/auth/tokens HTTP/1.1" 404 350 "-" "Grafana/5.3.4"

An example of a correctly formed URI looks like:

<ip redacted> - - [27/Nov/2018:14:49:58 +0000] "POST /v3/auth/tokens HTTP/1.1" 201 10038 "-" "python-openstackclient keystoneauth1/2.4.1 python-requests/2.9.1 CPython/2.7.12"

Note: An extra keystone version declaration is found in the access log associated to the error.

Keystone endpoint on controller

The endpoint on the controller already contains the version in the URL

  {
    "Service Type": "identity",
    "URL": "http://pod3controller-int:5000/v3/",
    "Region": "RegionOne",
    "Enabled": true,
    "Interface": "internal",
    "Service Name": "keystone",
    "ID": "9c5ad5235f7d4fc1a1b2d6b0a2b72230"
  }

TCP Conversation.

This is the TCP conversation as seen from the controller filtered on only the grafana host

POST /v3/auth/tokens HTTP/1.1
Host: pod3controller:8041
User-Agent: Grafana/5.3.4
Content-Length: 196
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.5
Content-Type: application/json
X-Forwarded-For: <IP redacted>, <IP redacted>
X-Grafana-Nocache: true
X-Grafana-Org-Id: 1

{"auth":{"identity":{"methods":["password"],"password":{"user":{"name":"admin","password":"<redacted>","domain":{"id":"Default"}}}},"scope":{"project":{"domain":{"id":"Default"},"name":"admin"}}}}HTTP/1.0 404 Not Found
Date: Tue, 27 Nov 2018 17:01:18 GMT
Server: WSGIServer/0.1 Python/2.7.12
Content-Length: 112
Content-Type: application/json; charset=UTF-8

{"message": "The resource could not be found.<br /><br />\n\n\n", "code": "404 Not Found", "title": "Not Found"}

Environment

Installed Grafana 5.3.4 (commit: 69630b9) by following the installation document for apt repository on a virtual instance of Ubuntu 16.04.5 LTS (xenial)

Installed the plugin following the Gnocchi plugin for Grafana

Datasource Config

image

Request

Anyone know why this extra version declaration is present in the plugin's keystone request for a token and how to correct it?

Use a different Keystone URL than Gnocchi

I'm not able to use the Keystone Auth Mode.

Even if the services are using the same URL, they don't share the same port.
As a result, I can't use the keystone configuration, but only the token one.
It may be the same problem encountered in #68.

I create a PR #70 to implement it.

Grafana Gnocchi datasource config difficulty

Hello. I'm trying to configure the Gnocchi Grafana plugin to access a lab install of Pike deployed using OpenStack-Ansible. By default, the deploy uses self-signed certs and the public Keystone VIP is automatically https. Since there is no Horizon plugin for metrics (that I'm aware of), it looks like this the winner for visualizing the metrics. The deploy seems to be working properly in all respects that I've tested including executing openstack CLI commands from an external server using the public endpoints. (For example, "openstack server list --insecure").

I can't seem to get anything to work with the Grafana plugin on an external server. It could be I'm just doing something simple incorrectly. I'm primarily testing the proxy method and receiving "Keystone failure: (502 Bad Gateway)". I'm testing against an OpenStack Pike environment using OpenStack Ansible 16.0.7.

Pretty much any combination of things I try result in some form of 502 keystone bad gateway error.

An example of settings I'm trying currently are seen in the attached image:

gnocchi-test-settings

Endpoints as seen from within the OS environment in the attached image:

osa-test-endpoints

If you can offer any pointers, please advise.

Thank you!

Request-URI Too Long

When selecting many (or all) instances, it will try to do a request to gnocchi, including all the instance ids as filters in the query. This will fail with Failed to load resource: the server responded with a status of 414 (Request-URI Too Long).

This should probably be decomposed in multiple requests.

Latest RDO: /etc/gnocchi/api-paste.ini

I found that enabling cors for gnocchi in the latest RDO requires the gnocchi api-paste.ini pipeline to look like:

[pipeline:main]
pipeline = cors gnocchi+auth

Missing or invalid fields: Query, Metric name when creating a dashboard

Hello,

I'm working on a setup on centos 7 with the following packages (gnocchi packages from rdo-ocata and grafana from grafana.net):

grafana-4.4.3-1.x86_64
openstack-gnocchi-api-3.1.9-1.el7.noarch
openstack-gnocchi-common-3.1.9-1.el7.noarch
openstack-gnocchi-indexer-sqlalchemy-3.1.9-1.el7.noarch
openstack-gnocchi-metricd-3.1.9-1.el7.noarch
python-gnocchi-3.1.9-1.el7.noarch

And I installed collectd-gnocchi (1.5.0) to get system metrics.

I installed 'gnocchixyz-gnocchi-datasource @ 1.2.0' with grafana-cli tool

I created a datasource (without keystone auth) and got "Success Data source is working"

When I tried to create a graph, I got the following error:

Missing or invalid fields: Query, Metric name when creating a dashboard

gnocchi

Do you have any idea how to fix this issue ?

Thanks

Feature Request: Units for metrics

Graphs should include units for metrics. It is hard enough to identify what a metric represents other than manually looking up the UUID with the gnocchi cli. The units would help us understand what the values illustrate.

RFE: Can the "resource type" field be a drop-down (or combo box)?

It seems as if the "resource type" field (when using a "resource search" query) ought to be a drop-down menu. It seems that in general there will be a relatively small number of resources types, and you can always use a combo box if you still want people to be able to type in an arbitrary value.

Can't use metric name for label in graphs?

I would like to use the metric name as the label in grafana graphs. When I enter name into the "Label" field, I see in the graph "attribute name not found". On the other hand, other attributes (like "creator") work fine. I'm confused, because gnocchi metrics clearly have a name attribute. Am I doing something wrong?

Don't load out of time range resources

Having a dashboard with range Last 24 hours.

Doing a resource search with query display_name = '[[server]]', returns me 9 resources (instances).
All of them are loaded, but only one has data.
On each resource, ended_at should be check if is null (not ended) or in range of time -
started_at, in order to avoid loading the other resources with no data at that time.

image

Gnocchi error returning `results` object in detail "(detail: [object Object])"

While attempting to add this plugin I get the error:
Gnocchi error: No response status code, is CORS correctly configured ? (detail: [object Object])

I find that this originates in dist/datasource.js:815 in _gnocchi_auth_request which reads:
reason.message = "Gnocchi error: No response status code, is CORS correctly configured ? (detail: " + reason + ")"

Can this be changed to reason.status or something more useful for trouble shooting CORS problems?

Dynamic aggregate for memory returns weird values

Hello,
we are using the Gnocchi Grafana datasource v1.6.2 and are trying to query the metrics of an OpenStack cluster. We noticed that the dynamic aggregate for the instance metric memory returns weird values. If you compare the resource search method using metric regex memory with dynamic aggregates using the Operation(metric memory mean), the result will be very different. Only the resource search method returns the correct memory allocation for each instance while the dynamic aggregate just returns zeros

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.