<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.expertiza.ncsu.edu/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Knielar</id>
	<title>Expertiza_Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.expertiza.ncsu.edu/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Knielar"/>
	<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=Special:Contributions/Knielar"/>
	<updated>2026-08-07T01:51:27Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.41.0</generator>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=Independent_Study_Spring_2018/Logging&amp;diff=117511</id>
		<title>Independent Study Spring 2018/Logging</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=Independent_Study_Spring_2018/Logging&amp;diff=117511"/>
		<updated>2018-05-09T17:16:08Z</updated>

		<summary type="html">&lt;p&gt;Knielar: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Logging capability in Expertiza=&lt;br /&gt;
==Useful links==&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/1148 Github Pull Request]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/nielarshi/expertiza-elk ELK configurations]&lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
Logging feature has been added to Expertiza through a custom logging module written uniquely to serve several purposes such as:&lt;br /&gt;
*Tracing application failure&lt;br /&gt;
*Analysing user request flow&lt;br /&gt;
*Managing different logging level&lt;br /&gt;
&lt;br /&gt;
==Message Format==&lt;br /&gt;
All the messages are logged in either of the below formats:&lt;br /&gt;
&lt;br /&gt;
'''TST=[2018-03-10 00:50:18 -0500] SVT=[&amp;lt;''log_level''&amp;gt;] PNM=[&amp;lt;''program_name''&amp;gt;] OIP=[&amp;lt;''origin_ip''&amp;gt;] RID=[&amp;lt;''request_id''&amp;gt;] CTR=[&amp;lt;''controller_name''&amp;gt;] UID=[&amp;lt;''user_id''&amp;gt;] MSG=[''Message'']'''&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
'''TST=[2018-03-10 00:50:18 -0500] SVT=[&amp;lt;''log_level''&amp;gt;] PNM=[&amp;lt;''program_name''&amp;gt;] OIP=[] RID=[] CTR=[&amp;lt;''controller_name''&amp;gt;] UID=[&amp;lt;''user_id''&amp;gt;] MSG=[[''origin_ip''] [''request_id''] ''Message'']'''&lt;br /&gt;
&lt;br /&gt;
Above variation is because when certain messages are logged, ExpertizaLogger is unaware of origin_ip and request_ip and thus it is appended to the message instead of their respective placeholders.&lt;br /&gt;
&lt;br /&gt;
===Meaning of each placeholder===&lt;br /&gt;
'''SVT''' - It denotes the severity level of the log. For eg, if the logging is done by calling logger.info, the severity level is &amp;quot;INFO&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
'''PNM''' - It's the program name and is same as provided by default Rails logger.&lt;br /&gt;
&lt;br /&gt;
'''OIP''' - It denotes the IP address of the system from where the request has been made. &lt;br /&gt;
&lt;br /&gt;
'''RID''' - It's the ID of the request. All subsequent calls made by the client till the actual response is returned will have same request ID. For eg, when a page is first requested, all smaller page template fetched, all method flow will have same request ID. This field can be used to understand how a certain request was served.&lt;br /&gt;
&lt;br /&gt;
'''CTR''' - It is the controller name from where the logging happened.&lt;br /&gt;
&lt;br /&gt;
'''UID''' - It is the unity id/user id of the user making requests. This field could also be used in identifying the cause of an error.&lt;br /&gt;
&lt;br /&gt;
'''Message''' - It is the actual message logged.&lt;br /&gt;
&lt;br /&gt;
==Log files==&lt;br /&gt;
For different log levels, log messages are written in different files named expertiza_&amp;lt;log_level&amp;gt;.log&lt;br /&gt;
&lt;br /&gt;
Currently, expertiza provides the capability of writing logs into 5 different custom log files.&lt;br /&gt;
&lt;br /&gt;
For eg, &lt;br /&gt;
&lt;br /&gt;
*expertiza_info.log&lt;br /&gt;
&lt;br /&gt;
*expertiza_warn.log&lt;br /&gt;
&lt;br /&gt;
*expertiza_error.log&lt;br /&gt;
&lt;br /&gt;
*expertiza_fatal.log&lt;br /&gt;
&lt;br /&gt;
*expertiza_debug.log&lt;br /&gt;
&lt;br /&gt;
Apart from above files, &amp;lt;environment&amp;gt;.log file is used for logging messages which could not be logged by ExpertizaLogger, like, page load messages or certain load time exceptions.&lt;br /&gt;
&lt;br /&gt;
Since Rails logger provides writing into a specific log file, to restrict least file switch, ExpertizaLogger holds different log level loggers in separate instance variables. A new logger instance is created and assigned whenever Rails removes the link to manage memory consumption.&lt;br /&gt;
&lt;br /&gt;
==Components==&lt;br /&gt;
===ExpertizaLogger===&lt;br /&gt;
&lt;br /&gt;
This class provides the logger needed for logging messages for different log levels.&lt;br /&gt;
It provides 5 different static methods namely '''info''', '''warn''', '''error''', '''fatal''' and '''debug''' which could be called as follows:&lt;br /&gt;
&lt;br /&gt;
'''ExpertizaLogger.info ''message'''''&lt;br /&gt;
&lt;br /&gt;
where ''message'' could be an instance of '''LoggerMessage''' or a string.&lt;br /&gt;
&lt;br /&gt;
===Custom LoggerMessage===&lt;br /&gt;
&lt;br /&gt;
A LoggerMessage instance could be created as follows:&lt;br /&gt;
&lt;br /&gt;
'''LoggerMessage.new(&amp;lt;controller_name&amp;gt;, &amp;lt;user_id&amp;gt;, &amp;lt;message&amp;gt;, &amp;lt;request object&amp;gt;)'''&lt;br /&gt;
&lt;br /&gt;
Fourth parameter i.e &amp;lt;request object&amp;gt; is an optional parameter. &lt;br /&gt;
&lt;br /&gt;
Whenever a request is made, the request object is injected into the controller and is available in the controller as &amp;quot;request&amp;quot;.&lt;br /&gt;
Similarly, &amp;lt;controller_name&amp;gt; is available in &amp;quot;controller_name&amp;quot; inside controller. For other trigger points, file name could be passed as a string.&lt;br /&gt;
&lt;br /&gt;
Since the request object holds the ''&amp;lt;origin_ip&amp;gt;'' and ''&amp;lt;request_id&amp;gt;'', it is used to capture and log both into the log message.&lt;br /&gt;
&lt;br /&gt;
===ExpertizaLogFormatter===&lt;br /&gt;
&lt;br /&gt;
It captures the message and determines if the message is an instance of LoggerMessage or not. Based on that, it creates a message by populating message placeholders as below:&lt;br /&gt;
&lt;br /&gt;
    if msg.is_a?(LoggerMessage)&lt;br /&gt;
      &amp;quot;TST=[#{ts}] SVT=[#{s}] PNM=[#{pg}] OIP=[#{msg.oip}] RID=[#{msg.req_id}] CTR=[#{msg.generator}] UID=[#{msg.unity_id}] MSG=[#{filter(msg.message)}]\n&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
      &amp;quot;TST=[#{ts}] SVT=[#{s}] PNM=[#{pg}] OIP=[] RID=[] CTR=[] UID=[] MSG=[#{filter(msg)}]\n&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
All the exceptions are preprocessed to remove newline characters so that it could fit in a single line as a message.&lt;br /&gt;
&lt;br /&gt;
All the messages that are not logged by ExpertizaLogger, there is a separate logger definition provided in config/environments/&amp;lt;environment&amp;gt;.rb as:&lt;br /&gt;
&lt;br /&gt;
  config.log_formatter = proc do |s, ts, pg, msg|&lt;br /&gt;
    if msg.is_a?(LoggerMessage)&lt;br /&gt;
      &amp;quot;TST=[#{ts}] SVT=[#{s}] PNM=[#{pg}] OIP=[#{msg.oip}] RID=[#{msg.req_id}] CTR=[#{msg.generator}] UID=[#{msg.unity_id}] MSG=[#{filter(msg.message)}]\n&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
      &amp;quot;TST=[#{ts}] SVT=[#{s}] PNM=[#{pg}] OIP=[] RID=[] CTR=[] UID=[] MSG=[#{filter(msg)}]\n&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===Environment config===&lt;br /&gt;
config.log_tags = [ :remote_ip, :uuid ]&lt;br /&gt;
&lt;br /&gt;
These config.log_tags entries make sure that &amp;lt;origin_ip&amp;gt; and &amp;lt;request_id&amp;gt; are prepended to messages. These are for messages which are not logged by ExpertizaLogger but by the Rails default logger.&lt;br /&gt;
These messages go in &amp;lt;environment&amp;gt;.log file.&lt;br /&gt;
&lt;br /&gt;
==Restrictions==&lt;br /&gt;
The request object is not available beyond the controllers. Hence, ''&amp;lt;origin_ip&amp;gt;'' and ''&amp;lt;request_id&amp;gt;'' remains uncaptured if messages are logged from somewhere other than controllers.&lt;br /&gt;
&lt;br /&gt;
==Visualization through ELK stack==&lt;br /&gt;
===Configuration===&lt;br /&gt;
&lt;br /&gt;
Filebeat (filebeat.yml)&lt;br /&gt;
&lt;br /&gt;
Changes:&lt;br /&gt;
&lt;br /&gt;
- type: log&lt;br /&gt;
&lt;br /&gt;
  # Change to true to enable this prospector configuration.&lt;br /&gt;
  enabled: true&lt;br /&gt;
&lt;br /&gt;
  # Paths that should be crawled and fetched. Glob based paths.&lt;br /&gt;
  paths:&lt;br /&gt;
    - &amp;lt;path to log files&amp;gt;*.log&lt;br /&gt;
&lt;br /&gt;
output.logstash:&lt;br /&gt;
  # The Logstash hosts&lt;br /&gt;
  hosts: [&amp;quot;&amp;lt;ip&amp;gt;:&amp;lt;5044:port of logstash&amp;gt;&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
Filebeat sends all log files to logstash.&lt;br /&gt;
&lt;br /&gt;
Logstash (expertiza-logstash.conf)&lt;br /&gt;
&lt;br /&gt;
   input { &lt;br /&gt;
        beats {&lt;br /&gt;
            port =&amp;gt; &amp;quot;5044&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
   }&lt;br /&gt;
   filter {&lt;br /&gt;
    grok {&lt;br /&gt;
    	match =&amp;gt; { &amp;quot;message&amp;quot; =&amp;gt; &amp;quot;TST=\[%{DATA:timestamp}\] SVT=\[%{DATA:sev}\] PNM=\[%{DATA:pgnm}\] OIP=\[%{DATA:originip}\] RID=\[%{DATA:requestid}\] CTR=\[%{DATA:generatedby}\] UID=\[% &lt;br /&gt;
   {DATA:unityid}\] MSG=\[%{GREEDYDATA:message}\]&amp;quot; }&lt;br /&gt;
    	overwrite =&amp;gt; [ &amp;quot;message&amp;quot;, &amp;quot;timestamp&amp;quot; ]&lt;br /&gt;
  	}&lt;br /&gt;
  	date {&lt;br /&gt;
    	match =&amp;gt; [&amp;quot;timestamp&amp;quot;, &amp;quot;ISO8601&amp;quot;]&lt;br /&gt;
  	}&lt;br /&gt;
  	&lt;br /&gt;
    }&lt;br /&gt;
    output {&lt;br /&gt;
      elasticsearch {&lt;br /&gt;
        hosts =&amp;gt; [ &amp;quot;localhost:9200&amp;quot; ]&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
Logstash reads each line from the log file and parses it based on the template provided in grok match above. It then sends each message entry into Elastic search.&lt;br /&gt;
&lt;br /&gt;
Kibana (config/kibana.yml)&lt;br /&gt;
&lt;br /&gt;
    elasticsearch.url: &amp;quot;http://localhost:9200&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Kibana picks each entry from Elastic search and provides into the web interface.&lt;br /&gt;
&lt;br /&gt;
===Setup===&lt;br /&gt;
ELK stack could be set up to visualize and analyze the messages from the log files.&lt;br /&gt;
&lt;br /&gt;
Once ELK is installed, below commands could be used to run each server:&lt;br /&gt;
&lt;br /&gt;
'''Clear Elastic search cache'''&lt;br /&gt;
&lt;br /&gt;
curl -X DELETE 'http://localhost:9200/_all'&lt;br /&gt;
&lt;br /&gt;
'''Filebeat'''&lt;br /&gt;
&lt;br /&gt;
sudo rm data/registry&lt;br /&gt;
&lt;br /&gt;
sudo ./filebeat -e -c filebeat.yml -d &amp;quot;publish&amp;quot;&lt;br /&gt;
&lt;br /&gt;
'''Logstash'''&lt;br /&gt;
&lt;br /&gt;
bin/logstash -f expertiza-logstash.conf --config.reload.automatic&lt;br /&gt;
&lt;br /&gt;
'''Kibana'''&lt;br /&gt;
&lt;br /&gt;
bin/kibana&lt;br /&gt;
&lt;br /&gt;
===Kibana Interface===&lt;br /&gt;
&lt;br /&gt;
Success message in Kibana&lt;br /&gt;
&lt;br /&gt;
[[File:kibana_success_msg.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Exception in kibana&lt;br /&gt;
&lt;br /&gt;
[[File:kibana_exception.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Tracing error in kibana&lt;br /&gt;
&lt;br /&gt;
[[File:kibana_tracing_error.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Search records using request ID in kibana&lt;br /&gt;
&lt;br /&gt;
[[File:kibana_search_req_id.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Searching records using unity id in kibana&lt;br /&gt;
&lt;br /&gt;
[[File:kibana_search_using_unityid.png|frame|upright|center]]&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=Independent_Study_Spring_2018/Logging&amp;diff=117510</id>
		<title>Independent Study Spring 2018/Logging</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=Independent_Study_Spring_2018/Logging&amp;diff=117510"/>
		<updated>2018-05-09T15:51:02Z</updated>

		<summary type="html">&lt;p&gt;Knielar: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Logging capability in Expertiza=&lt;br /&gt;
==Pull Request==&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/1148 'Github Pull Request']&lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
Logging feature has been added to Expertiza through a custom logging module written uniquely to serve several purposes such as:&lt;br /&gt;
*Tracing application failure&lt;br /&gt;
*Analysing user request flow&lt;br /&gt;
*Managing different logging level&lt;br /&gt;
&lt;br /&gt;
==Message Format==&lt;br /&gt;
All the messages are logged in either of the below formats:&lt;br /&gt;
&lt;br /&gt;
'''TST=[2018-03-10 00:50:18 -0500] SVT=[&amp;lt;''log_level''&amp;gt;] PNM=[&amp;lt;''program_name''&amp;gt;] OIP=[&amp;lt;''origin_ip''&amp;gt;] RID=[&amp;lt;''request_id''&amp;gt;] CTR=[&amp;lt;''controller_name''&amp;gt;] UID=[&amp;lt;''user_id''&amp;gt;] MSG=[''Message'']'''&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
'''TST=[2018-03-10 00:50:18 -0500] SVT=[&amp;lt;''log_level''&amp;gt;] PNM=[&amp;lt;''program_name''&amp;gt;] OIP=[] RID=[] CTR=[&amp;lt;''controller_name''&amp;gt;] UID=[&amp;lt;''user_id''&amp;gt;] MSG=[[''origin_ip''] [''request_id''] ''Message'']'''&lt;br /&gt;
&lt;br /&gt;
Above variation is because when certain messages are logged, ExpertizaLogger is unaware of origin_ip and request_ip and thus it is appended to the message instead of their respective placeholders.&lt;br /&gt;
&lt;br /&gt;
===Meaning of each placeholder===&lt;br /&gt;
'''SVT''' - It denotes the severity level of the log. For eg, if the logging is done by calling logger.info, the severity level is &amp;quot;INFO&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
'''PNM''' - It's the program name and is same as provided by default Rails logger.&lt;br /&gt;
&lt;br /&gt;
'''OIP''' - It denotes the IP address of the system from where the request has been made. &lt;br /&gt;
&lt;br /&gt;
'''RID''' - It's the ID of the request. All subsequent calls made by the client till the actual response is returned will have same request ID. For eg, when a page is first requested, all smaller page template fetched, all method flow will have same request ID. This field can be used to understand how a certain request was served.&lt;br /&gt;
&lt;br /&gt;
'''CTR''' - It is the controller name from where the logging happened.&lt;br /&gt;
&lt;br /&gt;
'''UID''' - It is the unity id/user id of the user making requests. This field could also be used in identifying the cause of an error.&lt;br /&gt;
&lt;br /&gt;
'''Message''' - It is the actual message logged.&lt;br /&gt;
&lt;br /&gt;
==Log files==&lt;br /&gt;
For different log levels, log messages are written in different files named expertiza_&amp;lt;log_level&amp;gt;.log&lt;br /&gt;
&lt;br /&gt;
Currently, expertiza provides the capability of writing logs into 5 different custom log files.&lt;br /&gt;
&lt;br /&gt;
For eg, &lt;br /&gt;
&lt;br /&gt;
*expertiza_info.log&lt;br /&gt;
&lt;br /&gt;
*expertiza_warn.log&lt;br /&gt;
&lt;br /&gt;
*expertiza_error.log&lt;br /&gt;
&lt;br /&gt;
*expertiza_fatal.log&lt;br /&gt;
&lt;br /&gt;
*expertiza_debug.log&lt;br /&gt;
&lt;br /&gt;
Apart from above files, &amp;lt;environment&amp;gt;.log file is used for logging messages which could not be logged by ExpertizaLogger, like, page load messages or certain load time exceptions.&lt;br /&gt;
&lt;br /&gt;
Since Rails logger provides writing into a specific log file, to restrict least file switch, ExpertizaLogger holds different log level loggers in separate instance variables. A new logger instance is created and assigned whenever Rails removes the link to manage memory consumption.&lt;br /&gt;
&lt;br /&gt;
==Components==&lt;br /&gt;
===ExpertizaLogger===&lt;br /&gt;
&lt;br /&gt;
This class provides the logger needed for logging messages for different log levels.&lt;br /&gt;
It provides 5 different static methods namely '''info''', '''warn''', '''error''', '''fatal''' and '''debug''' which could be called as follows:&lt;br /&gt;
&lt;br /&gt;
'''ExpertizaLogger.info ''message'''''&lt;br /&gt;
&lt;br /&gt;
where ''message'' could be an instance of '''LoggerMessage''' or a string.&lt;br /&gt;
&lt;br /&gt;
===Custom LoggerMessage===&lt;br /&gt;
&lt;br /&gt;
A LoggerMessage instance could be created as follows:&lt;br /&gt;
&lt;br /&gt;
'''LoggerMessage.new(&amp;lt;controller_name&amp;gt;, &amp;lt;user_id&amp;gt;, &amp;lt;message&amp;gt;, &amp;lt;request object&amp;gt;)'''&lt;br /&gt;
&lt;br /&gt;
Fourth parameter i.e &amp;lt;request object&amp;gt; is an optional parameter. &lt;br /&gt;
&lt;br /&gt;
Whenever a request is made, the request object is injected into the controller and is available in the controller as &amp;quot;request&amp;quot;.&lt;br /&gt;
Similarly, &amp;lt;controller_name&amp;gt; is available in &amp;quot;controller_name&amp;quot; inside controller. For other trigger points, file name could be passed as a string.&lt;br /&gt;
&lt;br /&gt;
Since the request object holds the ''&amp;lt;origin_ip&amp;gt;'' and ''&amp;lt;request_id&amp;gt;'', it is used to capture and log both into the log message.&lt;br /&gt;
&lt;br /&gt;
===ExpertizaLogFormatter===&lt;br /&gt;
&lt;br /&gt;
It captures the message and determines if the message is an instance of LoggerMessage or not. Based on that, it creates a message by populating message placeholders as below:&lt;br /&gt;
&lt;br /&gt;
    if msg.is_a?(LoggerMessage)&lt;br /&gt;
      &amp;quot;TST=[#{ts}] SVT=[#{s}] PNM=[#{pg}] OIP=[#{msg.oip}] RID=[#{msg.req_id}] CTR=[#{msg.generator}] UID=[#{msg.unity_id}] MSG=[#{filter(msg.message)}]\n&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
      &amp;quot;TST=[#{ts}] SVT=[#{s}] PNM=[#{pg}] OIP=[] RID=[] CTR=[] UID=[] MSG=[#{filter(msg)}]\n&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
All the exceptions are preprocessed to remove newline characters so that it could fit in a single line as a message.&lt;br /&gt;
&lt;br /&gt;
All the messages that are not logged by ExpertizaLogger, there is a separate logger definition provided in config/environments/&amp;lt;environment&amp;gt;.rb as:&lt;br /&gt;
&lt;br /&gt;
  config.log_formatter = proc do |s, ts, pg, msg|&lt;br /&gt;
    if msg.is_a?(LoggerMessage)&lt;br /&gt;
      &amp;quot;TST=[#{ts}] SVT=[#{s}] PNM=[#{pg}] OIP=[#{msg.oip}] RID=[#{msg.req_id}] CTR=[#{msg.generator}] UID=[#{msg.unity_id}] MSG=[#{filter(msg.message)}]\n&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
      &amp;quot;TST=[#{ts}] SVT=[#{s}] PNM=[#{pg}] OIP=[] RID=[] CTR=[] UID=[] MSG=[#{filter(msg)}]\n&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===Environment config===&lt;br /&gt;
config.log_tags = [ :remote_ip, :uuid ]&lt;br /&gt;
&lt;br /&gt;
These config.log_tags entries make sure that &amp;lt;origin_ip&amp;gt; and &amp;lt;request_id&amp;gt; are prepended to messages. These are for messages which are not logged by ExpertizaLogger but by the Rails default logger.&lt;br /&gt;
These messages go in &amp;lt;environment&amp;gt;.log file.&lt;br /&gt;
&lt;br /&gt;
==Restrictions==&lt;br /&gt;
The request object is not available beyond the controllers. Hence, ''&amp;lt;origin_ip&amp;gt;'' and ''&amp;lt;request_id&amp;gt;'' remains uncaptured if messages are logged from somewhere other than controllers.&lt;br /&gt;
&lt;br /&gt;
==Visualization through ELK stack==&lt;br /&gt;
===Configuration===&lt;br /&gt;
&lt;br /&gt;
Filebeat (filebeat.yml)&lt;br /&gt;
&lt;br /&gt;
Changes:&lt;br /&gt;
&lt;br /&gt;
- type: log&lt;br /&gt;
&lt;br /&gt;
  # Change to true to enable this prospector configuration.&lt;br /&gt;
  enabled: true&lt;br /&gt;
&lt;br /&gt;
  # Paths that should be crawled and fetched. Glob based paths.&lt;br /&gt;
  paths:&lt;br /&gt;
    - &amp;lt;path to log files&amp;gt;*.log&lt;br /&gt;
&lt;br /&gt;
output.logstash:&lt;br /&gt;
  # The Logstash hosts&lt;br /&gt;
  hosts: [&amp;quot;&amp;lt;ip&amp;gt;:&amp;lt;5044:port of logstash&amp;gt;&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
Filebeat sends all log files to logstash.&lt;br /&gt;
&lt;br /&gt;
Logstash (expertiza-logstash.conf)&lt;br /&gt;
&lt;br /&gt;
   input { &lt;br /&gt;
        beats {&lt;br /&gt;
            port =&amp;gt; &amp;quot;5044&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
   }&lt;br /&gt;
   filter {&lt;br /&gt;
    grok {&lt;br /&gt;
    	match =&amp;gt; { &amp;quot;message&amp;quot; =&amp;gt; &amp;quot;TST=\[%{DATA:timestamp}\] SVT=\[%{DATA:sev}\] PNM=\[%{DATA:pgnm}\] OIP=\[%{DATA:originip}\] RID=\[%{DATA:requestid}\] CTR=\[%{DATA:generatedby}\] UID=\[% &lt;br /&gt;
   {DATA:unityid}\] MSG=\[%{GREEDYDATA:message}\]&amp;quot; }&lt;br /&gt;
    	overwrite =&amp;gt; [ &amp;quot;message&amp;quot;, &amp;quot;timestamp&amp;quot; ]&lt;br /&gt;
  	}&lt;br /&gt;
  	date {&lt;br /&gt;
    	match =&amp;gt; [&amp;quot;timestamp&amp;quot;, &amp;quot;ISO8601&amp;quot;]&lt;br /&gt;
  	}&lt;br /&gt;
  	&lt;br /&gt;
    }&lt;br /&gt;
    output {&lt;br /&gt;
      elasticsearch {&lt;br /&gt;
        hosts =&amp;gt; [ &amp;quot;localhost:9200&amp;quot; ]&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
Logstash reads each line from the log file and parses it based on the template provided in grok match above. It then sends each message entry into Elastic search.&lt;br /&gt;
&lt;br /&gt;
Kibana (config/kibana.yml)&lt;br /&gt;
&lt;br /&gt;
    elasticsearch.url: &amp;quot;http://localhost:9200&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Kibana picks each entry from Elastic search and provides into the web interface.&lt;br /&gt;
&lt;br /&gt;
===Setup===&lt;br /&gt;
ELK stack could be set up to visualize and analyze the messages from the log files.&lt;br /&gt;
&lt;br /&gt;
Once ELK is installed, below commands could be used to run each server:&lt;br /&gt;
&lt;br /&gt;
'''Clear Elastic search cache'''&lt;br /&gt;
&lt;br /&gt;
curl -X DELETE 'http://localhost:9200/_all'&lt;br /&gt;
&lt;br /&gt;
'''Filebeat'''&lt;br /&gt;
&lt;br /&gt;
sudo rm data/registry&lt;br /&gt;
&lt;br /&gt;
sudo ./filebeat -e -c filebeat.yml -d &amp;quot;publish&amp;quot;&lt;br /&gt;
&lt;br /&gt;
'''Logstash'''&lt;br /&gt;
&lt;br /&gt;
bin/logstash -f expertiza-logstash.conf --config.reload.automatic&lt;br /&gt;
&lt;br /&gt;
'''Kibana'''&lt;br /&gt;
&lt;br /&gt;
bin/kibana&lt;br /&gt;
&lt;br /&gt;
===Kibana Interface===&lt;br /&gt;
&lt;br /&gt;
Success message in Kibana&lt;br /&gt;
&lt;br /&gt;
[[File:kibana_success_msg.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Exception in kibana&lt;br /&gt;
&lt;br /&gt;
[[File:kibana_exception.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Tracing error in kibana&lt;br /&gt;
&lt;br /&gt;
[[File:kibana_tracing_error.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Search records using request ID in kibana&lt;br /&gt;
&lt;br /&gt;
[[File:kibana_search_req_id.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Searching records using unity id in kibana&lt;br /&gt;
&lt;br /&gt;
[[File:kibana_search_using_unityid.png|frame|upright|center]]&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=Independent_Study_Spring_2018/Logging&amp;diff=117509</id>
		<title>Independent Study Spring 2018/Logging</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=Independent_Study_Spring_2018/Logging&amp;diff=117509"/>
		<updated>2018-05-08T18:01:37Z</updated>

		<summary type="html">&lt;p&gt;Knielar: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Logging capability in Expertiza=&lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
Logging feature has been added to Expertiza through a custom logging module written uniquely to serve several purposes such as:&lt;br /&gt;
*Tracing application failure&lt;br /&gt;
*Analysing user request flow&lt;br /&gt;
*Managing different logging level&lt;br /&gt;
&lt;br /&gt;
==Message Format==&lt;br /&gt;
All the messages are logged in either of the below formats:&lt;br /&gt;
&lt;br /&gt;
'''TST=[2018-03-10 00:50:18 -0500] SVT=[&amp;lt;''log_level''&amp;gt;] PNM=[&amp;lt;''program_name''&amp;gt;] OIP=[&amp;lt;''origin_ip''&amp;gt;] RID=[&amp;lt;''request_id''&amp;gt;] CTR=[&amp;lt;''controller_name''&amp;gt;] UID=[&amp;lt;''user_id''&amp;gt;] MSG=[''Message'']'''&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
'''TST=[2018-03-10 00:50:18 -0500] SVT=[&amp;lt;''log_level''&amp;gt;] PNM=[&amp;lt;''program_name''&amp;gt;] OIP=[] RID=[] CTR=[&amp;lt;''controller_name''&amp;gt;] UID=[&amp;lt;''user_id''&amp;gt;] MSG=[[''origin_ip''] [''request_id''] ''Message'']'''&lt;br /&gt;
&lt;br /&gt;
Above variation is because when certain messages are logged, ExpertizaLogger is unaware of origin_ip and request_ip and thus it is appended to the message instead of their respective placeholders.&lt;br /&gt;
&lt;br /&gt;
===Meaning of each placeholder===&lt;br /&gt;
'''SVT''' - It denotes the severity level of the log. For eg, if the logging is done by calling logger.info, the severity level is &amp;quot;INFO&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
'''PNM''' - It's the program name and is same as provided by default Rails logger.&lt;br /&gt;
&lt;br /&gt;
'''OIP''' - It denotes the IP address of the system from where the request has been made. &lt;br /&gt;
&lt;br /&gt;
'''RID''' - It's the ID of the request. All subsequent calls made by the client till the actual response is returned will have same request ID. For eg, when a page is first requested, all smaller page template fetched, all method flow will have same request ID. This field can be used to understand how a certain request was served.&lt;br /&gt;
&lt;br /&gt;
'''CTR''' - It is the controller name from where the logging happened.&lt;br /&gt;
&lt;br /&gt;
'''UID''' - It is the unity id/user id of the user making requests. This field could also be used in identifying the cause of an error.&lt;br /&gt;
&lt;br /&gt;
'''Message''' - It is the actual message logged.&lt;br /&gt;
&lt;br /&gt;
==Log files==&lt;br /&gt;
For different log levels, log messages are written in different files named expertiza_&amp;lt;log_level&amp;gt;.log&lt;br /&gt;
&lt;br /&gt;
Currently, expertiza provides the capability of writing logs into 5 different custom log files.&lt;br /&gt;
&lt;br /&gt;
For eg, &lt;br /&gt;
&lt;br /&gt;
*expertiza_info.log&lt;br /&gt;
&lt;br /&gt;
*expertiza_warn.log&lt;br /&gt;
&lt;br /&gt;
*expertiza_error.log&lt;br /&gt;
&lt;br /&gt;
*expertiza_fatal.log&lt;br /&gt;
&lt;br /&gt;
*expertiza_debug.log&lt;br /&gt;
&lt;br /&gt;
Apart from above files, &amp;lt;environment&amp;gt;.log file is used for logging messages which could not be logged by ExpertizaLogger, like, page load messages or certain load time exceptions.&lt;br /&gt;
&lt;br /&gt;
Since Rails logger provides writing into a specific log file, to restrict least file switch, ExpertizaLogger holds different log level loggers in separate instance variables. A new logger instance is created and assigned whenever Rails removes the link to manage memory consumption.&lt;br /&gt;
&lt;br /&gt;
==Components==&lt;br /&gt;
===ExpertizaLogger===&lt;br /&gt;
&lt;br /&gt;
This class provides the logger needed for logging messages for different log levels.&lt;br /&gt;
It provides 5 different static methods namely '''info''', '''warn''', '''error''', '''fatal''' and '''debug''' which could be called as follows:&lt;br /&gt;
&lt;br /&gt;
'''ExpertizaLogger.info ''message'''''&lt;br /&gt;
&lt;br /&gt;
where ''message'' could be an instance of '''LoggerMessage''' or a string.&lt;br /&gt;
&lt;br /&gt;
===Custom LoggerMessage===&lt;br /&gt;
&lt;br /&gt;
A LoggerMessage instance could be created as follows:&lt;br /&gt;
&lt;br /&gt;
'''LoggerMessage.new(&amp;lt;controller_name&amp;gt;, &amp;lt;user_id&amp;gt;, &amp;lt;message&amp;gt;, &amp;lt;request object&amp;gt;)'''&lt;br /&gt;
&lt;br /&gt;
Fourth parameter i.e &amp;lt;request object&amp;gt; is an optional parameter. &lt;br /&gt;
&lt;br /&gt;
Whenever a request is made, the request object is injected into the controller and is available in the controller as &amp;quot;request&amp;quot;.&lt;br /&gt;
Similarly, &amp;lt;controller_name&amp;gt; is available in &amp;quot;controller_name&amp;quot; inside controller. For other trigger points, file name could be passed as a string.&lt;br /&gt;
&lt;br /&gt;
Since the request object holds the ''&amp;lt;origin_ip&amp;gt;'' and ''&amp;lt;request_id&amp;gt;'', it is used to capture and log both into the log message.&lt;br /&gt;
&lt;br /&gt;
===ExpertizaLogFormatter===&lt;br /&gt;
&lt;br /&gt;
It captures the message and determines if the message is an instance of LoggerMessage or not. Based on that, it creates a message by populating message placeholders as below:&lt;br /&gt;
&lt;br /&gt;
    if msg.is_a?(LoggerMessage)&lt;br /&gt;
      &amp;quot;TST=[#{ts}] SVT=[#{s}] PNM=[#{pg}] OIP=[#{msg.oip}] RID=[#{msg.req_id}] CTR=[#{msg.generator}] UID=[#{msg.unity_id}] MSG=[#{filter(msg.message)}]\n&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
      &amp;quot;TST=[#{ts}] SVT=[#{s}] PNM=[#{pg}] OIP=[] RID=[] CTR=[] UID=[] MSG=[#{filter(msg)}]\n&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
All the exceptions are preprocessed to remove newline characters so that it could fit in a single line as a message.&lt;br /&gt;
&lt;br /&gt;
All the messages that are not logged by ExpertizaLogger, there is a separate logger definition provided in config/environments/&amp;lt;environment&amp;gt;.rb as:&lt;br /&gt;
&lt;br /&gt;
  config.log_formatter = proc do |s, ts, pg, msg|&lt;br /&gt;
    if msg.is_a?(LoggerMessage)&lt;br /&gt;
      &amp;quot;TST=[#{ts}] SVT=[#{s}] PNM=[#{pg}] OIP=[#{msg.oip}] RID=[#{msg.req_id}] CTR=[#{msg.generator}] UID=[#{msg.unity_id}] MSG=[#{filter(msg.message)}]\n&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
      &amp;quot;TST=[#{ts}] SVT=[#{s}] PNM=[#{pg}] OIP=[] RID=[] CTR=[] UID=[] MSG=[#{filter(msg)}]\n&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===Environment config===&lt;br /&gt;
config.log_tags = [ :remote_ip, :uuid ]&lt;br /&gt;
&lt;br /&gt;
These config.log_tags entries make sure that &amp;lt;origin_ip&amp;gt; and &amp;lt;request_id&amp;gt; are prepended to messages. These are for messages which are not logged by ExpertizaLogger but by the Rails default logger.&lt;br /&gt;
These messages go in &amp;lt;environment&amp;gt;.log file.&lt;br /&gt;
&lt;br /&gt;
==Restrictions==&lt;br /&gt;
The request object is not available beyond the controllers. Hence, ''&amp;lt;origin_ip&amp;gt;'' and ''&amp;lt;request_id&amp;gt;'' remains uncaptured if messages are logged from somewhere other than controllers.&lt;br /&gt;
&lt;br /&gt;
==Visualization through ELK stack==&lt;br /&gt;
===Configuration===&lt;br /&gt;
&lt;br /&gt;
Filebeat (filebeat.yml)&lt;br /&gt;
&lt;br /&gt;
Changes:&lt;br /&gt;
&lt;br /&gt;
- type: log&lt;br /&gt;
&lt;br /&gt;
  # Change to true to enable this prospector configuration.&lt;br /&gt;
  enabled: true&lt;br /&gt;
&lt;br /&gt;
  # Paths that should be crawled and fetched. Glob based paths.&lt;br /&gt;
  paths:&lt;br /&gt;
    - &amp;lt;path to log files&amp;gt;*.log&lt;br /&gt;
&lt;br /&gt;
output.logstash:&lt;br /&gt;
  # The Logstash hosts&lt;br /&gt;
  hosts: [&amp;quot;&amp;lt;ip&amp;gt;:&amp;lt;5044:port of logstash&amp;gt;&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
Filebeat sends all log files to logstash.&lt;br /&gt;
&lt;br /&gt;
Logstash (expertiza-logstash.conf)&lt;br /&gt;
&lt;br /&gt;
   input { &lt;br /&gt;
        beats {&lt;br /&gt;
            port =&amp;gt; &amp;quot;5044&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
   }&lt;br /&gt;
   filter {&lt;br /&gt;
    grok {&lt;br /&gt;
    	match =&amp;gt; { &amp;quot;message&amp;quot; =&amp;gt; &amp;quot;TST=\[%{DATA:timestamp}\] SVT=\[%{DATA:sev}\] PNM=\[%{DATA:pgnm}\] OIP=\[%{DATA:originip}\] RID=\[%{DATA:requestid}\] CTR=\[%{DATA:generatedby}\] UID=\[% &lt;br /&gt;
   {DATA:unityid}\] MSG=\[%{GREEDYDATA:message}\]&amp;quot; }&lt;br /&gt;
    	overwrite =&amp;gt; [ &amp;quot;message&amp;quot;, &amp;quot;timestamp&amp;quot; ]&lt;br /&gt;
  	}&lt;br /&gt;
  	date {&lt;br /&gt;
    	match =&amp;gt; [&amp;quot;timestamp&amp;quot;, &amp;quot;ISO8601&amp;quot;]&lt;br /&gt;
  	}&lt;br /&gt;
  	&lt;br /&gt;
    }&lt;br /&gt;
    output {&lt;br /&gt;
      elasticsearch {&lt;br /&gt;
        hosts =&amp;gt; [ &amp;quot;localhost:9200&amp;quot; ]&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
Logstash reads each line from the log file and parses it based on the template provided in grok match above. It then sends each message entry into Elastic search.&lt;br /&gt;
&lt;br /&gt;
Kibana (config/kibana.yml)&lt;br /&gt;
&lt;br /&gt;
    elasticsearch.url: &amp;quot;http://localhost:9200&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Kibana picks each entry from Elastic search and provides into the web interface.&lt;br /&gt;
&lt;br /&gt;
===Setup===&lt;br /&gt;
ELK stack could be set up to visualize and analyze the messages from the log files.&lt;br /&gt;
&lt;br /&gt;
Once ELK is installed, below commands could be used to run each server:&lt;br /&gt;
&lt;br /&gt;
'''Clear Elastic search cache'''&lt;br /&gt;
&lt;br /&gt;
curl -X DELETE 'http://localhost:9200/_all'&lt;br /&gt;
&lt;br /&gt;
'''Filebeat'''&lt;br /&gt;
&lt;br /&gt;
sudo rm data/registry&lt;br /&gt;
&lt;br /&gt;
sudo ./filebeat -e -c filebeat.yml -d &amp;quot;publish&amp;quot;&lt;br /&gt;
&lt;br /&gt;
'''Logstash'''&lt;br /&gt;
&lt;br /&gt;
bin/logstash -f expertiza-logstash.conf --config.reload.automatic&lt;br /&gt;
&lt;br /&gt;
'''Kibana'''&lt;br /&gt;
&lt;br /&gt;
bin/kibana&lt;br /&gt;
&lt;br /&gt;
===Kibana Interface===&lt;br /&gt;
&lt;br /&gt;
Success message in Kibana&lt;br /&gt;
&lt;br /&gt;
[[File:kibana_success_msg.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Exception in kibana&lt;br /&gt;
&lt;br /&gt;
[[File:kibana_exception.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Tracing error in kibana&lt;br /&gt;
&lt;br /&gt;
[[File:kibana_tracing_error.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Search records using request ID in kibana&lt;br /&gt;
&lt;br /&gt;
[[File:kibana_search_req_id.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Searching records using unity id in kibana&lt;br /&gt;
&lt;br /&gt;
[[File:kibana_search_using_unityid.png|frame|upright|center]]&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=Independent_Study_Spring_2018/Logging&amp;diff=117493</id>
		<title>Independent Study Spring 2018/Logging</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=Independent_Study_Spring_2018/Logging&amp;diff=117493"/>
		<updated>2018-05-08T03:06:45Z</updated>

		<summary type="html">&lt;p&gt;Knielar: /* Visualization */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Logging capability in Expertiza=&lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
Logging feature has been added to Expertiza through a custom logging module written uniquely to serve several purposes such as:&lt;br /&gt;
*Tracing application failure&lt;br /&gt;
*Analysing user request flow&lt;br /&gt;
*Managing different logging level&lt;br /&gt;
&lt;br /&gt;
==Message Format==&lt;br /&gt;
All the messages are logged in either of the below formats:&lt;br /&gt;
&lt;br /&gt;
'''TST=[2018-03-10 00:50:18 -0500] SVT=[&amp;lt;''log_level''&amp;gt;] PNM=[&amp;lt;''program_name''&amp;gt;] OIP=[&amp;lt;''origin_ip''&amp;gt;] RID=[&amp;lt;''request_id''&amp;gt;] CTR=[&amp;lt;''controller_name''&amp;gt;] UID=[&amp;lt;''user_id''&amp;gt;] MSG=[''Message'']'''&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
'''TST=[2018-03-10 00:50:18 -0500] SVT=[&amp;lt;''log_level''&amp;gt;] PNM=[&amp;lt;''program_name''&amp;gt;] OIP=[] RID=[] CTR=[&amp;lt;''controller_name''&amp;gt;] UID=[&amp;lt;''user_id''&amp;gt;] MSG=[[''origin_ip''] [''request_id''] ''Message'']'''&lt;br /&gt;
&lt;br /&gt;
Above variation is because when certain messages are logged, ExpertizaLogger is unaware of origin_ip and request_ip and thus it is appended to the message instead of their respective placeholders.&lt;br /&gt;
&lt;br /&gt;
===Meaning of each placeholder===&lt;br /&gt;
'''SVT''' - It denotes the severity level of the log. For eg, if the logging is done by calling logger.info, the severity level is &amp;quot;INFO&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
'''PNM''' - It's the program name and is same as provided by default Rails logger.&lt;br /&gt;
&lt;br /&gt;
'''OIP''' - It denotes the IP address of the system from where the request has been made. &lt;br /&gt;
&lt;br /&gt;
'''RID''' - It's the ID of the request. All subsequent calls made by the client till the actual response is returned will have same request ID. For eg, when a page is first requested, all smaller page template fetched, all method flow will have same request ID. This field can be used to understand how a certain request was served.&lt;br /&gt;
&lt;br /&gt;
'''CTR''' - It is the controller name from where the logging happened.&lt;br /&gt;
&lt;br /&gt;
'''UID''' - It is the unity id/user id of the user making requests. This field could also be used in identifying the cause of an error.&lt;br /&gt;
&lt;br /&gt;
'''Message''' - It is the actual message logged.&lt;br /&gt;
&lt;br /&gt;
==Log files==&lt;br /&gt;
For different log levels, log messages are written in different files named expertiza_&amp;lt;log_level&amp;gt;.log&lt;br /&gt;
&lt;br /&gt;
Currently, expertiza provides the capability of writing logs into 5 different custom log files.&lt;br /&gt;
&lt;br /&gt;
For eg, &lt;br /&gt;
&lt;br /&gt;
*expertiza_info.log&lt;br /&gt;
&lt;br /&gt;
*expertiza_warn.log&lt;br /&gt;
&lt;br /&gt;
*expertiza_error.log&lt;br /&gt;
&lt;br /&gt;
*expertiza_fatal.log&lt;br /&gt;
&lt;br /&gt;
*expertiza_debug.log&lt;br /&gt;
&lt;br /&gt;
Apart from above files, &amp;lt;environment&amp;gt;.log file is used for logging messages which could not be logged by ExpertizaLogger, like, page load messages or certain load time exceptions.&lt;br /&gt;
&lt;br /&gt;
Since Rails logger provides writing into a specific log file, to restrict least file switch, ExpertizaLogger holds different log level loggers in separate instance variables. A new logger instance is created and assigned whenever Rails removes the link to manage memory consumption.&lt;br /&gt;
&lt;br /&gt;
==Components==&lt;br /&gt;
===ExpertizaLogger===&lt;br /&gt;
&lt;br /&gt;
This class provides the logger needed for logging messages for different log levels.&lt;br /&gt;
It provides 5 different static methods namely '''info''', '''warn''', '''error''', '''fatal''' and '''debug''' which could be called as follows:&lt;br /&gt;
&lt;br /&gt;
'''ExpertizaLogger.info ''message'''''&lt;br /&gt;
&lt;br /&gt;
where ''message'' could be an instance of '''LogMessage''' or a string.&lt;br /&gt;
&lt;br /&gt;
===Custom LogMessage===&lt;br /&gt;
&lt;br /&gt;
A LogMessage instance could be created as follows:&lt;br /&gt;
&lt;br /&gt;
'''LogMessage.new(&amp;lt;controller_name&amp;gt;, &amp;lt;user_id&amp;gt;, &amp;lt;message&amp;gt;, &amp;lt;request object&amp;gt;)'''&lt;br /&gt;
&lt;br /&gt;
Fourth parameter i.e &amp;lt;request object&amp;gt; is an optional parameter. &lt;br /&gt;
&lt;br /&gt;
Whenever a request is made, the request object is injected into the controller and is available in the controller as &amp;quot;request&amp;quot;.&lt;br /&gt;
Similarly, &amp;lt;controller_name&amp;gt; is available in &amp;quot;controller_name&amp;quot; inside controller. For other trigger points, file name could be passed as a string.&lt;br /&gt;
&lt;br /&gt;
Since the request object holds the ''&amp;lt;origin_ip&amp;gt;'' and ''&amp;lt;request_id&amp;gt;'', it is used to capture and log both into the log message.&lt;br /&gt;
&lt;br /&gt;
===ExpertizaLogFormatter===&lt;br /&gt;
&lt;br /&gt;
It captures the message and determines if the message is an instance of LogMessage or not. Based on that, it creates a message by populating message placeholders as below:&lt;br /&gt;
&lt;br /&gt;
    if msg.is_a?(LogMessage)&lt;br /&gt;
      &amp;quot;TST=[#{ts}] SVT=[#{s}] PNM=[#{pg}] OIP=[#{msg.oip}] RID=[#{msg.req_id}] CTR=[#{msg.generator}] UID=[#{msg.unity_id}] MSG=[#{filter(msg.message)}]\n&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
      &amp;quot;TST=[#{ts}] SVT=[#{s}] PNM=[#{pg}] OIP=[] RID=[] CTR=[] UID=[] MSG=[#{filter(msg)}]\n&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
All the exceptions are preprocessed to remove newline characters so that it could fit in a single line as a message.&lt;br /&gt;
&lt;br /&gt;
All the messages that are not logged by ExpertizaLogger, there is a separate logger definition provided in config/environments/&amp;lt;environment&amp;gt;.rb as:&lt;br /&gt;
&lt;br /&gt;
  config.log_formatter = proc do |s, ts, pg, msg|&lt;br /&gt;
    if msg.is_a?(LogMessage)&lt;br /&gt;
      &amp;quot;TST=[#{ts}] SVT=[#{s}] PNM=[#{pg}] OIP=[#{msg.oip}] RID=[#{msg.req_id}] CTR=[#{msg.generator}] UID=[#{msg.unity_id}] MSG=[#{filter(msg.message)}]\n&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
      &amp;quot;TST=[#{ts}] SVT=[#{s}] PNM=[#{pg}] OIP=[] RID=[] CTR=[] UID=[] MSG=[#{filter(msg)}]\n&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===Environment config===&lt;br /&gt;
config.log_tags = [ :remote_ip, :uuid ]&lt;br /&gt;
&lt;br /&gt;
These config.log_tags entries make sure that &amp;lt;origin_ip&amp;gt; and &amp;lt;request_id&amp;gt; are prepended to messages. These are for messages which are not logged by ExpertizaLogger but by the Rails default logger.&lt;br /&gt;
These messages go in &amp;lt;environment&amp;gt;.log file.&lt;br /&gt;
&lt;br /&gt;
==Restrictions==&lt;br /&gt;
The request object is not available beyond the controllers. Hence, ''&amp;lt;origin_ip&amp;gt;'' and ''&amp;lt;request_id&amp;gt;'' remains uncaptured if messages are logged from somewhere other than controllers.&lt;br /&gt;
&lt;br /&gt;
==Visualization through ELK stack==&lt;br /&gt;
===Configuration===&lt;br /&gt;
&lt;br /&gt;
Filebeat (filebeat.yml)&lt;br /&gt;
&lt;br /&gt;
Changes:&lt;br /&gt;
&lt;br /&gt;
- type: log&lt;br /&gt;
&lt;br /&gt;
  # Change to true to enable this prospector configuration.&lt;br /&gt;
  enabled: true&lt;br /&gt;
&lt;br /&gt;
  # Paths that should be crawled and fetched. Glob based paths.&lt;br /&gt;
  paths:&lt;br /&gt;
    - &amp;lt;path to log files&amp;gt;*.log&lt;br /&gt;
&lt;br /&gt;
output.logstash:&lt;br /&gt;
  # The Logstash hosts&lt;br /&gt;
  hosts: [&amp;quot;&amp;lt;ip&amp;gt;:&amp;lt;5044:port of logstash&amp;gt;&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
Filebeat sends all log files to logstash.&lt;br /&gt;
&lt;br /&gt;
Logstash (expertiza-logstash.conf)&lt;br /&gt;
&lt;br /&gt;
   input { &lt;br /&gt;
        beats {&lt;br /&gt;
            port =&amp;gt; &amp;quot;5044&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
   }&lt;br /&gt;
   filter {&lt;br /&gt;
    grok {&lt;br /&gt;
    	match =&amp;gt; { &amp;quot;message&amp;quot; =&amp;gt; &amp;quot;TST=\[%{DATA:timestamp}\] SVT=\[%{DATA:sev}\] PNM=\[%{DATA:pgnm}\] OIP=\[%{DATA:originip}\] RID=\[%{DATA:requestid}\] CTR=\[%{DATA:generatedby}\] UID=\[% &lt;br /&gt;
   {DATA:unityid}\] MSG=\[%{GREEDYDATA:message}\]&amp;quot; }&lt;br /&gt;
    	overwrite =&amp;gt; [ &amp;quot;message&amp;quot;, &amp;quot;timestamp&amp;quot; ]&lt;br /&gt;
  	}&lt;br /&gt;
  	date {&lt;br /&gt;
    	match =&amp;gt; [&amp;quot;timestamp&amp;quot;, &amp;quot;ISO8601&amp;quot;]&lt;br /&gt;
  	}&lt;br /&gt;
  	&lt;br /&gt;
    }&lt;br /&gt;
    output {&lt;br /&gt;
      elasticsearch {&lt;br /&gt;
        hosts =&amp;gt; [ &amp;quot;localhost:9200&amp;quot; ]&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
Logstash reads each line from the log file and parses it based on the template provided in grok match above. It then sends each message entry into Elastic search.&lt;br /&gt;
&lt;br /&gt;
Kibana (config/kibana.yml)&lt;br /&gt;
&lt;br /&gt;
    elasticsearch.url: &amp;quot;http://localhost:9200&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Kibana picks each entry from Elastic search and provides into the web interface.&lt;br /&gt;
&lt;br /&gt;
===Setup===&lt;br /&gt;
ELK stack could be set up to visualize and analyze the messages from the log files.&lt;br /&gt;
&lt;br /&gt;
Once ELK is installed, below commands could be used to run each server:&lt;br /&gt;
&lt;br /&gt;
'''Clear Elastic search cache'''&lt;br /&gt;
&lt;br /&gt;
curl -X DELETE 'http://localhost:9200/_all'&lt;br /&gt;
&lt;br /&gt;
'''Filebeat'''&lt;br /&gt;
&lt;br /&gt;
sudo rm data/registry&lt;br /&gt;
&lt;br /&gt;
sudo ./filebeat -e -c filebeat.yml -d &amp;quot;publish&amp;quot;&lt;br /&gt;
&lt;br /&gt;
'''Logstash'''&lt;br /&gt;
&lt;br /&gt;
bin/logstash -f expertiza-logstash.conf --config.reload.automatic&lt;br /&gt;
&lt;br /&gt;
'''Kibana'''&lt;br /&gt;
&lt;br /&gt;
bin/kibana&lt;br /&gt;
&lt;br /&gt;
===Kibana Interface===&lt;br /&gt;
&lt;br /&gt;
Success message in Kibana&lt;br /&gt;
&lt;br /&gt;
[[File:kibana_success_msg.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Exception in kibana&lt;br /&gt;
&lt;br /&gt;
[[File:kibana_exception.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Tracing error in kibana&lt;br /&gt;
&lt;br /&gt;
[[File:kibana_tracing_error.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Search records using request ID in kibana&lt;br /&gt;
&lt;br /&gt;
[[File:kibana_search_req_id.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Searching records using unity id in kibana&lt;br /&gt;
&lt;br /&gt;
[[File:kibana_search_using_unityid.png|frame|upright|center]]&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=Independent_Study_Spring_2018/Logging&amp;diff=117492</id>
		<title>Independent Study Spring 2018/Logging</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=Independent_Study_Spring_2018/Logging&amp;diff=117492"/>
		<updated>2018-05-08T03:04:28Z</updated>

		<summary type="html">&lt;p&gt;Knielar: /* Visualization */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Logging capability in Expertiza=&lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
Logging feature has been added to Expertiza through a custom logging module written uniquely to serve several purposes such as:&lt;br /&gt;
*Tracing application failure&lt;br /&gt;
*Analysing user request flow&lt;br /&gt;
*Managing different logging level&lt;br /&gt;
&lt;br /&gt;
==Message Format==&lt;br /&gt;
All the messages are logged in either of the below formats:&lt;br /&gt;
&lt;br /&gt;
'''TST=[2018-03-10 00:50:18 -0500] SVT=[&amp;lt;''log_level''&amp;gt;] PNM=[&amp;lt;''program_name''&amp;gt;] OIP=[&amp;lt;''origin_ip''&amp;gt;] RID=[&amp;lt;''request_id''&amp;gt;] CTR=[&amp;lt;''controller_name''&amp;gt;] UID=[&amp;lt;''user_id''&amp;gt;] MSG=[''Message'']'''&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
'''TST=[2018-03-10 00:50:18 -0500] SVT=[&amp;lt;''log_level''&amp;gt;] PNM=[&amp;lt;''program_name''&amp;gt;] OIP=[] RID=[] CTR=[&amp;lt;''controller_name''&amp;gt;] UID=[&amp;lt;''user_id''&amp;gt;] MSG=[[''origin_ip''] [''request_id''] ''Message'']'''&lt;br /&gt;
&lt;br /&gt;
Above variation is because when certain messages are logged, ExpertizaLogger is unaware of origin_ip and request_ip and thus it is appended to the message instead of their respective placeholders.&lt;br /&gt;
&lt;br /&gt;
===Meaning of each placeholder===&lt;br /&gt;
'''SVT''' - It denotes the severity level of the log. For eg, if the logging is done by calling logger.info, the severity level is &amp;quot;INFO&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
'''PNM''' - It's the program name and is same as provided by default Rails logger.&lt;br /&gt;
&lt;br /&gt;
'''OIP''' - It denotes the IP address of the system from where the request has been made. &lt;br /&gt;
&lt;br /&gt;
'''RID''' - It's the ID of the request. All subsequent calls made by the client till the actual response is returned will have same request ID. For eg, when a page is first requested, all smaller page template fetched, all method flow will have same request ID. This field can be used to understand how a certain request was served.&lt;br /&gt;
&lt;br /&gt;
'''CTR''' - It is the controller name from where the logging happened.&lt;br /&gt;
&lt;br /&gt;
'''UID''' - It is the unity id/user id of the user making requests. This field could also be used in identifying the cause of an error.&lt;br /&gt;
&lt;br /&gt;
'''Message''' - It is the actual message logged.&lt;br /&gt;
&lt;br /&gt;
==Log files==&lt;br /&gt;
For different log levels, log messages are written in different files named expertiza_&amp;lt;log_level&amp;gt;.log&lt;br /&gt;
&lt;br /&gt;
Currently, expertiza provides the capability of writing logs into 5 different custom log files.&lt;br /&gt;
&lt;br /&gt;
For eg, &lt;br /&gt;
&lt;br /&gt;
*expertiza_info.log&lt;br /&gt;
&lt;br /&gt;
*expertiza_warn.log&lt;br /&gt;
&lt;br /&gt;
*expertiza_error.log&lt;br /&gt;
&lt;br /&gt;
*expertiza_fatal.log&lt;br /&gt;
&lt;br /&gt;
*expertiza_debug.log&lt;br /&gt;
&lt;br /&gt;
Apart from above files, &amp;lt;environment&amp;gt;.log file is used for logging messages which could not be logged by ExpertizaLogger, like, page load messages or certain load time exceptions.&lt;br /&gt;
&lt;br /&gt;
Since Rails logger provides writing into a specific log file, to restrict least file switch, ExpertizaLogger holds different log level loggers in separate instance variables. A new logger instance is created and assigned whenever Rails removes the link to manage memory consumption.&lt;br /&gt;
&lt;br /&gt;
==Components==&lt;br /&gt;
===ExpertizaLogger===&lt;br /&gt;
&lt;br /&gt;
This class provides the logger needed for logging messages for different log levels.&lt;br /&gt;
It provides 5 different static methods namely '''info''', '''warn''', '''error''', '''fatal''' and '''debug''' which could be called as follows:&lt;br /&gt;
&lt;br /&gt;
'''ExpertizaLogger.info ''message'''''&lt;br /&gt;
&lt;br /&gt;
where ''message'' could be an instance of '''LogMessage''' or a string.&lt;br /&gt;
&lt;br /&gt;
===Custom LogMessage===&lt;br /&gt;
&lt;br /&gt;
A LogMessage instance could be created as follows:&lt;br /&gt;
&lt;br /&gt;
'''LogMessage.new(&amp;lt;controller_name&amp;gt;, &amp;lt;user_id&amp;gt;, &amp;lt;message&amp;gt;, &amp;lt;request object&amp;gt;)'''&lt;br /&gt;
&lt;br /&gt;
Fourth parameter i.e &amp;lt;request object&amp;gt; is an optional parameter. &lt;br /&gt;
&lt;br /&gt;
Whenever a request is made, the request object is injected into the controller and is available in the controller as &amp;quot;request&amp;quot;.&lt;br /&gt;
Similarly, &amp;lt;controller_name&amp;gt; is available in &amp;quot;controller_name&amp;quot; inside controller. For other trigger points, file name could be passed as a string.&lt;br /&gt;
&lt;br /&gt;
Since the request object holds the ''&amp;lt;origin_ip&amp;gt;'' and ''&amp;lt;request_id&amp;gt;'', it is used to capture and log both into the log message.&lt;br /&gt;
&lt;br /&gt;
===ExpertizaLogFormatter===&lt;br /&gt;
&lt;br /&gt;
It captures the message and determines if the message is an instance of LogMessage or not. Based on that, it creates a message by populating message placeholders as below:&lt;br /&gt;
&lt;br /&gt;
    if msg.is_a?(LogMessage)&lt;br /&gt;
      &amp;quot;TST=[#{ts}] SVT=[#{s}] PNM=[#{pg}] OIP=[#{msg.oip}] RID=[#{msg.req_id}] CTR=[#{msg.generator}] UID=[#{msg.unity_id}] MSG=[#{filter(msg.message)}]\n&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
      &amp;quot;TST=[#{ts}] SVT=[#{s}] PNM=[#{pg}] OIP=[] RID=[] CTR=[] UID=[] MSG=[#{filter(msg)}]\n&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
All the exceptions are preprocessed to remove newline characters so that it could fit in a single line as a message.&lt;br /&gt;
&lt;br /&gt;
All the messages that are not logged by ExpertizaLogger, there is a separate logger definition provided in config/environments/&amp;lt;environment&amp;gt;.rb as:&lt;br /&gt;
&lt;br /&gt;
  config.log_formatter = proc do |s, ts, pg, msg|&lt;br /&gt;
    if msg.is_a?(LogMessage)&lt;br /&gt;
      &amp;quot;TST=[#{ts}] SVT=[#{s}] PNM=[#{pg}] OIP=[#{msg.oip}] RID=[#{msg.req_id}] CTR=[#{msg.generator}] UID=[#{msg.unity_id}] MSG=[#{filter(msg.message)}]\n&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
      &amp;quot;TST=[#{ts}] SVT=[#{s}] PNM=[#{pg}] OIP=[] RID=[] CTR=[] UID=[] MSG=[#{filter(msg)}]\n&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===Environment config===&lt;br /&gt;
config.log_tags = [ :remote_ip, :uuid ]&lt;br /&gt;
&lt;br /&gt;
These config.log_tags entries make sure that &amp;lt;origin_ip&amp;gt; and &amp;lt;request_id&amp;gt; are prepended to messages. These are for messages which are not logged by ExpertizaLogger but by the Rails default logger.&lt;br /&gt;
These messages go in &amp;lt;environment&amp;gt;.log file.&lt;br /&gt;
&lt;br /&gt;
==Restrictions==&lt;br /&gt;
The request object is not available beyond the controllers. Hence, ''&amp;lt;origin_ip&amp;gt;'' and ''&amp;lt;request_id&amp;gt;'' remains uncaptured if messages are logged from somewhere other than controllers.&lt;br /&gt;
&lt;br /&gt;
==Visualization through ELK stack==&lt;br /&gt;
===Configuration===&lt;br /&gt;
&lt;br /&gt;
Filebeat (filebeat.yml)&lt;br /&gt;
&lt;br /&gt;
Changes:&lt;br /&gt;
&lt;br /&gt;
- type: log&lt;br /&gt;
&lt;br /&gt;
  # Change to true to enable this prospector configuration.&lt;br /&gt;
  enabled: true&lt;br /&gt;
&lt;br /&gt;
  # Paths that should be crawled and fetched. Glob based paths.&lt;br /&gt;
  paths:&lt;br /&gt;
    - &amp;lt;path to log files&amp;gt;*.log&lt;br /&gt;
&lt;br /&gt;
output.logstash:&lt;br /&gt;
  # The Logstash hosts&lt;br /&gt;
  hosts: [&amp;quot;&amp;lt;ip&amp;gt;:&amp;lt;5044:port of logstash&amp;gt;&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
Filebeat sends all log files to logstash.&lt;br /&gt;
&lt;br /&gt;
Logstash (expertiza-logstash.conf)&lt;br /&gt;
&lt;br /&gt;
   input { &lt;br /&gt;
        beats {&lt;br /&gt;
            port =&amp;gt; &amp;quot;5044&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
   }&lt;br /&gt;
   filter {&lt;br /&gt;
    grok {&lt;br /&gt;
    	match =&amp;gt; { &amp;quot;message&amp;quot; =&amp;gt; &amp;quot;TST=\[%{DATA:timestamp}\] SVT=\[%{DATA:sev}\] PNM=\[%{DATA:pgnm}\] OIP=\[%{DATA:originip}\] RID=\[%{DATA:requestid}\] CTR=\[%{DATA:generatedby}\] UID=\[% &lt;br /&gt;
   {DATA:unityid}\] MSG=\[%{GREEDYDATA:message}\]&amp;quot; }&lt;br /&gt;
    	overwrite =&amp;gt; [ &amp;quot;message&amp;quot;, &amp;quot;timestamp&amp;quot; ]&lt;br /&gt;
  	}&lt;br /&gt;
  	date {&lt;br /&gt;
    	match =&amp;gt; [&amp;quot;timestamp&amp;quot;, &amp;quot;ISO8601&amp;quot;]&lt;br /&gt;
  	}&lt;br /&gt;
  	&lt;br /&gt;
    }&lt;br /&gt;
    output {&lt;br /&gt;
      elasticsearch {&lt;br /&gt;
        hosts =&amp;gt; [ &amp;quot;localhost:9200&amp;quot; ]&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
Logstash reads each line from the log file and parses it based on the template provided in grok match above. It then sends each message entry into Elastic search.&lt;br /&gt;
&lt;br /&gt;
Kibana (config/kibana.yml)&lt;br /&gt;
&lt;br /&gt;
    elasticsearch.url: &amp;quot;http://localhost:9200&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Kibana picks each entry from Elastic search and provides into the web interface.&lt;br /&gt;
&lt;br /&gt;
===Setup===&lt;br /&gt;
ELK stack could be set up to visualize and analyze the messages from the log files.&lt;br /&gt;
&lt;br /&gt;
Once ELK is installed, below commands could be used to run each server:&lt;br /&gt;
&lt;br /&gt;
'''Clear Elastic search cache'''&lt;br /&gt;
&lt;br /&gt;
curl -X DELETE 'http://localhost:9200/_all'&lt;br /&gt;
&lt;br /&gt;
'''Filebeat'''&lt;br /&gt;
&lt;br /&gt;
sudo rm data/registry&lt;br /&gt;
&lt;br /&gt;
sudo ./filebeat -e -c filebeat.yml -d &amp;quot;publish&amp;quot;&lt;br /&gt;
&lt;br /&gt;
'''Logstash'''&lt;br /&gt;
&lt;br /&gt;
bin/logstash -f expertiza-logstash.conf --config.reload.automatic&lt;br /&gt;
&lt;br /&gt;
'''Kibana'''&lt;br /&gt;
&lt;br /&gt;
bin/kibana&lt;br /&gt;
&lt;br /&gt;
===Visualization===&lt;br /&gt;
&lt;br /&gt;
Success message in Kibana&lt;br /&gt;
&lt;br /&gt;
[[File:kibana_success_msg.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Exception in kibana&lt;br /&gt;
&lt;br /&gt;
[[File:kibana_exception.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Tracing error in kibana&lt;br /&gt;
&lt;br /&gt;
[[File:kibana_tracing_error.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Search records using request ID in kibana&lt;br /&gt;
&lt;br /&gt;
[[File:kibana_search_req_id.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Searching records using unity id in kibana&lt;br /&gt;
&lt;br /&gt;
[[File:kibana_search_using_unityid.png|frame|upright|center]]&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Kibana_tracing_error.png&amp;diff=117491</id>
		<title>File:Kibana tracing error.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Kibana_tracing_error.png&amp;diff=117491"/>
		<updated>2018-05-08T03:03:44Z</updated>

		<summary type="html">&lt;p&gt;Knielar: uploaded a new version of &amp;amp;quot;File:Kibana tracing error.png&amp;amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Kibana_success_msg.png&amp;diff=117490</id>
		<title>File:Kibana success msg.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Kibana_success_msg.png&amp;diff=117490"/>
		<updated>2018-05-08T03:03:31Z</updated>

		<summary type="html">&lt;p&gt;Knielar: uploaded a new version of &amp;amp;quot;File:Kibana success msg.png&amp;amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Kibana_search_using_unityid.png&amp;diff=117489</id>
		<title>File:Kibana search using unityid.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Kibana_search_using_unityid.png&amp;diff=117489"/>
		<updated>2018-05-08T03:03:10Z</updated>

		<summary type="html">&lt;p&gt;Knielar: uploaded a new version of &amp;amp;quot;File:Kibana search using unityid.png&amp;amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Kibana_search_req_id.png&amp;diff=117488</id>
		<title>File:Kibana search req id.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Kibana_search_req_id.png&amp;diff=117488"/>
		<updated>2018-05-08T03:02:43Z</updated>

		<summary type="html">&lt;p&gt;Knielar: uploaded a new version of &amp;amp;quot;File:Kibana search req id.png&amp;amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Kibana_exception.png&amp;diff=117487</id>
		<title>File:Kibana exception.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Kibana_exception.png&amp;diff=117487"/>
		<updated>2018-05-08T03:01:25Z</updated>

		<summary type="html">&lt;p&gt;Knielar: uploaded a new version of &amp;amp;quot;File:Kibana exception.png&amp;amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=Independent_Study_Spring_2018/Logging&amp;diff=117486</id>
		<title>Independent Study Spring 2018/Logging</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=Independent_Study_Spring_2018/Logging&amp;diff=117486"/>
		<updated>2018-05-08T02:38:02Z</updated>

		<summary type="html">&lt;p&gt;Knielar: /* Visualization */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Logging capability in Expertiza=&lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
Logging feature has been added to Expertiza through a custom logging module written uniquely to serve several purposes such as:&lt;br /&gt;
*Tracing application failure&lt;br /&gt;
*Analysing user request flow&lt;br /&gt;
*Managing different logging level&lt;br /&gt;
&lt;br /&gt;
==Message Format==&lt;br /&gt;
All the messages are logged in either of the below formats:&lt;br /&gt;
&lt;br /&gt;
'''TST=[2018-03-10 00:50:18 -0500] SVT=[&amp;lt;''log_level''&amp;gt;] PNM=[&amp;lt;''program_name''&amp;gt;] OIP=[&amp;lt;''origin_ip''&amp;gt;] RID=[&amp;lt;''request_id''&amp;gt;] CTR=[&amp;lt;''controller_name''&amp;gt;] UID=[&amp;lt;''user_id''&amp;gt;] MSG=[''Message'']'''&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
'''TST=[2018-03-10 00:50:18 -0500] SVT=[&amp;lt;''log_level''&amp;gt;] PNM=[&amp;lt;''program_name''&amp;gt;] OIP=[] RID=[] CTR=[&amp;lt;''controller_name''&amp;gt;] UID=[&amp;lt;''user_id''&amp;gt;] MSG=[[''origin_ip''] [''request_id''] ''Message'']'''&lt;br /&gt;
&lt;br /&gt;
Above variation is because when certain messages are logged, ExpertizaLogger is unaware of origin_ip and request_ip and thus it is appended to the message instead of their respective placeholders.&lt;br /&gt;
&lt;br /&gt;
===Meaning of each placeholder===&lt;br /&gt;
'''SVT''' - It denotes the severity level of the log. For eg, if the logging is done by calling logger.info, the severity level is &amp;quot;INFO&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
'''PNM''' - It's the program name and is same as provided by default Rails logger.&lt;br /&gt;
&lt;br /&gt;
'''OIP''' - It denotes the IP address of the system from where the request has been made. &lt;br /&gt;
&lt;br /&gt;
'''RID''' - It's the ID of the request. All subsequent calls made by the client till the actual response is returned will have same request ID. For eg, when a page is first requested, all smaller page template fetched, all method flow will have same request ID. This field can be used to understand how a certain request was served.&lt;br /&gt;
&lt;br /&gt;
'''CTR''' - It is the controller name from where the logging happened.&lt;br /&gt;
&lt;br /&gt;
'''UID''' - It is the unity id/user id of the user making requests. This field could also be used in identifying the cause of an error.&lt;br /&gt;
&lt;br /&gt;
'''Message''' - It is the actual message logged.&lt;br /&gt;
&lt;br /&gt;
==Log files==&lt;br /&gt;
For different log levels, log messages are written in different files named expertiza_&amp;lt;log_level&amp;gt;.log&lt;br /&gt;
&lt;br /&gt;
Currently, expertiza provides the capability of writing logs into 5 different custom log files.&lt;br /&gt;
&lt;br /&gt;
For eg, &lt;br /&gt;
&lt;br /&gt;
*expertiza_info.log&lt;br /&gt;
&lt;br /&gt;
*expertiza_warn.log&lt;br /&gt;
&lt;br /&gt;
*expertiza_error.log&lt;br /&gt;
&lt;br /&gt;
*expertiza_fatal.log&lt;br /&gt;
&lt;br /&gt;
*expertiza_debug.log&lt;br /&gt;
&lt;br /&gt;
Apart from above files, &amp;lt;environment&amp;gt;.log file is used for logging messages which could not be logged by ExpertizaLogger, like, page load messages or certain load time exceptions.&lt;br /&gt;
&lt;br /&gt;
Since Rails logger provides writing into a specific log file, to restrict least file switch, ExpertizaLogger holds different log level loggers in separate instance variables. A new logger instance is created and assigned whenever Rails removes the link to manage memory consumption.&lt;br /&gt;
&lt;br /&gt;
==Components==&lt;br /&gt;
===ExpertizaLogger===&lt;br /&gt;
&lt;br /&gt;
This class provides the logger needed for logging messages for different log levels.&lt;br /&gt;
It provides 5 different static methods namely '''info''', '''warn''', '''error''', '''fatal''' and '''debug''' which could be called as follows:&lt;br /&gt;
&lt;br /&gt;
'''ExpertizaLogger.info ''message'''''&lt;br /&gt;
&lt;br /&gt;
where ''message'' could be an instance of '''LogMessage''' or a string.&lt;br /&gt;
&lt;br /&gt;
===Custom LogMessage===&lt;br /&gt;
&lt;br /&gt;
A LogMessage instance could be created as follows:&lt;br /&gt;
&lt;br /&gt;
'''LogMessage.new(&amp;lt;controller_name&amp;gt;, &amp;lt;user_id&amp;gt;, &amp;lt;message&amp;gt;, &amp;lt;request object&amp;gt;)'''&lt;br /&gt;
&lt;br /&gt;
Fourth parameter i.e &amp;lt;request object&amp;gt; is an optional parameter. &lt;br /&gt;
&lt;br /&gt;
Whenever a request is made, the request object is injected into the controller and is available in the controller as &amp;quot;request&amp;quot;.&lt;br /&gt;
Similarly, &amp;lt;controller_name&amp;gt; is available in &amp;quot;controller_name&amp;quot; inside controller. For other trigger points, file name could be passed as a string.&lt;br /&gt;
&lt;br /&gt;
Since the request object holds the ''&amp;lt;origin_ip&amp;gt;'' and ''&amp;lt;request_id&amp;gt;'', it is used to capture and log both into the log message.&lt;br /&gt;
&lt;br /&gt;
===ExpertizaLogFormatter===&lt;br /&gt;
&lt;br /&gt;
It captures the message and determines if the message is an instance of LogMessage or not. Based on that, it creates a message by populating message placeholders as below:&lt;br /&gt;
&lt;br /&gt;
    if msg.is_a?(LogMessage)&lt;br /&gt;
      &amp;quot;TST=[#{ts}] SVT=[#{s}] PNM=[#{pg}] OIP=[#{msg.oip}] RID=[#{msg.req_id}] CTR=[#{msg.generator}] UID=[#{msg.unity_id}] MSG=[#{filter(msg.message)}]\n&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
      &amp;quot;TST=[#{ts}] SVT=[#{s}] PNM=[#{pg}] OIP=[] RID=[] CTR=[] UID=[] MSG=[#{filter(msg)}]\n&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
All the exceptions are preprocessed to remove newline characters so that it could fit in a single line as a message.&lt;br /&gt;
&lt;br /&gt;
All the messages that are not logged by ExpertizaLogger, there is a separate logger definition provided in config/environments/&amp;lt;environment&amp;gt;.rb as:&lt;br /&gt;
&lt;br /&gt;
  config.log_formatter = proc do |s, ts, pg, msg|&lt;br /&gt;
    if msg.is_a?(LogMessage)&lt;br /&gt;
      &amp;quot;TST=[#{ts}] SVT=[#{s}] PNM=[#{pg}] OIP=[#{msg.oip}] RID=[#{msg.req_id}] CTR=[#{msg.generator}] UID=[#{msg.unity_id}] MSG=[#{filter(msg.message)}]\n&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
      &amp;quot;TST=[#{ts}] SVT=[#{s}] PNM=[#{pg}] OIP=[] RID=[] CTR=[] UID=[] MSG=[#{filter(msg)}]\n&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===Environment config===&lt;br /&gt;
config.log_tags = [ :remote_ip, :uuid ]&lt;br /&gt;
&lt;br /&gt;
These config.log_tags entries make sure that &amp;lt;origin_ip&amp;gt; and &amp;lt;request_id&amp;gt; are prepended to messages. These are for messages which are not logged by ExpertizaLogger but by the Rails default logger.&lt;br /&gt;
These messages go in &amp;lt;environment&amp;gt;.log file.&lt;br /&gt;
&lt;br /&gt;
==Restrictions==&lt;br /&gt;
The request object is not available beyond the controllers. Hence, ''&amp;lt;origin_ip&amp;gt;'' and ''&amp;lt;request_id&amp;gt;'' remains uncaptured if messages are logged from somewhere other than controllers.&lt;br /&gt;
&lt;br /&gt;
==Visualization through ELK stack==&lt;br /&gt;
===Configuration===&lt;br /&gt;
&lt;br /&gt;
Filebeat (filebeat.yml)&lt;br /&gt;
&lt;br /&gt;
Changes:&lt;br /&gt;
&lt;br /&gt;
- type: log&lt;br /&gt;
&lt;br /&gt;
  # Change to true to enable this prospector configuration.&lt;br /&gt;
  enabled: true&lt;br /&gt;
&lt;br /&gt;
  # Paths that should be crawled and fetched. Glob based paths.&lt;br /&gt;
  paths:&lt;br /&gt;
    - &amp;lt;path to log files&amp;gt;*.log&lt;br /&gt;
&lt;br /&gt;
output.logstash:&lt;br /&gt;
  # The Logstash hosts&lt;br /&gt;
  hosts: [&amp;quot;&amp;lt;ip&amp;gt;:&amp;lt;5044:port of logstash&amp;gt;&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
Filebeat sends all log files to logstash.&lt;br /&gt;
&lt;br /&gt;
Logstash (expertiza-logstash.conf)&lt;br /&gt;
&lt;br /&gt;
   input { &lt;br /&gt;
        beats {&lt;br /&gt;
            port =&amp;gt; &amp;quot;5044&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
   }&lt;br /&gt;
   filter {&lt;br /&gt;
    grok {&lt;br /&gt;
    	match =&amp;gt; { &amp;quot;message&amp;quot; =&amp;gt; &amp;quot;TST=\[%{DATA:timestamp}\] SVT=\[%{DATA:sev}\] PNM=\[%{DATA:pgnm}\] OIP=\[%{DATA:originip}\] RID=\[%{DATA:requestid}\] CTR=\[%{DATA:generatedby}\] UID=\[% &lt;br /&gt;
   {DATA:unityid}\] MSG=\[%{GREEDYDATA:message}\]&amp;quot; }&lt;br /&gt;
    	overwrite =&amp;gt; [ &amp;quot;message&amp;quot;, &amp;quot;timestamp&amp;quot; ]&lt;br /&gt;
  	}&lt;br /&gt;
  	date {&lt;br /&gt;
    	match =&amp;gt; [&amp;quot;timestamp&amp;quot;, &amp;quot;ISO8601&amp;quot;]&lt;br /&gt;
  	}&lt;br /&gt;
  	&lt;br /&gt;
    }&lt;br /&gt;
    output {&lt;br /&gt;
      elasticsearch {&lt;br /&gt;
        hosts =&amp;gt; [ &amp;quot;localhost:9200&amp;quot; ]&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
Logstash reads each line from the log file and parses it based on the template provided in grok match above. It then sends each message entry into Elastic search.&lt;br /&gt;
&lt;br /&gt;
Kibana (config/kibana.yml)&lt;br /&gt;
&lt;br /&gt;
    elasticsearch.url: &amp;quot;http://localhost:9200&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Kibana picks each entry from Elastic search and provides into the web interface.&lt;br /&gt;
&lt;br /&gt;
===Setup===&lt;br /&gt;
ELK stack could be set up to visualize and analyze the messages from the log files.&lt;br /&gt;
&lt;br /&gt;
Once ELK is installed, below commands could be used to run each server:&lt;br /&gt;
&lt;br /&gt;
'''Clear Elastic search cache'''&lt;br /&gt;
&lt;br /&gt;
curl -X DELETE 'http://localhost:9200/_all'&lt;br /&gt;
&lt;br /&gt;
'''Filebeat'''&lt;br /&gt;
&lt;br /&gt;
sudo rm data/registry&lt;br /&gt;
&lt;br /&gt;
sudo ./filebeat -e -c filebeat.yml -d &amp;quot;publish&amp;quot;&lt;br /&gt;
&lt;br /&gt;
'''Logstash'''&lt;br /&gt;
&lt;br /&gt;
bin/logstash -f expertiza-logstash.conf --config.reload.automatic&lt;br /&gt;
&lt;br /&gt;
'''Kibana'''&lt;br /&gt;
&lt;br /&gt;
bin/kibana&lt;br /&gt;
&lt;br /&gt;
===Visualization===&lt;br /&gt;
&lt;br /&gt;
Success message in Kibana&lt;br /&gt;
&lt;br /&gt;
[[File:kibana_success_msg.png|200px|thumb|left|alt text]]&lt;br /&gt;
&lt;br /&gt;
Exception in kibana&lt;br /&gt;
&lt;br /&gt;
[[File:kibana_exception.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Tracing error in kibana&lt;br /&gt;
&lt;br /&gt;
[[File:kibana_tracing_error.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Search records using request ID in kibana&lt;br /&gt;
&lt;br /&gt;
[[File:kibana_search_req_id.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Searching records using unity id in kibana&lt;br /&gt;
&lt;br /&gt;
[[File:kibana_search_using_unityid.png|frame|upright|center]]&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Kibana_tracing_error.png&amp;diff=117485</id>
		<title>File:Kibana tracing error.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Kibana_tracing_error.png&amp;diff=117485"/>
		<updated>2018-05-08T02:36:39Z</updated>

		<summary type="html">&lt;p&gt;Knielar: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Kibana_search_using_unityid.png&amp;diff=117484</id>
		<title>File:Kibana search using unityid.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Kibana_search_using_unityid.png&amp;diff=117484"/>
		<updated>2018-05-08T02:36:15Z</updated>

		<summary type="html">&lt;p&gt;Knielar: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Kibana_search_req_id.png&amp;diff=117483</id>
		<title>File:Kibana search req id.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Kibana_search_req_id.png&amp;diff=117483"/>
		<updated>2018-05-08T02:35:49Z</updated>

		<summary type="html">&lt;p&gt;Knielar: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Kibana_exception.png&amp;diff=117482</id>
		<title>File:Kibana exception.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Kibana_exception.png&amp;diff=117482"/>
		<updated>2018-05-08T02:35:15Z</updated>

		<summary type="html">&lt;p&gt;Knielar: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=Independent_Study_Spring_2018/Logging&amp;diff=117481</id>
		<title>Independent Study Spring 2018/Logging</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=Independent_Study_Spring_2018/Logging&amp;diff=117481"/>
		<updated>2018-05-08T02:34:25Z</updated>

		<summary type="html">&lt;p&gt;Knielar: /* Visualization through ELK stack */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Logging capability in Expertiza=&lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
Logging feature has been added to Expertiza through a custom logging module written uniquely to serve several purposes such as:&lt;br /&gt;
*Tracing application failure&lt;br /&gt;
*Analysing user request flow&lt;br /&gt;
*Managing different logging level&lt;br /&gt;
&lt;br /&gt;
==Message Format==&lt;br /&gt;
All the messages are logged in either of the below formats:&lt;br /&gt;
&lt;br /&gt;
'''TST=[2018-03-10 00:50:18 -0500] SVT=[&amp;lt;''log_level''&amp;gt;] PNM=[&amp;lt;''program_name''&amp;gt;] OIP=[&amp;lt;''origin_ip''&amp;gt;] RID=[&amp;lt;''request_id''&amp;gt;] CTR=[&amp;lt;''controller_name''&amp;gt;] UID=[&amp;lt;''user_id''&amp;gt;] MSG=[''Message'']'''&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
'''TST=[2018-03-10 00:50:18 -0500] SVT=[&amp;lt;''log_level''&amp;gt;] PNM=[&amp;lt;''program_name''&amp;gt;] OIP=[] RID=[] CTR=[&amp;lt;''controller_name''&amp;gt;] UID=[&amp;lt;''user_id''&amp;gt;] MSG=[[''origin_ip''] [''request_id''] ''Message'']'''&lt;br /&gt;
&lt;br /&gt;
Above variation is because when certain messages are logged, ExpertizaLogger is unaware of origin_ip and request_ip and thus it is appended to the message instead of their respective placeholders.&lt;br /&gt;
&lt;br /&gt;
===Meaning of each placeholder===&lt;br /&gt;
'''SVT''' - It denotes the severity level of the log. For eg, if the logging is done by calling logger.info, the severity level is &amp;quot;INFO&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
'''PNM''' - It's the program name and is same as provided by default Rails logger.&lt;br /&gt;
&lt;br /&gt;
'''OIP''' - It denotes the IP address of the system from where the request has been made. &lt;br /&gt;
&lt;br /&gt;
'''RID''' - It's the ID of the request. All subsequent calls made by the client till the actual response is returned will have same request ID. For eg, when a page is first requested, all smaller page template fetched, all method flow will have same request ID. This field can be used to understand how a certain request was served.&lt;br /&gt;
&lt;br /&gt;
'''CTR''' - It is the controller name from where the logging happened.&lt;br /&gt;
&lt;br /&gt;
'''UID''' - It is the unity id/user id of the user making requests. This field could also be used in identifying the cause of an error.&lt;br /&gt;
&lt;br /&gt;
'''Message''' - It is the actual message logged.&lt;br /&gt;
&lt;br /&gt;
==Log files==&lt;br /&gt;
For different log levels, log messages are written in different files named expertiza_&amp;lt;log_level&amp;gt;.log&lt;br /&gt;
&lt;br /&gt;
Currently, expertiza provides the capability of writing logs into 5 different custom log files.&lt;br /&gt;
&lt;br /&gt;
For eg, &lt;br /&gt;
&lt;br /&gt;
*expertiza_info.log&lt;br /&gt;
&lt;br /&gt;
*expertiza_warn.log&lt;br /&gt;
&lt;br /&gt;
*expertiza_error.log&lt;br /&gt;
&lt;br /&gt;
*expertiza_fatal.log&lt;br /&gt;
&lt;br /&gt;
*expertiza_debug.log&lt;br /&gt;
&lt;br /&gt;
Apart from above files, &amp;lt;environment&amp;gt;.log file is used for logging messages which could not be logged by ExpertizaLogger, like, page load messages or certain load time exceptions.&lt;br /&gt;
&lt;br /&gt;
Since Rails logger provides writing into a specific log file, to restrict least file switch, ExpertizaLogger holds different log level loggers in separate instance variables. A new logger instance is created and assigned whenever Rails removes the link to manage memory consumption.&lt;br /&gt;
&lt;br /&gt;
==Components==&lt;br /&gt;
===ExpertizaLogger===&lt;br /&gt;
&lt;br /&gt;
This class provides the logger needed for logging messages for different log levels.&lt;br /&gt;
It provides 5 different static methods namely '''info''', '''warn''', '''error''', '''fatal''' and '''debug''' which could be called as follows:&lt;br /&gt;
&lt;br /&gt;
'''ExpertizaLogger.info ''message'''''&lt;br /&gt;
&lt;br /&gt;
where ''message'' could be an instance of '''LogMessage''' or a string.&lt;br /&gt;
&lt;br /&gt;
===Custom LogMessage===&lt;br /&gt;
&lt;br /&gt;
A LogMessage instance could be created as follows:&lt;br /&gt;
&lt;br /&gt;
'''LogMessage.new(&amp;lt;controller_name&amp;gt;, &amp;lt;user_id&amp;gt;, &amp;lt;message&amp;gt;, &amp;lt;request object&amp;gt;)'''&lt;br /&gt;
&lt;br /&gt;
Fourth parameter i.e &amp;lt;request object&amp;gt; is an optional parameter. &lt;br /&gt;
&lt;br /&gt;
Whenever a request is made, the request object is injected into the controller and is available in the controller as &amp;quot;request&amp;quot;.&lt;br /&gt;
Similarly, &amp;lt;controller_name&amp;gt; is available in &amp;quot;controller_name&amp;quot; inside controller. For other trigger points, file name could be passed as a string.&lt;br /&gt;
&lt;br /&gt;
Since the request object holds the ''&amp;lt;origin_ip&amp;gt;'' and ''&amp;lt;request_id&amp;gt;'', it is used to capture and log both into the log message.&lt;br /&gt;
&lt;br /&gt;
===ExpertizaLogFormatter===&lt;br /&gt;
&lt;br /&gt;
It captures the message and determines if the message is an instance of LogMessage or not. Based on that, it creates a message by populating message placeholders as below:&lt;br /&gt;
&lt;br /&gt;
    if msg.is_a?(LogMessage)&lt;br /&gt;
      &amp;quot;TST=[#{ts}] SVT=[#{s}] PNM=[#{pg}] OIP=[#{msg.oip}] RID=[#{msg.req_id}] CTR=[#{msg.generator}] UID=[#{msg.unity_id}] MSG=[#{filter(msg.message)}]\n&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
      &amp;quot;TST=[#{ts}] SVT=[#{s}] PNM=[#{pg}] OIP=[] RID=[] CTR=[] UID=[] MSG=[#{filter(msg)}]\n&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
All the exceptions are preprocessed to remove newline characters so that it could fit in a single line as a message.&lt;br /&gt;
&lt;br /&gt;
All the messages that are not logged by ExpertizaLogger, there is a separate logger definition provided in config/environments/&amp;lt;environment&amp;gt;.rb as:&lt;br /&gt;
&lt;br /&gt;
  config.log_formatter = proc do |s, ts, pg, msg|&lt;br /&gt;
    if msg.is_a?(LogMessage)&lt;br /&gt;
      &amp;quot;TST=[#{ts}] SVT=[#{s}] PNM=[#{pg}] OIP=[#{msg.oip}] RID=[#{msg.req_id}] CTR=[#{msg.generator}] UID=[#{msg.unity_id}] MSG=[#{filter(msg.message)}]\n&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
      &amp;quot;TST=[#{ts}] SVT=[#{s}] PNM=[#{pg}] OIP=[] RID=[] CTR=[] UID=[] MSG=[#{filter(msg)}]\n&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===Environment config===&lt;br /&gt;
config.log_tags = [ :remote_ip, :uuid ]&lt;br /&gt;
&lt;br /&gt;
These config.log_tags entries make sure that &amp;lt;origin_ip&amp;gt; and &amp;lt;request_id&amp;gt; are prepended to messages. These are for messages which are not logged by ExpertizaLogger but by the Rails default logger.&lt;br /&gt;
These messages go in &amp;lt;environment&amp;gt;.log file.&lt;br /&gt;
&lt;br /&gt;
==Restrictions==&lt;br /&gt;
The request object is not available beyond the controllers. Hence, ''&amp;lt;origin_ip&amp;gt;'' and ''&amp;lt;request_id&amp;gt;'' remains uncaptured if messages are logged from somewhere other than controllers.&lt;br /&gt;
&lt;br /&gt;
==Visualization through ELK stack==&lt;br /&gt;
===Configuration===&lt;br /&gt;
&lt;br /&gt;
Filebeat (filebeat.yml)&lt;br /&gt;
&lt;br /&gt;
Changes:&lt;br /&gt;
&lt;br /&gt;
- type: log&lt;br /&gt;
&lt;br /&gt;
  # Change to true to enable this prospector configuration.&lt;br /&gt;
  enabled: true&lt;br /&gt;
&lt;br /&gt;
  # Paths that should be crawled and fetched. Glob based paths.&lt;br /&gt;
  paths:&lt;br /&gt;
    - &amp;lt;path to log files&amp;gt;*.log&lt;br /&gt;
&lt;br /&gt;
output.logstash:&lt;br /&gt;
  # The Logstash hosts&lt;br /&gt;
  hosts: [&amp;quot;&amp;lt;ip&amp;gt;:&amp;lt;5044:port of logstash&amp;gt;&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
Filebeat sends all log files to logstash.&lt;br /&gt;
&lt;br /&gt;
Logstash (expertiza-logstash.conf)&lt;br /&gt;
&lt;br /&gt;
   input { &lt;br /&gt;
        beats {&lt;br /&gt;
            port =&amp;gt; &amp;quot;5044&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
   }&lt;br /&gt;
   filter {&lt;br /&gt;
    grok {&lt;br /&gt;
    	match =&amp;gt; { &amp;quot;message&amp;quot; =&amp;gt; &amp;quot;TST=\[%{DATA:timestamp}\] SVT=\[%{DATA:sev}\] PNM=\[%{DATA:pgnm}\] OIP=\[%{DATA:originip}\] RID=\[%{DATA:requestid}\] CTR=\[%{DATA:generatedby}\] UID=\[% &lt;br /&gt;
   {DATA:unityid}\] MSG=\[%{GREEDYDATA:message}\]&amp;quot; }&lt;br /&gt;
    	overwrite =&amp;gt; [ &amp;quot;message&amp;quot;, &amp;quot;timestamp&amp;quot; ]&lt;br /&gt;
  	}&lt;br /&gt;
  	date {&lt;br /&gt;
    	match =&amp;gt; [&amp;quot;timestamp&amp;quot;, &amp;quot;ISO8601&amp;quot;]&lt;br /&gt;
  	}&lt;br /&gt;
  	&lt;br /&gt;
    }&lt;br /&gt;
    output {&lt;br /&gt;
      elasticsearch {&lt;br /&gt;
        hosts =&amp;gt; [ &amp;quot;localhost:9200&amp;quot; ]&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
Logstash reads each line from the log file and parses it based on the template provided in grok match above. It then sends each message entry into Elastic search.&lt;br /&gt;
&lt;br /&gt;
Kibana (config/kibana.yml)&lt;br /&gt;
&lt;br /&gt;
    elasticsearch.url: &amp;quot;http://localhost:9200&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Kibana picks each entry from Elastic search and provides into the web interface.&lt;br /&gt;
&lt;br /&gt;
===Setup===&lt;br /&gt;
ELK stack could be set up to visualize and analyze the messages from the log files.&lt;br /&gt;
&lt;br /&gt;
Once ELK is installed, below commands could be used to run each server:&lt;br /&gt;
&lt;br /&gt;
'''Clear Elastic search cache'''&lt;br /&gt;
&lt;br /&gt;
curl -X DELETE 'http://localhost:9200/_all'&lt;br /&gt;
&lt;br /&gt;
'''Filebeat'''&lt;br /&gt;
&lt;br /&gt;
sudo rm data/registry&lt;br /&gt;
&lt;br /&gt;
sudo ./filebeat -e -c filebeat.yml -d &amp;quot;publish&amp;quot;&lt;br /&gt;
&lt;br /&gt;
'''Logstash'''&lt;br /&gt;
&lt;br /&gt;
bin/logstash -f expertiza-logstash.conf --config.reload.automatic&lt;br /&gt;
&lt;br /&gt;
'''Kibana'''&lt;br /&gt;
&lt;br /&gt;
bin/kibana&lt;br /&gt;
&lt;br /&gt;
===Visualization===&lt;br /&gt;
&lt;br /&gt;
Success message in Kibana&lt;br /&gt;
&lt;br /&gt;
[[File:kibana_success_msg.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Exception in kibana&lt;br /&gt;
&lt;br /&gt;
[[File:kibana_exception.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Tracing error in kibana&lt;br /&gt;
&lt;br /&gt;
[[File:kibana_tracing_error.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Search records using request ID in kibana&lt;br /&gt;
&lt;br /&gt;
[[File:kibana_search_req_id.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Searching records using unity id in kibana&lt;br /&gt;
&lt;br /&gt;
[[File:kibana_search_using_unityid.png|frame|upright|center]]&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=MainPage&amp;diff=117480</id>
		<title>MainPage</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=MainPage&amp;diff=117480"/>
		<updated>2018-05-08T02:30:18Z</updated>

		<summary type="html">&lt;p&gt;Knielar: /* Expertiza */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
* [[Expertiza documentation]]&lt;br /&gt;
&lt;br /&gt;
* [[CSC/ECE 517 Summer 2008]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2010]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2011]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2012]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2013]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2014]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2015]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2016]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2014]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2015]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2016]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2017]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2017]]&lt;br /&gt;
* [[CSC/Independent Study Spring 2018]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project Juniper:Bookmark Enhancements]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1803: Introducing a Student View for Instructors]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1804: OSS project Yellow: Topic management]]&lt;br /&gt;
* [[CSC/ECE_517_Spring_2018- Project E1805: Convolutional data extraction from Github]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1808: Refactor review_mapping_controller.rb]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1810: Show sample submissions and reviews]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018/E1814 Write unit tests for collusion cycle.rb]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project M1802: 2D Canvas Rendering]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project M1802: 2D Canvas Rendering (Part 2)]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018 - E1800: Add past-due assignments to task list]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1812: on the fly calc.rb]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project M1803: Implement a web page fuzzer to find rendering mismatches ]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project M1803: Implement a web page fuzzer to find rendering mismatches (Part 2)]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018/E1813 Test Menu Items Model]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1816: Visualization for Instructors]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1817: Adding Student-generated Questions to Rubric]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1818:  Role-based reviewing]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1822: Extend the functionality of badging]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1815: Improvements to review grader]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1824: Let course staff as well as students do reviews]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1819: Improve self review, link self and peer review to derive grades]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1820 Review-Comment Tone Analysis Report]]&lt;br /&gt;
* [[CSC 456 Spring 2011|CSC 456 Spring 2012]]&lt;br /&gt;
* [[ECE 633]]&lt;br /&gt;
* [[KCU]]&lt;br /&gt;
* [[Progress reports]]&lt;br /&gt;
&lt;br /&gt;
==Application Behavior==&lt;br /&gt;
* [[Grading]]&lt;br /&gt;
&lt;br /&gt;
==Metaprogramming==&lt;br /&gt;
* [[CSC/ECE_517_Spring_2013/ch1b_1k_hf|Lecture on Metaprogramming]]&lt;br /&gt;
&lt;br /&gt;
==Development==&lt;br /&gt;
&lt;br /&gt;
''Expertiza now has a Java dependency, so the machine you are using to develop Expertiza on should have the JVM installed.''&lt;br /&gt;
&lt;br /&gt;
* [[Setting Up a Development Machine]]&lt;br /&gt;
* [[Creating a Linux Development Environment for Expertiza - Installation Guide]]&lt;br /&gt;
* [[Using git and github for projects]]&lt;br /&gt;
* [[Using heroku to deploy your projects]]&lt;br /&gt;
* [[How to Begin a Project from the Current Expertiza Repository]]&lt;br /&gt;
* [[Git]]&lt;br /&gt;
* [[How to Change a User's Password on a Development Machine]]&lt;br /&gt;
* [[Debugging Rails]]&lt;br /&gt;
* [http://rajanalwan.com/ui_guidelines/ Design Template]&lt;br /&gt;
&lt;br /&gt;
==Production==&lt;br /&gt;
* [[Deploying to Production]]&lt;br /&gt;
* [[Downloading Production Data]]&lt;br /&gt;
* [[Accessing the Production Server]]&lt;br /&gt;
&lt;br /&gt;
==Testing==&lt;br /&gt;
* [[Using Cucumber with Expertiza]]&lt;br /&gt;
* [[Rails Testing Overview]]&lt;br /&gt;
* [[Expertiza Continuous Integration]]&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
* [[Object-Oriented Design and Programming]]&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=MainPage&amp;diff=117479</id>
		<title>MainPage</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=MainPage&amp;diff=117479"/>
		<updated>2018-05-08T02:28:39Z</updated>

		<summary type="html">&lt;p&gt;Knielar: /* Expertiza */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
* [[Expertiza documentation]]&lt;br /&gt;
&lt;br /&gt;
* [[CSC/ECE 517 Summer 2008]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2010]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2011]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2012]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2013]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2014]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2015]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2016]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2014]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2015]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2016]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2017]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2017]]&lt;br /&gt;
* [[Independent Study Spring 2018]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project Juniper:Bookmark Enhancements]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1803: Introducing a Student View for Instructors]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1804: OSS project Yellow: Topic management]]&lt;br /&gt;
* [[CSC/ECE_517_Spring_2018- Project E1805: Convolutional data extraction from Github]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1808: Refactor review_mapping_controller.rb]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1810: Show sample submissions and reviews]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018/E1814 Write unit tests for collusion cycle.rb]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project M1802: 2D Canvas Rendering]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project M1802: 2D Canvas Rendering (Part 2)]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018 - E1800: Add past-due assignments to task list]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1812: on the fly calc.rb]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project M1803: Implement a web page fuzzer to find rendering mismatches ]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project M1803: Implement a web page fuzzer to find rendering mismatches (Part 2)]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018/E1813 Test Menu Items Model]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1816: Visualization for Instructors]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1817: Adding Student-generated Questions to Rubric]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1818:  Role-based reviewing]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1822: Extend the functionality of badging]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1815: Improvements to review grader]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1824: Let course staff as well as students do reviews]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1819: Improve self review, link self and peer review to derive grades]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1820 Review-Comment Tone Analysis Report]]&lt;br /&gt;
* [[CSC 456 Spring 2011|CSC 456 Spring 2012]]&lt;br /&gt;
* [[ECE 633]]&lt;br /&gt;
* [[KCU]]&lt;br /&gt;
* [[Progress reports]]&lt;br /&gt;
&lt;br /&gt;
==Application Behavior==&lt;br /&gt;
* [[Grading]]&lt;br /&gt;
&lt;br /&gt;
==Metaprogramming==&lt;br /&gt;
* [[CSC/ECE_517_Spring_2013/ch1b_1k_hf|Lecture on Metaprogramming]]&lt;br /&gt;
&lt;br /&gt;
==Development==&lt;br /&gt;
&lt;br /&gt;
''Expertiza now has a Java dependency, so the machine you are using to develop Expertiza on should have the JVM installed.''&lt;br /&gt;
&lt;br /&gt;
* [[Setting Up a Development Machine]]&lt;br /&gt;
* [[Creating a Linux Development Environment for Expertiza - Installation Guide]]&lt;br /&gt;
* [[Using git and github for projects]]&lt;br /&gt;
* [[Using heroku to deploy your projects]]&lt;br /&gt;
* [[How to Begin a Project from the Current Expertiza Repository]]&lt;br /&gt;
* [[Git]]&lt;br /&gt;
* [[How to Change a User's Password on a Development Machine]]&lt;br /&gt;
* [[Debugging Rails]]&lt;br /&gt;
* [http://rajanalwan.com/ui_guidelines/ Design Template]&lt;br /&gt;
&lt;br /&gt;
==Production==&lt;br /&gt;
* [[Deploying to Production]]&lt;br /&gt;
* [[Downloading Production Data]]&lt;br /&gt;
* [[Accessing the Production Server]]&lt;br /&gt;
&lt;br /&gt;
==Testing==&lt;br /&gt;
* [[Using Cucumber with Expertiza]]&lt;br /&gt;
* [[Rails Testing Overview]]&lt;br /&gt;
* [[Expertiza Continuous Integration]]&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
* [[Object-Oriented Design and Programming]]&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=MainPage&amp;diff=117478</id>
		<title>MainPage</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=MainPage&amp;diff=117478"/>
		<updated>2018-05-08T02:27:47Z</updated>

		<summary type="html">&lt;p&gt;Knielar: /* Expertiza */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
* [[Expertiza documentation]]&lt;br /&gt;
&lt;br /&gt;
* [[CSC/ECE 517 Summer 2008]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2010]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2011]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2012]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2013]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2014]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2015]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2016]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2014]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2015]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2016]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2017]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2017]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project Juniper:Bookmark Enhancements]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1803: Introducing a Student View for Instructors]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1804: OSS project Yellow: Topic management]]&lt;br /&gt;
* [[CSC/ECE_517_Spring_2018- Project E1805: Convolutional data extraction from Github]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1808: Refactor review_mapping_controller.rb]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1810: Show sample submissions and reviews]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018/E1814 Write unit tests for collusion cycle.rb]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project M1802: 2D Canvas Rendering]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project M1802: 2D Canvas Rendering (Part 2)]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018 - E1800: Add past-due assignments to task list]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1812: on the fly calc.rb]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project M1803: Implement a web page fuzzer to find rendering mismatches ]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project M1803: Implement a web page fuzzer to find rendering mismatches (Part 2)]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018/E1813 Test Menu Items Model]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1816: Visualization for Instructors]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1817: Adding Student-generated Questions to Rubric]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1818:  Role-based reviewing]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1822: Extend the functionality of badging]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1815: Improvements to review grader]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1824: Let course staff as well as students do reviews]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1819: Improve self review, link self and peer review to derive grades]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1820 Review-Comment Tone Analysis Report]]&lt;br /&gt;
* [[CSC 456 Spring 2011|CSC 456 Spring 2012]]&lt;br /&gt;
* [[ECE 633]]&lt;br /&gt;
* [[KCU]]&lt;br /&gt;
* [[Progress reports]]&lt;br /&gt;
&lt;br /&gt;
==Application Behavior==&lt;br /&gt;
* [[Grading]]&lt;br /&gt;
&lt;br /&gt;
==Metaprogramming==&lt;br /&gt;
* [[CSC/ECE_517_Spring_2013/ch1b_1k_hf|Lecture on Metaprogramming]]&lt;br /&gt;
&lt;br /&gt;
==Development==&lt;br /&gt;
&lt;br /&gt;
''Expertiza now has a Java dependency, so the machine you are using to develop Expertiza on should have the JVM installed.''&lt;br /&gt;
&lt;br /&gt;
* [[Setting Up a Development Machine]]&lt;br /&gt;
* [[Creating a Linux Development Environment for Expertiza - Installation Guide]]&lt;br /&gt;
* [[Using git and github for projects]]&lt;br /&gt;
* [[Using heroku to deploy your projects]]&lt;br /&gt;
* [[How to Begin a Project from the Current Expertiza Repository]]&lt;br /&gt;
* [[Git]]&lt;br /&gt;
* [[How to Change a User's Password on a Development Machine]]&lt;br /&gt;
* [[Debugging Rails]]&lt;br /&gt;
* [http://rajanalwan.com/ui_guidelines/ Design Template]&lt;br /&gt;
&lt;br /&gt;
==Production==&lt;br /&gt;
* [[Deploying to Production]]&lt;br /&gt;
* [[Downloading Production Data]]&lt;br /&gt;
* [[Accessing the Production Server]]&lt;br /&gt;
&lt;br /&gt;
==Testing==&lt;br /&gt;
* [[Using Cucumber with Expertiza]]&lt;br /&gt;
* [[Rails Testing Overview]]&lt;br /&gt;
* [[Expertiza Continuous Integration]]&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
* [[Object-Oriented Design and Programming]]&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Kibana_success_msg.png&amp;diff=117477</id>
		<title>File:Kibana success msg.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Kibana_success_msg.png&amp;diff=117477"/>
		<updated>2018-05-08T02:26:44Z</updated>

		<summary type="html">&lt;p&gt;Knielar: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=Independent_Study_Spring_2018/Logging&amp;diff=117475</id>
		<title>Independent Study Spring 2018/Logging</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=Independent_Study_Spring_2018/Logging&amp;diff=117475"/>
		<updated>2018-05-08T02:18:23Z</updated>

		<summary type="html">&lt;p&gt;Knielar: Created page with &amp;quot;=Logging capability in Expertiza=  ==Purpose== Logging feature has been added to Expertiza through a custom logging module written uniquely to serve several purposes such as: *Tr...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Logging capability in Expertiza=&lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
Logging feature has been added to Expertiza through a custom logging module written uniquely to serve several purposes such as:&lt;br /&gt;
*Tracing application failure&lt;br /&gt;
*Analysing user request flow&lt;br /&gt;
*Managing different logging level&lt;br /&gt;
&lt;br /&gt;
==Message Format==&lt;br /&gt;
All the messages are logged in either of the below formats:&lt;br /&gt;
&lt;br /&gt;
'''TST=[2018-03-10 00:50:18 -0500] SVT=[&amp;lt;''log_level''&amp;gt;] PNM=[&amp;lt;''program_name''&amp;gt;] OIP=[&amp;lt;''origin_ip''&amp;gt;] RID=[&amp;lt;''request_id''&amp;gt;] CTR=[&amp;lt;''controller_name''&amp;gt;] UID=[&amp;lt;''user_id''&amp;gt;] MSG=[''Message'']'''&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
'''TST=[2018-03-10 00:50:18 -0500] SVT=[&amp;lt;''log_level''&amp;gt;] PNM=[&amp;lt;''program_name''&amp;gt;] OIP=[] RID=[] CTR=[&amp;lt;''controller_name''&amp;gt;] UID=[&amp;lt;''user_id''&amp;gt;] MSG=[[''origin_ip''] [''request_id''] ''Message'']'''&lt;br /&gt;
&lt;br /&gt;
Above variation is because when certain messages are logged, ExpertizaLogger is unaware of origin_ip and request_ip and thus it is appended to the message instead of their respective placeholders.&lt;br /&gt;
&lt;br /&gt;
===Meaning of each placeholder===&lt;br /&gt;
'''SVT''' - It denotes the severity level of the log. For eg, if the logging is done by calling logger.info, the severity level is &amp;quot;INFO&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
'''PNM''' - It's the program name and is same as provided by default Rails logger.&lt;br /&gt;
&lt;br /&gt;
'''OIP''' - It denotes the IP address of the system from where the request has been made. &lt;br /&gt;
&lt;br /&gt;
'''RID''' - It's the ID of the request. All subsequent calls made by the client till the actual response is returned will have same request ID. For eg, when a page is first requested, all smaller page template fetched, all method flow will have same request ID. This field can be used to understand how a certain request was served.&lt;br /&gt;
&lt;br /&gt;
'''CTR''' - It is the controller name from where the logging happened.&lt;br /&gt;
&lt;br /&gt;
'''UID''' - It is the unity id/user id of the user making requests. This field could also be used in identifying the cause of an error.&lt;br /&gt;
&lt;br /&gt;
'''Message''' - It is the actual message logged.&lt;br /&gt;
&lt;br /&gt;
==Log files==&lt;br /&gt;
For different log levels, log messages are written in different files named expertiza_&amp;lt;log_level&amp;gt;.log&lt;br /&gt;
&lt;br /&gt;
Currently, expertiza provides the capability of writing logs into 5 different custom log files.&lt;br /&gt;
&lt;br /&gt;
For eg, &lt;br /&gt;
&lt;br /&gt;
*expertiza_info.log&lt;br /&gt;
&lt;br /&gt;
*expertiza_warn.log&lt;br /&gt;
&lt;br /&gt;
*expertiza_error.log&lt;br /&gt;
&lt;br /&gt;
*expertiza_fatal.log&lt;br /&gt;
&lt;br /&gt;
*expertiza_debug.log&lt;br /&gt;
&lt;br /&gt;
Apart from above files, &amp;lt;environment&amp;gt;.log file is used for logging messages which could not be logged by ExpertizaLogger, like, page load messages or certain load time exceptions.&lt;br /&gt;
&lt;br /&gt;
Since Rails logger provides writing into a specific log file, to restrict least file switch, ExpertizaLogger holds different log level loggers in separate instance variables. A new logger instance is created and assigned whenever Rails removes the link to manage memory consumption.&lt;br /&gt;
&lt;br /&gt;
==Components==&lt;br /&gt;
===ExpertizaLogger===&lt;br /&gt;
&lt;br /&gt;
This class provides the logger needed for logging messages for different log levels.&lt;br /&gt;
It provides 5 different static methods namely '''info''', '''warn''', '''error''', '''fatal''' and '''debug''' which could be called as follows:&lt;br /&gt;
&lt;br /&gt;
'''ExpertizaLogger.info ''message'''''&lt;br /&gt;
&lt;br /&gt;
where ''message'' could be an instance of '''LogMessage''' or a string.&lt;br /&gt;
&lt;br /&gt;
===Custom LogMessage===&lt;br /&gt;
&lt;br /&gt;
A LogMessage instance could be created as follows:&lt;br /&gt;
&lt;br /&gt;
'''LogMessage.new(&amp;lt;controller_name&amp;gt;, &amp;lt;user_id&amp;gt;, &amp;lt;message&amp;gt;, &amp;lt;request object&amp;gt;)'''&lt;br /&gt;
&lt;br /&gt;
Fourth parameter i.e &amp;lt;request object&amp;gt; is an optional parameter. &lt;br /&gt;
&lt;br /&gt;
Whenever a request is made, the request object is injected into the controller and is available in the controller as &amp;quot;request&amp;quot;.&lt;br /&gt;
Similarly, &amp;lt;controller_name&amp;gt; is available in &amp;quot;controller_name&amp;quot; inside controller. For other trigger points, file name could be passed as a string.&lt;br /&gt;
&lt;br /&gt;
Since the request object holds the ''&amp;lt;origin_ip&amp;gt;'' and ''&amp;lt;request_id&amp;gt;'', it is used to capture and log both into the log message.&lt;br /&gt;
&lt;br /&gt;
===ExpertizaLogFormatter===&lt;br /&gt;
&lt;br /&gt;
It captures the message and determines if the message is an instance of LogMessage or not. Based on that, it creates a message by populating message placeholders as below:&lt;br /&gt;
&lt;br /&gt;
    if msg.is_a?(LogMessage)&lt;br /&gt;
      &amp;quot;TST=[#{ts}] SVT=[#{s}] PNM=[#{pg}] OIP=[#{msg.oip}] RID=[#{msg.req_id}] CTR=[#{msg.generator}] UID=[#{msg.unity_id}] MSG=[#{filter(msg.message)}]\n&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
      &amp;quot;TST=[#{ts}] SVT=[#{s}] PNM=[#{pg}] OIP=[] RID=[] CTR=[] UID=[] MSG=[#{filter(msg)}]\n&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
All the exceptions are preprocessed to remove newline characters so that it could fit in a single line as a message.&lt;br /&gt;
&lt;br /&gt;
All the messages that are not logged by ExpertizaLogger, there is a separate logger definition provided in config/environments/&amp;lt;environment&amp;gt;.rb as:&lt;br /&gt;
&lt;br /&gt;
  config.log_formatter = proc do |s, ts, pg, msg|&lt;br /&gt;
    if msg.is_a?(LogMessage)&lt;br /&gt;
      &amp;quot;TST=[#{ts}] SVT=[#{s}] PNM=[#{pg}] OIP=[#{msg.oip}] RID=[#{msg.req_id}] CTR=[#{msg.generator}] UID=[#{msg.unity_id}] MSG=[#{filter(msg.message)}]\n&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
      &amp;quot;TST=[#{ts}] SVT=[#{s}] PNM=[#{pg}] OIP=[] RID=[] CTR=[] UID=[] MSG=[#{filter(msg)}]\n&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===Environment config===&lt;br /&gt;
config.log_tags = [ :remote_ip, :uuid ]&lt;br /&gt;
&lt;br /&gt;
These config.log_tags entries make sure that &amp;lt;origin_ip&amp;gt; and &amp;lt;request_id&amp;gt; are prepended to messages. These are for messages which are not logged by ExpertizaLogger but by the Rails default logger.&lt;br /&gt;
These messages go in &amp;lt;environment&amp;gt;.log file.&lt;br /&gt;
&lt;br /&gt;
==Restrictions==&lt;br /&gt;
The request object is not available beyond the controllers. Hence, ''&amp;lt;origin_ip&amp;gt;'' and ''&amp;lt;request_id&amp;gt;'' remains uncaptured if messages are logged from somewhere other than controllers.&lt;br /&gt;
&lt;br /&gt;
==Visualization through ELK stack==&lt;br /&gt;
===Configuration===&lt;br /&gt;
&lt;br /&gt;
Filebeat (filebeat.yml)&lt;br /&gt;
&lt;br /&gt;
Changes:&lt;br /&gt;
&lt;br /&gt;
- type: log&lt;br /&gt;
&lt;br /&gt;
  # Change to true to enable this prospector configuration.&lt;br /&gt;
  enabled: true&lt;br /&gt;
&lt;br /&gt;
  # Paths that should be crawled and fetched. Glob based paths.&lt;br /&gt;
  paths:&lt;br /&gt;
    - &amp;lt;path to log files&amp;gt;*.log&lt;br /&gt;
&lt;br /&gt;
output.logstash:&lt;br /&gt;
  # The Logstash hosts&lt;br /&gt;
  hosts: [&amp;quot;&amp;lt;ip&amp;gt;:&amp;lt;5044:port of logstash&amp;gt;&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
Filebeat sends all log files to logstash.&lt;br /&gt;
&lt;br /&gt;
Logstash (expertiza-logstash.conf)&lt;br /&gt;
&lt;br /&gt;
   input { &lt;br /&gt;
        beats {&lt;br /&gt;
            port =&amp;gt; &amp;quot;5044&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
   }&lt;br /&gt;
   filter {&lt;br /&gt;
    grok {&lt;br /&gt;
    	match =&amp;gt; { &amp;quot;message&amp;quot; =&amp;gt; &amp;quot;TST=\[%{DATA:timestamp}\] SVT=\[%{DATA:sev}\] PNM=\[%{DATA:pgnm}\] OIP=\[%{DATA:originip}\] RID=\[%{DATA:requestid}\] CTR=\[%{DATA:generatedby}\] UID=\[% &lt;br /&gt;
   {DATA:unityid}\] MSG=\[%{GREEDYDATA:message}\]&amp;quot; }&lt;br /&gt;
    	overwrite =&amp;gt; [ &amp;quot;message&amp;quot;, &amp;quot;timestamp&amp;quot; ]&lt;br /&gt;
  	}&lt;br /&gt;
  	date {&lt;br /&gt;
    	match =&amp;gt; [&amp;quot;timestamp&amp;quot;, &amp;quot;ISO8601&amp;quot;]&lt;br /&gt;
  	}&lt;br /&gt;
  	&lt;br /&gt;
    }&lt;br /&gt;
    output {&lt;br /&gt;
      elasticsearch {&lt;br /&gt;
        hosts =&amp;gt; [ &amp;quot;localhost:9200&amp;quot; ]&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
Logstash reads each line from the log file and parses it based on the template provided in grok match above. It then sends each message entry into Elastic search.&lt;br /&gt;
&lt;br /&gt;
Kibana (config/kibana.yml)&lt;br /&gt;
&lt;br /&gt;
    elasticsearch.url: &amp;quot;http://localhost:9200&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Kibana picks each entry from Elastic search and provides into the web interface.&lt;br /&gt;
&lt;br /&gt;
===Setup===&lt;br /&gt;
ELK stack could be set up to visualize and analyze the messages from the log files.&lt;br /&gt;
&lt;br /&gt;
Once ELK is installed, below commands could be used to run each server:&lt;br /&gt;
&lt;br /&gt;
'''Clear Elastic search cache'''&lt;br /&gt;
&lt;br /&gt;
curl -X DELETE 'http://localhost:9200/_all'&lt;br /&gt;
&lt;br /&gt;
'''Filebeat'''&lt;br /&gt;
&lt;br /&gt;
sudo rm data/registry&lt;br /&gt;
&lt;br /&gt;
sudo ./filebeat -e -c filebeat.yml -d &amp;quot;publish&amp;quot;&lt;br /&gt;
&lt;br /&gt;
'''Logstash'''&lt;br /&gt;
&lt;br /&gt;
bin/logstash -f expertiza-logstash.conf --config.reload.automatic&lt;br /&gt;
&lt;br /&gt;
'''Kibana'''&lt;br /&gt;
&lt;br /&gt;
bin/kibana&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/Independent_Study_Spring_2018&amp;diff=117473</id>
		<title>CSC/Independent Study Spring 2018</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/Independent_Study_Spring_2018&amp;diff=117473"/>
		<updated>2018-05-07T16:02:30Z</updated>

		<summary type="html">&lt;p&gt;Knielar: Created page with &amp;quot;'''Topics''' *Independent Study Spring 2018/Logging&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Topics'''&lt;br /&gt;
*[[Independent Study Spring 2018/Logging]]&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2017/E1793._Help_students_find_teams_to_join_Team1964&amp;diff=114684</id>
		<title>CSC/ECE 517 Fall 2017/E1793. Help students find teams to join Team1964</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2017/E1793._Help_students_find_teams_to_join_Team1964&amp;diff=114684"/>
		<updated>2017-12-11T19:13:58Z</updated>

		<summary type="html">&lt;p&gt;Knielar: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== About Expertiza ==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a Ruby on Rails based Open Source project. It is a collaboration tool which lets users with different roles (student, instructor, teaching assistant) to collaborate on a course in an institution. A collaboration could be for an assignment where students teams up for an assignment and instructors grades them on the basis of their submission. Students could review other's works and give feedback as well.&lt;br /&gt;
&lt;br /&gt;
===Github link===&lt;br /&gt;
*https://github.com/expertiza/expertiza&lt;br /&gt;
&lt;br /&gt;
===Wiki link===&lt;br /&gt;
*http://wiki.expertiza.ncsu.edu/index.php/Expertiza_documentation&lt;br /&gt;
&lt;br /&gt;
===Pull Request===&lt;br /&gt;
*https://github.com/expertiza/expertiza/pull/1129/ &lt;br /&gt;
&lt;br /&gt;
==='''Problem Statement'''===&lt;br /&gt;
*For team-based assignments, it always takes time to find suitable team members. &lt;br /&gt;
&lt;br /&gt;
*We already have bidding, which could help you to join a team with other team members hold similar bidding preferences. However, a student may not be satisfied with automated team formation and want to switch to another team. &lt;br /&gt;
&lt;br /&gt;
*'''In this project, we will build a new feature to help students find teams to join.'''&lt;br /&gt;
&lt;br /&gt;
Currently, there are 2 ways to find other students to join your team:&lt;br /&gt;
&lt;br /&gt;
*If your team is not full, you could invite people by inputting his/her UnityID. It will send an invitation to a certain user. If s/he accept your invitation,s/he will leave the original team and join your team.&lt;br /&gt;
&lt;br /&gt;
*You could create an advisement by clicking “Your team” link and then clicking “Create” link under “Advertisement for teammates” section. Then your advertisement will appear the last column of the signup sheet page with a horn icon. In this way, all classmates could see your advisement. Someone could send a request to join your team. If you accept their request, s/he will leave original team and join in your team. &lt;br /&gt;
&lt;br /&gt;
Below screenshots represents the description above.&lt;br /&gt;
&lt;br /&gt;
Student: Advertisement icon doesn't appear in Chrome browser.&lt;br /&gt;
&lt;br /&gt;
[[File:A_chrome_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Instructor: Advertisement icon doesn't appear in Chrome browser.&lt;br /&gt;
&lt;br /&gt;
[[File:A_instructor_cr_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Advertisement icon appears in Mozilla browser but not in the cell it should appear rather it is visible under &amp;quot;Actions&amp;quot; column.&lt;br /&gt;
&lt;br /&gt;
[[File:A_mozilla_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Change Request requirements:'''&lt;br /&gt;
*Students whose team is not full yet to be able to see a list of students who don’t already have teams.&lt;br /&gt;
*Students should have an option of inviting other students to join their teams.&lt;br /&gt;
*Instructors should be able to view a list of students who don't have teams.&lt;br /&gt;
&lt;br /&gt;
== Task Description ==&lt;br /&gt;
&lt;br /&gt;
====Change Request 1====&lt;br /&gt;
Fix the second way to find other students to join your team. Currently, after you create ​an​ ​advertisement,​ ​the​ ​horn​ ​icon​ ​does​ ​not​ ​appear​ ​in the​ ​the​ ​last​ ​column​ ​of​ ​the​ ​signup​ ​sheet.&lt;br /&gt;
&lt;br /&gt;
=====What did we do?=====&lt;br /&gt;
&lt;br /&gt;
We found out that the problem was due to the name of horn icon. Certain ad blockers block any element with name ad or advertisement and horn icon was named as ad.png.&lt;br /&gt;
We renamed it to ad_horn.png and it resolved the issue.&lt;br /&gt;
&lt;br /&gt;
We also found out that the issue was also due to some complex table cell population. When the assignment was not in finished stage, actions were put into a td cell and displayed, which was adding an extra row, but this was only for users who had signed up some topic. In other cases, the cell was not created every time, forcing table row to have lesser columns. &lt;br /&gt;
&lt;br /&gt;
We removed the conditional td creation, and added all conditional checks inside a parent td, which ensured that even if a user has no action to display, at least a td will be created.&lt;br /&gt;
&lt;br /&gt;
====Change Request 2====&lt;br /&gt;
For​ ​student​ ​end:  Display​ ​a​ ​list​ ​of​ ​​students​ ​who​ ​do​ ​not​ ​have​ ​a​ ​team​ ​with​ ​invitation​ ​links​ ​in student_teams#view​ ​page ○ You​ ​could​ ​invite​ ​students​ ​to​ ​your​ ​team​ ​by​ ​clicking​ ​invitation​ ​links.​ ​If​ ​s/he​ ​accept your​ ​invitation,s/he​ ​will​ ​leave​  the original​ ​team​ ​and​ ​join​ ​in​ ​your​ ​team.​ ​It​ ​will​ ​be​ ​more straightforward​ ​than​ ​typing​ ​UnityID.&lt;br /&gt;
&lt;br /&gt;
====Change Request 3====&lt;br /&gt;
For​ ​instructor​ ​end:  Display​ ​a​ ​list​ ​of​ ​​students​ ​who​ ​do​ ​not​ ​have​ ​team​ ​with​ ​invitation​ ​links​ ​in​ ​teams#list page &lt;br /&gt;
&lt;br /&gt;
=====What did we do?=====&lt;br /&gt;
'''This has solution step for CR2 and CR3.'''&lt;br /&gt;
&lt;br /&gt;
We created a helper method to fetch all participants from the database who did not have a team or whose teams have only one member(themselves). &lt;br /&gt;
We used Join queries to join tables participants, team_users, and teams to extract participants associated with the assignment with or without teams and then filtered out participants with team size &amp;gt; 1.&lt;br /&gt;
&lt;br /&gt;
'''def extract_assignment_participants(assignment_id, excluded_id = nil)'''&lt;br /&gt;
&lt;br /&gt;
Above method was defined in app/helpers/assignment_helper.rb.&lt;br /&gt;
The second parameter was required to exclude current student's id to be excluded to be returned for student whereas, for an Instructor, all students without teams or with single-member team had to be returned.&lt;br /&gt;
&lt;br /&gt;
More changes could be found here: [https://github.com/expertiza/expertiza/pull/1129/files#diff-e2d518aed0fccbb9ab0fc9e2e1ef8683 app/helpers/assignment_helper.rb]&lt;br /&gt;
&lt;br /&gt;
The method was made generic enough to be used by both app/controllers/student_teams_controller.rb (for student) and app/controllers/teams_controller.rb (for instructors).&lt;br /&gt;
&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/1129/files#diff-113f035d853c52fdfd3a00851a3db407 app/controllers/student_teams_controller.rb(for student)]&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/1129/files#diff-7543048f54ac556dff85edee281fafd8 app/controllers/teams_controller.rb(for instructors)]&lt;br /&gt;
&lt;br /&gt;
For student, we checked if student can actually send invites or not, and based on that we fetched the participant list.&lt;br /&gt;
We considered below cases for verifying if a student can send invite or not:&lt;br /&gt;
&lt;br /&gt;
*Student can't send invite if student doesn\’t have a team&lt;br /&gt;
*Student can't send invite if current team size is 1 and assignment\’s allowed team size is also 1&lt;br /&gt;
*Student can send invite if assignment\’s allowed team size is &amp;gt;1 and current team size is less than allowed team size&lt;br /&gt;
*Student can't send invite if current team size is equal to allowed team size&lt;br /&gt;
*Student can't send invite if assignment is in finished stage&lt;br /&gt;
*Student can send invite if assignment is not in finished state&lt;br /&gt;
&lt;br /&gt;
The table containing the list of students to send an invite to was created/not created based on above criteria only.&lt;br /&gt;
&lt;br /&gt;
For Instructor, there were no such criteria to be considered. &lt;br /&gt;
&lt;br /&gt;
== Modified Files ==&lt;br /&gt;
1)Conrollers:-&lt;br /&gt;
*app/controllers/student_teams_controller.rb&lt;br /&gt;
*app/controllers/teams_controller.rb&lt;br /&gt;
2)Helper:-&lt;br /&gt;
*app/helpers/assignment_helper.rb&lt;br /&gt;
3)Views:-&lt;br /&gt;
*app/views/join_team_requests/_list_not_initiated.html.erb&lt;br /&gt;
*app/views/join_team_requests/_list_received.html.erb&lt;br /&gt;
*app/views/join_team_requests/_list_sent.html.erb&lt;br /&gt;
*app/views/sign_up_sheet/_add_signup_topics.html.erb&lt;br /&gt;
*app/views/sign_up_sheet/_table_line.html.erb&lt;br /&gt;
*app/views/sign_up_sheet/list.html.erb&lt;br /&gt;
*app/views/student_teams/view.html.erb&lt;br /&gt;
*app/views/teams/list.html.erb&lt;br /&gt;
4)Tests:-&lt;br /&gt;
*spec/controllers/student_teams_controller_spec.rb&lt;br /&gt;
*spec/features/team_invitation_spec.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
&lt;br /&gt;
=== Test Cases ===&lt;br /&gt;
&lt;br /&gt;
We will be writing automated tests to check if the changes made are working correctly. &lt;br /&gt;
&lt;br /&gt;
For that, we considered the following scenarios&lt;br /&gt;
Testing invitation criteria:-&lt;br /&gt;
*Scenario 1 - Student can't see list of students to invite if student doesn\’t have a team&lt;br /&gt;
*Scenario 2 - Student can't see list of students to invite if current team size is 1 and assignment\’s allowed team size is also 1&lt;br /&gt;
*Scenario 3 - Student can see list of students to invite if assignment\’s allowed team size is &amp;gt;1 and current team size is less than allowed team size&lt;br /&gt;
*Scenario 4 - Student can't see list of students to invite if current team size is equal to allowed team size&lt;br /&gt;
*Scenario 5 - Student can't see list of students to invite if assignment is in finished stage&lt;br /&gt;
*Scenario 6 - Student can see list of students to invite if assignment is not in finished state&lt;br /&gt;
*Scenario 7 - The list of students contains only those students who don't have a team yet or whose team is not yet complete and who have not created an advertisement link.&lt;br /&gt;
*Scenario 8 - A student can create an invitation link only if his team is not yet full.&lt;br /&gt;
*Scenario 9 - The same student who accepted the invitation link actually gets added to the team. &lt;br /&gt;
*Scenario 10 - A student won't be able to send the invitation to himself as he is already a member of that team.&lt;br /&gt;
*Scenario 11 - An instructor sees only the list of the students who do not have teams with invitation link.&lt;br /&gt;
&lt;br /&gt;
All tests could be found here: &lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/1129/files#diff-d2b8c8df44cb32268062c72be7da59fb spec/controllers/student_teams_controller_spec.rb]&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/1129/files#diff-d1d14865d734d2f66dc726c70cb1bcb9 spec/features/team_invitation_spec.rb]&lt;br /&gt;
&lt;br /&gt;
== Visual representation of changes made ==&lt;br /&gt;
&lt;br /&gt;
Horn icon appearing in correct column in signup sheet table.&lt;br /&gt;
&lt;br /&gt;
[[File:A_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
All students whose teams are not complete would see list of other students without teams on their &amp;quot;your team&amp;quot; view so that they could invite them by an easy &amp;quot;Invite&amp;quot; link as displayed below:&lt;br /&gt;
&lt;br /&gt;
[[File:Join_request_main_page_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
===Change Video===&lt;br /&gt;
*https://youtu.be/B3h3O8UtJ8E &lt;br /&gt;
&lt;br /&gt;
==Team Information==&lt;br /&gt;
[mailto:tpahuja@ncsu.edu Tushar Pahuja]&amp;lt;br&amp;gt;&lt;br /&gt;
[mailto:pmgandh2@ncsu.edu Pragam Manoj Gandhi]&amp;lt;br&amp;gt;&lt;br /&gt;
[mailto:knielar@ncsu.edu Nielarshi Kumar]&amp;lt;br&amp;gt;&lt;br /&gt;
[mailto:abhardw3@ncsu.edu Abhishek Bhardwaj]&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2017/E1793._Help_students_find_teams_to_join_Team1964&amp;diff=114683</id>
		<title>CSC/ECE 517 Fall 2017/E1793. Help students find teams to join Team1964</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2017/E1793._Help_students_find_teams_to_join_Team1964&amp;diff=114683"/>
		<updated>2017-12-11T19:08:12Z</updated>

		<summary type="html">&lt;p&gt;Knielar: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== About Expertiza ==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a Ruby on Rails based Open Source project. It is a collaboration tool which lets users with different roles (student, instructor, teaching assistant) to collaborate on a course in an institution. A collaboration could be for an assignment where students teams up for an assignment and instructors grades them on the basis of their submission. Students could review other's works and give feedback as well.&lt;br /&gt;
&lt;br /&gt;
===Github link===&lt;br /&gt;
*https://github.com/expertiza/expertiza&lt;br /&gt;
&lt;br /&gt;
===Wiki link===&lt;br /&gt;
*http://wiki.expertiza.ncsu.edu/index.php/Expertiza_documentation&lt;br /&gt;
&lt;br /&gt;
===Pull Request===&lt;br /&gt;
*https://github.com/expertiza/expertiza/pull/1129/ &lt;br /&gt;
&lt;br /&gt;
==='''Problem Statement'''===&lt;br /&gt;
*For team-based assignments, it always takes time to find suitable team members. &lt;br /&gt;
&lt;br /&gt;
*We already have bidding, which could help you to join a team with other team members hold similar bidding preferences. However, a student may not be satisfied with automated team formation and want to switch to another team. &lt;br /&gt;
&lt;br /&gt;
*'''In this project, we will build a new feature to help students find teams to join.'''&lt;br /&gt;
&lt;br /&gt;
Currently, there are 2 ways to find other students to join your team:&lt;br /&gt;
&lt;br /&gt;
*If your team is not full, you could invite people by inputting his/her UnityID. It will send an invitation to a certain user. If s/he accept your invitation,s/he will leave the original team and join your team.&lt;br /&gt;
&lt;br /&gt;
*You could create an advisement by clicking “Your team” link and then clicking “Create” link under “Advertisement for teammates” section. Then your advertisement will appear the last column of the signup sheet page with a horn icon. In this way, all classmates could see your advisement. Someone could send a request to join your team. If you accept their request, s/he will leave original team and join in your team. &lt;br /&gt;
&lt;br /&gt;
Below screenshots represents the description above.&lt;br /&gt;
&lt;br /&gt;
Student: Advertisement icon doesn't appear in Chrome browser.&lt;br /&gt;
&lt;br /&gt;
[[File:A_chrome_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Instructor: Advertisement icon doesn't appear in Chrome browser.&lt;br /&gt;
&lt;br /&gt;
[[File:A_instructor_cr_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Advertisement icon appears in Mozilla browser but not in the cell it should appear rather it is visible under &amp;quot;Actions&amp;quot; column.&lt;br /&gt;
&lt;br /&gt;
[[File:A_mozilla_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Change Request requirements:'''&lt;br /&gt;
*Students whose team is not full yet to be able to see a list of students who don’t already have teams.&lt;br /&gt;
*Students should have an option of inviting other students to join their teams.&lt;br /&gt;
*Instructors should be able to view a list of students who don't have teams.&lt;br /&gt;
&lt;br /&gt;
== Task Description ==&lt;br /&gt;
&lt;br /&gt;
====Change Request 1====&lt;br /&gt;
Fix the second way to find other students to join your team. Currently, after you create ​an​ ​advertisement,​ ​the​ ​horn​ ​icon​ ​does​ ​not​ ​appear​ ​in the​ ​the​ ​last​ ​column​ ​of​ ​the​ ​signup​ ​sheet.&lt;br /&gt;
&lt;br /&gt;
=====What did we do?=====&lt;br /&gt;
&lt;br /&gt;
We found out that the problem was due to the name of horn icon. Certain ad blockers block any element with name ad or advertisement and horn icon was named as ad.png.&lt;br /&gt;
We renamed it to ad_horn.png and it resolved the issue.&lt;br /&gt;
&lt;br /&gt;
We also found out that the issue was also due to some complex table cell population. When the assignment was not in finished stage, actions were put into a td cell and displayed, which was adding an extra row, but this was only for users who had signed up some topic. In other cases, the cell was not created every time, forcing table row to have lesser columns. &lt;br /&gt;
&lt;br /&gt;
We removed the conditional td creation, and added all conditional checks inside a parent td, which ensured that even if a user has no action to display, at least a td will be created.&lt;br /&gt;
&lt;br /&gt;
====Change Request 2====&lt;br /&gt;
For​ ​student​ ​end:  Display​ ​a​ ​list​ ​of​ ​​students​ ​who​ ​do​ ​not​ ​have​ ​a​ ​team​ ​with​ ​invitation​ ​links​ ​in student_teams#view​ ​page ○ You​ ​could​ ​invite​ ​students​ ​to​ ​your​ ​team​ ​by​ ​clicking​ ​invitation​ ​links.​ ​If​ ​s/he​ ​accept your​ ​invitation,s/he​ ​will​ ​leave​  the original​ ​team​ ​and​ ​join​ ​in​ ​your​ ​team.​ ​It​ ​will​ ​be​ ​more straightforward​ ​than​ ​typing​ ​UnityID.&lt;br /&gt;
&lt;br /&gt;
====Change Request 3====&lt;br /&gt;
For​ ​instructor​ ​end:  Display​ ​a​ ​list​ ​of​ ​​students​ ​who​ ​do​ ​not​ ​have​ ​team​ ​with​ ​invitation​ ​links​ ​in​ ​teams#list page &lt;br /&gt;
&lt;br /&gt;
=====What did we do?=====&lt;br /&gt;
'''This has solution step for CR2 and CR3.'''&lt;br /&gt;
&lt;br /&gt;
We created a helper method to fetch all participants from the database who did not have a team or whose teams have only one member(themselves). &lt;br /&gt;
We used Join queries to join tables participants, team_users, and teams to extract participants associated with the assignment with or without teams and then filtered out participants with team size &amp;gt; 1.&lt;br /&gt;
&lt;br /&gt;
'''def extract_assignment_participants(assignment_id, excluded_id = nil)'''&lt;br /&gt;
&lt;br /&gt;
Above method was defined in app/helpers/assignment_helper.rb.&lt;br /&gt;
The second parameter was required to exclude current student's id to be excluded to be returned for student whereas, for an Instructor, all students without teams or with single-member team had to be returned.&lt;br /&gt;
&lt;br /&gt;
More changes could be found here: [https://github.com/expertiza/expertiza/pull/1129/files#diff-e2d518aed0fccbb9ab0fc9e2e1ef8683 app/helpers/assignment_helper.rb]&lt;br /&gt;
&lt;br /&gt;
The method was made generic enough to be used by both app/controllers/student_teams_controller.rb (for student) and app/controllers/teams_controller.rb (for instructors).&lt;br /&gt;
&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/1129/files#diff-113f035d853c52fdfd3a00851a3db407 app/controllers/student_teams_controller.rb(for student)]&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/1129/files#diff-7543048f54ac556dff85edee281fafd8 app/controllers/teams_controller.rb(for instructors)]&lt;br /&gt;
&lt;br /&gt;
For student, we checked if student can actually send invites or not, and based on that we fetched the participant list.&lt;br /&gt;
We considered below cases for verifying if a student can send invite or not:&lt;br /&gt;
&lt;br /&gt;
*Student can't send invite if student doesn\’t have a team&lt;br /&gt;
*Student can't send invite if current team size is 1 and assignment\’s allowed team size is also 1&lt;br /&gt;
*Student can send invite if assignment\’s allowed team size is &amp;gt;1 and current team size is less than allowed team size&lt;br /&gt;
*Student can't send invite if current team size is equal to allowed team size&lt;br /&gt;
*Student can't send invite if assignment is in finished stage&lt;br /&gt;
*Student can send invite if assignment is not in finished state&lt;br /&gt;
&lt;br /&gt;
The table containing the list of students to send an invite to was created/not created based on above criteria only.&lt;br /&gt;
&lt;br /&gt;
For Instructor, there were no such criteria to be considered. &lt;br /&gt;
&lt;br /&gt;
== Modified Files ==&lt;br /&gt;
1)Conrollers:-&lt;br /&gt;
*app/controllers/student_teams_controller.rb&lt;br /&gt;
*app/controllers/teams_controller.rb&lt;br /&gt;
2)Helper:-&lt;br /&gt;
*app/helpers/assignment_helper.rb&lt;br /&gt;
3)Views:-&lt;br /&gt;
*app/views/join_team_requests/_list_not_initiated.html.erb&lt;br /&gt;
*app/views/join_team_requests/_list_received.html.erb&lt;br /&gt;
*app/views/join_team_requests/_list_sent.html.erb&lt;br /&gt;
*app/views/sign_up_sheet/_add_signup_topics.html.erb&lt;br /&gt;
*app/views/sign_up_sheet/_table_line.html.erb&lt;br /&gt;
*app/views/sign_up_sheet/list.html.erb&lt;br /&gt;
*app/views/student_teams/view.html.erb&lt;br /&gt;
*app/views/teams/list.html.erb&lt;br /&gt;
4)Tests:-&lt;br /&gt;
*spec/controllers/student_teams_controller_spec.rb&lt;br /&gt;
*spec/features/team_invitation_spec.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
&lt;br /&gt;
=== Test Cases ===&lt;br /&gt;
&lt;br /&gt;
We will be writing automated tests to check if the changes made are working correctly. &lt;br /&gt;
&lt;br /&gt;
For that, we considered the following scenarios&lt;br /&gt;
Testing invitation criteria:-&lt;br /&gt;
*Scenario 1 - Student can't see list of students to invite if student doesn\’t have a team&lt;br /&gt;
*Scenario 2 - Student can't see list of students to invite if current team size is 1 and assignment\’s allowed team size is also 1&lt;br /&gt;
*Scenario 3 - Student can see list of students to invite if assignment\’s allowed team size is &amp;gt;1 and current team size is less than allowed team size&lt;br /&gt;
*Scenario 4 - Student can't see list of students to invite if current team size is equal to allowed team size&lt;br /&gt;
*Scenario 5 - Student can't see list of students to invite if assignment is in finished stage&lt;br /&gt;
*Scenario 6 - Student can see list of students to invite if assignment is not in finished state&lt;br /&gt;
*Scenario 7 - The list of students contains only those students who don't have a team yet or whose team is not yet complete and who have not created an advertisement link.&lt;br /&gt;
*Scenario 8 - A student can create an invitation link only if his team is not yet full.&lt;br /&gt;
*Scenario 9 - The same student who accepted the invitation link actually gets added to the team. &lt;br /&gt;
*Scenario 10 - A student won't be able to send the invitation to himself as he is already a member of that team.&lt;br /&gt;
*Scenario 11 - An instructor sees only the list of the students who do not have teams with invitation link.&lt;br /&gt;
&lt;br /&gt;
All tests could be found here: &lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/1129/files#diff-d2b8c8df44cb32268062c72be7da59fb spec/controllers/student_teams_controller_spec.rb]&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/1129/files#diff-d1d14865d734d2f66dc726c70cb1bcb9 spec/features/team_invitation_spec.rb]&lt;br /&gt;
&lt;br /&gt;
== Visual representation of changes made ==&lt;br /&gt;
&lt;br /&gt;
All other students who have not created advertisements, each student would see their list on their &amp;quot;your team&amp;quot; view so that they could invite them by an easy &amp;quot;Invite&amp;quot; link as displayed below:&lt;br /&gt;
&lt;br /&gt;
[[File:Invite_unity_id_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
[[File:Join_request_main_page_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
===Change Video===&lt;br /&gt;
*https://youtu.be/B3h3O8UtJ8E &lt;br /&gt;
&lt;br /&gt;
==Team Information==&lt;br /&gt;
[mailto:tpahuja@ncsu.edu Tushar Pahuja]&amp;lt;br&amp;gt;&lt;br /&gt;
[mailto:pmgandh2@ncsu.edu Pragam Manoj Gandhi]&amp;lt;br&amp;gt;&lt;br /&gt;
[mailto:knielar@ncsu.edu Nielarshi Kumar]&amp;lt;br&amp;gt;&lt;br /&gt;
[mailto:abhardw3@ncsu.edu Abhishek Bhardwaj]&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2017/E1793._Help_students_find_teams_to_join_Team1964&amp;diff=114682</id>
		<title>CSC/ECE 517 Fall 2017/E1793. Help students find teams to join Team1964</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2017/E1793._Help_students_find_teams_to_join_Team1964&amp;diff=114682"/>
		<updated>2017-12-11T19:02:58Z</updated>

		<summary type="html">&lt;p&gt;Knielar: /* What did we do? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== About Expertiza ==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a Ruby on Rails based Open Source project. It is a collaboration tool which lets users with different roles (student, instructor, teaching assistant) to collaborate on a course in an institution. A collaboration could be for an assignment where students teams up for an assignment and instructors grades them on the basis of their submission. Students could review other's works and give feedback as well.&lt;br /&gt;
&lt;br /&gt;
===Github link===&lt;br /&gt;
*https://github.com/expertiza/expertiza&lt;br /&gt;
&lt;br /&gt;
===Wiki link===&lt;br /&gt;
*http://wiki.expertiza.ncsu.edu/index.php/Expertiza_documentation&lt;br /&gt;
&lt;br /&gt;
==='''Problem Statement'''===&lt;br /&gt;
*For team-based assignments, it always takes time to find suitable team members. &lt;br /&gt;
&lt;br /&gt;
*We already have bidding, which could help you to join a team with other team members hold similar bidding preferences. However, a student may not be satisfied with automated team formation and want to switch to another team. &lt;br /&gt;
&lt;br /&gt;
*'''In this project, we will build a new feature to help students find teams to join.'''&lt;br /&gt;
&lt;br /&gt;
Currently, there are 2 ways to find other students to join your team:&lt;br /&gt;
&lt;br /&gt;
*If your team is not full, you could invite people by inputting his/her UnityID. It will send an invitation to a certain user. If s/he accept your invitation,s/he will leave the original team and join your team.&lt;br /&gt;
&lt;br /&gt;
*You could create an advisement by clicking “Your team” link and then clicking “Create” link under “Advertisement for teammates” section. Then your advertisement will appear the last column of the signup sheet page with a horn icon. In this way, all classmates could see your advisement. Someone could send a request to join your team. If you accept their request, s/he will leave original team and join in your team. &lt;br /&gt;
&lt;br /&gt;
Below screenshots represents the description above.&lt;br /&gt;
&lt;br /&gt;
Student: Advertisement icon doesn't appear in Chrome browser.&lt;br /&gt;
&lt;br /&gt;
[[File:A_chrome_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Instructor: Advertisement icon doesn't appear in Chrome browser.&lt;br /&gt;
&lt;br /&gt;
[[File:A_instructor_cr_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Advertisement icon appears in Mozilla browser but not in the cell it should appear rather it is visible under &amp;quot;Actions&amp;quot; column.&lt;br /&gt;
&lt;br /&gt;
[[File:A_mozilla_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Change Request requirements:'''&lt;br /&gt;
*Students whose team is not full yet to be able to see a list of students who don’t already have teams.&lt;br /&gt;
*Students should have an option of inviting other students to join their teams.&lt;br /&gt;
*Instructors should be able to view a list of students who don't have teams.&lt;br /&gt;
&lt;br /&gt;
== Task Description ==&lt;br /&gt;
&lt;br /&gt;
====Change Request 1====&lt;br /&gt;
Fix the second way to find other students to join your team. Currently, after you create ​an​ ​advertisement,​ ​the​ ​horn​ ​icon​ ​does​ ​not​ ​appear​ ​in the​ ​the​ ​last​ ​column​ ​of​ ​the​ ​signup​ ​sheet.&lt;br /&gt;
&lt;br /&gt;
=====What did we do?=====&lt;br /&gt;
&lt;br /&gt;
We found out that the problem was due to the name of horn icon. Certain ad blockers block any element with name ad or advertisement and horn icon was named as ad.png.&lt;br /&gt;
We renamed it to ad_horn.png and it resolved the issue.&lt;br /&gt;
&lt;br /&gt;
We also found out that the issue was also due to some complex table cell population. When the assignment was not in finished stage, actions were put into a td cell and displayed, which was adding an extra row, but this was only for users who had signed up some topic. In other cases, the cell was not created every time, forcing table row to have lesser columns. &lt;br /&gt;
&lt;br /&gt;
We removed the conditional td creation, and added all conditional checks inside a parent td, which ensured that even if a user has no action to display, at least a td will be created.&lt;br /&gt;
&lt;br /&gt;
====Change Request 2====&lt;br /&gt;
For​ ​student​ ​end:  Display​ ​a​ ​list​ ​of​ ​​students​ ​who​ ​do​ ​not​ ​have​ ​a​ ​team​ ​with​ ​invitation​ ​links​ ​in student_teams#view​ ​page ○ You​ ​could​ ​invite​ ​students​ ​to​ ​your​ ​team​ ​by​ ​clicking​ ​invitation​ ​links.​ ​If​ ​s/he​ ​accept your​ ​invitation,s/he​ ​will​ ​leave​  the original​ ​team​ ​and​ ​join​ ​in​ ​your​ ​team.​ ​It​ ​will​ ​be​ ​more straightforward​ ​than​ ​typing​ ​UnityID.&lt;br /&gt;
&lt;br /&gt;
====Change Request 3====&lt;br /&gt;
For​ ​instructor​ ​end:  Display​ ​a​ ​list​ ​of​ ​​students​ ​who​ ​do​ ​not​ ​have​ ​team​ ​with​ ​invitation​ ​links​ ​in​ ​teams#list page &lt;br /&gt;
&lt;br /&gt;
=====What did we do?=====&lt;br /&gt;
'''This has solution step for CR2 and CR3.'''&lt;br /&gt;
&lt;br /&gt;
We created a helper method to fetch all participants from the database who did not have a team or whose teams have only one member(themselves). &lt;br /&gt;
We used Join queries to join tables participants, team_users, and teams to extract participants associated with the assignment with or without teams and then filtered out participants with team size &amp;gt; 1.&lt;br /&gt;
&lt;br /&gt;
'''def extract_assignment_participants(assignment_id, excluded_id = nil)'''&lt;br /&gt;
&lt;br /&gt;
Above method was defined in app/helpers/assignment_helper.rb.&lt;br /&gt;
The second parameter was required to exclude current student's id to be excluded to be returned for student whereas, for an Instructor, all students without teams or with single-member team had to be returned.&lt;br /&gt;
&lt;br /&gt;
More changes could be found here: [https://github.com/expertiza/expertiza/pull/1129/files#diff-e2d518aed0fccbb9ab0fc9e2e1ef8683 app/helpers/assignment_helper.rb]&lt;br /&gt;
&lt;br /&gt;
The method was made generic enough to be used by both app/controllers/student_teams_controller.rb (for student) and app/controllers/teams_controller.rb (for instructors).&lt;br /&gt;
&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/1129/files#diff-113f035d853c52fdfd3a00851a3db407 app/controllers/student_teams_controller.rb(for student)]&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/1129/files#diff-7543048f54ac556dff85edee281fafd8 app/controllers/teams_controller.rb(for instructors)]&lt;br /&gt;
&lt;br /&gt;
For student, we checked if student can actually send invites or not, and based on that we fetched the participant list.&lt;br /&gt;
We considered below cases for verifying if a student can send invite or not:&lt;br /&gt;
&lt;br /&gt;
*Student can't send invite if student doesn\’t have a team&lt;br /&gt;
*Student can't send invite if current team size is 1 and assignment\’s allowed team size is also 1&lt;br /&gt;
*Student can send invite if assignment\’s allowed team size is &amp;gt;1 and current team size is less than allowed team size&lt;br /&gt;
*Student can't send invite if current team size is equal to allowed team size&lt;br /&gt;
*Student can't send invite if assignment is in finished stage&lt;br /&gt;
*Student can send invite if assignment is not in finished state&lt;br /&gt;
&lt;br /&gt;
The table containing the list of students to send an invite to was created/not created based on above criteria only.&lt;br /&gt;
&lt;br /&gt;
For Instructor, there were no such criteria to be considered. &lt;br /&gt;
&lt;br /&gt;
== Modified Files ==&lt;br /&gt;
1)Conrollers:-&lt;br /&gt;
*app/controllers/student_teams_controller.rb&lt;br /&gt;
*app/controllers/teams_controller.rb&lt;br /&gt;
2)Helper:-&lt;br /&gt;
*app/helpers/assignment_helper.rb&lt;br /&gt;
3)Views:-&lt;br /&gt;
*app/views/join_team_requests/_list_not_initiated.html.erb&lt;br /&gt;
*app/views/join_team_requests/_list_received.html.erb&lt;br /&gt;
*app/views/join_team_requests/_list_sent.html.erb&lt;br /&gt;
*app/views/sign_up_sheet/_add_signup_topics.html.erb&lt;br /&gt;
*app/views/sign_up_sheet/_table_line.html.erb&lt;br /&gt;
*app/views/sign_up_sheet/list.html.erb&lt;br /&gt;
*app/views/student_teams/view.html.erb&lt;br /&gt;
*app/views/teams/list.html.erb&lt;br /&gt;
4)Tests:-&lt;br /&gt;
*spec/controllers/student_teams_controller_spec.rb&lt;br /&gt;
*spec/features/team_invitation_spec.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
&lt;br /&gt;
=== Test Cases ===&lt;br /&gt;
&lt;br /&gt;
We will be writing automated tests to check if the changes made are working correctly. &lt;br /&gt;
&lt;br /&gt;
For that, we considered the following scenarios&lt;br /&gt;
Testing invitation criteria:-&lt;br /&gt;
*Scenario 1 - Student can't see list of students to invite if student doesn\’t have a team&lt;br /&gt;
*Scenario 2 - Student can't see list of students to invite if current team size is 1 and assignment\’s allowed team size is also 1&lt;br /&gt;
*Scenario 3 - Student can see list of students to invite if assignment\’s allowed team size is &amp;gt;1 and current team size is less than allowed team size&lt;br /&gt;
*Scenario 4 - Student can't see list of students to invite if current team size is equal to allowed team size&lt;br /&gt;
*Scenario 5 - Student can't see list of students to invite if assignment is in finished stage&lt;br /&gt;
*Scenario 6 - Student can see list of students to invite if assignment is not in finished state&lt;br /&gt;
*Scenario 7 - The list of students contains only those students who don't have a team yet or whose team is not yet complete and who have not created an advertisement link.&lt;br /&gt;
*Scenario 8 - A student can create an invitation link only if his team is not yet full.&lt;br /&gt;
*Scenario 9 - The same student who accepted the invitation link actually gets added to the team. &lt;br /&gt;
*Scenario 10 - A student won't be able to send the invitation to himself as he is already a member of that team.&lt;br /&gt;
*Scenario 11 - An instructor sees only the list of the students who do not have teams with invitation link.&lt;br /&gt;
&lt;br /&gt;
All tests could be found here: &lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/1129/files#diff-d2b8c8df44cb32268062c72be7da59fb spec/controllers/student_teams_controller_spec.rb]&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/1129/files#diff-d1d14865d734d2f66dc726c70cb1bcb9 spec/features/team_invitation_spec.rb]&lt;br /&gt;
&lt;br /&gt;
== Visual representation of changes made ==&lt;br /&gt;
&lt;br /&gt;
All other students who have not created advertisements, each student would see their list on their &amp;quot;your team&amp;quot; view so that they could invite them by an easy &amp;quot;Invite&amp;quot; link as displayed below:&lt;br /&gt;
&lt;br /&gt;
[[File:Invite_unity_id_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
[[File:Join_request_main_page_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
==Team Information==&lt;br /&gt;
[mailto:tpahuja@ncsu.edu Tushar Pahuja]&amp;lt;br&amp;gt;&lt;br /&gt;
[mailto:pmgandh2@ncsu.edu Pragam Manoj Gandhi]&amp;lt;br&amp;gt;&lt;br /&gt;
[mailto:knielar@ncsu.edu Nielarshi Kumar]&amp;lt;br&amp;gt;&lt;br /&gt;
[mailto:abhardw3@ncsu.edu Abhishek Bhardwaj]&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2017/E1793._Help_students_find_teams_to_join_Team1964&amp;diff=114681</id>
		<title>CSC/ECE 517 Fall 2017/E1793. Help students find teams to join Team1964</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2017/E1793._Help_students_find_teams_to_join_Team1964&amp;diff=114681"/>
		<updated>2017-12-11T19:01:45Z</updated>

		<summary type="html">&lt;p&gt;Knielar: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== About Expertiza ==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a Ruby on Rails based Open Source project. It is a collaboration tool which lets users with different roles (student, instructor, teaching assistant) to collaborate on a course in an institution. A collaboration could be for an assignment where students teams up for an assignment and instructors grades them on the basis of their submission. Students could review other's works and give feedback as well.&lt;br /&gt;
&lt;br /&gt;
===Github link===&lt;br /&gt;
*https://github.com/expertiza/expertiza&lt;br /&gt;
&lt;br /&gt;
===Wiki link===&lt;br /&gt;
*http://wiki.expertiza.ncsu.edu/index.php/Expertiza_documentation&lt;br /&gt;
&lt;br /&gt;
==='''Problem Statement'''===&lt;br /&gt;
*For team-based assignments, it always takes time to find suitable team members. &lt;br /&gt;
&lt;br /&gt;
*We already have bidding, which could help you to join a team with other team members hold similar bidding preferences. However, a student may not be satisfied with automated team formation and want to switch to another team. &lt;br /&gt;
&lt;br /&gt;
*'''In this project, we will build a new feature to help students find teams to join.'''&lt;br /&gt;
&lt;br /&gt;
Currently, there are 2 ways to find other students to join your team:&lt;br /&gt;
&lt;br /&gt;
*If your team is not full, you could invite people by inputting his/her UnityID. It will send an invitation to a certain user. If s/he accept your invitation,s/he will leave the original team and join your team.&lt;br /&gt;
&lt;br /&gt;
*You could create an advisement by clicking “Your team” link and then clicking “Create” link under “Advertisement for teammates” section. Then your advertisement will appear the last column of the signup sheet page with a horn icon. In this way, all classmates could see your advisement. Someone could send a request to join your team. If you accept their request, s/he will leave original team and join in your team. &lt;br /&gt;
&lt;br /&gt;
Below screenshots represents the description above.&lt;br /&gt;
&lt;br /&gt;
Student: Advertisement icon doesn't appear in Chrome browser.&lt;br /&gt;
&lt;br /&gt;
[[File:A_chrome_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Instructor: Advertisement icon doesn't appear in Chrome browser.&lt;br /&gt;
&lt;br /&gt;
[[File:A_instructor_cr_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Advertisement icon appears in Mozilla browser but not in the cell it should appear rather it is visible under &amp;quot;Actions&amp;quot; column.&lt;br /&gt;
&lt;br /&gt;
[[File:A_mozilla_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Change Request requirements:'''&lt;br /&gt;
*Students whose team is not full yet to be able to see a list of students who don’t already have teams.&lt;br /&gt;
*Students should have an option of inviting other students to join their teams.&lt;br /&gt;
*Instructors should be able to view a list of students who don't have teams.&lt;br /&gt;
&lt;br /&gt;
== Task Description ==&lt;br /&gt;
&lt;br /&gt;
====Change Request 1====&lt;br /&gt;
Fix the second way to find other students to join your team. Currently, after you create ​an​ ​advertisement,​ ​the​ ​horn​ ​icon​ ​does​ ​not​ ​appear​ ​in the​ ​the​ ​last​ ​column​ ​of​ ​the​ ​signup​ ​sheet.&lt;br /&gt;
&lt;br /&gt;
=====What did we do?=====&lt;br /&gt;
&lt;br /&gt;
We found out that the problem was due to the name of horn icon. Certain ad blockers blocks any element with name ad or advertisement and horn icon was named as ad.png.&lt;br /&gt;
We renamed it to ad_horn.png and it resolved the issue.&lt;br /&gt;
&lt;br /&gt;
We also found out that the issue was also due to some complex table cell population. When a the signment was not in finished stage, actions were put into a td cell and displayed, which was adding an extra row, but this was only for users who had signed up some topic. In other case, the cell was not created everytime, forcing table row to have lesser columns. &lt;br /&gt;
&lt;br /&gt;
We removed the conditional td creation, and added all conditional checks inside a parent td, which ensured that even if a user has no action to display, atleast a td will be created.&lt;br /&gt;
&lt;br /&gt;
====Change Request 2====&lt;br /&gt;
For​ ​student​ ​end:  Display​ ​a​ ​list​ ​of​ ​​students​ ​who​ ​do​ ​not​ ​have​ ​a​ ​team​ ​with​ ​invitation​ ​links​ ​in student_teams#view​ ​page ○ You​ ​could​ ​invite​ ​students​ ​to​ ​your​ ​team​ ​by​ ​clicking​ ​invitation​ ​links.​ ​If​ ​s/he​ ​accept your​ ​invitation,s/he​ ​will​ ​leave​  the original​ ​team​ ​and​ ​join​ ​in​ ​your​ ​team.​ ​It​ ​will​ ​be​ ​more straightforward​ ​than​ ​typing​ ​UnityID.&lt;br /&gt;
&lt;br /&gt;
====Change Request 3====&lt;br /&gt;
For​ ​instructor​ ​end:  Display​ ​a​ ​list​ ​of​ ​​students​ ​who​ ​do​ ​not​ ​have​ ​team​ ​with​ ​invitation​ ​links​ ​in​ ​teams#list page &lt;br /&gt;
&lt;br /&gt;
=====What did we do?=====&lt;br /&gt;
'''This has solution step for CR2 and CR3.'''&lt;br /&gt;
&lt;br /&gt;
We created a helper method to fetch all participants from the database who did not have a team or whose teams have only one member(themselves). &lt;br /&gt;
We used Join queries to join tables participants, team_users, and teams to extract participants associated with the assignment with or without teams and then filtered out participants with team size &amp;gt; 1.&lt;br /&gt;
&lt;br /&gt;
'''def extract_assignment_participants(assignment_id, excluded_id = nil)'''&lt;br /&gt;
&lt;br /&gt;
Above method was defined in app/helpers/assignment_helper.rb.&lt;br /&gt;
The second parameter was required to exclude current student's id to be excluded to be returned for student whereas, for an Instructor, all students without teams or with single-member team had to be returned.&lt;br /&gt;
&lt;br /&gt;
More changes could be found here: [https://github.com/expertiza/expertiza/pull/1129/files#diff-e2d518aed0fccbb9ab0fc9e2e1ef8683 app/helpers/assignment_helper.rb]&lt;br /&gt;
&lt;br /&gt;
The method was made generic enough to be used by both app/controllers/student_teams_controller.rb (for student) and app/controllers/teams_controller.rb (for instructors).&lt;br /&gt;
&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/1129/files#diff-113f035d853c52fdfd3a00851a3db407 app/controllers/student_teams_controller.rb(for student)]&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/1129/files#diff-7543048f54ac556dff85edee281fafd8 app/controllers/teams_controller.rb(for instructors)]&lt;br /&gt;
&lt;br /&gt;
For student, we checked if student can actually send invites or not, and based on that we fetched the participant list.&lt;br /&gt;
We considered below cases for verifying if a student can send invite or not:&lt;br /&gt;
&lt;br /&gt;
*Student can't send invite if student doesn\’t have a team&lt;br /&gt;
*Student can't send invite if current team size is 1 and assignment\’s allowed team size is also 1&lt;br /&gt;
*Student can send invite if assignment\’s allowed team size is &amp;gt;1 and current team size is less than allowed team size&lt;br /&gt;
*Student can't send invite if current team size is equal to allowed team size&lt;br /&gt;
*Student can't send invite if assignment is in finished stage&lt;br /&gt;
*Student can send invite if assignment is not in finished state&lt;br /&gt;
&lt;br /&gt;
The table containing the list of students to send an invite to was created/not created based on above criteria only.&lt;br /&gt;
&lt;br /&gt;
For Instructor, there were no such criteria to be considered. &lt;br /&gt;
&lt;br /&gt;
== Modified Files ==&lt;br /&gt;
1)Conrollers:-&lt;br /&gt;
*app/controllers/student_teams_controller.rb&lt;br /&gt;
*app/controllers/teams_controller.rb&lt;br /&gt;
2)Helper:-&lt;br /&gt;
*app/helpers/assignment_helper.rb&lt;br /&gt;
3)Views:-&lt;br /&gt;
*app/views/join_team_requests/_list_not_initiated.html.erb&lt;br /&gt;
*app/views/join_team_requests/_list_received.html.erb&lt;br /&gt;
*app/views/join_team_requests/_list_sent.html.erb&lt;br /&gt;
*app/views/sign_up_sheet/_add_signup_topics.html.erb&lt;br /&gt;
*app/views/sign_up_sheet/_table_line.html.erb&lt;br /&gt;
*app/views/sign_up_sheet/list.html.erb&lt;br /&gt;
*app/views/student_teams/view.html.erb&lt;br /&gt;
*app/views/teams/list.html.erb&lt;br /&gt;
4)Tests:-&lt;br /&gt;
*spec/controllers/student_teams_controller_spec.rb&lt;br /&gt;
*spec/features/team_invitation_spec.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
&lt;br /&gt;
=== Test Cases ===&lt;br /&gt;
&lt;br /&gt;
We will be writing automated tests to check if the changes made are working correctly. &lt;br /&gt;
&lt;br /&gt;
For that, we considered the following scenarios&lt;br /&gt;
Testing invitation criteria:-&lt;br /&gt;
*Scenario 1 - Student can't see list of students to invite if student doesn\’t have a team&lt;br /&gt;
*Scenario 2 - Student can't see list of students to invite if current team size is 1 and assignment\’s allowed team size is also 1&lt;br /&gt;
*Scenario 3 - Student can see list of students to invite if assignment\’s allowed team size is &amp;gt;1 and current team size is less than allowed team size&lt;br /&gt;
*Scenario 4 - Student can't see list of students to invite if current team size is equal to allowed team size&lt;br /&gt;
*Scenario 5 - Student can't see list of students to invite if assignment is in finished stage&lt;br /&gt;
*Scenario 6 - Student can see list of students to invite if assignment is not in finished state&lt;br /&gt;
*Scenario 7 - The list of students contains only those students who don't have a team yet or whose team is not yet complete and who have not created an advertisement link.&lt;br /&gt;
*Scenario 8 - A student can create an invitation link only if his team is not yet full.&lt;br /&gt;
*Scenario 9 - The same student who accepted the invitation link actually gets added to the team. &lt;br /&gt;
*Scenario 10 - A student won't be able to send the invitation to himself as he is already a member of that team.&lt;br /&gt;
*Scenario 11 - An instructor sees only the list of the students who do not have teams with invitation link.&lt;br /&gt;
&lt;br /&gt;
All tests could be found here: &lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/1129/files#diff-d2b8c8df44cb32268062c72be7da59fb spec/controllers/student_teams_controller_spec.rb]&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/1129/files#diff-d1d14865d734d2f66dc726c70cb1bcb9 spec/features/team_invitation_spec.rb]&lt;br /&gt;
&lt;br /&gt;
== Visual representation of changes made ==&lt;br /&gt;
&lt;br /&gt;
All other students who have not created advertisements, each student would see their list on their &amp;quot;your team&amp;quot; view so that they could invite them by an easy &amp;quot;Invite&amp;quot; link as displayed below:&lt;br /&gt;
&lt;br /&gt;
[[File:Invite_unity_id_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
[[File:Join_request_main_page_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
==Team Information==&lt;br /&gt;
[mailto:tpahuja@ncsu.edu Tushar Pahuja]&amp;lt;br&amp;gt;&lt;br /&gt;
[mailto:pmgandh2@ncsu.edu Pragam Manoj Gandhi]&amp;lt;br&amp;gt;&lt;br /&gt;
[mailto:knielar@ncsu.edu Nielarshi Kumar]&amp;lt;br&amp;gt;&lt;br /&gt;
[mailto:abhardw3@ncsu.edu Abhishek Bhardwaj]&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2017/E1793._Help_students_find_teams_to_join_Team1964&amp;diff=114680</id>
		<title>CSC/ECE 517 Fall 2017/E1793. Help students find teams to join Team1964</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2017/E1793._Help_students_find_teams_to_join_Team1964&amp;diff=114680"/>
		<updated>2017-12-11T18:52:07Z</updated>

		<summary type="html">&lt;p&gt;Knielar: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== About Expertiza ==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a Ruby on Rails based Open Source project. It is a collaboration tool which lets users with different roles (student, instructor, teaching assistant) to collaborate on a course in an institution. A collaboration could be for an assignment where students teams up for an assignment and instructors grades them on the basis of their submission. Students could review other's works and give feedback as well.&lt;br /&gt;
&lt;br /&gt;
===Github link===&lt;br /&gt;
*https://github.com/expertiza/expertiza&lt;br /&gt;
&lt;br /&gt;
===Wiki link===&lt;br /&gt;
*http://wiki.expertiza.ncsu.edu/index.php/Expertiza_documentation&lt;br /&gt;
&lt;br /&gt;
==='''Problem Statement'''===&lt;br /&gt;
*For team-based assignments, it always takes time to find suitable team members. &lt;br /&gt;
&lt;br /&gt;
*We already have bidding, which could help you to join a team with other team members hold similar bidding preferences. However, a student may not be satisfied with automated team formation and want to switch to another team. &lt;br /&gt;
&lt;br /&gt;
*'''In this project, we will build a new feature to help students find teams to join.'''&lt;br /&gt;
&lt;br /&gt;
Currently, there are 2 ways to find other students to join your team:&lt;br /&gt;
&lt;br /&gt;
*If your team is not full, you could invite people by inputting his/her UnityID. It will send an invitation to a certain user. If s/he accept your invitation,s/he will leave the original team and join your team.&lt;br /&gt;
&lt;br /&gt;
*You could create an advisement by clicking “Your team” link and then clicking “Create” link under “Advertisement for teammates” section. Then your advertisement will appear the last column of the signup sheet page with a horn icon. In this way, all classmates could see your advisement. Someone could send a request to join your team. If you accept their request, s/he will leave original team and join in your team. &lt;br /&gt;
&lt;br /&gt;
Below screenshots represents the description above.&lt;br /&gt;
&lt;br /&gt;
Student: Advertisement icon doesn't appear in Chrome browser.&lt;br /&gt;
&lt;br /&gt;
[[File:A_chrome_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Instructor: Advertisement icon doesn't appear in Chrome browser.&lt;br /&gt;
&lt;br /&gt;
[[File:A_instructor_cr_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Advertisement icon appears in Mozilla browser but not in the cell it should appear rather it is visible under &amp;quot;Actions&amp;quot; column.&lt;br /&gt;
&lt;br /&gt;
[[File:A_mozilla_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Change Request requirements:'''&lt;br /&gt;
*Students whose team is not full yet to be able to see a list of students who don’t already have teams.&lt;br /&gt;
*Students should have an option of inviting other students to join their teams.&lt;br /&gt;
*Instructors should be able to view a list of students who don't have teams.&lt;br /&gt;
&lt;br /&gt;
== Task Description ==&lt;br /&gt;
&lt;br /&gt;
====Change Request 1====&lt;br /&gt;
Fix the second way to find other students to join your ​team. Currently,​ ​after​ ​you​ ​create​ ​an​ ​advertisement,​ ​the​ ​horn​ ​icon​ ​does​ ​not​ ​appear​ ​in the​ ​the​ ​last​ ​column​ ​of​ ​the​ ​signup​ ​sheet.&lt;br /&gt;
&lt;br /&gt;
=====What did we do?=====&lt;br /&gt;
&lt;br /&gt;
We found out that the problem was due to the name of horn icon. Certain ad blockers blocks any element with name ad or advertisement and horn icon was named as ad.png.&lt;br /&gt;
We renamed it to ad_horn.png and it resolved the issue.&lt;br /&gt;
&lt;br /&gt;
We also found out that the issue was also due to some complex table cell population. When assignment was not in finished stage, actions were put into a td cell and displayed, which was adding an extra row, but this was only for users who had signed up some topic. In other case, the cell was not created everytime, forcing table row to have lesser columns. &lt;br /&gt;
&lt;br /&gt;
We removed the conditional td creation, and added all conditional checks inside a parent td, which ensured that even if a user has no action to display, atleast a td will be created.&lt;br /&gt;
&lt;br /&gt;
====Change Request 2====&lt;br /&gt;
For​ ​student​ ​end:  Display​ ​a​ ​list​ ​of​ ​​students​ ​who​ ​do​ ​not​ ​have​ ​a​ ​team​ ​with​ ​invitation​ ​links​ ​in student_teams#view​ ​page ○ You​ ​could​ ​invite​ ​students​ ​to​ ​your​ ​team​ ​by​ ​clicking​ ​invitation​ ​links.​ ​If​ ​s/he​ ​accept your​ ​invitation,s/he​ ​will​ ​leave​  the original​ ​team​ ​and​ ​join​ ​in​ ​your​ ​team.​ ​It​ ​will​ ​be​ ​more straightforward​ ​than​ ​typing​ ​UnityID.&lt;br /&gt;
&lt;br /&gt;
====Change Request 3====&lt;br /&gt;
For​ ​instructor​ ​end:  Display​ ​a​ ​list​ ​of​ ​​students​ ​who​ ​do​ ​not​ ​have​ ​team​ ​with​ ​invitation​ ​links​ ​in​ ​teams#list page &lt;br /&gt;
&lt;br /&gt;
=====What did we do?=====&lt;br /&gt;
This has solution step for CR2 and CR3.&lt;br /&gt;
&lt;br /&gt;
We created a helper method to fetch all participants from database who did not have a team or whose teams has only one member(themselves). &lt;br /&gt;
We used Join queries to join tables participants, team_users, and teams to extract participants associated with the assignment with or without teams and then filtered out participants with team size &amp;gt; 1.&lt;br /&gt;
&lt;br /&gt;
def extract_assignment_participants(assignment_id, excluded_id = nil)&lt;br /&gt;
&lt;br /&gt;
Above method was defined in app/helpers/assignment_helper.rb.&lt;br /&gt;
The second parameter was required to exclude current student's id to be excluded to be returned for student whereas, for an Instructor, all students without teams or with single member team had to be returned.&lt;br /&gt;
&lt;br /&gt;
More changes could be found here: [https://github.com/expertiza/expertiza/pull/1129/files#diff-e2d518aed0fccbb9ab0fc9e2e1ef8683]&lt;br /&gt;
&lt;br /&gt;
The method was made generic enough to be used by both app/controllers/student_teams_controller.rb (for student) and app/controllers/teams_controller.rb (for instructors).&lt;br /&gt;
&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/1129/files#diff-113f035d853c52fdfd3a00851a3db407]&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/1129/files#diff-7543048f54ac556dff85edee281fafd8]&lt;br /&gt;
&lt;br /&gt;
For student, we checked if student can actually send invites or not, and based on that we fetched the participant list.&lt;br /&gt;
We considered below cases for verifying if a student can send invite or not:&lt;br /&gt;
&lt;br /&gt;
*Student can't send invite if student doesn\’t have a team&lt;br /&gt;
*Student can't send invite if current team size is 1 and assignment\’s allowed team size is also 1&lt;br /&gt;
*Student can send invite if assignment\’s allowed team size is &amp;gt;1 and current team size is less than allowed team size&lt;br /&gt;
*Student can't send invite if current team size is equal to allowed team size&lt;br /&gt;
*Student can't send invite if assignment is in finished stage&lt;br /&gt;
*Student can send invite if assignment is not in finished state&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Modified Files ==&lt;br /&gt;
1)Conrollers:-&lt;br /&gt;
*app/controllers/student_teams_controller.rb&lt;br /&gt;
*app/controllers/teams_controller.rb&lt;br /&gt;
2)Helper:-&lt;br /&gt;
*app/helpers/assignment_helper.rb&lt;br /&gt;
3)Views:-&lt;br /&gt;
*app/views/join_team_requests/_list_not_initiated.html.erb&lt;br /&gt;
*app/views/join_team_requests/_list_received.html.erb&lt;br /&gt;
*app/views/join_team_requests/_list_sent.html.erb&lt;br /&gt;
*app/views/sign_up_sheet/_add_signup_topics.html.erb&lt;br /&gt;
*app/views/sign_up_sheet/_table_line.html.erb&lt;br /&gt;
*app/views/sign_up_sheet/list.html.erb&lt;br /&gt;
*app/views/student_teams/view.html.erb&lt;br /&gt;
*app/views/teams/list.html.erb&lt;br /&gt;
4)Tests:-&lt;br /&gt;
*spec/controllers/student_teams_controller_spec.rb&lt;br /&gt;
*spec/features/team_invitation_spec.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
&lt;br /&gt;
=== Test Cases ===&lt;br /&gt;
&lt;br /&gt;
We will be writing automated tests to check if the changes made are working correctly. &lt;br /&gt;
&lt;br /&gt;
For that, we considered the following scenarios&lt;br /&gt;
Testing invitation criteria:-&lt;br /&gt;
*Scenario 1 - Student can't see list of students to invite if student doesn\’t have a team&lt;br /&gt;
*Scenario 2 - Student can't see list of students to invite if current team size is 1 and assignment\’s allowed team size is also 1&lt;br /&gt;
*Scenario 3 - Student can see list of students to invite if assignment\’s allowed team size is &amp;gt;1 and current team size is less than allowed team size&lt;br /&gt;
*Scenario 4 - Student can't see list of students to invite if current team size is equal to allowed team size&lt;br /&gt;
*Scenario 5 - Student can't see list of students to invite if assignment is in finished stage&lt;br /&gt;
*Scenario 6 - Student can see list of students to invite if assignment is not in finished state&lt;br /&gt;
*Scenario 7 - The list of students contains only those students who don't have a team yet or whose team is not yet complete and who have not created an advertisement link.&lt;br /&gt;
*Scenario 8 - A student can create an invitation link only if his team is not yet full.&lt;br /&gt;
*Scenario 9 - The same student who accepted the invitation link actually gets added to the team. &lt;br /&gt;
*Scenario 10 - A student won't be able to send the invitation to himself as he is already a member of that team.&lt;br /&gt;
*Scenario 11 - An instructor sees only the list of the students who do not have teams with invitation link.&lt;br /&gt;
&lt;br /&gt;
== Visual representation of changes made ==&lt;br /&gt;
&lt;br /&gt;
All other students who have not created advertisements, each student would see their list on their &amp;quot;your team&amp;quot; view so that they could invite them by an easy &amp;quot;Invite&amp;quot; link as displayed below:&lt;br /&gt;
&lt;br /&gt;
[[File:Invite_unity_id_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
[[File:Join_request_main_page_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
==Team Information==&lt;br /&gt;
[mailto:tpahuja@ncsu.edu Tushar Pahuja]&amp;lt;br&amp;gt;&lt;br /&gt;
[mailto:pmgandh2@ncsu.edu Pragam Manoj Gandhi]&amp;lt;br&amp;gt;&lt;br /&gt;
[mailto:knielar@ncsu.edu Nielarshi Kumar]&amp;lt;br&amp;gt;&lt;br /&gt;
[mailto:abhardw3@ncsu.edu Abhishek Bhardwaj]&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Uml-action-da.jpg&amp;diff=113434</id>
		<title>File:Uml-action-da.jpg</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Uml-action-da.jpg&amp;diff=113434"/>
		<updated>2017-11-15T02:38:34Z</updated>

		<summary type="html">&lt;p&gt;Knielar: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2017/E1793._Help_students_find_teams_to_join_Team1964&amp;diff=113432</id>
		<title>CSC/ECE 517 Fall 2017/E1793. Help students find teams to join Team1964</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2017/E1793._Help_students_find_teams_to_join_Team1964&amp;diff=113432"/>
		<updated>2017-11-15T02:38:06Z</updated>

		<summary type="html">&lt;p&gt;Knielar: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== About Expertiza ==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a Ruby on Rails based Open Source project. It is a collaboration tool which lets users with different roles (student, instructor, teaching assistant) to collaborate on a course in an institution. A collaboration could be for an assignment where students teams up for an assignment and instructors grades them on the basis of their submission. Students could review other's works and give feedback as well.&lt;br /&gt;
&lt;br /&gt;
===Github link===&lt;br /&gt;
*https://github.com/expertiza/expertiza&lt;br /&gt;
&lt;br /&gt;
===Wiki link===&lt;br /&gt;
*http://wiki.expertiza.ncsu.edu/index.php/Expertiza_documentation&lt;br /&gt;
&lt;br /&gt;
==='''Problem Statement'''===&lt;br /&gt;
*For team-based assignments, it always takes time to find suitable team members. &lt;br /&gt;
&lt;br /&gt;
*We already have bidding, which could help you to join a team with other team members hold similar bidding preferences. However, a student may not be satisfied with automated team formation and want to switch to another team. &lt;br /&gt;
&lt;br /&gt;
*'''In this project, we will build a new feature to help students find teams to join.'''&lt;br /&gt;
&lt;br /&gt;
Currently, there are 2 ways to find other students to join your team:&lt;br /&gt;
&lt;br /&gt;
*If your team is not full, you could invite people by inputting his/her UnityID. It will send an invitation to a certain user. If s/he accept your invitation,s/he will leave the original team and join your team.&lt;br /&gt;
&lt;br /&gt;
*You could create an advisement by clicking “Your team” link and then clicking “Create” link under “Advertisement for teammates” section. Then your advertisement will appear the last column of the signup sheet page with a horn icon. In this way, all classmates could see your advisement. Someone could send a request to join your team. If you accept their request, s/he will leave original team and join in your team. &lt;br /&gt;
&lt;br /&gt;
Below screenshots represents the description above.&lt;br /&gt;
&lt;br /&gt;
Student: Advertisement icon doesn't appear in Chrome browser.&lt;br /&gt;
&lt;br /&gt;
[[File:A_chrome_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Instructor: Advertisement icon doesn't appear in Chrome browser.&lt;br /&gt;
&lt;br /&gt;
[[File:A_instructor_cr_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Advertisement icon appears in Mozilla browser but not in the cell it should appear rather it is visible under &amp;quot;Actions&amp;quot; column.&lt;br /&gt;
&lt;br /&gt;
[[File:A_mozilla_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Sending invitation to a particular student using their unity id as per below.&lt;br /&gt;
&lt;br /&gt;
[[File:Invite_unity_id_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Creating advertisements for joining a team (this is available only after signing up a topic).&lt;br /&gt;
&lt;br /&gt;
[[File:A_by_teammate_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
'''Change Request requirements:'''&lt;br /&gt;
*Students who do not have a team yet or whose team is not full yet to be able to see a list of students who don’t already have teams.&lt;br /&gt;
*Students should have an option of inviting other students to join their teams.&lt;br /&gt;
*Instructors should be able to view a list of students who don't have teams.&lt;br /&gt;
&lt;br /&gt;
== Task Description ==&lt;br /&gt;
&lt;br /&gt;
====Change Request 1====&lt;br /&gt;
Fix the second way to find other students to join​ ​your​ ​team. Currently,​ ​after​ ​you​ ​create​ ​an​ ​advertisement,​ ​the​ ​horn​ ​icon​ ​does​ ​not​ ​appear​ ​in the​ ​the​ ​last​ ​column​ ​of​ ​the​ ​signup​ ​sheet.&lt;br /&gt;
&lt;br /&gt;
====Change Request 2====&lt;br /&gt;
For​ ​student​ ​end:  Display​ ​a​ ​list​ ​of​ ​​students​ ​who​ ​do​ ​not​ ​have​ ​a​ ​team​ ​with​ ​invitation​ ​links​ ​in student_teams#view​ ​page ○ You​ ​could​ ​invite​ ​students​ ​to​ ​your​ ​team​ ​by​ ​clicking​ ​invitation​ ​links.​ ​If​ ​s/he​ ​accept your​ ​invitation,s/he​ ​will​ ​leave​  the original​ ​team​ ​and​ ​join​ ​in​ ​your​ ​team.​ ​It​ ​will​ ​be​ ​more straightforward​ ​than​ ​typing​ ​UnityID.&lt;br /&gt;
&lt;br /&gt;
====Change Request 3====&lt;br /&gt;
For​ ​instructor​ ​end:  Display​ ​a​ ​list​ ​of​ ​​students​ ​who​ ​do​ ​not​ ​have​ ​team​ ​with​ ​invitation​ ​links​ ​in​ ​teams#list page &lt;br /&gt;
&lt;br /&gt;
== '''USE CASE SCENARIO''' ==&lt;br /&gt;
&lt;br /&gt;
'''For Students'''&lt;br /&gt;
&lt;br /&gt;
*USE CASE 1- &lt;br /&gt;
A student can create advertisement links for his/her team, which can be used by other students to join their team.&lt;br /&gt;
&lt;br /&gt;
*USE CASE 2- &lt;br /&gt;
A student can click on an advertisement link to join a team&lt;br /&gt;
&lt;br /&gt;
*USE CASE 3- &lt;br /&gt;
A student can view a list of advertisement links.&lt;br /&gt;
&lt;br /&gt;
*USE CASE 4- &lt;br /&gt;
A student can respond to other students who requested to join his/her team by clicking on the invitation link.&lt;br /&gt;
&lt;br /&gt;
*USE CASE 5- &lt;br /&gt;
A student can send an invite to other students to join his/her team using their unity ID.&lt;br /&gt;
&lt;br /&gt;
*USE CASE 6-&lt;br /&gt;
A student can accept an invitation for joining a team.&lt;br /&gt;
&lt;br /&gt;
*USE CASE 7- &lt;br /&gt;
A student can see a list of students without teams. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''For Intructors'''&lt;br /&gt;
&lt;br /&gt;
*USE CASE 1- &lt;br /&gt;
An Instructor can view a list of students without teams. &lt;br /&gt;
&lt;br /&gt;
*USE CASE 2- &lt;br /&gt;
An Instructor can view a list of teams. &lt;br /&gt;
&lt;br /&gt;
*USE CASE 3- &lt;br /&gt;
An Instructor can view a separate list of students who don’t have teams yet.&lt;br /&gt;
&lt;br /&gt;
*USE CASE 4- &lt;br /&gt;
An Instructor can add a student to a team. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Uml-action-da.jpg|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
&lt;br /&gt;
=== Edge cases ===&lt;br /&gt;
&lt;br /&gt;
We will be writing automated tests to check if the changes made are working correctly. &lt;br /&gt;
&lt;br /&gt;
For that, we considered the following scenarios&lt;br /&gt;
&lt;br /&gt;
*If the team is full, the person who received an invitation link would not be able to accept that. &lt;br /&gt;
*If a student leaves a team, then he is able to see his previous teammates in the available list of students that do not have a complete team and have not created an invitation link.&lt;br /&gt;
*Student sees a horn icon in the last column if any of the students have created an advertisement for that topic.&lt;br /&gt;
*The list of students contains only those students who don't have a team yet or whose team is not yet complete and who have not created an advertisement link.&lt;br /&gt;
*A student can create an invitation link only if his team is not yet full.&lt;br /&gt;
*The same student who accepted the invitation link actually gets added to the team. &lt;br /&gt;
*A student won't be able to send the invitation to himself as he is already a member of that team.&lt;br /&gt;
*An instructor sees only the list of the students who do not have teams with invitation link.&lt;br /&gt;
*If a student joins a team using an invitation link, then he gets all the rights that a team member of that team has. Ex: Now, he will be able to approve a team join request and then correspondingly send the invitation for joining the group to that student.&lt;br /&gt;
&lt;br /&gt;
== Visual representation of planned changes ==&lt;br /&gt;
&lt;br /&gt;
Inviting students by creating an advertisement.&lt;br /&gt;
&lt;br /&gt;
Once a student creates an advertisement, it would appear in the sign up sheet as below.&lt;br /&gt;
It would be visible to all other students visiting sign up sheet.&lt;br /&gt;
&lt;br /&gt;
[[File:A_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Once a student decides to respond to the advertisement, he clicks on the icon corresponding to the team and topic. He sees the description of the advertisement and a link to respond to it.&lt;br /&gt;
&lt;br /&gt;
[[File:A_request_invitation_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
The student would be presented by a form as below once he/she chooses to request for an invitation.&lt;br /&gt;
&lt;br /&gt;
[[File:A_response.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Student would respond by completing the form and clicking on create. His request would be confirmed by showing a screen as below:&lt;br /&gt;
&lt;br /&gt;
[[File:Join_request_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Team receiving the request would see the incoming request on his &amp;quot;your team&amp;quot; view, from where he could send invites for joining the team.&lt;br /&gt;
&lt;br /&gt;
*Note - this approach was considered to avoid random assignment of student into a team.&lt;br /&gt;
A student could chose more than 1 team to respond to their advertisements. In that case, the team accepting 1st would get the student into their team and it would be complex to handle the other invitations as the student who has sent the invitation would be juggling around or may not be able to choose the best fit.&lt;br /&gt;
&lt;br /&gt;
*Our take - Each student may choose to respond to more than 1 advertisements but also should have choice of selecting teams as per their comfort.&lt;br /&gt;
&lt;br /&gt;
When a student respond to an advertisement, the team receiving it should send an invitation if they find the student matching the criteria and the student then choose to accept one out of all the invitation he receives.&lt;br /&gt;
&lt;br /&gt;
Below screenshots shows the steps:&lt;br /&gt;
&lt;br /&gt;
The team who has got a response on their advertisement would see the incoming request, which they can accept or decline.&lt;br /&gt;
&lt;br /&gt;
[[File:Received_request_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Once the team accepts the invitation, an invite would be sent to the student to join the team. The team could see their sent invitation as below:&lt;br /&gt;
&lt;br /&gt;
[[File:Sent_invitation_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
The student sees the invitation on his/her &amp;quot;your team&amp;quot; view as below:&lt;br /&gt;
&lt;br /&gt;
[[File:Received_invitation_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Once the student chooses to accept the invitation, he/she could click on the accept link, upon which the user would be presented with a prompt dialog to confirm the acceptance&lt;br /&gt;
as the student would be removed from the current team and placed into the team whose invitation he/she would accept.&lt;br /&gt;
&lt;br /&gt;
[[File:Accept_invitation_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Upon successful acceptance, he/she becomes a member of the team.&lt;br /&gt;
&lt;br /&gt;
[[File:Accepted_request_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
All other students who have not created advertisements, each student would see their list on their &amp;quot;your team&amp;quot; view so that they could invite them by an easy &amp;quot;Invite&amp;quot; link as displayed below:&lt;br /&gt;
&lt;br /&gt;
[[File:Invite_unity_id_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
[[File:Join_request_main_page_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
==Team Information==&lt;br /&gt;
[mailto:tpahuja@ncsu.edu Tushar Pahuja]&amp;lt;br&amp;gt;&lt;br /&gt;
[mailto:pmgandh2@ncsu.edu Pragam Manoj Gandhi]&amp;lt;br&amp;gt;&lt;br /&gt;
[mailto:knielar@ncsu.edu Nielarshi Kumar]&amp;lt;br&amp;gt;&lt;br /&gt;
[mailto:abhardw3@ncsu.edu Abhishek Bhardwaj]&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Uml-advertisement.jpg&amp;diff=113428</id>
		<title>File:Uml-advertisement.jpg</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Uml-advertisement.jpg&amp;diff=113428"/>
		<updated>2017-11-15T02:35:20Z</updated>

		<summary type="html">&lt;p&gt;Knielar: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2017/E1793._Help_students_find_teams_to_join_Team1964&amp;diff=113427</id>
		<title>CSC/ECE 517 Fall 2017/E1793. Help students find teams to join Team1964</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2017/E1793._Help_students_find_teams_to_join_Team1964&amp;diff=113427"/>
		<updated>2017-11-15T02:34:46Z</updated>

		<summary type="html">&lt;p&gt;Knielar: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== About Expertiza ==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a Ruby on Rails based Open Source project. It is a collaboration tool which lets users with different roles (student, instructor, teaching assistant) to collaborate on a course in an institution. A collaboration could be for an assignment where students teams up for an assignment and instructors grades them on the basis of their submission. Students could review other's works and give feedback as well.&lt;br /&gt;
&lt;br /&gt;
===Github link===&lt;br /&gt;
*https://github.com/expertiza/expertiza&lt;br /&gt;
&lt;br /&gt;
===Wiki link===&lt;br /&gt;
*http://wiki.expertiza.ncsu.edu/index.php/Expertiza_documentation&lt;br /&gt;
&lt;br /&gt;
==='''Problem Statement'''===&lt;br /&gt;
*For team-based assignments, it always takes time to find suitable team members. &lt;br /&gt;
&lt;br /&gt;
*We already have bidding, which could help you to join a team with other team members hold similar bidding preferences. However, a student may not be satisfied with automated team formation and want to switch to another team. &lt;br /&gt;
&lt;br /&gt;
*'''In this project, we will build a new feature to help students find teams to join.'''&lt;br /&gt;
&lt;br /&gt;
Currently, there are 2 ways to find other students to join your team:&lt;br /&gt;
&lt;br /&gt;
*If your team is not full, you could invite people by inputting his/her UnityID. It will send an invitation to a certain user. If s/he accept your invitation,s/he will leave the original team and join your team.&lt;br /&gt;
&lt;br /&gt;
*You could create an advisement by clicking “Your team” link and then clicking “Create” link under “Advertisement for teammates” section. Then your advertisement will appear the last column of the signup sheet page with a horn icon. In this way, all classmates could see your advisement. Someone could send a request to join your team. If you accept their request, s/he will leave original team and join in your team. &lt;br /&gt;
&lt;br /&gt;
Below screenshots represents the description above.&lt;br /&gt;
&lt;br /&gt;
Student: Advertisement icon doesn't appear in Chrome browser.&lt;br /&gt;
&lt;br /&gt;
[[File:A_chrome_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Instructor: Advertisement icon doesn't appear in Chrome browser.&lt;br /&gt;
&lt;br /&gt;
[[File:A_instructor_cr_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Advertisement icon appears in Mozilla browser but not in the cell it should appear rather it is visible under &amp;quot;Actions&amp;quot; column.&lt;br /&gt;
&lt;br /&gt;
[[File:A_mozilla_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Sending invitation to a particular student using their unity id as per below.&lt;br /&gt;
&lt;br /&gt;
[[File:Invite_unity_id_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Creating advertisements for joining a team (this is available only after signing up a topic).&lt;br /&gt;
&lt;br /&gt;
[[File:A_by_teammate_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
'''Change Request requirements:'''&lt;br /&gt;
*Students who do not have a team yet or whose team is not full yet to be able to see a list of students who don’t already have teams.&lt;br /&gt;
*Students should have an option of inviting other students to join their teams.&lt;br /&gt;
*Instructors should be able to view a list of students who don't have teams.&lt;br /&gt;
&lt;br /&gt;
== Task Description ==&lt;br /&gt;
&lt;br /&gt;
====Change Request 1====&lt;br /&gt;
Fix the second way to find other students to join​ ​your​ ​team. Currently,​ ​after​ ​you​ ​create​ ​an​ ​advertisement,​ ​the​ ​horn​ ​icon​ ​does​ ​not​ ​appear​ ​in the​ ​the​ ​last​ ​column​ ​of​ ​the​ ​signup​ ​sheet.&lt;br /&gt;
&lt;br /&gt;
====Change Request 2====&lt;br /&gt;
For​ ​student​ ​end:  Display​ ​a​ ​list​ ​of​ ​​students​ ​who​ ​do​ ​not​ ​have​ ​a​ ​team​ ​with​ ​invitation​ ​links​ ​in student_teams#view​ ​page ○ You​ ​could​ ​invite​ ​students​ ​to​ ​your​ ​team​ ​by​ ​clicking​ ​invitation​ ​links.​ ​If​ ​s/he​ ​accept your​ ​invitation,s/he​ ​will​ ​leave​  the original​ ​team​ ​and​ ​join​ ​in​ ​your​ ​team.​ ​It​ ​will​ ​be​ ​more straightforward​ ​than​ ​typing​ ​UnityID.&lt;br /&gt;
&lt;br /&gt;
====Change Request 3====&lt;br /&gt;
For​ ​instructor​ ​end:  Display​ ​a​ ​list​ ​of​ ​​students​ ​who​ ​do​ ​not​ ​have​ ​team​ ​with​ ​invitation​ ​links​ ​in​ ​teams#list page &lt;br /&gt;
&lt;br /&gt;
== '''USE CASE SCENARIO''' ==&lt;br /&gt;
&lt;br /&gt;
'''For Students'''&lt;br /&gt;
&lt;br /&gt;
*USE CASE 1- &lt;br /&gt;
A student can create advertisement links for his/her team, which can be used by other students to join their team.&lt;br /&gt;
&lt;br /&gt;
*USE CASE 2- &lt;br /&gt;
A student can click on an advertisement link to join a team&lt;br /&gt;
&lt;br /&gt;
*USE CASE 3- &lt;br /&gt;
A student can view a list of advertisement links.&lt;br /&gt;
&lt;br /&gt;
*USE CASE 4- &lt;br /&gt;
A student can respond to other students who requested to join his/her team by clicking on the invitation link.&lt;br /&gt;
&lt;br /&gt;
*USE CASE 5- &lt;br /&gt;
A student can send an invite to other students to join his/her team using their unity ID.&lt;br /&gt;
&lt;br /&gt;
*USE CASE 6-&lt;br /&gt;
A student can accept an invitation for joining a team.&lt;br /&gt;
&lt;br /&gt;
*USE CASE 7- &lt;br /&gt;
A student can see a list of students without teams. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''For Intructors'''&lt;br /&gt;
&lt;br /&gt;
*USE CASE 1- &lt;br /&gt;
An Instructor can view a list of students without teams. &lt;br /&gt;
&lt;br /&gt;
*USE CASE 2- &lt;br /&gt;
An Instructor can view a list of teams. &lt;br /&gt;
&lt;br /&gt;
*USE CASE 3- &lt;br /&gt;
An Instructor can view a separate list of students who don’t have teams yet.&lt;br /&gt;
&lt;br /&gt;
*USE CASE 4- &lt;br /&gt;
An Instructor can add a student to a team. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Uml-advertisement.jpg|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
&lt;br /&gt;
=== Edge cases ===&lt;br /&gt;
&lt;br /&gt;
We will be writing automated tests to check if the changes made are working correctly. &lt;br /&gt;
&lt;br /&gt;
For that, we considered the following scenarios&lt;br /&gt;
&lt;br /&gt;
*If the team is full, the person who received an invitation link would not be able to accept that. &lt;br /&gt;
*If a student leaves a team, then he is able to see his previous teammates in the available list of students that do not have a complete team and have not created an invitation link.&lt;br /&gt;
*Student sees a horn icon in the last column if any of the students have created an advertisement for that topic.&lt;br /&gt;
*The list of students contains only those students who don't have a team yet or whose team is not yet complete and who have not created an advertisement link.&lt;br /&gt;
*A student can create an invitation link only if his team is not yet full.&lt;br /&gt;
*The same student who accepted the invitation link actually gets added to the team. &lt;br /&gt;
*A student won't be able to send the invitation to himself as he is already a member of that team.&lt;br /&gt;
*An instructor sees only the list of the students who do not have teams with invitation link.&lt;br /&gt;
*If a student joins a team using an invitation link, then he gets all the rights that a team member of that team has. Ex: Now, he will be able to approve a team join request and then correspondingly send the invitation for joining the group to that student.&lt;br /&gt;
&lt;br /&gt;
== Visual representation of planned changes ==&lt;br /&gt;
&lt;br /&gt;
Inviting students by creating an advertisement.&lt;br /&gt;
&lt;br /&gt;
Once a student creates an advertisement, it would appear in the sign up sheet as below.&lt;br /&gt;
It would be visible to all other students visiting sign up sheet.&lt;br /&gt;
&lt;br /&gt;
[[File:A_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Once a student decides to respond to the advertisement, he clicks on the icon corresponding to the team and topic. He sees the description of the advertisement and a link to respond to it.&lt;br /&gt;
&lt;br /&gt;
[[File:A_request_invitation_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
The student would be presented by a form as below once he/she chooses to request for an invitation.&lt;br /&gt;
&lt;br /&gt;
[[File:A_response.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Student would respond by completing the form and clicking on create. His request would be confirmed by showing a screen as below:&lt;br /&gt;
&lt;br /&gt;
[[File:Join_request_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Team receiving the request would see the incoming request on his &amp;quot;your team&amp;quot; view, from where he could send invites for joining the team.&lt;br /&gt;
&lt;br /&gt;
*Note - this approach was considered to avoid random assignment of student into a team.&lt;br /&gt;
A student could chose more than 1 team to respond to their advertisements. In that case, the team accepting 1st would get the student into their team and it would be complex to handle the other invitations as the student who has sent the invitation would be juggling around or may not be able to choose the best fit.&lt;br /&gt;
&lt;br /&gt;
*Our take - Each student may choose to respond to more than 1 advertisements but also should have choice of selecting teams as per their comfort.&lt;br /&gt;
&lt;br /&gt;
When a student respond to an advertisement, the team receiving it should send an invitation if they find the student matching the criteria and the student then choose to accept one out of all the invitation he receives.&lt;br /&gt;
&lt;br /&gt;
Below screenshots shows the steps:&lt;br /&gt;
&lt;br /&gt;
The team who has got a response on their advertisement would see the incoming request, which they can accept or decline.&lt;br /&gt;
&lt;br /&gt;
[[File:Received_request_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Once the team accepts the invitation, an invite would be sent to the student to join the team. The team could see their sent invitation as below:&lt;br /&gt;
&lt;br /&gt;
[[File:Sent_invitation_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
The student sees the invitation on his/her &amp;quot;your team&amp;quot; view as below:&lt;br /&gt;
&lt;br /&gt;
[[File:Received_invitation_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Once the student chooses to accept the invitation, he/she could click on the accept link, upon which the user would be presented with a prompt dialog to confirm the acceptance&lt;br /&gt;
as the student would be removed from the current team and placed into the team whose invitation he/she would accept.&lt;br /&gt;
&lt;br /&gt;
[[File:Accept_invitation_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Upon successful acceptance, he/she becomes a member of the team.&lt;br /&gt;
&lt;br /&gt;
[[File:Accepted_request_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
All other students who have not created advertisements, each student would see their list on their &amp;quot;your team&amp;quot; view so that they could invite them by an easy &amp;quot;Invite&amp;quot; link as displayed below:&lt;br /&gt;
&lt;br /&gt;
[[File:Invite_unity_id_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
[[File:Join_request_main_page_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
==Team Information==&lt;br /&gt;
[mailto:tpahuja@ncsu.edu Tushar Pahuja]&amp;lt;br&amp;gt;&lt;br /&gt;
[mailto:pmgandh2@ncsu.edu Pragam Manoj Gandhi]&amp;lt;br&amp;gt;&lt;br /&gt;
[mailto:knielar@ncsu.edu Nielarshi Kumar]&amp;lt;br&amp;gt;&lt;br /&gt;
[mailto:abhardw3@ncsu.edu Abhishek Bhardwaj]&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2017/E1793._Help_students_find_teams_to_join_Team1964&amp;diff=112012</id>
		<title>CSC/ECE 517 Fall 2017/E1793. Help students find teams to join Team1964</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2017/E1793._Help_students_find_teams_to_join_Team1964&amp;diff=112012"/>
		<updated>2017-11-06T20:12:29Z</updated>

		<summary type="html">&lt;p&gt;Knielar: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== About Expertiza ==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a Ruby on Rails based Open Source project. It is a collaboration tool which lets users with different roles (student, instructor, teaching assistant) to collaborate on a course in an institution. A collaboration could be for an assignment where students teams up for an assignment and instructors grades them on the basis of their submission. Students could review other's works and give feedback as well.&lt;br /&gt;
&lt;br /&gt;
===Github link===&lt;br /&gt;
*https://github.com/expertiza/expertiza&lt;br /&gt;
&lt;br /&gt;
===Wiki link===&lt;br /&gt;
*http://wiki.expertiza.ncsu.edu/index.php/Expertiza_documentation&lt;br /&gt;
&lt;br /&gt;
==='''Problem Statement'''===&lt;br /&gt;
*For team-based assignments, it always takes time to find suitable team members. &lt;br /&gt;
&lt;br /&gt;
*We already have bidding, which could help you to join in a team with other team members hold similar bidding preferences. However, a student may not be satisfied with automated team formation and want to switch to another team. &lt;br /&gt;
&lt;br /&gt;
*'''In this project, we will build a new feature to help students find teams to join.'''&lt;br /&gt;
&lt;br /&gt;
Currently, there are 2 ways to find other students to join your team:&lt;br /&gt;
&lt;br /&gt;
*If your team is not full, you could invite people by inputting his/her UnityID. It will send an invitation to a certain user. If s/he accept your invitation,s/he will leave original team and join your team.&lt;br /&gt;
&lt;br /&gt;
*You could create an advisement by clicking “Your team” link and then clicking “Create” link under “Advertisement for teammates” section. Then your advertisement will appear the last column of the signup sheet page with a horn icon. In this way, all classmates could see your advisement. Someone could send a request to join your team. If you accept their request, s/he will leave original team and join in your team. &lt;br /&gt;
&lt;br /&gt;
Below screenshots represents the description above.&lt;br /&gt;
&lt;br /&gt;
Student: Advertisement icon doesn't appear in Chrome browser.&lt;br /&gt;
&lt;br /&gt;
[[File:A_chrome_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Instructor: Advertisement icon doesn't appear in Chrome browser.&lt;br /&gt;
&lt;br /&gt;
[[File:A_instructor_cr_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Advertisement icon appears in Mozilla browser but not in the cell it should appear rather it is visible under &amp;quot;Actions&amp;quot; column.&lt;br /&gt;
&lt;br /&gt;
[[File:A_mozilla_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Sending invitation to a particular student using their unity id as per below.&lt;br /&gt;
&lt;br /&gt;
[[File:Invite_unity_id_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Creating advertisements for joining a team (this is available only after signing up a topic).&lt;br /&gt;
&lt;br /&gt;
[[File:A_by_teammate_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
'''Change Request requirements:'''&lt;br /&gt;
*Students who do not have a team yet or whose team is not full yet to be able to see a list of students who don’t already have teams.&lt;br /&gt;
*Students should have an option of inviting other students to join their teams.&lt;br /&gt;
*Instructors should be able to view list of students who don't have teams.&lt;br /&gt;
&lt;br /&gt;
== Task Description ==&lt;br /&gt;
&lt;br /&gt;
====Change Request 1====&lt;br /&gt;
Fix the second way to find other students ​to​ ​join​ ​your​ ​team. Currently,​ ​after​ ​you​ ​create​ ​an​ ​advertisement,​ ​the​ ​horn​ ​icon​ ​does​ ​not​ ​appear​ ​in the​ ​the​ ​last​ ​column​ ​of​ ​the​ ​signup​ ​sheet.&lt;br /&gt;
&lt;br /&gt;
====Change Request 2====&lt;br /&gt;
For​ ​student​ ​end:  Display​ ​a​ ​list​ ​of​ ​​students​ ​who​ ​do​ ​not​ ​have​ ​a​ ​team​ ​with​ ​invitation​ ​links​ ​in student_teams#view​ ​page ○ You​ ​could​ ​invite​ ​students​ ​to​ ​your​ ​team​ ​by​ ​clicking​ ​invitation​ ​links.​ ​If​ ​s/he​ ​accept your​ ​invitation,s/he​ ​will​ ​leave​  the original​ ​team​ ​and​ ​join​ ​in​ ​your​ ​team.​ ​It​ ​will​ ​be​ ​more straightforward​ ​than​ ​typing​ ​UnityID.&lt;br /&gt;
&lt;br /&gt;
====Change Request 3====&lt;br /&gt;
For​ ​instructor​ ​end:  Display​ ​a​ ​list​ ​of​ ​​students​ ​who​ ​do​ ​not​ ​have​ ​team​ ​with​ ​invitation​ ​links​ ​in​ ​teams#list page &lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
&lt;br /&gt;
=== Edge cases ===&lt;br /&gt;
&lt;br /&gt;
We will be writing automated tests to check if the changes made are working correctly. &lt;br /&gt;
&lt;br /&gt;
For that, we considered the following scenarios&lt;br /&gt;
&lt;br /&gt;
*If the team is full, the person who received an invitation link would not be able to accept that. &lt;br /&gt;
*If a student leaves a team, then he is able to see his previous teammates in the available list of students that do not have a complete team and have not created an invitation link.&lt;br /&gt;
*Student sees a horn icon in the last column if any of the students have created an advertisement for that topic.&lt;br /&gt;
*The list of students contains only those students who don't have a team yet or whose team is not yet complete and who have not created an advertisement link.&lt;br /&gt;
*A student can create an invitation link only if his team is not yet full.&lt;br /&gt;
*The same student who accepted the invitation link actually gets added to the team. &lt;br /&gt;
*A student won't be able to send the invitation to himself as he is already a member of that team.&lt;br /&gt;
*An instructor sees only the list of the students who do not have teams with invitation link.&lt;br /&gt;
*If a student joins a team using an invitation link, then he gets all the rights that a team member of that team has. Ex: Now, he will be able to approve a team join request and then correspondingly send the invitation for joining the group to that student.&lt;br /&gt;
&lt;br /&gt;
== Visual representation of planned changes ==&lt;br /&gt;
&lt;br /&gt;
Inviting students by creating an advertisement.&lt;br /&gt;
&lt;br /&gt;
Once a student creates an advertisement, it would appear in the sign up sheet as below.&lt;br /&gt;
It would be visible to all other students visiting sign up sheet.&lt;br /&gt;
&lt;br /&gt;
[[File:A_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Once a student decides to respond to the advertisement, he clicks on the icon corresponding to the team and topic. He sees the description of the advertisement and a link to respond to it.&lt;br /&gt;
&lt;br /&gt;
[[File:A_request_invitation_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
The student would be presented by a form as below once he/she chooses to request for an invitation.&lt;br /&gt;
&lt;br /&gt;
[[File:A_response.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Student would respond by completing the form and clicking on create. His request would be confirmed by showing a screen as below:&lt;br /&gt;
&lt;br /&gt;
[[File:Join_request_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Team receiving the request would see the incoming request on his &amp;quot;your team&amp;quot; view, from where he could send invites for joining the team.&lt;br /&gt;
&lt;br /&gt;
*Note - this approach was considered to avoid random assignment of student into a team.&lt;br /&gt;
A student could chose more than 1 team to respond to their advertisements. In that case, the team accepting 1st would get the student into their team and it would be complex to handle the other invitations as the student who has sent the invitation would be juggling around or may not be able to choose the best fit.&lt;br /&gt;
&lt;br /&gt;
*Our take - Each student may choose to respond to more than 1 advertisements but also should have choice of selecting teams as per their comfort.&lt;br /&gt;
&lt;br /&gt;
When a student respond to an advertisement, the team receiving it should send an invitation if they find the student matching the criteria and the student then choose to accept one out of all the invitation he receives.&lt;br /&gt;
&lt;br /&gt;
Below screenshots shows the steps:&lt;br /&gt;
&lt;br /&gt;
The team who has got a response on their advertisement would see the incoming request, which they can accept or decline.&lt;br /&gt;
&lt;br /&gt;
[[File:Received_request_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Once the team accepts the invitation, an invite would be sent to the student to join the team. The team could see their sent invitation as below:&lt;br /&gt;
&lt;br /&gt;
[[File:Sent_invitation_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
The student sees the invitation on his/her &amp;quot;your team&amp;quot; view as below:&lt;br /&gt;
&lt;br /&gt;
[[File:Received_invitation_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Once the student chooses to accept the invitation, he/she could click on the accept link, upon which the user would be presented with a prompt dialog to confirm the acceptance&lt;br /&gt;
as the student would be removed from the current team and placed into the team whose invitation he/she would accept.&lt;br /&gt;
&lt;br /&gt;
[[File:Accept_invitation_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
Upon successful acceptance, he/she becomes a member of the team.&lt;br /&gt;
&lt;br /&gt;
[[File:Accepted_request_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
All other students who have not created advertisements, each student would see their list on their &amp;quot;your team&amp;quot; view so that they could invite them by an easy &amp;quot;Invite&amp;quot; link as displayed below:&lt;br /&gt;
&lt;br /&gt;
[[File:Invite_unity_id_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
[[File:Join_request_main_page_after.png|frame|upright|center]]&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2017/E1793._Help_students_find_teams_to_join_Team1964&amp;diff=111999</id>
		<title>CSC/ECE 517 Fall 2017/E1793. Help students find teams to join Team1964</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2017/E1793._Help_students_find_teams_to_join_Team1964&amp;diff=111999"/>
		<updated>2017-11-06T18:57:17Z</updated>

		<summary type="html">&lt;p&gt;Knielar: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== About Expertiza ==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a Ruby on Rails based Open Source project. It is a collaboration tool which lets users with different roles (student, instructor, teaching assistant) to collaborate on a course in an institution. A collaboration could be for an assignment where students teams up for an assignment and instructors grades them on the basis of their submission. Students could review other's works and give feedback as well.&lt;br /&gt;
&lt;br /&gt;
===Github link===&lt;br /&gt;
*https://github.com/expertiza/expertiza&lt;br /&gt;
&lt;br /&gt;
===Wiki link===&lt;br /&gt;
*http://wiki.expertiza.ncsu.edu/index.php/Expertiza_documentation&lt;br /&gt;
&lt;br /&gt;
==='''Problem Statement'''===&lt;br /&gt;
*For team-based assignments, it always takes time to find suitable team members. &lt;br /&gt;
&lt;br /&gt;
*We already have bidding, which could help you to join in a team with other team members hold similar bidding preferences. However, a student may not be satisfied with automated team formation and want to switch to another team. &lt;br /&gt;
&lt;br /&gt;
*'''In this project, we will build a new feature to help students find teams to join.'''&lt;br /&gt;
&lt;br /&gt;
Currently, there are 2 ways to find other students to join your team:&lt;br /&gt;
&lt;br /&gt;
*If your team is not full, you could invite people by inputting his/her UnityID. It will send an invitation to a certain user. If s/he accept your invitation,s/he will leave original team and join your team.&lt;br /&gt;
&lt;br /&gt;
*You could create an advisement by clicking “Your team” link and then clicking “Create” link under “Advertisement for teammates” section. Then your advertisement will appear the last column of the signup sheet page with a horn icon. In this way, all classmates could see your advisement. Someone could send a request to join your team. If you accept their request, s/he will leave original team and join in your team. &lt;br /&gt;
&lt;br /&gt;
Below screenshots represents the description above.&lt;br /&gt;
&lt;br /&gt;
[[File:A_mozilla_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
[[File:Invite_unity_id_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
[[File:A_by_teammate_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
[[File:A_chrome_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
[[File:A_instructor_cr_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
'''Change Request requirements:'''&lt;br /&gt;
*Students who do not have a team yet or whose team is not full yet to be able to see a list of students who don’t already have teams.&lt;br /&gt;
*Students should have an option of inviting other students to join their teams.&lt;br /&gt;
*Instructors should be able to view list of students who don't have teams.&lt;br /&gt;
&lt;br /&gt;
== Task Description ==&lt;br /&gt;
&lt;br /&gt;
====Change Request 1====&lt;br /&gt;
Fix the second way to find​ ​other​ ​students​ ​to​ ​join​ ​your​ ​team. Currently,​ ​after​ ​you​ ​create​ ​an​ ​advertisement,​ ​the​ ​horn​ ​icon​ ​does​ ​not​ ​appear​ ​in the​ ​the​ ​last​ ​column​ ​of​ ​the​ ​signup​ ​sheet.&lt;br /&gt;
&lt;br /&gt;
====Change Request 2====&lt;br /&gt;
For​ ​student​ ​end:  Display​ ​a​ ​list​ ​of​ ​​students​ ​who​ ​do​ ​not​ ​have​ ​a​ ​team​ ​with​ ​invitation​ ​links​ ​in student_teams#view​ ​page ○ You​ ​could​ ​invite​ ​students​ ​to​ ​your​ ​team​ ​by​ ​clicking​ ​invitation​ ​links.​ ​If​ ​s/he​ ​accept your​ ​invitation,s/he​ ​will​ ​leave​  the original​ ​team​ ​and​ ​join​ ​in​ ​your​ ​team.​ ​It​ ​will​ ​be​ ​more straightforward​ ​than​ ​typing​ ​UnityID.&lt;br /&gt;
&lt;br /&gt;
====Change Request 3====&lt;br /&gt;
For​ ​instructor​ ​end:  Display​ ​a​ ​list​ ​of​ ​​students​ ​who​ ​do​ ​not​ ​have​ ​team​ ​with​ ​invitation​ ​links​ ​in​ ​teams#list page &lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
&lt;br /&gt;
=== Edge cases ===&lt;br /&gt;
&lt;br /&gt;
We will be writing automated tests to check if the changes made are working correctly. &lt;br /&gt;
&lt;br /&gt;
For that, we considered the following scenarios&lt;br /&gt;
&lt;br /&gt;
*If the team is full, the person who received an invitation link would not be able to accept that. &lt;br /&gt;
*If a student leaves a team, then he is able to see his previous teammates in the available list of students that do not have a complete team and have not created an invitation link.&lt;br /&gt;
*Student sees a horn icon in the last column if any of the students have created an advertisement for that topic.&lt;br /&gt;
*The list of students contains only those students who don't have a team yet or whose team is not yet complete and who have not created an advertisement link.&lt;br /&gt;
*A student can create an invitation link only if his team is not yet full.&lt;br /&gt;
*The same student who accepted the invitation link actually gets added to the team. &lt;br /&gt;
*A student won't be able to send the invitation to himself as he is already a member of that team.&lt;br /&gt;
*An instructor sees only the list of the students who do not have teams with invitation link.&lt;br /&gt;
*If a student joins a team using an invitation link, then he gets all the rights that a team member of that team has. Ex: Now, he will be able to approve a team join request and then correspondingly send the invitation for joining the group to that student.&lt;br /&gt;
&lt;br /&gt;
== Visual representation of planned changes ==&lt;br /&gt;
&lt;br /&gt;
[[File:Accept_invitation_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
[[File:Accepted_request_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
[[File:A_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
[[File:A_mozilla_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
[[File:A_request_invitation_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
[[File:A_response.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
[[File:Invite_unity_id_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
[[File:Join_request_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
[[File:Join_request_main_page_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
[[File:Received_invitation_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
[[File:Received_request_after.png|frame|upright|center]]&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:A_response.png&amp;diff=111996</id>
		<title>File:A response.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:A_response.png&amp;diff=111996"/>
		<updated>2017-11-06T18:55:31Z</updated>

		<summary type="html">&lt;p&gt;Knielar: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:A_request_invitation_after.png&amp;diff=111994</id>
		<title>File:A request invitation after.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:A_request_invitation_after.png&amp;diff=111994"/>
		<updated>2017-11-06T18:55:09Z</updated>

		<summary type="html">&lt;p&gt;Knielar: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:A_mozilla_before.png&amp;diff=111993</id>
		<title>File:A mozilla before.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:A_mozilla_before.png&amp;diff=111993"/>
		<updated>2017-11-06T18:54:46Z</updated>

		<summary type="html">&lt;p&gt;Knielar: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:A_mozilla_after.png&amp;diff=111992</id>
		<title>File:A mozilla after.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:A_mozilla_after.png&amp;diff=111992"/>
		<updated>2017-11-06T18:54:19Z</updated>

		<summary type="html">&lt;p&gt;Knielar: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:A_instructor_cr_before.png&amp;diff=111990</id>
		<title>File:A instructor cr before.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:A_instructor_cr_before.png&amp;diff=111990"/>
		<updated>2017-11-06T18:53:36Z</updated>

		<summary type="html">&lt;p&gt;Knielar: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:A_chrome_before.png&amp;diff=111988</id>
		<title>File:A chrome before.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:A_chrome_before.png&amp;diff=111988"/>
		<updated>2017-11-06T18:53:07Z</updated>

		<summary type="html">&lt;p&gt;Knielar: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:A_by_teammate_before.png&amp;diff=111987</id>
		<title>File:A by teammate before.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:A_by_teammate_before.png&amp;diff=111987"/>
		<updated>2017-11-06T18:52:37Z</updated>

		<summary type="html">&lt;p&gt;Knielar: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:A_after.png&amp;diff=111986</id>
		<title>File:A after.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:A_after.png&amp;diff=111986"/>
		<updated>2017-11-06T18:52:12Z</updated>

		<summary type="html">&lt;p&gt;Knielar: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Advertisement_instructor_cr_before.png&amp;diff=111984</id>
		<title>File:Advertisement instructor cr before.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Advertisement_instructor_cr_before.png&amp;diff=111984"/>
		<updated>2017-11-06T18:47:19Z</updated>

		<summary type="html">&lt;p&gt;Knielar: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Advertisement_instructor_chrome_before.png&amp;diff=111982</id>
		<title>File:Advertisement instructor chrome before.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Advertisement_instructor_chrome_before.png&amp;diff=111982"/>
		<updated>2017-11-06T18:43:30Z</updated>

		<summary type="html">&lt;p&gt;Knielar: uploaded a new version of &amp;amp;quot;File:Advertisement instructor chrome before.png&amp;amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2017/E1793._Help_students_find_teams_to_join_Team1964&amp;diff=111972</id>
		<title>CSC/ECE 517 Fall 2017/E1793. Help students find teams to join Team1964</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2017/E1793._Help_students_find_teams_to_join_Team1964&amp;diff=111972"/>
		<updated>2017-11-06T05:09:26Z</updated>

		<summary type="html">&lt;p&gt;Knielar: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== About Expertiza ==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a Ruby on Rails based Open Source project. It is a collaboration tool which lets users with different roles (student, instructor, teaching assistant) to collaborate on a course in an institution. A collaboration could be for an assignment where students teams up for an assignment and instructors grades them on the basis of their submission. Students could review other's works and give feedback as well.&lt;br /&gt;
&lt;br /&gt;
===Github link===&lt;br /&gt;
*https://github.com/expertiza/expertiza&lt;br /&gt;
&lt;br /&gt;
===Wiki link===&lt;br /&gt;
*http://wiki.expertiza.ncsu.edu/index.php/Expertiza_documentation&lt;br /&gt;
&lt;br /&gt;
==='''Problem Statement'''===&lt;br /&gt;
*For team-based assignments, it always takes time to find suitable team members. &lt;br /&gt;
&lt;br /&gt;
*We already have bidding, which could help you to join in a team with other team members hold similar bidding preferences. However, a student may not be satisfied with automated team formation and want to switch to another team. &lt;br /&gt;
&lt;br /&gt;
*'''In this project, we will build a new feature to help students find teams to join.'''&lt;br /&gt;
&lt;br /&gt;
Currently, there are 2 ways to find other students to join your team:&lt;br /&gt;
&lt;br /&gt;
*If your team is not full, you could invite people by inputting his/her UnityID. It will send an invitation to a certain user. If s/he accept your invitation,s/he will leave original team and join your team.&lt;br /&gt;
&lt;br /&gt;
*You could create an advisement by clicking “Your team” link and then clicking “Create” link under “Advertisement for teammates” section. Then your advertisement will appear the last column of the signup sheet page with a horn icon. In this way, all classmates could see your advisement. Someone could send a request to join your team. If you accept their request, s/he will leave original team and join in your team. &lt;br /&gt;
&lt;br /&gt;
Below screenshots represents the description above.&lt;br /&gt;
&lt;br /&gt;
[[File:Advertisement_mozilla_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
[[File:Invite_unity_id_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
[[File:Advertisement_by_teammate_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
[[File:Advertisement_chrome_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
[[File:Advertisement_instructor_chrome_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
'''Change Request requirements:'''&lt;br /&gt;
*Students who do not have a team yet or whose team is not full yet to be able to see a list of students who don’t already have teams.&lt;br /&gt;
*Students should have an option of inviting other students to join their teams.&lt;br /&gt;
*Instructors should be able to view list of students who don't have teams.&lt;br /&gt;
&lt;br /&gt;
== Task Description ==&lt;br /&gt;
&lt;br /&gt;
====Change Request 1====&lt;br /&gt;
Fix the second way to find​ ​other​ ​students​ ​to​ ​join​ ​your​ ​team. Currently,​ ​after​ ​you​ ​create​ ​an​ ​advertisement,​ ​the​ ​horn​ ​icon​ ​does​ ​not​ ​appear​ ​in the​ ​the​ ​last​ ​column​ ​of​ ​the​ ​signup​ ​sheet.&lt;br /&gt;
&lt;br /&gt;
====Change Request 2====&lt;br /&gt;
For​ ​student​ ​end:  Display​ ​a​ ​list​ ​of​ ​​students​ ​who​ ​do​ ​not​ ​have​ ​a​ ​team​ ​with​ ​invitation​ ​links​ ​in student_teams#view​ ​page ○ You​ ​could​ ​invite​ ​students​ ​to​ ​your​ ​team​ ​by​ ​clicking​ ​invitation​ ​links.​ ​If​ ​s/he​ ​accept your​ ​invitation,s/he​ ​will​ ​leave​  the original​ ​team​ ​and​ ​join​ ​in​ ​your​ ​team.​ ​It​ ​will​ ​be​ ​more straightforward​ ​than​ ​typing​ ​UnityID.&lt;br /&gt;
&lt;br /&gt;
====Change Request 3====&lt;br /&gt;
For​ ​instructor​ ​end:  Display​ ​a​ ​list​ ​of​ ​​students​ ​who​ ​do​ ​not​ ​have​ ​team​ ​with​ ​invitation​ ​links​ ​in​ ​teams#list page &lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
&lt;br /&gt;
=== Edge cases ===&lt;br /&gt;
&lt;br /&gt;
We will be writing automated tests to check if the changes made are working correctly. &lt;br /&gt;
&lt;br /&gt;
For that, we considered the following scenarios&lt;br /&gt;
&lt;br /&gt;
*If the team is full, the person who received an invitation link would not be able to accept that. &lt;br /&gt;
*If a student leaves a team, then he is able to see his previous teammates in the available list of students that do not have a complete team and have not created an invitation link.&lt;br /&gt;
*Student sees a horn icon in the last column if any of the students have created an advertisement for that topic.&lt;br /&gt;
*The list of students contains only those students who don't have a team yet or whose team is not yet complete and who have not created an advertisement link.&lt;br /&gt;
*A student can create an invitation link only if his team is not yet full.&lt;br /&gt;
*The same student who accepted the invitation link actually gets added to the team. &lt;br /&gt;
*A student won't be able to send the invitation to himself as he is already a member of that team.&lt;br /&gt;
*An instructor sees only the list of the students who do not have teams with invitation link.&lt;br /&gt;
*If a student joins a team using an invitation link, then he gets all the rights that a team member of that team has. Ex: Now, he will be able to approve a team join request and then correspondingly send the invitation for joining the group to that student.&lt;br /&gt;
&lt;br /&gt;
== Visual representation of planned changes ==&lt;br /&gt;
&lt;br /&gt;
[[File:Accept_invitation_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
[[File:Accepted_request_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
[[File:Advertisement_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
[[File:Advertisement_mozilla_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
[[File:Advertisement_request_invitation_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
[[File:Advertisement_response.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
[[File:Invite_unity_id_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
[[File:Join_request_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
[[File:Join_request_main_page_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
[[File:Received_invitation_after.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
[[File:Received_request_after.png|frame|upright|center]]&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Advertisement_mozilla_before.png&amp;diff=111971</id>
		<title>File:Advertisement mozilla before.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Advertisement_mozilla_before.png&amp;diff=111971"/>
		<updated>2017-11-06T05:05:39Z</updated>

		<summary type="html">&lt;p&gt;Knielar: uploaded a new version of &amp;amp;quot;File:Advertisement mozilla before.png&amp;amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2017/E1793._Help_students_find_teams_to_join_Team1964&amp;diff=111970</id>
		<title>CSC/ECE 517 Fall 2017/E1793. Help students find teams to join Team1964</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2017/E1793._Help_students_find_teams_to_join_Team1964&amp;diff=111970"/>
		<updated>2017-11-06T05:04:23Z</updated>

		<summary type="html">&lt;p&gt;Knielar: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== About Expertiza ==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a Ruby on Rails based Open Source project. It is a collaboration tool which lets users with different roles (student, instructor, teaching assistant) to collaborate on a course in an institution. A collaboration could be for an assignment where students teams up for an assignment and instructors grades them on the basis of their submission. Students could review other's works and give feedback as well.&lt;br /&gt;
&lt;br /&gt;
===Github link===&lt;br /&gt;
*https://github.com/expertiza/expertiza&lt;br /&gt;
&lt;br /&gt;
===Wiki link===&lt;br /&gt;
*http://wiki.expertiza.ncsu.edu/index.php/Expertiza_documentation&lt;br /&gt;
&lt;br /&gt;
==='''Problem Statement'''===&lt;br /&gt;
*For team-based assignments, it always takes time to find suitable team members. &lt;br /&gt;
&lt;br /&gt;
*We already have bidding, which could help you to join in a team with other team members hold similar bidding preferences. However, a student may not be satisfied with automated team formation and want to switch to another team. &lt;br /&gt;
&lt;br /&gt;
*'''In this project, we will build a new feature to help students find teams to join.'''&lt;br /&gt;
&lt;br /&gt;
Currently, there are 2 ways to find other students to join your team:&lt;br /&gt;
&lt;br /&gt;
*If your team is not full, you could invite people by inputting his/her UnityID. It will send an invitation to a certain user. If s/he accept your invitation,s/he will leave original team and join your team.&lt;br /&gt;
&lt;br /&gt;
*You could create an advisement by clicking “Your team” link and then clicking “Create” link under “Advertisement for teammates” section. Then your advertisement will appear the last column of the signup sheet page with a horn icon. In this way, all classmates could see your advisement. Someone could send a request to join your team. If you accept their request, s/he will leave original team and join in your team. &lt;br /&gt;
&lt;br /&gt;
Below screenshots represents the description above.&lt;br /&gt;
&lt;br /&gt;
[[File:Advertisement_mozilla_before.png|frame|upright|center]]&lt;br /&gt;
[[File:Invite_unity_id_before.png|frame|upright|center]]&lt;br /&gt;
[[File:Advertisement_by_teammate_before.png|frame|upright|center]]&lt;br /&gt;
[[File:Advertisement_chrome_before.png|frame|upright|center]]&lt;br /&gt;
[[File:Advertisement_instructor_chrome_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
'''Change Request requirements:'''&lt;br /&gt;
*Students who do not have a team yet or whose team is not full yet to be able to see a list of students who don’t already have teams.&lt;br /&gt;
*Students should have an option of inviting other students to join their teams.&lt;br /&gt;
*Instructors should be able to view list of students who don't have teams.&lt;br /&gt;
&lt;br /&gt;
== Task Description ==&lt;br /&gt;
&lt;br /&gt;
====Change Request 1====&lt;br /&gt;
Fix the second way to find​ ​other​ ​students​ ​to​ ​join​ ​your​ ​team. Currently,​ ​after​ ​you​ ​create​ ​an​ ​advertisement,​ ​the​ ​horn​ ​icon​ ​does​ ​not​ ​appear​ ​in the​ ​the​ ​last​ ​column​ ​of​ ​the​ ​signup​ ​sheet.&lt;br /&gt;
&lt;br /&gt;
====Change Request 2====&lt;br /&gt;
For​ ​student​ ​end:  Display​ ​a​ ​list​ ​of​ ​​students​ ​who​ ​do​ ​not​ ​have​ ​a​ ​team​ ​with​ ​invitation​ ​links​ ​in student_teams#view​ ​page ○ You​ ​could​ ​invite​ ​students​ ​to​ ​your​ ​team​ ​by​ ​clicking​ ​invitation​ ​links.​ ​If​ ​s/he​ ​accept your​ ​invitation,s/he​ ​will​ ​leave​  the original​ ​team​ ​and​ ​join​ ​in​ ​your​ ​team.​ ​It​ ​will​ ​be​ ​more straightforward​ ​than​ ​typing​ ​UnityID.&lt;br /&gt;
&lt;br /&gt;
====Change Request 3====&lt;br /&gt;
For​ ​instructor​ ​end:  Display​ ​a​ ​list​ ​of​ ​​students​ ​who​ ​do​ ​not​ ​have​ ​team​ ​with​ ​invitation​ ​links​ ​in​ ​teams#list page &lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
&lt;br /&gt;
=== Edge cases ===&lt;br /&gt;
&lt;br /&gt;
We will be writing automated tests to check if the changes made are working correctly. &lt;br /&gt;
&lt;br /&gt;
For that, we considered the following scenarios&lt;br /&gt;
&lt;br /&gt;
*If the team is full, the person who received an invitation link would not be able to accept that. &lt;br /&gt;
*If a student leaves a team, then he is able to see his previous teammates in the available list of students that do not have a complete team and have not created an invitation link.&lt;br /&gt;
*Student sees a horn icon in the last column if any of the students have created an advertisement for that topic.&lt;br /&gt;
*The list of students contains only those students who don't have a team yet or whose team is not yet complete and who have not created an advertisement link.&lt;br /&gt;
*A student can create an invitation link only if his team is not yet full.&lt;br /&gt;
*The same student who accepted the invitation link actually gets added to the team. &lt;br /&gt;
*A student won't be able to send the invitation to himself as he is already a member of that team.&lt;br /&gt;
*An instructor sees only the list of the students who do not have teams with invitation link.&lt;br /&gt;
*If a student joins a team using an invitation link, then he gets all the rights that a team member of that team has. Ex: Now, he will be able to approve a team join request and then correspondingly send the invitation for joining the group to that student.&lt;br /&gt;
&lt;br /&gt;
== Visual representation of planned changes ==&lt;br /&gt;
&lt;br /&gt;
[[File:Accept_invitation_after.png|frame|upright|center]]&lt;br /&gt;
[[File:Accepted_request_after.png|frame|upright|center]]&lt;br /&gt;
[[File:Advertisement_after.png|frame|upright|center]]&lt;br /&gt;
[[File:Advertisement_mozilla_after.png|frame|upright|center]]&lt;br /&gt;
[[File:Advertisement_request_invitation_after.png|frame|upright|center]]&lt;br /&gt;
[[File:Advertisement_response.png|frame|upright|center]]&lt;br /&gt;
[[File:Invite_unity_id_after.png|frame|upright|center]]&lt;br /&gt;
[[File:Join_request_after.png|frame|upright|center]]&lt;br /&gt;
[[File:Join_request_main_page_after.png|frame|upright|center]]&lt;br /&gt;
[[File:Received_invitation_after.png|frame|upright|center]]&lt;br /&gt;
[[File:Received_request_after.png|frame|upright|center]]&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2017/E1793._Help_students_find_teams_to_join_Team1964&amp;diff=111969</id>
		<title>CSC/ECE 517 Fall 2017/E1793. Help students find teams to join Team1964</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2017/E1793._Help_students_find_teams_to_join_Team1964&amp;diff=111969"/>
		<updated>2017-11-06T05:02:23Z</updated>

		<summary type="html">&lt;p&gt;Knielar: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== About Expertiza ==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a Ruby on Rails based Open Source project. It is a collaboration tool which lets users with different roles (student, instructor, teaching assistant) to collaborate on a course in an institution. A collaboration could be for an assignment where students teams up for an assignment and instructors grades them on the basis of their submission. Students could review other's works and give feedback as well.&lt;br /&gt;
&lt;br /&gt;
===Github link===&lt;br /&gt;
*https://github.com/expertiza/expertiza&lt;br /&gt;
&lt;br /&gt;
===Wiki link===&lt;br /&gt;
*http://wiki.expertiza.ncsu.edu/index.php/Expertiza_documentation&lt;br /&gt;
&lt;br /&gt;
==='''Problem Statement'''===&lt;br /&gt;
*For team-based assignments, it always takes time to find suitable team members. &lt;br /&gt;
&lt;br /&gt;
*We already have bidding, which could help you to join in a team with other team members hold similar bidding preferences. However, a student may not be satisfied with automated team formation and want to switch to another team. &lt;br /&gt;
&lt;br /&gt;
*'''In this project, we will build a new feature to help students find teams to join.'''&lt;br /&gt;
&lt;br /&gt;
Currently, there are 2 ways to find other students to join your team:&lt;br /&gt;
&lt;br /&gt;
*If your team is not full, you could invite people by inputting his/her UnityID. It will send an invitation to a certain user. If s/he accept your invitation,s/he will leave original team and join your team.&lt;br /&gt;
&lt;br /&gt;
*You could create an advisement by clicking “Your team” link and then clicking “Create” link under “Advertisement for teammates” section. Then your advertisement will appear the last column of the signup sheet page with a horn icon. In this way, all classmates could see your advisement. Someone could send a request to join your team. If you accept their request, s/he will leave original team and join in your team. &lt;br /&gt;
&lt;br /&gt;
Below screenshots represents the description above.&lt;br /&gt;
&lt;br /&gt;
[[File:advertisement_mozilla_before.png|frame|upright|center]]&lt;br /&gt;
[[File:Invite_unity_id_before.png|frame|upright|center]]&lt;br /&gt;
[[File:advertisement_by_teammate_before.png|frame|upright|center]]&lt;br /&gt;
[[File:advertisement_chrome_before.png|frame|upright|center]]&lt;br /&gt;
[[File:advertisement_instructor_chrome_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
'''Change Request requirements:'''&lt;br /&gt;
*Students who do not have a team yet or whose team is not full yet to be able to see a list of students who don’t already have teams.&lt;br /&gt;
*Students should have an option of inviting other students to join their teams.&lt;br /&gt;
*Instructors should be able to view list of students who don't have teams.&lt;br /&gt;
&lt;br /&gt;
== Task Description ==&lt;br /&gt;
&lt;br /&gt;
====Change Request 1====&lt;br /&gt;
Fix the second way to find​ ​other​ ​students​ ​to​ ​join​ ​your​ ​team. Currently,​ ​after​ ​you​ ​create​ ​an​ ​advertisement,​ ​the​ ​horn​ ​icon​ ​does​ ​not​ ​appear​ ​in the​ ​the​ ​last​ ​column​ ​of​ ​the​ ​signup​ ​sheet.&lt;br /&gt;
&lt;br /&gt;
====Change Request 2====&lt;br /&gt;
For​ ​student​ ​end:  Display​ ​a​ ​list​ ​of​ ​​students​ ​who​ ​do​ ​not​ ​have​ ​a​ ​team​ ​with​ ​invitation​ ​links​ ​in student_teams#view​ ​page ○ You​ ​could​ ​invite​ ​students​ ​to​ ​your​ ​team​ ​by​ ​clicking​ ​invitation​ ​links.​ ​If​ ​s/he​ ​accept your​ ​invitation,s/he​ ​will​ ​leave​  the original​ ​team​ ​and​ ​join​ ​in​ ​your​ ​team.​ ​It​ ​will​ ​be​ ​more straightforward​ ​than​ ​typing​ ​UnityID.&lt;br /&gt;
&lt;br /&gt;
====Change Request 3====&lt;br /&gt;
For​ ​instructor​ ​end:  Display​ ​a​ ​list​ ​of​ ​​students​ ​who​ ​do​ ​not​ ​have​ ​team​ ​with​ ​invitation​ ​links​ ​in​ ​teams#list page &lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
&lt;br /&gt;
=== Edge cases ===&lt;br /&gt;
&lt;br /&gt;
We will be writing automated tests to check if the changes made are working correctly. &lt;br /&gt;
&lt;br /&gt;
For that, we considered the following scenarios&lt;br /&gt;
&lt;br /&gt;
*If the team is full, the person who received an invitation link would not be able to accept that. &lt;br /&gt;
*If a student leaves a team, then he is able to see his previous teammates in the available list of students that do not have a complete team and have not created an invitation link.&lt;br /&gt;
*Student sees a horn icon in the last column if any of the students have created an advertisement for that topic.&lt;br /&gt;
*The list of students contains only those students who don't have a team yet or whose team is not yet complete and who have not created an advertisement link.&lt;br /&gt;
*A student can create an invitation link only if his team is not yet full.&lt;br /&gt;
*The same student who accepted the invitation link actually gets added to the team. &lt;br /&gt;
*A student won't be able to send the invitation to himself as he is already a member of that team.&lt;br /&gt;
*An instructor sees only the list of the students who do not have teams with invitation link.&lt;br /&gt;
*If a student joins a team using an invitation link, then he gets all the rights that a team member of that team has. Ex: Now, he will be able to approve a team join request and then correspondingly send the invitation for joining the group to that student.&lt;br /&gt;
&lt;br /&gt;
== Visual representation of planned changes ==&lt;br /&gt;
&lt;br /&gt;
[[File:Accept_invitation_after.png|frame|upright|center]]&lt;br /&gt;
[[File:Accepted_request_after.png|frame|upright|center]]&lt;br /&gt;
[[File:Advertisement_after.png|frame|upright|center]]&lt;br /&gt;
[[File:Advertisement_mozilla_after.png|frame|upright|center]]&lt;br /&gt;
[[File:Advertisement_request_invitation_after.png|frame|upright|center]]&lt;br /&gt;
[[File:Advertisement_response.png|frame|upright|center]]&lt;br /&gt;
[[File:Invite_unity_id_after.png|frame|upright|center]]&lt;br /&gt;
[[File:Join_request_after.png|frame|upright|center]]&lt;br /&gt;
[[File:Join_request_main_page_after.png|frame|upright|center]]&lt;br /&gt;
[[File:Received_invitation_after.png|frame|upright|center]]&lt;br /&gt;
[[File:Received_request_after.png|frame|upright|center]]&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2017/E1793._Help_students_find_teams_to_join_Team1964&amp;diff=111968</id>
		<title>CSC/ECE 517 Fall 2017/E1793. Help students find teams to join Team1964</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2017/E1793._Help_students_find_teams_to_join_Team1964&amp;diff=111968"/>
		<updated>2017-11-06T04:52:13Z</updated>

		<summary type="html">&lt;p&gt;Knielar: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== About Expertiza ==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a Ruby on Rails based Open Source project. It is a collaboration tool which lets users with different roles (student, instructor, teaching assistant) to collaborate on a course in an institution. A collaboration could be for an assignment where students teams up for an assignment and instructors grades them on the basis of their submission. Students could review other's works and give feedback as well.&lt;br /&gt;
&lt;br /&gt;
===Github link===&lt;br /&gt;
*https://github.com/expertiza/expertiza&lt;br /&gt;
&lt;br /&gt;
===Wiki link===&lt;br /&gt;
*http://wiki.expertiza.ncsu.edu/index.php/Expertiza_documentation&lt;br /&gt;
&lt;br /&gt;
==='''Problem Statement'''===&lt;br /&gt;
*For team-based assignments, it always takes time to find suitable team members. &lt;br /&gt;
&lt;br /&gt;
*We already have bidding, which could help you to join in a team with other team members hold similar bidding preferences. However, a student may not be satisfied with automated team formation and want to switch to another team. &lt;br /&gt;
&lt;br /&gt;
*'''In this project, we will build a new feature to help students find teams to join.'''&lt;br /&gt;
&lt;br /&gt;
Currently, there are 2 ways to find other students to join your team:&lt;br /&gt;
&lt;br /&gt;
*If your team is not full, you could invite people by inputting his/her UnityID. It will send an invitation to a certain user. If s/he accept your invitation,s/he will leave original team and join your team.&lt;br /&gt;
&lt;br /&gt;
*You could create an advisement by clicking “Your team” link and then clicking “Create” link under “Advertisement for teammates” section. Then your advertisement will appear the last column of the signup sheet page with a horn icon. In this way, all classmates could see your advisement. Someone could send a request to join your team. If you accept their request, s/he will leave original team and join in your team. &lt;br /&gt;
&lt;br /&gt;
Below screenshots represents the description above.&lt;br /&gt;
&lt;br /&gt;
[[File:Advertisement_mozilla_before.png|frame|upright|center]]&lt;br /&gt;
[[File:Invite_unity_id_before.png|frame|upright|center]]&lt;br /&gt;
[[File:Advertisement_by_teammate_before.png|frame|upright|center]]&lt;br /&gt;
[[File:Advertisement_chrome_before.png|frame|upright|center]]&lt;br /&gt;
[[File:Advertisement_instructor_chrome_before.png|frame|upright|center]]&lt;br /&gt;
&lt;br /&gt;
'''Change Request requirements:'''&lt;br /&gt;
*Students who do not have a team yet or whose team is not full yet to be able to see a list of students who don’t already have teams.&lt;br /&gt;
*Students should have an option of inviting other students to join their teams.&lt;br /&gt;
*Instructors should be able to view list of students who don't have teams.&lt;br /&gt;
&lt;br /&gt;
== Task Description ==&lt;br /&gt;
&lt;br /&gt;
====Change Request 1====&lt;br /&gt;
Fix the second way to find​ ​other​ ​students​ ​to​ ​join​ ​your​ ​team. Currently,​ ​after​ ​you​ ​create​ ​an​ ​advertisement,​ ​the​ ​horn​ ​icon​ ​does​ ​not​ ​appear​ ​in the​ ​the​ ​last​ ​column​ ​of​ ​the​ ​signup​ ​sheet.&lt;br /&gt;
&lt;br /&gt;
====Change Request 2====&lt;br /&gt;
For​ ​student​ ​end:  Display​ ​a​ ​list​ ​of​ ​​students​ ​who​ ​do​ ​not​ ​have​ ​a​ ​team​ ​with​ ​invitation​ ​links​ ​in student_teams#view​ ​page ○ You​ ​could​ ​invite​ ​students​ ​to​ ​your​ ​team​ ​by​ ​clicking​ ​invitation​ ​links.​ ​If​ ​s/he​ ​accept your​ ​invitation,s/he​ ​will​ ​leave​  the original​ ​team​ ​and​ ​join​ ​in​ ​your​ ​team.​ ​It​ ​will​ ​be​ ​more straightforward​ ​than​ ​typing​ ​UnityID.&lt;br /&gt;
&lt;br /&gt;
====Change Request 3====&lt;br /&gt;
For​ ​instructor​ ​end:  Display​ ​a​ ​list​ ​of​ ​​students​ ​who​ ​do​ ​not​ ​have​ ​team​ ​with​ ​invitation​ ​links​ ​in​ ​teams#list page &lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
&lt;br /&gt;
=== Edge cases ===&lt;br /&gt;
&lt;br /&gt;
We will be writing automated tests to check if the changes made are working correctly. &lt;br /&gt;
&lt;br /&gt;
For that, we considered the following scenarios&lt;br /&gt;
&lt;br /&gt;
*If the team is full, the person who received an invitation link would not be able to accept that. &lt;br /&gt;
*If a student leaves a team, then he is able to see his previous teammates in the available list of students that do not have a complete team and have not created an invitation link.&lt;br /&gt;
*Student sees a horn icon in the last column if any of the students have created an advertisement for that topic.&lt;br /&gt;
*The list of students contains only those students who don't have a team yet or whose team is not yet complete and who have not created an advertisement link.&lt;br /&gt;
*A student can create an invitation link only if his team is not yet full.&lt;br /&gt;
*The same student who accepted the invitation link actually gets added to the team. &lt;br /&gt;
*A student won't be able to send the invitation to himself as he is already a member of that team.&lt;br /&gt;
*An instructor sees only the list of the students who do not have teams with invitation link.&lt;br /&gt;
*If a student joins a team using an invitation link, then he gets all the rights that a team member of that team has. Ex: Now, he will be able to approve a team join request and then correspondingly send the invitation for joining the group to that student.&lt;br /&gt;
&lt;br /&gt;
== Visual representation of planned changes ==&lt;br /&gt;
&lt;br /&gt;
[[File:Accept_invitation_after.png|frame|upright|center]]&lt;br /&gt;
[[File:Accepted_request_after.png|frame|upright|center]]&lt;br /&gt;
[[File:Advertisement_after.png|frame|upright|center]]&lt;br /&gt;
[[File:Advertisement_mozilla_after.png|frame|upright|center]]&lt;br /&gt;
[[File:Advertisement_request_invitation_after.png|frame|upright|center]]&lt;br /&gt;
[[File:Advertisement_response.png|frame|upright|center]]&lt;br /&gt;
[[File:Invite_unity_id_after.png|frame|upright|center]]&lt;br /&gt;
[[File:Join_request_after.png|frame|upright|center]]&lt;br /&gt;
[[File:Join_request_main_page_after.png|frame|upright|center]]&lt;br /&gt;
[[File:Received_invitation_after.png|frame|upright|center]]&lt;br /&gt;
[[File:Received_request_after.png|frame|upright|center]]&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Sent_invitation_after.png&amp;diff=111966</id>
		<title>File:Sent invitation after.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Sent_invitation_after.png&amp;diff=111966"/>
		<updated>2017-11-06T04:41:09Z</updated>

		<summary type="html">&lt;p&gt;Knielar: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Received_request_after.png&amp;diff=111965</id>
		<title>File:Received request after.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Received_request_after.png&amp;diff=111965"/>
		<updated>2017-11-06T04:37:53Z</updated>

		<summary type="html">&lt;p&gt;Knielar: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Knielar</name></author>
	</entry>
</feed>