diff --git a/answers.md b/answers.md
index 092b6d280..e1ab91fcb 100644
--- a/answers.md
+++ b/answers.md
@@ -1 +1,366 @@
-Your answers to the questions go here.
+
Julia Szymanski Datadog Technical Assessment
+
+Notes on Prerequisites:
+I took this assessment as a great opportunity to learn about Docker and opted for the Containerized approach using Docker for Desktop (Mac M1) and the dockerized Datadog agent.
+
+
+
+
+
+📈 Collecting Metrics:
+1. I added tags in the datadog.yaml file and was very happy to see that they showed up in the Host Map on the UI. Encouraging so far!
+
+
+Code block: datadog.yaml with tags
+
+
+```
+apm_config:
+ apm_non_local_traffic: true
+
+jmx_use_container_support: true
+
+tags:
+ - "name:Julia Szymanski"
+ - "email:julszymanski@gmail.com"
+ - "region:us-east-1"
+ - "tag:test"
+ - "env:staging"
+```
+
+Host map with tags
+
+
+
+
+2. Next, I updated PostgreSQL on my machine and installed the PostgreSQL Datadog integration.
+
+
+At first, this is the error I was seeing in the root terminal and dd-agent log:
+
+
+
+
+
+
+
+
+
+
+
+
+The issue was that I had set host to localhost in postgres.d/conf.yaml in the container. So, how did I need to change host in the container to point to Postgres on my machine? I reset the host value to be host.docker.internal. This enabled the connection of the container with the database service on the host by forwarding to the internal IP address used by the host.
+
+
+postgres.d/conf.yaml
+
+```
+init_config:
+
+instances:
+
+ - host: host.docker.internal
+
+ port: 5432
+```
+
+
+
+Postgres on Agent status report
+
+
+
+
+3. Next, I created a custom Agent check that submits a metric named my_metric with a random value between 0 and 1000.
+
+Code block: checks.d/custom_my_metric.py
+
+```
+import random
+
+try:
+ from datadog_checks.base import AgentCheck
+except ImportError:
+ from checks import AgentCheck
+
+__version__ = "1.0.0"
+
+class HelloCheck(AgentCheck):
+ def check(self, instance):
+ self.gauge('my_metric', random.randint(0,1000), tags=["host:docker-desktop"] + self.instance.get('tags', []))
+```
+Custom_my_metric on Agent status report
+
+
+
+
+4. Finally, I changed my check's collection interval so that it only submits the metric once every 45 seconds by modifying the respective yaml file.
+
+
+An important note on min_collection_interval: If the min_collection_interval is set to 45, it does not mean that the metric is collected every 45 seconds, but rather that it could be collected as often as every 45 seconds. The collector tries to run the check every 45 seconds but the check might need to wait in line, depending on how many integrations are enabled on the same Agent. Also if the check method takes more than 45 seconds to finish, the Agent skips execution until the next interval.
+
+
+Code block: conf.d/custom_my_metric.yaml
+
+```
+init_config:
+
+instances:
+ - min_collection_interval: 45
+```
+
+
+Bonus Question: By modifying custom_my_metric.yaml that lives in the conf.d folder, I already changed the collection interval without modifying custom_my_metric.py. 🙌
+
+📈 Visualizing Data:
+
+To start, I created an Application Key and verified that the App Key and the API Key are valid via Postman. Then I wrote the script for a timeboard importing the Datadog API.
+
+Code block: Complete script in timeboard.py
+
+
+```
+"""
+Create a new dashboard returns "OK" response
+"""
+
+from datadog_api_client.v1 import ApiClient, Configuration
+from datadog_api_client.v1.api.dashboards_api import DashboardsApi
+from datadog_api_client.v1.model.dashboard import Dashboard
+from datadog_api_client.v1.model.dashboard_layout_type import DashboardLayoutType
+from datadog_api_client.v1.model.log_query_definition import LogQueryDefinition
+from datadog_api_client.v1.model.log_query_definition_group_by import LogQueryDefinitionGroupBy
+from datadog_api_client.v1.model.log_query_definition_group_by_sort import LogQueryDefinitionGroupBySort
+from datadog_api_client.v1.model.log_query_definition_search import LogQueryDefinitionSearch
+from datadog_api_client.v1.model.logs_query_compute import LogsQueryCompute
+from datadog_api_client.v1.model.timeseries_widget_definition import TimeseriesWidgetDefinition
+from datadog_api_client.v1.model.timeseries_widget_definition_type import TimeseriesWidgetDefinitionType
+from datadog_api_client.v1.model.timeseries_widget_request import TimeseriesWidgetRequest
+from datadog_api_client.v1.model.widget import Widget
+from datadog_api_client.v1.model.widget_sort import WidgetSort
+
+body = Dashboard(
+ layout_type=DashboardLayoutType("ordered"),
+ title="my_metric Dash",
+ widgets=[
+ Widget(
+ definition=TimeseriesWidgetDefinition(
+ type=TimeseriesWidgetDefinitionType("timeseries"),
+ title="Avg of My_Metric",
+ requests=[
+ TimeseriesWidgetRequest(
+ q="avg:my_metric{host:docker-desktop}")
+ ],
+ )
+ ),
+ Widget(
+ definition=TimeseriesWidgetDefinition(
+ type=TimeseriesWidgetDefinitionType("timeseries"),
+ title="Database + Anomaly - Avg of PostgreSQL Connections",
+ requests=[
+ TimeseriesWidgetRequest(
+ q="anomalies(avg:postgresql.connections{db:julia}, 'basic', 2)"
+ )
+ ],
+ )
+ ),
+ Widget(
+ definition=TimeseriesWidgetDefinition(
+ type=TimeseriesWidgetDefinitionType("timeseries"),
+ title="My_Metric with Rollup Function - Sum of All Points in Last Hour",
+ requests=[
+ TimeseriesWidgetRequest(
+ q="my_metric{host:docker-desktop}.rollup(sum, 3600)"
+ )
+ ],
+ )
+ )
+ ]
+)
+
+
+configuration = Configuration()
+with ApiClient(configuration) as api_client:
+ api_instance = DashboardsApi(api_client)
+ response = api_instance.create_dashboard(body=body)
+
+ print(response)
+
+```
+
+
+
+Let's take a closer look at the code displayed above.
+
+1. I used the generic timeseries widget to graph my_metric over time. Widgets are building blocks for timeboards and dashboards.
+
+
+
+
+2. I applied an anomaly function using the postgres.connections metric as an argument.
+
+
+
+
+3. The rollup function is used to aggregate metrics data. The two arguments passed to the rollup function are the aggregator (min, max, in this case sum) and the optional time interval. In my rollup function, I sum all my_metric values collected in the last hour.
+
+
+
+
+
+4. I zoomed in on the timeframe to view metrics collected over the past five minutes.
+
+
+5. Finally, I took a snapshot of the graph and used the @ notation to email it to myself. 📸 📧
+
+
+
+
+
+
+Bonus Question: Anomaly Graph
+Anomaly detection is an algorithmic feature that identifies when a metric is behaving differently than it has in the past. It takes into account trends, seasonal day-of-week, and time-of-day patterns, and is appropriate for metrics with recurring patterns. A metric is considered to be anomalous (deviating from what is standard, normal, or expected) if it is outside of the gray anomaly band in the anomaly graph.
+
+My anomaly graph
+
+
+Example of an anomaly graph with a recurring pattern, anomalous data shown in red
+
+
+
+📈 Monitoring Data:
+
+1. I created a new Metric Monitor that watches the average of my_metric and will alert if it's above the following values over the past 5 min:
+
+• Warning threshold of 500
+• Alerting threshold of 800
+• And also ensure that it will notify me if there is No Data for this query over the past 10m.
+
+
+
+2. I set the monitor to send me an email whenenever it is triggered.
+
+
+3. I created different messages based on whether the monitor is in an Alert, Warning, or No Data state.
+
+
+4. I included the metric value that caused the monitor to trigger as well as the host name and IP for an Alert state trigger.
+
+
+5. Here is a screenshot of an email notification for the Alert state sent by the monitor.
+
+
+
+Bonus question: I set up two scheduled downtimes for this monitor.
+
+
+
+1. The first one silenced the monitor from 7pm to 9am daily Monday-Friday. 💤
+
+
+
+
+
+2. The second one silenced the monitor all day on Saturday and Sunday. 🌴 🏄 🏖️
+
+
+
+
+
+3. 📧 My email was notified when I scheduled the downtimes.
+
+
+
+📈 Collecting APM Data:
+
+First, I placed my_app.py in the root folder of the container.
+
+Code block: Flask app my_app.py
+
+```
+from flask import Flask
+import logging
+import sys
+
+# Have flask use stdout as the logger
+main_logger = logging.getLogger()
+main_logger.setLevel(logging.DEBUG)
+c = logging.StreamHandler(sys.stdout)
+formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
+c.setFormatter(formatter)
+main_logger.addHandler(c)
+
+app = Flask(__name__)
+
+@app.route('/')
+def api_entry():
+ return 'Entrypoint to the Application'
+
+@app.route('/api/apm')
+def apm_endpoint():
+ return 'Getting APM Started'
+
+@app.route('/api/trace')
+def trace_endpoint():
+ return 'Posting Traces'
+
+if __name__ == '__main__':
+ app.run(host='0.0.0.0', port='5050')
+
+```
+
+I went to APM > Service Setup and clicked the Container-Based tab.
+
+Step 1: I chose my environment (Docker) and application language (Python).
+
+ Step 2: I ran the Agent to enable trace collection in my environment using the command below.
+
+```
+docker run -d -v /var/run/docker.sock:/var/run/docker.sock:ro \
+ -v /proc/:/host/proc/:ro \
+ -v /sys/fs/cgroup/:/host/sys/fs/cgroup:ro \
+ -p 127.0.0.1:8126:8126/tcp \
+ -e DD_API_KEY= \
+ datadog/agent:latest
+```
+
+ Step 3: I installed the Python client.
+
+```
+pip install ddtrace
+```
+ Step 4: I built a configuration snippet to automatically instrument my Python application, ran it in the command line, and finished the installation by restarting my device.
+
+```
+DD_SERVICE="my_service" DD_ENV="env" DD_LOGS_INJECTION=true ddtrace-run python my_app.py
+```
+my_service in APM > Services
+
+
+Screenshot of Integrations + APM Dashboard
+
+
+Click here to see Integrations + APM Dashboard
+
+Bonus Question: Difference between a Service and a Resource
+
+
+
+
+Services are the building blocks of microservice architectures. A service groups together endpoints, queries, or jobs for the purposes of building your application. For example, a database service groups resources such as database queries. Resources belong to services.
+
+Resources are actions for your services - they are typically an instrumented web endpoint, database query, or background job.
+
+
+
+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?
+
+When I first moved to Atlanta, I moved into an older, neglected house with a rodent problem. I measured rodent activity in the house by taking mental notes of the frequency of the scuttling sounds in the ceilings and walls. While reading about the creative ways Datadog has been used in the past, I thought of a more efficient data-driven solution to remove my unwelcome house guests. 🐿️
+
+It would be interesting to place sensors in the ceilings and walls of my house to measure rodent activity. These sensors could be accelerometers that detect vibrations, thermal cameras, or scanners. I can integrate the sensors with a microprocessor like Raspberry Pi with the Datadog Agent installed on it. Then I can write an Agent check to collect metrics from the sensor's data. Using dashboard widgets, I can display the scanner metrics for each sensor location. From there, I can map where rodent activity is highest. The next time I hire Critter Stoppers, they could use these dashboards to place traps in the areas with the highest measured rodent activity.
+
+I can apply anomaly detection to monitor activity patterns, since rodent_activity is a metric with a recurrent pattern. Squirrels tend to be active during the day, so the anomaly graph would show low nighttime activity within the gray area. I can be alerted if rodent activity drops during the day after an exterminator visit, a deviation from what is normal, meaning that the exterminator did a great job.
\ No newline at end of file
diff --git a/images/Alert Conditions.png b/images/Alert Conditions.png
new file mode 100644
index 000000000..ea66f8f78
Binary files /dev/null and b/images/Alert Conditions.png differ
diff --git a/images/Avg of My_Metric 5min.png b/images/Avg of My_Metric 5min.png
new file mode 100644
index 000000000..e3319fec1
Binary files /dev/null and b/images/Avg of My_Metric 5min.png differ
diff --git a/images/Avg of My_Metric.png b/images/Avg of My_Metric.png
new file mode 100644
index 000000000..0bcdee2e4
Binary files /dev/null and b/images/Avg of My_Metric.png differ
diff --git a/images/Database + Anomaly - Avg of PostgreSQL Connections.png b/images/Database + Anomaly - Avg of PostgreSQL Connections.png
new file mode 100644
index 000000000..c1e76a9b0
Binary files /dev/null and b/images/Database + Anomaly - Avg of PostgreSQL Connections.png differ
diff --git a/images/Database + Anomaly Bonus.png b/images/Database + Anomaly Bonus.png
new file mode 100644
index 000000000..3c9a92545
Binary files /dev/null and b/images/Database + Anomaly Bonus.png differ
diff --git a/images/Scope My_Metric Over Host.png b/images/Scope My_Metric Over Host.png
new file mode 100644
index 000000000..e91c0d1fe
Binary files /dev/null and b/images/Scope My_Metric Over Host.png differ
diff --git a/images/Sum of My_Metric Points.png b/images/Sum of My_Metric Points.png
new file mode 100644
index 000000000..a19af1478
Binary files /dev/null and b/images/Sum of My_Metric Points.png differ
diff --git a/images/alert_message.png b/images/alert_message.png
new file mode 100644
index 000000000..ba54760a1
Binary files /dev/null and b/images/alert_message.png differ
diff --git a/images/anomaly-detection.png b/images/anomaly-detection.png
new file mode 100644
index 000000000..0d29db644
Binary files /dev/null and b/images/anomaly-detection.png differ
diff --git a/images/anomaly.png b/images/anomaly.png
new file mode 100644
index 000000000..730ce8349
Binary files /dev/null and b/images/anomaly.png differ
diff --git a/images/custom_my_metric.png b/images/custom_my_metric.png
new file mode 100644
index 000000000..9354bf0a4
Binary files /dev/null and b/images/custom_my_metric.png differ
diff --git a/images/dashboard.png b/images/dashboard.png
new file mode 100644
index 000000000..8c035e594
Binary files /dev/null and b/images/dashboard.png differ
diff --git a/images/dockerlog.png b/images/dockerlog.png
new file mode 100644
index 000000000..a1ad60dd8
Binary files /dev/null and b/images/dockerlog.png differ
diff --git a/images/downtime.png b/images/downtime.png
new file mode 100644
index 000000000..2eb0afed3
Binary files /dev/null and b/images/downtime.png differ
diff --git a/images/email.png b/images/email.png
new file mode 100644
index 000000000..f803d4e0a
Binary files /dev/null and b/images/email.png differ
diff --git a/images/hostmap.png b/images/hostmap.png
new file mode 100644
index 000000000..305a2fc4e
Binary files /dev/null and b/images/hostmap.png differ
diff --git a/images/localhost.png b/images/localhost.png
new file mode 100644
index 000000000..e4b24b212
Binary files /dev/null and b/images/localhost.png differ
diff --git a/images/message.png b/images/message.png
new file mode 100644
index 000000000..029933591
Binary files /dev/null and b/images/message.png differ
diff --git a/images/my_service.png b/images/my_service.png
new file mode 100644
index 000000000..32bf886a3
Binary files /dev/null and b/images/my_service.png differ
diff --git a/images/notification.png b/images/notification.png
new file mode 100644
index 000000000..43ec847cf
Binary files /dev/null and b/images/notification.png differ
diff --git a/images/notify.png b/images/notify.png
new file mode 100644
index 000000000..50c406d20
Binary files /dev/null and b/images/notify.png differ
diff --git a/images/postgres.png b/images/postgres.png
new file mode 100644
index 000000000..0200ae9d4
Binary files /dev/null and b/images/postgres.png differ
diff --git a/images/postgres_integration.png b/images/postgres_integration.png
new file mode 100644
index 000000000..f3b3a7daf
Binary files /dev/null and b/images/postgres_integration.png differ
diff --git a/images/postgreserror.png b/images/postgreserror.png
new file mode 100644
index 000000000..4eeb26210
Binary files /dev/null and b/images/postgreserror.png differ
diff --git a/images/rollup.png b/images/rollup.png
new file mode 100644
index 000000000..784a93d72
Binary files /dev/null and b/images/rollup.png differ
diff --git a/images/snapshot.png b/images/snapshot.png
new file mode 100644
index 000000000..3ddc67528
Binary files /dev/null and b/images/snapshot.png differ
diff --git a/images/weekday.png b/images/weekday.png
new file mode 100644
index 000000000..80649b45b
Binary files /dev/null and b/images/weekday.png differ
diff --git a/images/weekend.png b/images/weekend.png
new file mode 100644
index 000000000..1c47dafb1
Binary files /dev/null and b/images/weekend.png differ
diff --git a/images/weekend_downtime.png b/images/weekend_downtime.png
new file mode 100644
index 000000000..3bd64de7a
Binary files /dev/null and b/images/weekend_downtime.png differ
diff --git a/images/whale.gif b/images/whale.gif
new file mode 100644
index 000000000..438b6e787
Binary files /dev/null and b/images/whale.gif differ
diff --git a/my_app.py b/my_app.py
new file mode 100644
index 000000000..310f40b20
--- /dev/null
+++ b/my_app.py
@@ -0,0 +1,28 @@
+from flask import Flask
+import logging
+import sys
+
+# Have flask use stdout as the logger
+main_logger = logging.getLogger()
+main_logger.setLevel(logging.DEBUG)
+c = logging.StreamHandler(sys.stdout)
+formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
+c.setFormatter(formatter)
+main_logger.addHandler(c)
+
+app = Flask(__name__)
+
+@app.route('/')
+def api_entry():
+ return 'Entrypoint to the Application'
+
+@app.route('/api/apm')
+def apm_endpoint():
+ return 'Getting APM Started'
+
+@app.route('/api/trace')
+def trace_endpoint():
+ return 'Posting Traces'
+
+if __name__ == '__main__':
+ app.run(host='0.0.0.0', port='5050')
\ No newline at end of file