@@ -6,33 +6,21 @@ import java.net.URI
66import java .time .Instant
77import play .api .{Logger , Play }
88import play .api .Play .current
9- import play .api .libs .json .{JsValue , Json }
9+ import play .api .libs .json .{JsObject , JsValue , Json }
1010
1111object 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
2519class 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