-
Notifications
You must be signed in to change notification settings - Fork 85
Expand file tree
/
Copy pathLogger.scala
More file actions
83 lines (73 loc) · 3.18 KB
/
Copy pathLogger.scala
File metadata and controls
83 lines (73 loc) · 3.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package utilities
import play.api.mvc.{Request, AnyContent}
import play.api.libs.concurrent.Execution.Implicits.defaultContext
import play.api.libs.json.{JsValue, JsArray, Json}
import play.api.libs.ws.WS
import org.joda.time.{DateTimeZone, DateTime}
import org.joda.time.format.{DateTimeFormat, ISODateTimeFormat}
object Logger {
val elasticURL = Conf.get("elastic.URL")
val instanceID = Conf.getOrEmpty("application.instanceID")
val dtFormat = ISODateTimeFormat.dateTime()
val indexFmt = DateTimeFormat.forPattern("yyyy.MM.dd")
/** LogStash-format logger, allows passing anything that can be expressed as a JsValue in addition to standard fields
* @param sourcePath source path of event
* @param msg event message
* @param eventType event type
* @param fields arbitrary data as JsValue
**/
def log(sourcePath: String, msg: String, eventType: String, fields: Option[JsValue]) {
val now = new DateTime(DateTimeZone.UTC)
val logItem = Json.obj(
"@source" -> instanceID,
"@tags" -> JsArray(),
"@fields" -> fields,
"@timestamp" -> dtFormat.print(now),
"@source_host" -> "mn.local",
"@source_path" -> sourcePath,
"@message" -> msg,
"@type" -> eventType
)
WS.url(elasticURL + "/logstash-" + indexFmt.print(now) + "/play").post(logItem)
}
/** Simple request logger, logs request including Geo Data if available. Uses LogStash-style logger above.
* @param req request
* @param msg event message
* @param httpCode HTTP code of connection (e.g. 200 or 404)
* @param duration duration of connection in milliseconds
**/
def logRequest(req: Request[AnyContent], msg: String, httpCode: Int, duration: Long) {
val userAgent = req.headers.get("User-Agent").getOrElse("")
/** basic request log item */
val logItem = Json.obj(
"instanceID" -> instanceID,
"request" -> req.toString(),
"requestID" -> req.id,
"user-agent" -> userAgent,
"httpCode" -> httpCode,
"duration_ms" -> duration
)
/** freegeoip needs IPv4 addresses, ignore local requests with IPv6 addresses for logging */
if (!req.remoteAddress.contains(":")) {
val geoRequest = WS.url("http://freegeoip.net/json/" + req.remoteAddress).withTimeout(2000).get()
/** log with geo data if service accessible */
geoRequest.onSuccess {
case res => {
val geoLogItem = logItem ++ Json.obj(
"country_code" -> res.json \ "country_code",
"country" -> res.json \ "country_name",
"region_code" -> res.json \ "region_code",
"region" -> res.json \ "region_name",
"city" -> res.json \ "city",
"geoJSON" -> JsArray(Seq(res.json \ "longitude", res.json \ "latitude")),
"long" -> res.json \ "longitude",
"lat" -> res.json \ "latitude")
log(req.toString(), msg, "INFO", Some(geoLogItem))
}
}
/** log without geo data in case of failure such as connection timeout */
geoRequest.onFailure { case _ => log(req.toString(), msg, "INFO", Some(logItem)) }
}
else { log(req.toString(), msg, "INFO", Some(logItem)) }
}
}