<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ana Jimenez Santamaria</title>
    <description>The latest articles on DEV Community by Ana Jimenez Santamaria (@anajsana95).</description>
    <link>https://dev.to/anajsana95</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F344556%2F14026695-23be-418b-9da5-19702e8fd18d.jpg</url>
      <title>DEV Community: Ana Jimenez Santamaria</title>
      <link>https://dev.to/anajsana95</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/anajsana95"/>
    <language>en</language>
    <item>
      <title>Dockerizing your first web app with python and flask</title>
      <dc:creator>Ana Jimenez Santamaria</dc:creator>
      <pubDate>Sun, 19 Jul 2020 21:02:28 +0000</pubDate>
      <link>https://dev.to/anajsana95/dockerizing-your-first-web-app-with-python-and-flask-2fn2</link>
      <guid>https://dev.to/anajsana95/dockerizing-your-first-web-app-with-python-and-flask-2fn2</guid>
      <description>&lt;p&gt;Second part of &lt;a href="https://dev.to/anajsana95/how-to-measure-covid-19-impact-on-jitsi-project-with-python-and-elasticsearch-154j"&gt;how to measure covid-19 impact on Jitsi project with python and elasticsearch&lt;/a&gt;. This time, my colleagues (&lt;a href="https://www.linkedin.com/in/david-dur%C3%A1n-prieto-86326b17a/"&gt;David&lt;/a&gt;, &lt;a href="https://www.linkedin.com/in/gerardoadrianaguirrevivar/"&gt;Gerardo&lt;/a&gt;) and I (&lt;a href="https://www.linkedin.com/in/ana-jim%C3%A9nez-santamar%C3%ADa/"&gt;Ana&lt;/a&gt;) built a web app with Python technology and Flask framework and dockerized it. Here we explain you how&lt;/p&gt;

&lt;h1&gt;
  
  
  Docker architecture
&lt;/h1&gt;

&lt;p&gt;First, we have to build a docker application with three containers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ElasticSearch image&lt;/li&gt;
&lt;li&gt;Kibana image&lt;/li&gt;
&lt;li&gt;Web app image&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dd3fr8CR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0fc1l36wew4xqcmll5ak.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dd3fr8CR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0fc1l36wew4xqcmll5ak.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For ElasticSearch and Kibana, we use pre-built images from &lt;strong&gt;DockerHub&lt;/strong&gt; using 7.8.0 version. Web application uses a redis-alpine image.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Note: The reason why using alpine, is because this alternative is smaller and more resource efficient than traditional GNU/Linux distributions (such as Ubuntu)&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Required files and configuration
&lt;/h1&gt;

&lt;p&gt;You can get the required materials on &lt;a href="https://gitlab.com/msdatascienceurjc/docker-jitsi-app"&gt;GitLab&lt;/a&gt;. The image below shows the different files you will get by cloning the repo&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GOsXshkx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/mj5uq81ywtnzv85supi8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GOsXshkx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/mj5uq81ywtnzv85supi8.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Docker-compose.yml structure
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;docker-compose.yml&lt;/code&gt; file shows the structure explained in previous section&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;
&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3'&lt;/span&gt;
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;web&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
  &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;5000:5000&lt;/span&gt;
  &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;elastic&lt;/span&gt;
&lt;span class="na"&gt;redis&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
   &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;redis:alpine"&lt;/span&gt;
&lt;span class="na"&gt;es01&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
   &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker.elastic.co/elasticsearch/elasticsearch:7.8.0&lt;/span&gt;
   &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;es01&lt;/span&gt;
   &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;node.name=es01&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cluster.name=es-docker-cluster&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;discovery.type=single-node&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;bootstrap.memory_lock=true&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ES_JAVA_OPTS=-Xms1024m&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;-Xmx1024m"&lt;/span&gt;
&lt;span class="err"&gt;  &lt;/span&gt;&lt;span class="na"&gt;ulimits&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;memlock&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;soft&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;-1&lt;/span&gt;
        &lt;span class="na"&gt;hard&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;-1&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;data01:/usr/share/elasticsearch/data&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;9200:9200&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;elastic&lt;/span&gt;
  &lt;span class="na"&gt;kib01&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker.elastic.co/kibana/kibana:7.8.0&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kib01&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;5601:5601&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;ELASTICSEARCH_URL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://es01:9200&lt;/span&gt;
      &lt;span class="na"&gt;ELASTICSEARCH_HOSTS&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://es01:9200&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;elastic&lt;/span&gt;
&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;data01&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;local&lt;/span&gt;
  &lt;span class="na"&gt;data02&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;local&lt;/span&gt;
  &lt;span class="na"&gt;data03&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;local&lt;/span&gt;
&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;elastic&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bridge&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's take a look at the main tags stated at &lt;code&gt;docker-compose.yml&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Ports: configures docker port with host machine port where docker runs. In this case, 5000, 5601 and 9200.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Image: docker image that is downloaded for the required service&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Networks: this is named as 'elastic' in order to connect the three services&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Environment: configures environment variables essential to operate among services, such as RAM memory parameters. Within Kibana service, it is necessary to define the variables &lt;code&gt;ELASTICSEARCH_URL&lt;/code&gt; and &lt;code&gt;ELASTICSEARCH_HOSTS&lt;/code&gt;, in order to link it with the Elasticsearch service.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Dockerfile configuration
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Dockerfile&lt;/code&gt; has the required steps to configure the web application to link with our python script that extract and store the data in an Elasticsearch cluster, that at the same time imports &lt;code&gt;impact_dashboard.ndjson&lt;/code&gt; on Kibana for previous visualization.&lt;/p&gt;

&lt;p&gt;It runs on alpine distribution to copy the required folders to get the app running. Moreover, and thanks to &lt;code&gt;requirements.txt&lt;/code&gt;, you can add all the dependencies that the python script needs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; python:3.7-alpine&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /code&lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; FLASK_APP jitsi-data.py&lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; FLASK_RUN_HOST 0.0.0.0&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;apk add &lt;span class="nt"&gt;--no-cache&lt;/span&gt; git
&lt;span class="k"&gt;RUN &lt;/span&gt;apk add &lt;span class="nt"&gt;--no-cache&lt;/span&gt; tk-dev
&lt;span class="k"&gt;RUN &lt;/span&gt;apk add &lt;span class="nt"&gt;--no-cache&lt;/span&gt; gcc musl-dev linux-headers
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; requirements.txt requirements.txt&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; mapping.json mapping.json&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; templates templates&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; impact_dashboard.ndjson impact_dashboard.ndjson&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 5000&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["flask", "run"]&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  How to start containters
&lt;/h1&gt;

&lt;p&gt;In order to start the application (with docker and docker-compose previously installed) open your terminal and execute the following command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker-compose up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will initiate the different commands stated in dockerfile and download the required docker images. Once that's finished, you can check that Elasticsearch (localhost:9200) and Kibana (localhost:5601) are succesfully running.&lt;/p&gt;

&lt;p&gt;Now, it's time to go where python Flask application web app is located, using port &lt;code&gt;5000&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fP60sDC7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/bdgpwjr7erskgbabf5jm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fP60sDC7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/bdgpwjr7erskgbabf5jm.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Clicking on &lt;code&gt;start button&lt;/code&gt; will initialize data extraction from Jitsi git data (check &lt;code&gt;jitsi-data.py&lt;/code&gt; for more details) and will store such data to our ElasticSearch. Finally, it will import &lt;code&gt;impact_dashboard.ndjson&lt;/code&gt; to our Kibana, allowing us to interactively play with the data.&lt;/p&gt;

&lt;p&gt;Once the process is finished, the browser will show the next message:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--C6Dq2tYI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/1sp3n4dv335v5fa8erp9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--C6Dq2tYI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/1sp3n4dv335v5fa8erp9.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Of course, we can see if our Elasticsearch index and Kibana dashboard have successfully being added to our instances:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HPa6w-DP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/kjmu8sf90cjcxyzt3eoy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HPa6w-DP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/kjmu8sf90cjcxyzt3eoy.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lOc-p6Ba--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/uhymzlhkkknaf0m9k629.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lOc-p6Ba--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/uhymzlhkkknaf0m9k629.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By default the time filter is set to the last 15 minutes. You can use the Time Picker to change the time filter or select a specific time interval or time range in the histogram at the top of the page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s----WD-1QZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/atm4deo5nw6u92s6fwg4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s----WD-1QZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/atm4deo5nw6u92s6fwg4.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;et voilà&lt;/em&gt; now you have a cool dashboard up and running to analyze how a pandemic can impact Jitsi software development activity.&lt;/p&gt;

&lt;h1&gt;
  
  
  Bonus point: uploading a Docker image to Docker Hub
&lt;/h1&gt;

&lt;p&gt;With a Docker Hub account, you can build an image where &lt;code&gt;dockerfile&lt;/code&gt; is located. Simply type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ docker build -t dockerhubID/DockerHubreponame:imagetag .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, upload the image to your Docker Hub repo (you can create the repo using the Docker Hub UI&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ sudo docker push dockerhubID/DockerHubreponame:imagetag
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the image is uploaded to Docker Hub, any user can use and run the app with the following docker-compose.yml&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3'&lt;/span&gt;
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;web&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;daviddp92/jitsi-data-extraction:1.0.0&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;5000:5000&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;elastic&lt;/span&gt;
  &lt;span class="na"&gt;es01&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker.elastic.co/elasticsearch/elasticsearch:7.8.0&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;es01&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;node.name=es01&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cluster.name=es-docker-cluster&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;discovery.type=single-node&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;bootstrap.memory_lock=true&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ES_JAVA_OPTS=-Xms1024m&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;-Xmx1024m"&lt;/span&gt;
    &lt;span class="na"&gt;ulimits&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;memlock&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;soft&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;-1&lt;/span&gt;
        &lt;span class="na"&gt;hard&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;-1&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;data01:/usr/share/elasticsearch/data&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;9200:9200&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;elastic&lt;/span&gt;
  &lt;span class="na"&gt;kib01&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker.elastic.co/kibana/kibana:7.8.0&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kib01&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;5601:5601&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;ELASTICSEARCH_URL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://es01:9200&lt;/span&gt;
      &lt;span class="na"&gt;ELASTICSEARCH_HOSTS&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://es01:9200&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;elastic&lt;/span&gt;
&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;data01&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;local&lt;/span&gt;
  &lt;span class="na"&gt;data02&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;local&lt;/span&gt;
  &lt;span class="na"&gt;data03&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;local&lt;/span&gt;
&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;elastic&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bridge&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Closing thoughts
&lt;/h2&gt;

&lt;p&gt;We have learned how to dockerize a web app with Python technology and Flask framework using docker-compose. We also saw how to use and run the application using Docker Hub images.&lt;/p&gt;

&lt;p&gt;What do you think about this project? What should we improve? Feedback is more than welcome :)&lt;/p&gt;

</description>
      <category>docker</category>
      <category>python</category>
    </item>
    <item>
      <title>How to measure Covid-19 impact on Jitsi project with Python and ElasticSearch</title>
      <dc:creator>Ana Jimenez Santamaria</dc:creator>
      <pubDate>Fri, 03 Jul 2020 13:13:32 +0000</pubDate>
      <link>https://dev.to/anajsana95/how-to-measure-covid-19-impact-on-jitsi-project-with-python-and-elasticsearch-154j</link>
      <guid>https://dev.to/anajsana95/how-to-measure-covid-19-impact-on-jitsi-project-with-python-and-elasticsearch-154j</guid>
      <description>&lt;p&gt;The situation with Covid-19 limits the possibility of face-to-face communication. Remote work is now a reality, and the demand for video conferencing such as &lt;a href="https://jitsi.org/jitsi-meet/"&gt;Jitsi Meet&lt;/a&gt; continues breaking records.&lt;/p&gt;

&lt;p&gt;Could it be possible that &lt;a href="https://github.com/jitsi/jitsi-meet"&gt;Jitsi’s software development&lt;/a&gt; activity and community are on high-demand too?&lt;/p&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--775iecqK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1250136493378744322/V63YMKSb_normal.jpg" alt="Jitsi profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        Jitsi
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        @jitsinews
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      👋 We are seeing high volumes of traffic from our friends all over the world (specially in Italy) and we just wanted to let everyone know that we tripled our deployment size in the busiest regions! 📈&lt;br&gt;Happy Meetings! ❤️
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      13:15 PM - 06 Mar 2020
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1235916871783919617" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1235916871783919617" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1235916871783919617" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


&lt;p&gt;This post summarizes one of the analysis that my colleagues &lt;a href="https://www.linkedin.com/in/david-dur%C3%A1n-prieto/"&gt;David Duran&lt;/a&gt;, &lt;a href="https://www.linkedin.com/in/gerardoadrianaguirrevivar/"&gt;Gerardo Aguirre&lt;/a&gt; and &lt;a href="https://www.linkedin.com/in/ana-jim%C3%A9nez-santamar%C3%ADa/"&gt;I&lt;/a&gt; did for our M.S. in Data Science. Following the &lt;a href="https://en.wikipedia.org/wiki/GQM"&gt;GQM approach&lt;/a&gt;, we defined a clear goal and some related questions. Then, we decided the best metrics to answer those questions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Goal
&lt;/h2&gt;

&lt;p&gt;Analyze the impact that a global pandemic such as Covid-19 has on Jitsi&lt;/p&gt;

&lt;h2&gt;
  
  
  Questions
&lt;/h2&gt;

&lt;p&gt;Did Covid-19 countermeasures change:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Jitsi’s activity patterns?&lt;/li&gt;
&lt;li&gt;Jitsi’s diversity patterns? &lt;/li&gt;
&lt;li&gt;Jitsi’s community risk? &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As we are trying to measure impact, we need to see potential changes. For instance, did software development activity change during covid-19 outbreak compared to last year?&lt;/p&gt;

&lt;p&gt;We selected Feb 1st- May 31st 2019 and 2020 as our timeframe to measure such impact.&lt;/p&gt;

&lt;h2&gt;
  
  
  Metrics
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Contributor Activity&lt;/th&gt;
&lt;th&gt;Contributor Diversity&lt;/th&gt;
&lt;th&gt;Community Risk&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Total Contributors&lt;/td&gt;
&lt;td&gt;Organization Diversity&lt;/td&gt;
&lt;td&gt;Bus Factor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total Commits&lt;/td&gt;
&lt;td&gt;Gender diversity&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Timezone Diversity&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Total Contributors: number of authors that made a commit over a period of time&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Total Commits: number of commits over a period of time&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--G72le187--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/sqv6d5djj15gmod6pngq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--G72le187--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/sqv6d5djj15gmod6pngq.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Organization Diversity: different email domains over a period of time. Here we can find company’s domains (e.g jitsi, 8x8, etc) or individual’s (gmail, users, etc)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OoNWhbBm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/blv3ynp7xys9z8ol8buz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OoNWhbBm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/blv3ynp7xys9z8ol8buz.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Gender Diversity: total share of female and male author names that made a commit&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7tuZSL_I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/12ak5i88ifxtmtplk6mp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7tuZSL_I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/12ak5i88ifxtmtplk6mp.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Timezone diversity: existing authors on each timezone&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TTyOw5_a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/g8zpkasr9r9yljwuaybv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TTyOw5_a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/g8zpkasr9r9yljwuaybv.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bus Factor: minimum number of contributors needed to make the 50% of git code on Jitsi over a period of time&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tools used
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--r9SjGSBK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/fia7rw50qwwcd3ui2u2b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--r9SjGSBK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/fia7rw50qwwcd3ui2u2b.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data gathering and storage&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For data gathering we used an open source tool called Perceval. &lt;a href="https://github.com/chaoss/grimoirelab-perceval"&gt;Perceval&lt;/a&gt; offers a Python module for retrieving data from repositories related to software development. It works with many data sources, from Git repositories and GitHub projects to mailing lists, Gerrit or StackOverflow.&lt;/p&gt;

&lt;p&gt;For this specific analysis, we will just need Jitsi Git data.&lt;/p&gt;

&lt;p&gt;If you are running Jitsi-data.py available in &lt;a href="https://gitlab.com/msdatascienceurjc/ELK-perceval/-/blob/master/jitsi-data.py"&gt;this Gitlab repo&lt;/a&gt;, make sure you have installed perceval first&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ pip install perceval
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can simply use perceval git module on python with perceval.backends.core.git:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;elasticsearch&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Elasticsearch&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;logging&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;  &lt;span class="c1"&gt;# to specify a specific timeframe
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;gender_guesser.detector&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;gender&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;perceval.backends.core.git&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Git&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;dateutil.parser&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;parse&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perceval has 2 arguments for Git: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;URI: the repository or list of repos from GitLab or GitHub you want to analyze&lt;/li&gt;
&lt;li&gt;Gitpath: usually something like /tmp/repo-name.git
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# It has 2 arguments, uri and gitpath: repo = Git(uri=repository, gitpath='/tmp/'+repository.git)
&lt;/span&gt;&lt;span class="n"&gt;data_repo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Git&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'https://github.com/jitsi/jitsi-meet'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gitpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'/tmp/jitsi-meet.git'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Moreover, we use &lt;a href="https://elasticsearch-py.readthedocs.io/en/master/"&gt;Python Elasticsearch client&lt;/a&gt; to store data and mapping from python script to our ElasticSearch instance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Instance of elasticsearch to put the data into ElasticSearch/Kibana system (it is necessary to have both up on localhost)
&lt;/span&gt;    &lt;span class="n"&gt;elastic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Elasticsearch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="c1"&gt;# Read mapping json file to ElasticSearch
&lt;/span&gt;    &lt;span class="n"&gt;mapping_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"mapping.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"r"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;mapping&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mapping_file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# Creation of ElasticSearch index using the mapping
&lt;/span&gt;    &lt;span class="n"&gt;index_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"repo_jitsi_index_def"&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;elastic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;index_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;mapping&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;ignore&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;  &lt;span class="c1"&gt;# ignore 400 already exists code
&lt;/span&gt;    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Data transformation and mapping&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Perceval gives us raw git data with a lot of information over a period of time (we specify this thanks to datetime python package): Commit, Author, Lines added, Lines removed, Email, Commit Date and more.&lt;/p&gt;

&lt;p&gt;However, in order to analyze contributor diversity, we need to create new fields with the data provided. That's why we add organization (based on email domains), gender (using a &lt;a href="https://pypi.org/project/gender-guesser/"&gt;gender detector&lt;/a&gt; python package) and timezone fields (cleaning item field)&lt;/p&gt;

&lt;p&gt;You can see how we iterate through the different fields provided by Perceval to get the data in our &lt;a href="https://gitlab.com/msdatascienceurjc/ELK-perceval/-/blob/master/jitsi-data.py"&gt;GitLab repo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once we generate these new fields, we create our Elasticsearch mapping, transforming item data into a new structure matching the mapping for ElasticSearch&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data visualization&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you are running unity-data.py script with your Elasticsearch and Kibana instance opened, you can go to your Kibana localhost (usually &lt;code&gt;5601&lt;/code&gt;) &amp;gt; management &amp;gt; index patterns and click on create index pattern. You should see the index name given at jitsi-data.py (by default is &lt;code&gt;repo_jitsi_index_def&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5HSeo3lz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/c65qt40ifcq766i971dg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5HSeo3lz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/c65qt40ifcq766i971dg.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We then elaborate a Kibana dashboard with the specific visualizations that fits best with our defined metrics. We called it “impact_dashoard”&lt;/p&gt;

&lt;p&gt;At a first glance, we can see an uncommon behavior on Jitsi’s activity since February 2020:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wL2tbVLe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/di5lvgrp62ildldelwhi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wL2tbVLe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/di5lvgrp62ildldelwhi.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And when comparing 2019 period with 2020, results are also quite interesting:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fbJePzYg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/cnxl43zhjvjr95fki4yg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fbJePzYg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/cnxl43zhjvjr95fki4yg.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Image below highlights major changes regarding contributor’s diversity and activity:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZdVVwPTo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ch8yeo8d20moarqgbinu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZdVVwPTo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ch8yeo8d20moarqgbinu.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can see that:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Contributor’s Activity increased:&lt;/em&gt; there is an increase in commit activity, lines added and removed, authors and organizations involved on Jitsi’s software development&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Contributor's Diversity increased:&lt;/em&gt; It’s interesting to see that women activity was under 1% last year and since covid-19 started, it increased to 8%. Still a low number, but is a good indicator. &lt;/p&gt;

&lt;p&gt;Also, we see some author activity in Asia that didn’t existed before.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Disclaimer: there are “unknown” data that our gender detector couldn’t guess. The main reason is because some Jitsi’s developers have non-occidental characters and our gender detector is optimized for occidental names. We did an exhaustive cleaning for the most relevant names though, reducing our “unknown” data, but we couldn’t erase it completely.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What about Community Risk?
&lt;/h2&gt;

&lt;p&gt;To answer our last question and metric, we work on a query using &lt;a href="https://jupyter.org/"&gt;Jupyter Notebook&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;The Bus Factor for developers isn’t something new: It is the minimum number of team members that have to suddenly disappear from a project before the project stalls due to lack of knowledgeable or competent personnel. In other words:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fXB53LEH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ztm46s5c6lyxor377e4x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fXB53LEH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ztm46s5c6lyxor377e4x.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our Bus Factor approach for our specific goal answers the question &lt;strong&gt;Which is the minimum number of contributors needed to make the 50% of git code on Jitsi?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As a result, we get that in 2019, Jitsi only needed 2 developers to make the 50% of git code while in 2020 Jitsi needs at least 9 developers. This fact is indeed good for Jitsi’s project health!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dvu4WgDA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/lcv4ds4uzvu6u0vf11w8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dvu4WgDA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/lcv4ds4uzvu6u0vf11w8.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see Jupyter Notebook query in our &lt;a href="https://gitlab.com/msdatascienceurjc/ELK-perceval"&gt;GitLab repo&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Future Work
&lt;/h2&gt;

&lt;p&gt;This is just a very introductory analysis to measure covid-19 impact on Jitsi. Of course, we can improve a lot of things. Some future work might be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Improve author affiliation: We know an existing open source tooling called &lt;a href="https://github.com/chaoss/grimoirelab-sortinghat"&gt;SortingHat&lt;/a&gt;, that can be implemented with Perceval and other &lt;a href="https://github.com/chaoss/grimoirelab"&gt;GrimoireLab&lt;/a&gt; components. SortingHat is an identity affiliation management. Thus, identities corresponding to the same real person can be merged in the same unique identity with a unique uuid.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Filter “unknown” category within gender term: Maybe gender-guesser package is not the best one to use. Do you know other python packages we can use? Leave your comments below :) &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Work on new metric for risk assessment, such as the &lt;a href="https://en.wikipedia.org/wiki/Gini_coefficient"&gt;Gini coefficient&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And last but not least: &lt;strong&gt;Correlation does not imply causation&lt;/strong&gt;. We don’t have all the domain knowledge Jitsi maintainers and community specialists might have. A relationship between Covid-19 and contributor's activity might be just coincidence&lt;/p&gt;

</description>
      <category>python</category>
      <category>datascience</category>
      <category>git</category>
    </item>
    <item>
      <title>Remote work: The Open Source Way</title>
      <dc:creator>Ana Jimenez Santamaria</dc:creator>
      <pubDate>Fri, 13 Mar 2020 22:40:59 +0000</pubDate>
      <link>https://dev.to/anajsana95/remote-work-the-open-source-way-i52</link>
      <guid>https://dev.to/anajsana95/remote-work-the-open-source-way-i52</guid>
      <description>&lt;p&gt;Working remotely has become mission-critical now more than ever. Since one of the recommendations to stop COVID-19 massive spread is to stay at home, many companies are seeking effective strategies and tools for remote work.&lt;/p&gt;

&lt;p&gt;For many people, this situation could be an overwhelming first-time experience, but for many others this is not something new: People behind Open Source programs have been involved in remote collaborative workspaces since decades. How does the Open Source ecosystem manage remote workforce? &lt;/p&gt;

&lt;h2&gt;
  
  
  Everything starts with culture
&lt;/h2&gt;

&lt;p&gt;People is desperately asking for collaborative tools to stay productive and connected. But is that the best approach? &lt;/p&gt;

&lt;p&gt;Think about it, &lt;em&gt;Why giving to someone that has never handle remote work, a bunch of tools without context?&lt;/em&gt; In fact, tooling is the last thing you should be thinking of. Open Source has succeed over the past years not just because of tools, but because of culture&lt;/p&gt;

&lt;p&gt;Before going nuts with &lt;em&gt;what tools should people use&lt;/em&gt;, I suggest to first investigate &lt;em&gt;what strategies are used within open source communities&lt;/em&gt; and &lt;em&gt;what can companies learn from them&lt;/em&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This way of thinking can somehow relate to InnerSource term: a methodology which main goal is to establish &lt;em&gt;open source-like culture within organizations&lt;/em&gt;. It has a consolidated and active community, called &lt;a href="https://innersourcecommons.org/"&gt;InnerSource Commons&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Hands on remote-work: Best practices and suggestions
&lt;/h2&gt;

&lt;p&gt;In my company -Committed Open Source practitioners- working from home has never been a problem- We have been doing it since always!- This might be the reason why, some people from Twitterverse and Instagram asked me about best practices to follow in order to manage remote collaboration and productivity. Then I though that the best way to answer was by sharing &lt;em&gt;my top 6 best practices&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Document everything:&lt;/strong&gt; As in person-meetings are not an option, internal documentation plays an important role to ensure collaboration. This is a really common practice within open source projects, as code is being build collaboratively and remotely, done by people from different time zones and cultures. Some of them are experienced contributors, others are just newbies trying to get into their first open source contribution. in both cases, they need to know &lt;em&gt;how to contribute&lt;/em&gt; - as well as pitfalls to avoid, guidelines, etc- and such information needs to be accessible and visible for everyone.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Build a Kanban board&lt;/strong&gt;: One of the main resources coming from Agile methodologies that can be applied for any situations that requires organizing and scheduling tasks. This is so helpfull that I'm not only use it at work to coordinate tasks with my team, but also with my classmates for my Data Science MS... Even for my personal projects!&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9H92OQGt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/itck9tnxctfd54tbhb11.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9H92OQGt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/itck9tnxctfd54tbhb11.jpg" alt="Kanban board" title="Kanban board"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Schedule daily meetings to keep track of current work:&lt;/strong&gt; This will help to keep your team synchronized, know what they are working at and find potential bottle necks... A good idea is to focus on short tasks, that can be done within 1 or 3 days period to track better the activity&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Set your own working hours and breaks:&lt;/strong&gt; set up an alarm and create a daily routine for work. The same way you do at work,dress up -avoid full-day pijama- and have specific clock-in and clock-out hours. This is very helpful to divide work vs spare time, and &lt;em&gt;not fall into an endless working state&lt;/em&gt; that at some point will lead into a &lt;em&gt;burnout&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/3o6Mblpo7jq1JBaXLi/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/3o6Mblpo7jq1JBaXLi/giphy.gif" alt="time" title="time"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Socialize:&lt;/strong&gt; working from home doesn't mean you can't have great coffee break conversations with your teammates!. At my company, Every Friday at 2:00pm, we have what we call &lt;em&gt;coffee-chats&lt;/em&gt; -. We join the call,  talk about our week, and enjoy a nice cup of coffee with friends!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/687qS11pXwjCM/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/687qS11pXwjCM/giphy.gif" alt="Coffee time" title="Coffee friends"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Do Exercise + healthy diet:&lt;/strong&gt; I'm quite a restless person*, which means I need to remain focus and productive as much as possible if I want to do all the activities I've planned for that day. &lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;*I have full-time work, Data Science MS, Japanese, and boxing classes, while saving time for my family and friends... All in the same week!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Boxing classes helped me a lot when covid-19 situation was not there, but now that gym is not the best place to be, I still doing some cardio at home to relieve stress. Moreover, avoiding added sugar and fast food intake made me feel less tired and more proactive during the day&lt;/p&gt;

&lt;h2&gt;
  
  
  Tooling
&lt;/h2&gt;

&lt;p&gt;Once you have define a way of collaborative work and clear daily routines, it's time to look at the resources you need to make that possible.&lt;/p&gt;

&lt;p&gt;There are lots of things you need to keep an eye on when choosing the best tool for you: Data Privacy, licenses, budget, scalability and more. However, taking into account that I'm not an expert on this field, I'll just enumerate some of my favorite tools I have been using during the past year at work or personal projects, grouped by different scenarios:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Communication Apps&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://slack.com/"&gt;Slack&lt;/a&gt;: similar to telegram, but more specialized for remote teams. you can have different channels which makes great to communicate among different working teams, topics or departments&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Video chat&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://meet.jit.si/"&gt;Jitsi.meet&lt;/a&gt;: No log ins and completely free video conferencing. You know what's best? it's fully encrypted!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Time management&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://trello.com"&gt;Trello&lt;/a&gt;: really useful for those willing to use a &lt;a href="https://en.wikipedia.org/wiki/Kanban_(development)"&gt;Kanban&lt;/a&gt; board to manage daily tasks&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;File hosting services&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://nextcloud.com/"&gt;NextCloud&lt;/a&gt;: Actually this is the only one I haven't use it yet, but I've heard a lot of positive feedback about this tool! Despite other alternatives, this solution does NOT store your data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Podcast/interview recording&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://etercast.com/"&gt;Etercast&lt;/a&gt; If you're planing to have several guests for an interview, Etercast might be a good solution. No log in, free and very easy to manage&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: &lt;a href="http://jgbarah.github.io/Notes/foss-distance-learning.html"&gt;This post by Jesús González-Barahona&lt;/a&gt; shows more resources, also applied for &lt;em&gt;distance learning&lt;/em&gt;. The best thing is that all of them are entirely free, open source software (FOSS)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Closing thoughts
&lt;/h2&gt;

&lt;p&gt;Not every business is suitable for remote work: My goal here is not to show that everyone can work remotely -cause we can't-, but to give some guidance to those few who &lt;em&gt;potentially can&lt;/em&gt; but &lt;em&gt;don't know how to start with&lt;/em&gt; and share my thoughts and experience working in remote and collaborative environments.&lt;/p&gt;

&lt;p&gt;Thanks for reading until the end. For those experienced people in collaborative and remote environments, I'd love to see any suggestions or tools that you might find useful to share to folks who are facing remote work for their first time. &lt;/p&gt;

&lt;p&gt;Feedback is more than welcome :)&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>remotework</category>
    </item>
  </channel>
</rss>
