Skip to content

Commit be90ae1

Browse files
committed
Merge branch 'develop' into release/1.15.1
# Conflicts: # CHANGELOG.md # app/services/EventSinkService.scala
2 parents cf31063 + 1e304e6 commit be90ae1

File tree

2 files changed

+91
-92
lines changed

2 files changed

+91
-92
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
99
### Fixed
1010
- Several views were throwing errors trying to access a None value in `EventSinkService` when a user was not logged in.
1111
Replaced `get()` with `getOrElse()`.
12+
- Consolidated field names sent by the EventSinkService to maximize reuse.
13+
- Changed `EventSinkService` logging to debug to minimize chatter.
1214

1315
## 1.15.0 - 2021-03-03
1416

app/services/EventSinkService.scala

Lines changed: 89 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -6,33 +6,21 @@ import java.net.URI
66
import java.time.Instant
77
import play.api.{Logger, Play}
88
import play.api.Play.current
9-
import play.api.libs.json.{JsValue, Json}
9+
import play.api.libs.json.{JsObject, JsValue, Json}
1010

1111
object EventSinkService {
1212
val EXCHANGE_NAME_CONFIG_KEY = "eventsink.exchangename"
1313
val QUEUE_NAME_CONFIG_KEY = "eventsink.queuename"
1414

1515
val EXCHANGE_NAME_DEFAULT_VALUE = "clowder.metrics"
1616
val QUEUE_NAME_DEFAULT_VALUE = "event.sink"
17-
18-
// TODO: Make sure these match the real config key names
19-
val AMPLITUDE_CONFIG_KEY = "amplitude.apikey"
20-
val GA_CONFIG_KEY = "google.analytics"
21-
val INFLUX_AUTH_CONFIG_KEY = "influx.uri"
22-
val MONGO_AUTH_CONFIG_KEY = "mongo.uri"
2317
}
2418

2519
class EventSinkService {
2620
val messageService: MessageService = DI.injector.getInstance(classOf[MessageService])
2721
val userService: UserService = DI.injector.getInstance(classOf[UserService])
2822
val appConfig: AppConfigurationService = DI.injector.getInstance(classOf[AppConfigurationService])
2923

30-
// UNUSED: Fetch directly from config on demand
31-
def getGoogleAnalytics(): String = Play.configuration.getString(EventSinkService.GA_CONFIG_KEY).getOrElse("")
32-
def getAmplitudeApiKey(): String = Play.configuration.getString(EventSinkService.AMPLITUDE_CONFIG_KEY).getOrElse("")
33-
def getMongoAuth(): String = Play.configuration.getString(EventSinkService.AMPLITUDE_CONFIG_KEY).getOrElse("")
34-
def getInfluxAuth(): String = Play.configuration.getString(EventSinkService.INFLUX_AUTH_CONFIG_KEY).getOrElse("")
35-
3624
/** Event Sink exchange name in RabbitMQ */
3725
val exchangeName = Play.configuration.getString(EventSinkService.EXCHANGE_NAME_CONFIG_KEY)
3826
.getOrElse(EventSinkService.EXCHANGE_NAME_DEFAULT_VALUE)
@@ -41,20 +29,18 @@ class EventSinkService {
4129
val queueName = Play.configuration.getString(EventSinkService.QUEUE_NAME_CONFIG_KEY)
4230
.getOrElse(EventSinkService.QUEUE_NAME_DEFAULT_VALUE)
4331

44-
def logEvent(category: String, metadata: JsValue) = {
45-
Logger.info("eventsink.exchangename=" + exchangeName)
46-
Logger.info("eventsink.queueName=" + queueName)
47-
48-
Logger.info("Submitting message to event sink exchange: " + Json.stringify(metadata))
49-
50-
//val message = EventSinkMessage(Instant.now().getEpochSecond, category, metadata)
51-
messageService.submit(exchangeName, queueName, metadata, "fanout")
32+
def logEvent(message: JsValue) = {
33+
// Inject timestamp before logging the event
34+
val event = message.as[JsObject] + ("created" -> Json.toJson(java.util.Date.from(Instant.now())))
35+
Logger.info("Submitting message to event sink exchange: " + Json.stringify(event))
36+
messageService.submit(exchangeName, queueName, event, "fanout")
5237
}
5338

5439
/** Log an event when user signs up */
5540
def logUserSignupEvent(user: User) = {
56-
Logger.info("New user signed up: " + user.id.stringify)
57-
logEvent("user_activity", Json.obj(
41+
Logger.debug("New user signed up: " + user.id.stringify)
42+
logEvent(Json.obj(
43+
"category" -> "user_activity",
5844
"type" -> "signup",
5945
"user_id" -> user.id,
6046
"user_name" -> user.fullName
@@ -63,8 +49,9 @@ class EventSinkService {
6349

6450
/** Log an event when user logs in */
6551
def logUserLoginEvent(user: User) = {
66-
Logger.info("User logged in: " + user.id.stringify)
67-
logEvent("user_activity", Json.obj(
52+
Logger.debug("User logged in: " + user.id.stringify)
53+
logEvent(Json.obj(
54+
"category" -> "user_activity",
6855
"type" -> "login",
6956
"user_id" -> user.id,
7057
"user_name" -> user.fullName
@@ -73,191 +60,201 @@ class EventSinkService {
7360

7461
/** Log an event when user views a dataset */
7562
def logDatasetViewEvent(dataset: Dataset, viewer: Option[User]) = {
76-
Logger.info("User viewed a dataset: " + dataset.id.stringify)
77-
logEvent("view_resource", Json.obj(
63+
Logger.debug("User viewed a dataset: " + dataset.id.stringify)
64+
logEvent(Json.obj(
65+
"category" -> "view_resource",
7866
"type" -> "dataset",
7967
"resource_id" -> dataset.id,
8068
"resource_name" -> dataset.name,
8169
"author_id" -> dataset.author.id,
8270
"author_name" -> dataset.author.fullName,
83-
"viewer_id" -> viewer.getOrElse(User.anonymous).id,
84-
"viewer_name" -> viewer.getOrElse(User.anonymous).getMiniUser.fullName
71+
"user_id" -> viewer.getOrElse(User.anonymous).id,
72+
"user_name" -> viewer.getOrElse(User.anonymous).getMiniUser.fullName
8573
))
8674
}
8775

8876
/** Log an event when user views a file */
8977
def logFileViewEvent(file: File, viewer: Option[User]) = {
90-
Logger.info("User viewed a file: " + file.id.stringify)
91-
logEvent("view_resource", Json.obj(
78+
Logger.debug("User viewed a file: " + file.id.stringify)
79+
logEvent(Json.obj(
80+
"category" -> "view_resource",
9281
"type" -> "file",
9382
"resource_id" -> file.id,
9483
"resource_name" -> file.filename,
9584
"author_id" -> file.author.id,
9685
"author_name" -> file.author.fullName,
97-
"viewer_id" -> viewer.getOrElse(User.anonymous).id,
98-
"viewer_name" -> viewer.getOrElse(User.anonymous).getMiniUser.fullName
86+
"user_id" -> viewer.getOrElse(User.anonymous).id,
87+
"user_name" -> viewer.getOrElse(User.anonymous).getMiniUser.fullName
9988
))
10089
}
10190

10291
/** Log an event when user views a collection */
10392
def logCollectionViewEvent(collection: Collection, viewer: Option[User]) = {
104-
Logger.info("User viewed a collection: " + collection.id.stringify)
105-
logEvent("view_resource", Json.obj(
93+
Logger.debug("User viewed a collection: " + collection.id.stringify)
94+
logEvent(Json.obj(
95+
"category" -> "view_resource",
10696
"type" -> "collection",
10797
"resource_id" -> collection.id,
10898
"resource_name" -> collection.name,
10999
"author_id" -> collection.author.id,
110100
"author_name" -> collection.author.fullName,
111-
"viewer_id" -> viewer.getOrElse(User.anonymous).id,
112-
"viewer_name" -> viewer.getOrElse(User.anonymous).getMiniUser.fullName
101+
"user_id" -> viewer.getOrElse(User.anonymous).id,
102+
"user_name" -> viewer.getOrElse(User.anonymous).getMiniUser.fullName
113103
))
114104
}
115105

116106
/** Log an event when user views a space */
117107
def logSpaceViewEvent(space: ProjectSpace, viewer: Option[User]) = {
118-
Logger.info("User viewed a space: " + space.id.stringify)
108+
Logger.debug("User viewed a space: " + space.id.stringify)
119109
(viewer, userService.get(space.creator)) match {
120110
case (Some(v), Some(author)) => {
121-
logEvent("view_resource", Json.obj(
111+
logEvent(Json.obj(
112+
"category" -> "view_resource",
122113
"type" -> "space",
123114
"resource_id" -> space.id,
124115
"resource_name" -> space.name,
125116
"author_id" -> space.creator.stringify,
126117
"author_name" -> author.fullName,
127-
"viewer_id" -> v.id,
128-
"viewer_name" -> v.getMiniUser.fullName
118+
"user_id" -> v.id,
119+
"user_name" -> v.getMiniUser.fullName
129120
))
130121
}
131122
case (None, Some(author)) => {
132-
logEvent("view_resource", Json.obj(
123+
logEvent(Json.obj(
124+
"category" -> "view_resource",
133125
"type" -> "space",
134126
"resource_id" -> space.id,
135127
"resource_name" -> space.name,
136128
"author_id" -> author.id,
137129
"author_name" -> author.fullName,
138-
"viewer_id" -> User.anonymous.id,
139-
"viewer_name" -> User.anonymous.fullName
130+
"user_id" -> User.anonymous.id,
131+
"user_name" -> User.anonymous.fullName
140132
))
141133
}
142134
case (Some(v), None) => {
143135
// TODO: Is this a real case? Is this needed?
144-
logEvent("view_resource", Json.obj(
136+
logEvent(Json.obj(
137+
"category" -> "view_resource",
145138
"type" -> "space",
146139
"resource_id" -> space.id,
147140
"resource_name" -> space.name,
148141
"author_id" -> space.creator.stringify,
149142
"author_name" -> "",
150-
"viewer_id" -> v.id,
151-
"viewer_name" -> v.getMiniUser.fullName
143+
"user_id" -> v.id,
144+
"user_name" -> v.getMiniUser.fullName
152145
))
153146
}
154147
case (None, None) => {
155148
// TODO: Is this a real case? Is this needed?
156-
logEvent("view_resource", Json.obj(
149+
logEvent(Json.obj(
150+
"category" -> "view_resource",
157151
"type" -> "space",
158152
"resource_id" -> space.id,
159153
"resource_name" -> space.name,
160154
"author_id" -> space.creator.stringify,
161155
"author_name" -> "",
162-
"viewer_id" -> User.anonymous.id,
163-
"viewer_name" -> User.anonymous.fullName
156+
"user_id" -> User.anonymous.id,
157+
"user_name" -> User.anonymous.fullName
164158
))
165159
}
166160
}
167161
}
168162

169163
def logSubmitFileToExtractorEvent(file: File, extractorName: String, submitter: Option[User]) = {
170-
logEvent("extraction", Json.obj(
164+
logEvent(Json.obj(
165+
"category" -> "extraction",
171166
"type" -> "file",
172167
"extractor_name" -> extractorName,
173168
"resource_id" -> file.id,
174169
"resource_name" -> file.filename,
175170
"author_id" -> file.author.id,
176171
"author_name" -> file.author.fullName,
177-
"submitter_id" -> submitter.getOrElse(User.anonymous).id,
178-
"submitter_name" -> submitter.getOrElse(User.anonymous).getMiniUser.fullName
172+
"user_id" -> submitter.getOrElse(User.anonymous).id,
173+
"user_name" -> submitter.getOrElse(User.anonymous).getMiniUser.fullName
179174
))
180175
}
181176

182177
def logSubmitDatasetToExtractorEvent(dataset: Dataset, extractorName: String, submitter: Option[User]) = {
183-
logEvent("extraction", Json.obj(
178+
logEvent(Json.obj(
179+
"category" -> "extraction",
184180
"type" -> "dataset",
185181
"extractor_name" -> extractorName,
186182
"resource_id" -> dataset.id,
187183
"resource_name" -> dataset.name,
188184
"author_id" -> dataset.author.id,
189185
"author_name" -> dataset.author.fullName,
190-
"submitter_id" -> submitter.getOrElse(User.anonymous).id,
191-
"submitter_name" -> submitter.getOrElse(User.anonymous).getMiniUser.fullName
186+
"user_id" -> submitter.getOrElse(User.anonymous).id,
187+
"user_name" -> submitter.getOrElse(User.anonymous).getMiniUser.fullName
192188
))
193189
}
194190

195191
def logSubmitSelectionToExtractorEvent(dataset: Dataset, extractorName: String, submitter: Option[User]) = {
196192
// TODO: Is this a real case? Is this needed?
197-
logEvent("extraction", Json.obj(
193+
logEvent(Json.obj(
194+
"category" -> "extraction",
198195
"type" -> "selection",
199196
"extractor_name" -> extractorName,
200197
"resource_id" -> dataset.id,
201198
"resource_name" -> dataset.name,
202199
"author_id" -> dataset.author.id,
203200
"author_name" -> dataset.author.fullName,
204-
"submitter_id" -> submitter.getOrElse(User.anonymous).id,
205-
"submitter_name" -> submitter.getOrElse(User.anonymous).getMiniUser.fullName
201+
"user_id" -> submitter.getOrElse(User.anonymous).id,
202+
"user_name" -> submitter.getOrElse(User.anonymous).getMiniUser.fullName
206203
))
207204
}
208205

209206
def logFileUploadEvent(file: File, dataset: Option[Dataset], uploader: Option[User]) = {
210207
dataset match {
211208
case Some(d) => {
212-
logEvent("upload", Json.obj(
209+
logEvent(Json.obj(
210+
"category" -> "upload",
213211
"dataset_id" -> d.id,
214212
"dataset_name" -> d.name,
215-
"dataset_author_name" -> d.author.fullName,
216-
"dataset_author_id" -> d.author.id,
217-
"uploader_id" -> uploader.getOrElse(User.anonymous).id,
218-
"uploader_name" -> uploader.getOrElse(User.anonymous).getMiniUser.fullName,
219-
"filename" -> file.filename,
220-
"length" -> file.length
213+
"author_name" -> d.author.fullName,
214+
"author_id" -> d.author.id,
215+
"user_id" -> uploader.getOrElse(User.anonymous).id,
216+
"user_name" -> uploader.getOrElse(User.anonymous).getMiniUser.fullName,
217+
"resource_name" -> file.filename,
218+
"size" -> file.length
221219
))
222220
}
223221
case None => {
224-
logEvent("upload", Json.obj(
225-
"uploader_id" -> uploader.getOrElse(User.anonymous).id,
226-
"uploader_name" -> uploader.getOrElse(User.anonymous).getMiniUser.fullName,
227-
"filename" -> file.filename,
228-
"length" -> file.length
222+
logEvent(Json.obj(
223+
"category" -> "upload",
224+
"user_id" -> uploader.getOrElse(User.anonymous).id,
225+
"user_name" -> uploader.getOrElse(User.anonymous).getMiniUser.fullName,
226+
"resource_name" -> file.filename,
227+
"size" -> file.length
229228
))
230229
}
231230
}
232231
}
233232

234-
def logFileDownloadEvent(file: File, /*dataset: Dataset,*/ downloader: Option[User]) = {
235-
logEvent("download", Json.obj(
236-
/*"dataset_id" -> dataset.id,
237-
"dataset_name" -> dataset.name,
238-
"dataset_author_name" -> dataset.author.fullName,
239-
"dataset_author_id" -> dataset.author.id,*/
233+
def logFileDownloadEvent(file: File, downloader: Option[User]) = {
234+
logEvent(Json.obj(
235+
"category" -> "download",
240236
"type" -> "file",
241-
"uploader_id" -> file.author.id,
242-
"uploader_name" -> file.author.fullName,
243-
"downloader_id" -> downloader.getOrElse(User.anonymous).id,
244-
"downloader_name" -> downloader.getOrElse(User.anonymous).getMiniUser.fullName,
245-
"filename" -> file.filename,
246-
"length" -> file.length
237+
"resource_id" -> file.id,
238+
"resource_name" -> file.filename,
239+
"author_id" -> file.author.id,
240+
"author_name" -> file.author.fullName,
241+
"user_id" -> downloader.getOrElse(User.anonymous).id,
242+
"user_name" -> downloader.getOrElse(User.anonymous).getMiniUser.fullName,
243+
"size" -> file.length
247244
))
248245
}
249246

250247
def logDatasetDownloadEvent(dataset: Dataset, downloader: Option[User]) = {
251-
logEvent("download", Json.obj(
248+
logEvent(Json.obj(
249+
"category" -> "download",
252250
"type" -> "dataset",
253-
"dataset_id" -> dataset.id,
254-
"dataset_name" -> dataset.name,
255-
"dataset_author_name" -> dataset.author.fullName,
256-
"dataset_author_id" -> dataset.author.id,
257-
"downloader_id" -> downloader.getOrElse(User.anonymous).id,
258-
"downloader_name" -> downloader.getOrElse(User.anonymous).getMiniUser.fullName,
259-
"files_length" -> dataset.files.length,
260-
"folder_length" -> dataset.folders.length
251+
"resource_id" -> dataset.id,
252+
"resource_name" -> dataset.name,
253+
"author_name" -> dataset.author.fullName,
254+
"author_id" -> dataset.author.id,
255+
"user_id" -> downloader.getOrElse(User.anonymous).id,
256+
"user_name" -> downloader.getOrElse(User.anonymous).getMiniUser.fullName,
257+
"size" -> (dataset.files.length + dataset.folders.length)
261258
))
262259
}
263260
}

0 commit comments

Comments
 (0)