---
title: Getting started
sort_rank: 3
---

# Getting started

This guide is a "Hello World"-style tutorial which shows how to install,
configure, and use Prometheus in a simple example setup. You will build and run
Prometheus locally, configure it to scrape itself and an example application,
and then work with queries, rules, and graphs to make use of the collected time
series data.

## Getting Prometheus

First, fetch the latest Prometheus collector server code:

```language-bash
git clone https://github.com/prometheus/prometheus.git
```

## Building Prometheus

Building Prometheus currently still requires a `make` step, as some parts of
the source are autogenerated (protobufs, web assets, lexer/parser files).

```language-bash
cd prometheus
make build
```

If you encounter problems building Prometheus, see [the more detailed build
instructions](https://github.com/prometheus/prometheus#use-make) in the
README.md.

## Configuring Prometheus to monitor itself

Prometheus collects metrics from monitored targets by scraping metrics HTTP
endpoints on these targets. Since Prometheus also exposes data in the same
manner about itself, it may also be used to scrape and monitor its own health.

While a Prometheus server which collects only data about itself is not very
useful in practice, it is a good starting example. Save the following basic
Prometheus configuration as a file named `prometheus.conf`:

```
# Global default settings.
global: {
  scrape_interval: "15s"     # By default, scrape targets every 15 seconds.
  evaluation_interval: "15s" # By default, evaluate rules every 15 seconds.

  # Attach these extra labels to all time series collected by this Prometheus instance.
  labels: {
    label: {
      name: "monitor"
      value: "tutorial-monitor"
    }
  }
}

# A job definition containing exactly one endpoint to scrape: Prometheus itself.
job: {
  # The job name is added as a label `job={job-name}` to any time series scraped from this job.
  name: "prometheus"
  # Override the global default and scrape targets from this job every 5 seconds.
  scrape_interval: "5s"

  # Let's define a group of static targets to scrape for this job. In this
  # case, only one.
  target_group: {
    # These endpoints are scraped via HTTP.
    target: "http://localhost:9090/metrics"
  }
}
```

Prometheus configuration is supplied in an ASCII form of [protocol
buffers](https://developers.google.com/protocol-buffers/docs/overview/). The
[schema definition](https://github.com/prometheus/prometheus/blob/master/config/config.proto)
has a complete documentation of all available configuration options.

## Starting Prometheus

To start Prometheus with your newly created configuration file, change to your
Prometheus build directory and run:

```language-bash
# Start Prometheus.
# By default, Prometheus stores its database in /tmp/metrics (flag -storage.local.path).
./prometheus -config.file=prometheus.conf
```

Prometheus should start up and it should show a status page about itself at
http://localhost:9090. Give it a couple of seconds to start collecting data
about itself from its own HTTP metrics endpoint.

You can also verify that Prometheus is serving metrics about itself by
navigating to its metrics exposure endpoint: http://localhost:9090/metrics

By default, Prometheus will only execute at most one OS thread at a
time. In production scenarios on multi-CPU machines, you will most
likely achieve better performance by setting the `GOMAXPROCS`
environment variable to a value similar to the number of available CPU
cores:

```language-bash
GOMAXPROCS=8 ./prometheus -config.file=prometheus.conf
```

Blindly setting `GOMAXPROCS` to a high value can be
counterproductive. See the relevant [Go
FAQs](http://golang.org/doc/faq#Why_no_multi_CPU).

## Using the expression browser

Let's try looking at some data that Prometheus has collected about itself. To
use Prometheus's built-in expression browser, navigate to
http://localhost:9090/graph and choose the "Tabular" view within the "Graph"
tab.

As you can gather from http://localhost:9090/metrics, one metric that
Prometheus exports about itself is called
`prometheus_target_interval_length_seconds` (the actual amount of time between
target scrapes). Go ahead and enter this into the expression console:

```
prometheus_target_interval_length_seconds
```

This should return a lot of different time series (along with the latest value
recorded for each), all with the metric name
`prometheus_target_interval_length_seconds`, but with different labels. These
labels designate different latency percentiles and target group intervals.

If we were only interested in the 99th percentile latencies, we could use this
query to retrieve that information:

```
prometheus_target_interval_length_seconds{quantile="0.99"}
```

To count the number of returned time series, you could write:

```
count(prometheus_target_interval_length_seconds)
```

For further details about the expression language, see the
[expression language documentation](/docs/querying/basics/).

## Using the graphing interface

To graph expressions, navigate to http://localhost:9090/graph and use the "Graph"
tab.

For example, enter the following expression to graph the per-second rate of all
storage chunk operations happening in the self-scraped Prometheus:

```
rate(prometheus_local_storage_chunk_ops_total[1m])
```

Experiment with the graph range parameters and other settings.

## Starting up some sample targets

Let's make this more interesting and start some example targets for Prometheus
to scrape.

The Go client library includes an example which exports fictional RPC latencies
for three services with different latency distributions.

Download the Go client library for Prometheus and run three of these example
processes:

```bash
# Fetch the client library code and compile example.
git clone https://github.com/prometheus/client_golang.git
cd client_golang
make example_random

# Start 3 example targets in separate terminals:
./example_random -listen-address=:8080
./example_random -listen-address=:8081
./example_random -listen-address=:8082
```

You should now have example targets listening on http://localhost:8080/metrics,
http://localhost:8081/metrics, and http://localhost:8082/metrics.

## Configuring Prometheus to monitor the sample targets

Now we'll configure Prometheus to scrape these new targets. Let's group all
three endpoints into one job called `example-random`. However, imagine that the
first two endpoints are production targets, while the third one represents a
canary instance. To model this in Prometheus, we can add several groups of
endpoints to a single job, adding extra labels to each group of targets. In
this example, we'll add the `group="production"` label to the first group of
targets, while adding `group="canary"` to the second.

To achieve this, add the following job definition to your `prometheus.conf` and
restart your Prometheus instance:

```
job: {
  name: "example-random"
  scrape_interval: "5s"

  # The "production" targets for this job.
  target_group: {
    target: "http://localhost:8080/metrics"
    target: "http://localhost:8081/metrics"
    labels: {
      label: {
        name: "group"
        value: "production"
      }
    }
  }
  # The "canary" targets for this job.
  target_group: {
    target: "http://localhost:8082/metrics"
    labels: {
      label: {
        name: "group"
        value: "canary"
      }
    }
  }
}
```

Go to the expression browser and verify that Prometheus now has information
about time series that these example endpoints expose, such as the
`rpc_durations_microseconds` metric.

## Configure rules for aggregating scraped data into new time series

Though not a problem in our example, queries that aggregate over thousands of
time series can get slow when computed ad-hoc. To make this more efficient,
Prometheus allows you to prerecord expressions into completely new persisted
time series via configured recording rules. Let's say we are interested in
recording the per-second rate of example RPCs
(`rpc_durations_microseconds_count`) averaged over all instances (but
preserving the `job` and `service` dimensions) as measured over a window of 5
minutes. We could write this as:

```
avg(rate(rpc_durations_microseconds_count[5m])) by (job, service)
```

Try graphing this expression.

To record the time series resulting from this expression into a new metric
called `job_service:rpc_durations_microseconds_count:avg_rate5m`, create a file
with the following recording rule and save it as `prometheus.rules`:

```
job_service:rpc_durations_microseconds_count:avg_rate5m = avg(rate(rpc_durations_microseconds_count[5m])) by (job, service)
```

To make Prometheus pick up this new rule, add a `rule_files` statement to the
global configuration section in your `prometheus.conf`. The config should now
look like this:

```
# Global default settings.
global: {
  scrape_interval: "15s"     # By default, scrape targets every 15 seconds.
  evaluation_interval: "15s" # By default, evaluate rules every 15 seconds.

  # Attach these extra labels to all time series collected by this Prometheus instance.
  labels: {
    label: {
      name: "monitor"
      value: "tutorial-monitor"
    }
  }
  # Load and evaluate rules in this file every 'evaluation_interval' seconds. This field may be repeated.
  rule_file: "prometheus.rules"
}

job: {
  name: "example-random"
  scrape_interval: "5s"

  # The "production" targets for this job.
  target_group: {
    target: "http://localhost:8080/metrics"
    target: "http://localhost:8081/metrics"
    labels: {
      label: {
        name: "group"
        value: "production"
      }
    }
  }
  # The "canary" targets for this job.
  target_group: {
    target: "http://localhost:8082/metrics"
    labels: {
      label: {
        name: "group"
        value: "canary"
      }
    }
  }
}
```

Restart Prometheus with the new configuration and verify that a new time series
with the metric name `job_service:rpc_durations_microseconds_count:avg_rate5m`
is now available by querying it through the expression browser or graphing it.
