Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# These owners will be the default owners for everything in
# the repo. Any future lines will overwrite this default. The last pattern
# that matches, will be the final pattern.
# See https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners

* @DataDog/training @DataDog/corpweb
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ services:
ports:
- '3030:8080'
labels:
com.datadoghq.ad.logs: '[{"source": "java", "service": "ads-java"}]'
com.datadoghq.ad.logs: '[{"source": "java", "service": "store-ads-java"}]'
com.datadoghq.tags.env: '${DD_ENV-dev}'
com.datadoghq.tags.service: 'store-ads-java'
com.datadoghq.tags.version: '${DD_VERSION-7}'
Expand Down
2 changes: 2 additions & 0 deletions services/ads/java/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ dependencies {
'commons-io:commons-io:2.4',
'org.springframework.boot:spring-boot-starter-web'
)
implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.2'
implementation 'net.logstash.logback:logstash-logback-encoder:7.0'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

Expand Down
22 changes: 15 additions & 7 deletions services/ads/java/src/main/java/adsjava/AdsJavaApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,35 +16,43 @@
import java.util.concurrent.TimeoutException;
import org.springframework.web.bind.annotation.RequestHeader;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


@SpringBootApplication
@RestController
public class AdsJavaApplication {

private static final Logger logger = LoggerFactory.getLogger(AdsJavaApplication.class);

@RequestMapping("/")
public String home() {
logger.info("home url for ads called");
return "Welcome to Java - Ads Service";
}

@CrossOrigin(origins = {"*"})
@RequestMapping(
value = "/banners/{id}",
produces = MediaType.IMAGE_JPEG_VALUE
)
public @ResponseBody byte[] getImageWithMediaType() throws IOException {
logger.info("/banners/{id} called");
int randomNum = ThreadLocalRandom.current().nextInt(1, 3 + 1);
String imagePath = "/static/ads/ad" + randomNum + ".jpg";
InputStream in = getClass()
.getResourceAsStream(imagePath);
return IOUtils.toByteArray(in);
}

@RequestMapping("/")
public String home() {
return "Welcome to Java - Ads Service";
}

@CrossOrigin(origins = {"*"})
@RequestMapping(
value = "/ads",
produces = MediaType.APPLICATION_JSON_VALUE
)
public HashMap[] ads(@RequestHeader HashMap<String, String> headers) {
logger.info("/ads called");

boolean errorFlag = false;
if(headers.get("x-throw-error") != null) {
Expand All @@ -62,7 +70,7 @@ public HashMap[] ads(@RequestHeader HashMap<String, String> headers) {
try {
throw new TimeoutException("took too long to get a response");
} catch (Exception e) {
System.out.println("took too long to get a response");
logger.error("Request failed, check the request headers.");
throw new RuntimeException(e);
}
} else {
Expand All @@ -80,8 +88,8 @@ public HashMap[] ads(@RequestHeader HashMap<String, String> headers) {
map3.put("id", "3");
map3.put("name", "Nic Bags");
map3.put("path", "3.jpg");
System.out.println("ads called");
HashMap[] myArr = { map1, map2, map3 };
logger.info("Total responses available: " + myArr.length);
return myArr;
}
}
Expand Down
19 changes: 19 additions & 0 deletions services/ads/java/src/main/resources/logback-spring.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<configuration>

<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>
%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>

<appender name="JSON_CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="net.logstash.logback.encoder.LogstashEncoder"/>
</appender>

<root level="INFO">
<appender-ref ref="JSON_CONSOLE" />
</root>

</configuration>
56 changes: 33 additions & 23 deletions services/ads/python/ads.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import json_log_formatter
from ddtrace import tracer
import logging
import requests
import random
import time
Expand All @@ -11,10 +14,8 @@
from bootstrap import create_app
from models import Advertisement, db

from ddtrace import patch; patch(logging=True)
import logging
from ddtrace import tracer
import json_log_formatter
from ddtrace import patch
patch(logging=True)

formatter = json_log_formatter.VerboseJSONFormatter()
json_handler = logging.StreamHandler(sys.stdout)
Expand All @@ -27,36 +28,44 @@
CORS(app)
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

## Add filter to remove color-encoding from logs e.g. "[37mGET / HTTP/1.1 [0m" 200 -
# Add filter to remove color-encoding from logs e.g. "[37mGET / HTTP/1.1 [0m" 200 -


class NoEscape(logging.Filter):
def __init__(self):
self.regex = re.compile(r'(\x9B|\x1B\[)[0-?]*[ -\/]*[@-~]')

def strip_esc(self, s):
try: # string-like
return self.regex.sub('',s)
except: # non-string-like
try: # string-like
return self.regex.sub('', s)
except: # non-string-like
return s

def filter(self, record):
record.msg = self.strip_esc(record.msg)
if type(record.args) is tuple:
record.args = tuple(map(self.strip_esc, record.args))
return 1

remove_color_filter =NoEscape()

remove_color_filter = NoEscape()
logger.addFilter(remove_color_filter)


@tracer.wrap()
@app.route('/')
def hello():
logger.info("home url for ads called")
return Response({'Hello from Advertisements!': 'world'}, mimetype='application/json')


@tracer.wrap()
@app.route('/banners/<path:banner>')
def banner_image(banner):
logger.info(f"attempting to grab banner at {banner}")
return send_from_directory('ads', banner)


@tracer.wrap()
@app.route('/weighted-banners/<float:weight>')
def weighted_image(weight):
Expand All @@ -66,6 +75,7 @@ def weighted_image(weight):
if ad.weight < weight:
return jsonify(ad.serialize())


@tracer.wrap()
@app.route('/ads', methods=['GET', 'POST'])
def status():
Expand All @@ -90,29 +100,29 @@ def status():
err = jsonify({'error': 'Internal Server Error'})
err.status_code = 500
return err

else:

try:
advertisements = Advertisement.query.all()
logger.info(f"Total advertisements available: {len(advertisements)}")
return jsonify([b.serialize() for b in advertisements])
try:
advertisements = Advertisement.query.all()
logger.info(
f"Total advertisements available: {len(advertisements)}")
return jsonify([b.serialize() for b in advertisements])

except:
logger.error("An error occurred while getting ad.")
err = jsonify({'error': 'Internal Server Error'})
err.status_code = 500
return err

except:
logger.error("An error occurred while getting ad.")
err = jsonify({'error': 'Internal Server Error'})
err.status_code = 500
return err

elif flask_request.method == 'POST':

try:
# create a new advertisement with random name and value
advertisements_count = len(Advertisement.query.all())
new_advertisement = Advertisement('Advertisement ' + str(advertisements_count + 1),
'/',
random.randint(10,500))
'/',
random.randint(10, 500))
logger.info(f"Adding advertisement {new_advertisement}")
db.session.add(new_advertisement)
db.session.commit()
Expand All @@ -130,4 +140,4 @@ def status():
else:
err = jsonify({'error': 'Invalid request method'})
err.status_code = 405
return err
return err
2 changes: 1 addition & 1 deletion services/ads/python/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
certifi==2020.11.8
chardet==3.0.4
click==7.1.2
ddtrace==1.7.2
ddtrace==2.10.4
Flask==1.1.2
Flask-Cors==3.0.10
Flask-SQLAlchemy==2.4.4
Expand Down
Loading