Skip to content
This repository was archived by the owner on Aug 26, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
85af566
Initial commit
ddalq Oct 7, 2013
1082ea4
Update README.md
ddalq Oct 7, 2013
8389b7f
Create answers.md
ddalq Oct 7, 2013
4947f61
Update README.md
ddalq Oct 7, 2013
3380871
Update README.md
ddalq Oct 7, 2013
8c90d4a
Update README.md
ddalq Oct 8, 2013
4fd69cf
Update README.md
ddalq Oct 8, 2013
7d510f0
Added more levels
ddalq Oct 10, 2013
581fbfe
Update README.md
ddalq Oct 10, 2013
f2d836c
Update README.md
ddalq Oct 10, 2013
f4ad427
Update README.md
ddalq Oct 10, 2013
e3339fc
Neutral master readme.
ddalq Jul 7, 2014
1bf5c0f
Update README.md
ddalq Jul 7, 2014
e7402a1
Fix link to Devops Evangelist branch
Aug 7, 2014
ef429c0
Update README.md
pvfkb Jan 28, 2017
5a692a2
Update answers.md
jinmei612 Oct 15, 2017
f58bfb5
Update answers.md
jinmei612 Oct 15, 2017
a283dfe
Update answers.md
jinmei612 Oct 20, 2017
a526560
Update answers.md
jinmei612 Oct 21, 2017
e02c459
Update answers.md
jinmei612 Oct 22, 2017
072dc12
Update answers.md
jinmei612 Oct 22, 2017
4bbf725
Update answers.md
jinmei612 Oct 22, 2017
88b8f2e
Update answers.md
jinmei612 Oct 23, 2017
bc885fb
updating positions list
Dec 27, 2017
60456a8
Merge pull request #324 from DataDog/kevin_w/update-challenge
kwwalter Dec 27, 2017
365d5c9
Merge pull request #529 from jinmei612/master
jinmei612 Aug 20, 2018
b27d4a5
revert candidate answer merge
burnsie7 Sep 11, 2018
ba0a823
Merge pull request #561 from DataDog/revert_365d5c9
burnsie7 Sep 11, 2018
63f0f5e
Create Table of Contents and Setting Up the Environment
Elronia Nov 28, 2021
e45884f
Create Table of Contents and Setting Up the Environment
Elronia Nov 28, 2021
8bff77e
Add some links
Elronia Nov 28, 2021
eab0c61
Add some links
Elronia Nov 28, 2021
ff1a39e
Upload screenshots and Flask app
Elronia Nov 28, 2021
1af0f5b
Add Agent Reporting Metrics screenshot
Elronia Nov 29, 2021
b903c52
Add screenshots of my host and its tags on the Host Map page in Datadog
Elronia Nov 29, 2021
3e1be3a
Describe steps for Collecting Metrics and Visualizing Data
Elronia Nov 29, 2021
029c965
Describe steps for Collecting Metrics and Visualizing Data
Elronia Nov 29, 2021
d264465
Add some spacing
Elronia Nov 29, 2021
25013e7
Visualizing Data
Elronia Nov 29, 2021
4cc5c1b
Replace screenshots
Elronia Nov 29, 2021
574db0d
Add screenshots to Monitoring Data section
Elronia Nov 29, 2021
462ae97
Finish Monitoring Data section
Elronia Nov 29, 2021
cdd6208
Add Downtime Settings screenshots
Elronia Nov 29, 2021
c209bb4
Describe steps for Collecting APM Data
Elronia Nov 29, 2021
d584e28
Finish Collecting APM Data
Elronia Nov 29, 2021
798478c
Fixed broken image
Elronia Nov 29, 2021
6d35320
Answer Final Question
Elronia Nov 29, 2021
a2f8cc7
Add Dashboard links
Elronia Nov 29, 2021
0440222
Remove the space
Elronia Nov 29, 2021
9027f19
Dashboard Results
Elronia Nov 29, 2021
888ee4d
Merge branch 'my-branch' into solutions-engineer
Elronia Nov 29, 2021
84dc9dc
Added one more example
Elronia Nov 30, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
Binary file added .DS_Store
Binary file not shown.
327 changes: 326 additions & 1 deletion answers.md
Original file line number Diff line number Diff line change
@@ -1 +1,326 @@
Your answers to the questions go here.
My answers to the questions go here.
## Table of Contents
* [Setting Up the Environment](#setting-up-the-environment)
* [Collecting Metrics](#collecting-metrics)
* [Visualizing Data](#visualizing-data)
* [Monitoring Data](#monitoring-data)
* [Collecting APM Data](#collecting-apm-data)
* [Final Question](#final-question)

<a name="setting-up-the-environment"/>

## Prerequisites - Setting Up the Environment
1. First, I spinned up a fresh linux Ubuntu VM via Vagrant on Virtual Box on my Mac. I followed these steps: https://medium.com/devops-dudes/how-to-setup-vagrant-and-virtual-box-for-ubuntu-20-04-7374bf9cc3fa
2. Next, I signed up for Datadog (used “Datadog Recruiting Candidate” in the “Company” field).
3. And installed the Datadog Agent on the Vagrant Box by running this command for ubuntu:
```DD_AGENT_MAJOR_VERSION=7 DD_API_KEY=########## DD_SITE="datadoghq.com" bash -c "$(curl -L https://s3.amazonaws.com/dd-agent/scripts/install_script.sh)"```
I removed the key for security purposes.
4. Finally, got the Agent reporting metrics from my local machine:
<img src='./screenshots/Agent Reporting Metrics.png'> </img>

<a name="collecting-metrics"/>

## Collecting Metrics
1. Added tags in the Agent config file and here is the screenshot of the host and its tags on the Host Map page in Datadog.
<img src='./screenshots/Datadog Agent Yaml Tags 1.png'> </img>
<img src='./screenshots/Datadog Yaml Tags 2.png'> </img>
<img src='./screenshots/Datadog Dashboard Tags.png'> </img>

2. Installed PostgreSQL on the Vagrant machine and then installed the respective Datadog integration for that database.
- Added the public GPG key:
```wget -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -```
- Created a file with the repository address:
```echo deb http://apt.postgresql.org/pub/repos/apt/ precise-pgdg main | sudo tee /etc/apt/sources.list.d/postgresql.list```
- To install PostgreSQL I ran:
```sudo apt-get update```
```sudo apt-get install postgresql-9.3 postgresql-contrib-9.3```
- After installing PostgreSQL, I ran the following command to create a user for Datadog in the database.
```create user datadog with password ‘######’;```
3. Created a script file and a config file in order to create a custom metric and send it to Datadog servers through the Agent.

<img src='./screenshots/Postgres conf.d.png'></img>

After ```mymetric.py``` was created ```~/.datadog-agent/checks.d/mymetric.py``` added the following to the file:

<img src='./screenshots/mymetric.py.png'></img>

Then I created ```mymetric.yaml ~/.datadog-agent/conf.d/mymetric.yaml``` and added the code below.

<img src='./screenshots/mymetric yaml.png'></img>

After I restarted the Agent.
<img src='./screenshots/mymetric Dashboard.png'></img>

On the Datadog dashboard, I went to ```Metrics > Explorer```, and searched for my custom metric.
The Agent was running the collector in intervals of 15–20 seconds.

4. To change my check’s collection interval I edited the config file ```~/.datadog-agent/conf.d/mymetric.yaml``` and changed the ```min_collection_interval``` globally to the interval of 45 seconds.

<img src='./screenshots/mymetric yaml 45 interval.png'></img>

And restarted the Agent again.
<img src='./screenshots/mymetric Dashboard 45 Interval.png'></img>

5. **Bonus Question:** Can you change the collection interval without modifying the Python check file you created?
**Answer:** Yes, the interval can be set by changing the instance description in the ```yaml``` file, like this:
```
init_config:
min_collection_interval: 45
instances:
[{}]
```

<a name="visualizing-data"/>

## Visualizing Data
1. This board was created using the PostMan API editor.
<img src='./screenshots/Postman API Editor.png'> </img>
To create my dashboard I used the content of this curl command:
```
curl --location --request POST 'https://api.datadoghq.com/api/v1/dashboard' \
--header 'Content-Type: application/json' \
--header 'Cookie: DD-PSHARD=217' \
--header 'DD-API-KEY: xxxxxxxxxxxxxxxxxxxxxxxxxx' \
--header 'DD-APPLICATION-KEY: xxxxxxxxxxxxxxxxxxxxxxxxxx' \
--data-raw '{
"title": "Dev.Zarudnaya Hourly Anomalies",
"description": "A custom agent check configured to submit a metric named `my_metric` with a random value between 0 and 1000.",
"layout_type": "ordered",
"is_read_only": false,
"widgets": [
{
"definition": {
"type": "timeseries",
"title": "my metric timeseries",
"requests": [
{
"q": "my_metric{host:datadog.dev.zarudnaya.info}"
}
]
},
"layout": {
"x": 0,
"y": 0,
"width": 4,
"height": 2
}
},
{
"definition": {
"type": "timeseries",
"title": "Postgres Sql Return Rows Anamolies",
"requests": [
{
"q": "anomalies(sum:postgresql.rows_returned{host:datadog.dev.zarudnaya.info}, '\''basic'\'', 5)"
}
]
},
"layout": {
"x": 4,
"y": 0,
"width": 4,
"height": 2
}
},
{
"definition": {
"type": "timeseries",
"title": "Sum of my metric points per hour",
"requests": [
{
"q": "sum:my_metric{*}.rollup(sum, 3600)"
}
]
},
"layout": {
"x": 8,
"y": 0,
"width": 4,
"height": 2
}
}
]
}'
```

2. Once this was created, I accessed the Dashboard from the Dashboard List in the UI:
##### My Hourly Timeboard
<img src='./screenshots/My Hourly Timeboard.png'> </img>

3. The sum of my metric is grouped into hours (per instructions) so it did not show properly in a 5 minute time span. I expanded the time period on the widget and included a snapshot here.
<img src='./screenshots/mymetric sum.png'> </img>

[Hourly Anomalies Dashboard Link](https://p.datadoghq.com/sb/ab7cb560-3783-11ec-9ab2-da7ad0900002-6fcd0e111c4fd4be11af2203756fb0b8)

4. Took a snapshot of this graph and used the @ notation to send it to myself. The email notice included a thumbnail, and also buttons that take you directly to the item in the Datadog panel.
<img src='./screenshots/Email notice of snapshot anamolies.png'> </img>

5. **Bonus Question:** What is the Anomaly graph displaying?
**Answer:** The Anomaly graph presents suspicious behaviour. I stressed PostgreSQL and made the tables list, thus, causing it to perform in a certain way. The graph provides a visualization of this performance as it relates to PostgreSQL.

<a name="monitoring-data"/>

## Monitoring Data
#### Create a New Metric:
1. From Datadog dashboard ```Monitors > New Monitor > Metric Monitor > Metric``` I defined the specs for ```my_metric``` based on the requirements.
- Changed the metric to the custom metric ``my_metric``.
- Changed the warning threshold to 500.
- Changed the alerting threshold to 800.
- Ensured notifications for No Data past 10 minutes.

#### Monitor Metrics:
<img src='./screenshots/Monitor metric Dashboard Timeboard.png'> </img>
<img src='./screenshots/Monitor metric Dashboard Timeboard 2.png'> </img>

#### Configure the Monitor's Message:
2. I configured the monitor message with below settings:
<img src='./screenshots/Configure the monitor Message.png'> </img>

#### Monitor Message Email Notifications
3. Created different messages based on whether the monitor is in an Alert, Warning, or No Data state.

#### Alert:
<img src='./screenshots/Alert Email.png'> </img>

#### Warning:
<img src='./screenshots/Warn Email.png'> </img>

#### Missing Data:
<img src='./screenshots/Missing Data Email.png'> </img>

**Bonus Question:** Since this monitor is going to alert pretty often, you don’t want to be alerted when you are out of the office. Set up two scheduled downtimes for this monitor:
#### Downtime Settings:
1. From Datadog dashboard ```Monitors > Manage Downtime``` clicked 'Schedule Downtime':

<img src='./screenshots/Downtime setting dashboard.png'> </img>

2. Created a recurring downtime for days of the week and weekends. I used EST since this is my time zone and Datadog HQ time zone.
#### Downtime Weekday Settings:
<img src='./screenshots/Downtime Weekday Settings.png'> </img>

#### Downtime Weekend Settings:
<img src='./screenshots/Downtime Weekend.png'> </img>

<a name="collecting-apm-data"/>

## Collecting APM Data
1. For this exercise I created a basic **To Do** Flask app on my Vagrant VM using this command:
```pip install Flask```, for the database I used Flask-SQLAlchemy using this command:
```pip install Flask-SQLAlchemy```.

2. Created a ```venv``` environment for the Flask app on the Vagrant machine. I installed DDtrace module using this command:
```pip install ddtrace``` and enabled APM in the Datadog ```yaml``` file:

<img src='./screenshots/APM Datadog Yaml.png'> </img>

3. Injected ```ddtrace``` in the ```app.py```:
```
from flask import Flask, render_template, request, redirect, url_for
from flask_sqlalchemy import SQLAlchemy
from ddtrace import tracer

app = Flask(__name__)

app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)

class Todo(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100))
complete = db.Column(db.Boolean)

@app.route("/")
def home():
todo_list = Todo.query.all()
return render_template("base.html", todo_list=todo_list)

@app.route("/add", methods=["POST"])
@tracer.wrap("flask.request", service='flask', resource="POST /add", span_type='web')
def add():
title = request.form.get("title")
new_todo = Todo(title=title, complete=False)
db.session.add(new_todo)
db.session.commit()
return redirect(url_for("home"))

@app.route("/update/<int:todo_id>")
def update(todo_id):
todo = Todo.query.filter_by(id=todo_id).first()
todo.complete = not todo.complete
db.session.commit()
return redirect(url_for("home"))

@app.route("/delete/<int:todo_id>")
def delete(todo_id):
todo = Todo.query.filter_by(id=todo_id).first()
db.session.delete(todo)
db.session.commit()
return redirect(url_for("home"))

if __name__ == "__main__":
db.create_all()
app.run(debug=True)
app.run(host='0.0.0.0', port='5000')
```
4. I ran this command to start tracking APM logs:
```DD_SERVICE="app" DD_ENV="dev" DD_LOGS_INJECTION=true ddtrace-run python3 app.py```

<img src='./screenshots/APM ddtrace python app run.png'> </img>

5. In order for my Flask app on port 5000 to run I modified the agent port to 5050:

<img src='./screenshots/APM Datadog Yaml port 5050.png'> </img>

My To Do App on the browser:
<img src='./screenshots/APM To Do app on the browser.png'> </img>

APM dashboard on Datadog website:

<img src='./screenshots/APM dashboard on datadog website Get results.png'> </img>

6. Created some entries in my To Do APP and it is showing on the APM Dashboard:

<img src='./screenshots/APM To Do app showing entries.png'> </img>

#### Dashboard with both APM and Infrastructure Metrics:
<img src='./screenshots/APM and Infrastructure Metrics Dashboard.png'> </img>
[Dashboard APM link](https://p.datadoghq.com/sb/ab7cb560-3783-11ec-9ab2-da7ad0900002-b486ce8c5579c41542cd9f0d78eed153) (Flask app was run on November, 21st. Please change the time range to 1 month to see the results)

7. **Bonus Question:** What is the difference between a Service and a Resource?
**Answer:** Services are the building blocks of modern microservice architectures. A service groups together endpoints.
A resource is an action given to a service, such as a query to a database or an endpoint.
[Reference](https://docs.datadoghq.com/tracing/visualization/#pagetitle)

<a name="final-question"/>

## Final Question
Datadog has been used in a lot of creative ways in the past. We’ve written some blog posts about using Datadog to monitor the NYC Subway System, Pokemon Go, and even office restroom availability!

Is there anything creative you would use Datadog for?

**Answer:** Datadog can be used in many creative ways ([Datadog in the wild: 5 fun projects](https://www.datadoghq.com/blog/datadog-in-the-wild-5-fun-projects/)). In this pandemic times lots of people are dependent on medical equipment. For example, medical systems could use Datadog monitoring to ensure that they are functioning correctly in case of an emergency or an unforeseen event and alert for any anomalies.
Another example how I could use Datadog is to compare prices on different e-commerce websites and select the cheapest price. It could also help to monitor information regarding sales and items that are back in stock.























Binary file added flask-app/__pycache__/app.cpython-36.pyc
Binary file not shown.
47 changes: 47 additions & 0 deletions flask-app/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
from flask import Flask, render_template, request, redirect, url_for
from flask_sqlalchemy import SQLAlchemy
from ddtrace import tracer

app = Flask(__name__)

app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)

class Todo(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100))
complete = db.Column(db.Boolean)

@app.route("/")
def home():
todo_list = Todo.query.all()
return render_template("base.html", todo_list=todo_list)

@app.route("/add", methods=["POST"])
@tracer.wrap("flask.request", service='flask', resource="POST /add", span_type='web')
def add():
title = request.form.get("title")
new_todo = Todo(title=title, complete=False)
db.session.add(new_todo)
db.session.commit()
return redirect(url_for("home"))

@app.route("/update/<int:todo_id>")
def update(todo_id):
todo = Todo.query.filter_by(id=todo_id).first()
todo.complete = not todo.complete
db.session.commit()
return redirect(url_for("home"))

@app.route("/delete/<int:todo_id>")
def delete(todo_id):
todo = Todo.query.filter_by(id=todo_id).first()
db.session.delete(todo)
db.session.commit()
return redirect(url_for("home"))

if __name__ == "__main__":
db.create_all()
app.run(debug=True)
app.run(host='0.0.0.0', port='5000')
Binary file added flask-app/db.sqlite
Binary file not shown.
Loading