tag:blogger.com,1999:blog-150843822024-03-12T21:50:23.396-07:00Ken's BlogThoughts on software, gardening, jazz, LA transit, cycling, and urban planningKen Weinerhttp://www.blogger.com/profile/12369783173503766970noreply@blogger.comBlogger227125tag:blogger.com,1999:blog-15084382.post-42484081560052211372023-12-02T11:51:00.000-08:002023-12-02T11:51:09.767-08:00Monggo con Carne with Tomi Chips: Filipino-Style Chili<p>A favorite chili recipe of mine originally at <a href="https://www.pepper.ph/filipino-chili-tomi-chips/">https://www.pepper.ph/filipino-chili-tomi-chips/</a> seems to have been permanently removed. I couldn't find it anywhere on the Internet except from the trusty <a href="https://web.archive.org/web/20180312194339/https://www.pepper.ph/filipino-chili-tomi-chips/">Wayback machine</a>, so I am going to post it here in case anyone else is searching for it.</p><h1 class="single__header__title" style="background-color: white; box-sizing: border-box; font-family: "GT Pressura", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 3.25rem; line-height: 1.15; margin: 0px auto 0.9375rem;">Monggo con Carne with Tomi Chips: Filipino-Style Chili</h1><p><span class="posts__date" style="background-color: white; box-sizing: border-box; font-family: "GT Pressura", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 0.875rem; line-height: 1.2;">June 17, 2014</span><span style="background-color: white; font-family: "GT Pressura", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 16px;"> Tagged: </span><span class="tags" style="background-color: white; box-sizing: border-box; font-family: "GT Pressura", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 0.875rem; line-height: 1.2;">beef beans filipino</span></p><ul style="background-color: white; box-sizing: border-box; font-family: "GT Pressura", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 16px; line-height: 1; list-style: none; margin: 0px; padding: 0px;"><li style="box-sizing: border-box; font-size: 0.875rem; line-height: 1; margin-bottom: 0.625rem;">Mikka Wee<span style="box-sizing: border-box; font-size: 0.625rem; font-weight: bold; letter-spacing: 0.0625em; line-height: 1.2; margin-left: 0.4375rem; text-transform: uppercase;">WORDS</span></li><li style="box-sizing: border-box; font-size: 0.875rem; line-height: 1; margin-bottom: 0.625rem;">Mylene Chung<span style="box-sizing: border-box; font-size: 0.625rem; font-weight: bold; letter-spacing: 0.0625em; line-height: 1.2; margin-left: 0.4375rem; text-transform: uppercase;">PHOTOGRAPHY</span></li><li style="box-sizing: border-box; font-size: 0.875rem; line-height: 1; margin-bottom: 0.625rem;">Katherine Jao<span style="box-sizing: border-box; font-size: 0.625rem; font-weight: bold; letter-spacing: 0.0625em; line-height: 1.2; margin-left: 0.4375rem; text-transform: uppercase;">STYLING AND RECIPE DEVELOPMENT</span></li><li style="box-sizing: border-box; font-size: 0.875rem; line-height: 1; margin-bottom: 0.625rem;"><span style="box-sizing: border-box; font-size: 0.625rem; font-weight: bold; letter-spacing: 0.0625em; line-height: 1.2; margin-left: 0.4375rem; text-transform: uppercase;"><br /></span></li></ul><div><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 18px;">There are just some days when I need my bowl of chili. Regarded by many as one of the top players in comfort food lists, chili can really be all you need to get through a stressful day. When daydreams start to kick in, and visions of a piping-hot bowl filled with robust, beefy flavors finished by some tart sour cream start to toy around with your brain, you know that the calling is loud and clear—make some damn chili. But here’s a version that might just tempt you to up your chili game.</span></div><div><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 18px;"><br /></span></div><div><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 18px;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEjZFpPV3rz_8CFKoR7FBFZ6DKicE4nxNFq0hi-OdIZc8Ce0ypGKnisoHHSbkp0cp2AREN470VxPcaQKkKw7bTxvJ9sZsS-PiiFEHgNlofT9eLzMNwF7rJ7l9zDCKE_rCB9afgHR3tf_jSZwRBDnYLclhWZlXPnkvf7VPi4z6oklI2rQoeRb2PxF4g" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="1500" data-original-width="1000" height="400" src="https://blogger.googleusercontent.com/img/a/AVvXsEjZFpPV3rz_8CFKoR7FBFZ6DKicE4nxNFq0hi-OdIZc8Ce0ypGKnisoHHSbkp0cp2AREN470VxPcaQKkKw7bTxvJ9sZsS-PiiFEHgNlofT9eLzMNwF7rJ7l9zDCKE_rCB9afgHR3tf_jSZwRBDnYLclhWZlXPnkvf7VPi4z6oklI2rQoeRb2PxF4g=w267-h400" width="267" /></a></div><br /></span><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 18px;">Mung Beans (monggo) aren’t the most attractive veggies around. These round little dark-green spheres are always shadowed by the brighter-looking produce. But mung beans, in fact, make a great chili base. They’re a good choice for thickening agents, and that’s what we want in a good stew or chili. It’s also a healthier alternative if you’re gunning for a six-pack.</span></div><div><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 18px;"><br /></span></div><div><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 18px;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEhgGaRcNbu1Z76xh9uMfjgNPzu-qoF9YvpB-Hu0z3AqnAORShaHevIoob8Av5T-doMr-GrRTEqTHdziz3aOQXXlH9EFz8eQCYPt5aPrfP3uhojii8oYTtS6y7R7EejJj8J9079W7Bg8isoszBq-AYrhf_F0pi0LVjxPY-U3z_UgsX167oG6cCjQbQ" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="667" data-original-width="1000" height="266" src="https://blogger.googleusercontent.com/img/a/AVvXsEhgGaRcNbu1Z76xh9uMfjgNPzu-qoF9YvpB-Hu0z3AqnAORShaHevIoob8Av5T-doMr-GrRTEqTHdziz3aOQXXlH9EFz8eQCYPt5aPrfP3uhojii8oYTtS6y7R7EejJj8J9079W7Bg8isoszBq-AYrhf_F0pi0LVjxPY-U3z_UgsX167oG6cCjQbQ=w400-h266" width="400" /></a></div><br /></span><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 18px;">The versatility from the mung beans provides a lot of room for creativity. The deep red sauce spiced with paprika provides a gentle heat with a kick from the cumin. Finish it with a generous sprinkle of our beloved Tomi Corn Chips that provide a nostalgic sweetness that can only be traced to our childhood days.</span></div><div><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 18px;"><br /></span></div><div><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 18px;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEirGhy271ZG2FUkb0JrMkN6cQGv9xPi4ArXLyOuejqD-UuDkezDQme2XrzPJ5Jj9Q5OBSchcx9_Do4xXKgM96PO4LrXHAOUUVFNnPfRL7fooqzYEC1-vuWwocHuGfGcZB4fpg9-_6UNzpHil_dnXI9yaBa_aRRp0g5S_ixZcVjuK2ExnbPr0J4mkw" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="667" data-original-width="1000" height="266" src="https://blogger.googleusercontent.com/img/a/AVvXsEirGhy271ZG2FUkb0JrMkN6cQGv9xPi4ArXLyOuejqD-UuDkezDQme2XrzPJ5Jj9Q5OBSchcx9_Do4xXKgM96PO4LrXHAOUUVFNnPfRL7fooqzYEC1-vuWwocHuGfGcZB4fpg9-_6UNzpHil_dnXI9yaBa_aRRp0g5S_ixZcVjuK2ExnbPr0J4mkw=w400-h266" width="400" /></a></div><br /></span><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 18px;">The idea may seem hilarious on paper, but might I say, it’s one of the recipes I wolfed down on my own—without sharing.</span></div><div><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 18px;"><br /></span></div><div><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 18px;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEhM06ehylzOtmZvkSbuNtW6E1ahjOr_XA4iLCX5YqPjCAABVBY2MdcNIq9-Nvn93bPdT9EbNGTl_QXFjfq27vjtN16WrnD6IT5zpvdWk-20lsUKQiVdzmK3gdTg4PoO7i6rtLKSKJZoB5Rs7FKA6z4dNw15FMA0AqUD4QMFqX8lvwTRl3G2qO8Wgg" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="667" data-original-width="1000" height="266" src="https://blogger.googleusercontent.com/img/a/AVvXsEhM06ehylzOtmZvkSbuNtW6E1ahjOr_XA4iLCX5YqPjCAABVBY2MdcNIq9-Nvn93bPdT9EbNGTl_QXFjfq27vjtN16WrnD6IT5zpvdWk-20lsUKQiVdzmK3gdTg4PoO7i6rtLKSKJZoB5Rs7FKA6z4dNw15FMA0AqUD4QMFqX8lvwTRl3G2qO8Wgg=w400-h266" width="400" /></a></div><br /></span><h1 style="background-color: white; box-sizing: border-box; font-family: "GT Pressura", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 3.25rem; font-weight: normal; line-height: 1.25; margin: 1rem auto 0.75rem;">Monggo con Carne (Filipino Chili)</h1><h3 style="background-color: white; border-color: rgb(194, 194, 194); border-image: initial; border-style: dashed; border-width: 0.0625rem 0px; box-sizing: border-box; display: inline-block; font-family: "GT Pressura", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 1.25rem; font-weight: normal; letter-spacing: 0.00625em; line-height: 1.5; margin: 0px auto 1.5em; padding: 0.8125rem 0px; width: 600.922px;">Total Time: 120 minutes | Yield: 8 servings</h3></div><div><h2 style="background-color: white; box-sizing: border-box; color: #e0a729; font-family: "GT Pressura", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 1.5rem; letter-spacing: 0.0625rem; line-height: 1.3; margin: 0em auto 1em; text-transform: uppercase;">INGREDIENTS</h2><ul style="text-align: left;"><li><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 1.125rem;">3 tbsp olive oil</span></li><li><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 1.125rem;">1 tbsp garlic, </span><em style="background-color: white; box-sizing: border-box; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 1.125rem;">minced</em></li><li><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 1.125rem;">4 pcs bird’s eye chili/ siling labuyo,</span><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 1.125rem;"> </span><em style="background-color: white; box-sizing: border-box; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 1.125rem;">chopped</em></li><li><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 1.125rem;">1 pc white onion,</span><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 1.125rem;"> </span><em style="background-color: white; box-sizing: border-box; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 1.125rem;">chopped</em></li><li><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 1.125rem;">1 cup ground beef</span></li><li><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 1.125rem;">200 grams uncooked monggo</span></li><li><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 1.125rem;">2 cans crushed tomatoes</span></li><li><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 1.125rem;">1 tsp paprika</span></li><li><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 1.125rem;">1 tsp cumin</span></li><li><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 1.125rem;">1 tsp chili powder</span></li><li><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 1.125rem;">2 beef bouillon cubes</span></li><li><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 1.125rem;">salt and pepper,</span><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 1.125rem;"> </span><em style="background-color: white; box-sizing: border-box; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 1.125rem;">to taste</em></li><li><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 1.125rem;">enough water to soften monggo (</span><em style="background-color: white; box-sizing: border-box; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 1.125rem;">about 4-6 cups</em><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 1.125rem;">)</span></li><li><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 1.125rem;">sour cream,</span><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 1.125rem;"> </span><em style="background-color: white; box-sizing: border-box; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 1.125rem;">as topping</em></li><li><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 1.125rem;">cilantro,</span><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 1.125rem;"> </span><em style="background-color: white; box-sizing: border-box; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 1.125rem;">as topping</em></li><li><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 1.125rem;">Tomi chips,</span><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 1.125rem;"> </span><em style="background-color: white; box-sizing: border-box; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 1.125rem;">as topping</em></li></ul><div><h2 style="background-color: white; box-sizing: border-box; color: #e0a729; font-family: "GT Pressura", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 1.5rem; letter-spacing: 0.0625rem; line-height: 1.3; margin: 1.75em auto 1em; text-transform: uppercase;">PROCEDURE</h2><ol style="text-align: left;"><li><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 1.125rem;">Heat olive oil in pot and sauté galic, chili, and white onion for 2-3 minutes or until soft but not browned.</span></li><li><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 1.125rem;">Add in the ground beef and sauté until cooked.</span></li><li><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 1.125rem;">Add in beans, crushed tomatoes, paprika, cumin, chili powder, and beef bouillon cubes. Mix well.</span></li><li><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 1.125rem;">Pour water and let it boil. Cook until beans are soft, to your liking. This will take about 60-90 minutes.</span></li><li><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 1.125rem;">Once softness is achieved, and consistency is thick, adjust the seasoning to your liking.</span></li><li><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 1.125rem;">Turn off the fire and transfer to bowls.</span></li><li><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 1.125rem;">Top with sour cream, chopped cilantro and crushed Tomi chips.</span></li><li><span style="background-color: white; font-family: Merriweather, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 1.125rem;">Serve immediately.</span></li></ol><div><section class="single__content content" style="background-color: white; box-sizing: border-box; float: left; font-family: "GT Pressura", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 16px; margin: 0px auto; padding: 1.875rem 0px; position: relative; width: 600.922px;"><h3 style="border-color: rgb(194, 194, 194); border-image: initial; border-style: dashed; border-width: 0.0625rem 0px; box-sizing: border-box; display: inline-block; font-size: 1.25rem; font-weight: normal; letter-spacing: 0.00625em; line-height: 1.5; margin: 0px auto 1.5em; padding: 0.8125rem 0px; width: 600.922px;">Note: You can add more monggo if you want more beans than meat. You can also soak the monggo beans for 2 hours before prepping to speed up the cooking time.</h3></section></div></div></div>Ken Weinerhttp://www.blogger.com/profile/12369783173503766970noreply@blogger.com0tag:blogger.com,1999:blog-15084382.post-81017186928679880492020-12-28T20:05:00.002-08:002020-12-28T20:05:40.332-08:00Sia Not a Fit for Personal Backups<div style="text-align: left;">In this post, I will describe my experience trying to use Sia as personal backup service. <a href="https://sia.tech/" target="_blank">Sia</a> is a decentralized cloud storage platform. I heard about Sia back in late 2017 when just about everyone was talking about cryptocurrencies, altcoins, and blockchains. It appears to still be active 3 years later, so I took that as a good sign. Spoiler alert - I got everything working, but learned that Sia is not a good fit for a personal backup service.</div><div style="text-align: left;"><br /></div><h3 style="text-align: left;">Alternative to CrashPlan</h3><div>Ever since CrashPlan <a href="https://www.groovypost.com/reviews/crashplan-for-home-users-shutting-down-alternative-cloud-storage-services/" target="_blank">changed their focus</a> to enterprise users and raise their price to a minimum of $10/month, I have been looking for a lower-cost file backup alternative for my home computer. I finally decided to give Sia a try. If it worked out, I could reduce my annual backup expense from $120 to just $5!</div><div><br /></div><div>Before I get into my Sia experience, here is an overview of all the steps I will attempt:</div><div><ol style="text-align: left;"><li>Read about Sia (30 minutes)</li><li>Download Sia UI (5 minutes)</li><li>Wait for blockchain syncing to complete (8 hours)</li><li>Purchase Siacoin in Bittrex (30 minutes). Note, if you don't already have an account with a crypto exchange that supports Siacoin, then this step might take up to 24 hours to get set up.</li><li>Transfer Siacoin to Sia UI wallet (60 minutes)</li><li>Download SiaSync (10 minutes)</li><li>Sync files (3 hours)</li><li>Verify ability to restore on a different computer (4 hours)</li></ol><div><br /></div></div><h3 style="text-align: left;">Sia Terminology</h3><div>I did a little reading on Sia's website to get familiar with their terminology. I am a <b>Renter</b> that will be uploading files to other computers owned by other people called <b>Hosts</b>. For that privilege, I will be configuring an <b>Allowance</b> of <a href="Siacoin (SIA)" target="_blank">Siacoin (SIA)</a>, which is how much money I'm willing to spend.</div><div><br /></div><div><h3 style="text-align: left;">The Sia UI</h3><div>My home computer is an Ubuntu 18.04 desktop. I downloaded the <a href="https://sia.tech/releases/Sia-UI-v1.5.3.AppImage" target="_blank">SIA UI Linux application</a> from their <a href="https://sia.tech/get-started" target="_blank">Getting Started</a> page. Double clicking it didn't do anything. I made it executable and then launched it from the command line:</div><div><br /></div><div><span style="background-color: #666666; color: white; font-family: courier;">chmod +x Sia-UI-v1.5.3.AppImage</span></div><div><span style="background-color: #666666; color: white; font-family: courier;">./Sia-UI-v1.5.3.AppImage</span></div><div><br /></div><div>This brought up the SIA UI. It assigned me a Sia Seed which I saved as a secure LastPass note. The app displayed a message saying it was syncing and I could see the Block Height continue to increase, but I didn't know what that meant. I selected Rent from the menu and then Setup Allowance. This launched a calculator where I plugged in my estimated initial usage of 0.1 TB (100 GB). It said the target price was 1250 SC which is the cost of a TB per month. I wasn't sure if that is the current market rate or some kind of bid that I will be placing, but I kept it as-is, and continued. Next I was asked if I am sure I want to set an allowance of 250 SC to rent storage on Sia. I confirmed and was then given an error message saying that I have to wait for Sia to finish syncing before I can set an allowance. I actually tried this several times because at first it seemed like nothing happened. <i>Later I found out that all of these contracts were queuing up and would go into effect as soon as my SC arrived in my wallet. I wish the Sia UI had shown me these pending contracts so I wouldn't have generated so many!</i> My Block Height had reached over 40,000 by this point, but there was no indication of how long I'd have to wait for syncing to complete.</div><div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzVtMecPh7paRLEagLMQBzSdFQl1541OCL4n7HVHTubAFuOqnsnzzIAp4Y6Q1qVAgZyJmHep1b1dKLFlk3weuFDI3u1paEkGIMj0Hq0gX6vRDrCanPcFuwguS12larCf_GEaf9Ug/s807/sia-ui.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img alt="Sia UI" border="0" data-original-height="551" data-original-width="807" height="218" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzVtMecPh7paRLEagLMQBzSdFQl1541OCL4n7HVHTubAFuOqnsnzzIAp4Y6Q1qVAgZyJmHep1b1dKLFlk3weuFDI3u1paEkGIMj0Hq0gX6vRDrCanPcFuwguS12larCf_GEaf9Ug/w320-h218/sia-ui.png" title="Sia UI" width="320" /></a></div></div><h3 style="text-align: left;">The Big Wait</h3><div>I found this support post <a href="https://support.sia.tech/article/LVKiCq8UwU-why-does-sia-ui-take-so-long-to-sync" target="_blank">Why does Sia take so long to sync?</a> which explained that before getting started, Sia would have to download an entire copy of its blockchain (over 22 GB) which could take several hours to over a day! They should really tell you this when you first open the UI. I decided to leave this to finish syncing over night and come back in the morning. According to <a href="https://siastats.info/" target="_blank">SiaStats</a>, the Block Height needed to get to 292,652. Sure enough, it had completed syncing by the morning. The Dashboard showed 292,652 Block Height, 9 Connected Peers, and 203 Active Hosts.</div><div><br /></div><div>With the Sync completed, I selected Rent in the UI and tried to set up an Allowance. I received a message saying Allowance successfully updated. However, nothing in the Rent or Wallet section updated, so I have a feeling nothing actually happened since I don't have any Siacoin yet.</div><div><br /></div><h3 style="text-align: left;">Getting Siacoin</h3><div>The next step was to obtain some Siacoin (SC) I could use to purchase a contract. Luckily I already had a <a href="http://bittrex.com/" target="_blank">Bittrex</a> account which is one of the <a href="https://airtable.com/shrq4MSLNxinvnaR7/tblBYpPz8NRekRYGx" target="_blank">exchanges</a> where you can trade for Siacoin. Siacoin was currently trading at 1 SC for 0.00000013 BTC. I tried to buy 1,500 SC for 0.00019568 BTC ($5.30 USD) which I estimated would last me a whole year. Bittrex warned me that the minimum trade was 0.0005 BTC. So I increased to 4,500 SC for 0.00058704 BTC ($15.91 USD) and tried again.</div><div><br /></div><div><table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvMSDRgASpd4GymOoqLSfA27RklC4AXVAhousxn89w6YlCW0lWJbgjyLeuODvy-kncOi8Mw0lVmZ8wlfgzgDqZPL1k9kO31SVaisAL6MzJxIjADrepbvfJr-k0840L4ClQbAYDLA/s306/siacoin-purchase.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" data-original-height="211" data-original-width="306" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvMSDRgASpd4GymOoqLSfA27RklC4AXVAhousxn89w6YlCW0lWJbgjyLeuODvy-kncOi8Mw0lVmZ8wlfgzgDqZPL1k9kO31SVaisAL6MzJxIjADrepbvfJr-k0840L4ClQbAYDLA/s0/siacoin-purchase.png" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Bittrex Limit Order of SC</td></tr></tbody></table></div><h3 style="text-align: left;">Transferring Siacoin</h3><div>Once the order went through, I had to transfer the SC out of Bittrex and into my Sia UI Wallet. Within the Sia UI, I went to Wallet, then Receive, then Generate New Address. I initiated a Withdrawal within Bittrex, and entered the wallet address that I just generated from Sia UI. The withdrawal showed as Completed in Bittrex pretty quickly. However, I had to wait about 7 minutes before it showed up in the Sia UI. I was relieved it showed up, though, as cryptocurrency transfers generally make me nervous. The transaction status showed as 0/6, and I had to wait another 10 minutes before transaction fully completed with status of 6/6. I transferred 1,500 SC, but was charged a 0.1 SC transaction fee, so 1499.9 SC ended up in my Sia UI wallet.</div><div><br /></div><h3 style="text-align: left;">Contracts</h3><div>Looks like 50 Contracts got created and and 143.52 SC were allocated when I attempted to set up an Allowance several times earlier. I still don't really understand Contracts well enough to know how many I should have. For now I'm going to assume that I have more than what I need and move on.</div><div><br /></div><h3 style="text-align: left;">Syncing Files</h3><div>To set up file syncing between my desktop and the Sia network, I turned to <a href="https://github.com/tbenz9/siasync" target="_blank">Siasync</a>. As new files are created or removed from a source folder, it will add or remove them from the Sia network accordingly. This replicates the behavior I had with CrashPlan and what we're all used to with services like Dropbox. Following their instructions, I downloaded the Siasync binaries for the latest version, <a href="https://github.com/tbenz9/siasync/releases/tag/1.0.1-beta.1">1.0.1 beta 1</a> and made the file executable from the command line:</div><div><br /></div><div><span style="background-color: #666666; color: white; font-family: courier;">chmod +x Siasync-linux-amd64</span></div><div><br /></div><div>I was hoping I could make a single folder containing symlinks to other folders I wanted to sync. I tried it, but Siasync wasn't recognizing any symlinked folders. To sync multiple folders as subfolders to a single backup folder on the Sia network, I used the following separate commands:</div><div><br /></div><div><div><div><span style="background-color: #666666; color: white; font-family: courier;">./Siasync-linux-amd64 -sync-only -size-only -subfolder backups/Desktop ~/Desktop</span></div><div><div><div><span style="background-color: #666666; color: white; font-family: courier;">./Siasync-linux-amd64 -sync-only -size-only -subfolder backups/Music ~/Music</span></div><div><div><span style="background-color: #666666; color: white; font-family: courier;">./Siasync-linux-amd64 -sync-only -size-only -subfolder backups/Pictures ~/Pictures</span></div></div></div></div></div><div><span style="background-color: #666666; color: white; font-family: courier;">./Siasync-linux-amd64 -sync-only -size-only -debug -subfolder backups/Videos ~/Videos</span></div></div><div><br /></div><div>This worked, and all my files got backed up on the Sia network!</div><div><br /></div><div>While searching for solutions on syncing using symlinks, I came across this <a href="https://extensions.gnome.org/extension/1032/sia-cloud-storage/" target="_blank">Sia Cloud Storage Extension for GNOME</a> which promises to take the place of Siasync with support for symlinks that you can put in a synced ~/Sia folder. I made a note to try that later. </div><div><br /></div><h3 style="text-align: left;">Sanity Check</h3><div>As a last step, I wanted to check if I could access my files from another computer. To do this, I downloaded Sia on a Macbook Pro. To try to save some time, I copied the consensus.db file (all 22 GB of it) from my Ubuntu desktop (192.168.0.51) so Sia UI wouldn't have to download it again:</div><div><br /></div><div><span style="background-color: #666666; color: white;">scp ken@192.168.0.51:.config/Sia-UI/sia/consensus/consensus.db ~/Library/Application Support/Sia-UI/sia/consensus/.</span></div><div><br /></div><div>This only took a few minutes, but Sia UI was still taking hours to finish configuring itself.</div><div><br /></div><div>While waiting, I checked back with the Sia UI on my Ubuntu desktop and saw that the file uploads appeared to be stuck. The health of each file was still at 0% and the number of items uploading wasn't changing. I read lots of Sia documentation, but I couldn't figure out if something was wrong or if I just had to wait longer. I found that Sia had a <a href="https://discord.com/invite/sia" target="_blank">Discord server</a>, so I signed on there to try to get help from the community. I posted about my problem in the #help channel, and a nice person named Covalent helped me out. He asked me to show him the output of <span style="background-color: #666666; color: white; font-family: courier;">siac renter -v</span>. After seeing that he concluded that my allowance was way too small. He also explained to me that each file would take up a minimum of 40 MB! With over 35,000 files, I was going to have to pay for over 1.4 TB of data! That would make my backups cost even more than I was paying for CrashPlan. Sia docs mention this 40 MB atomic file size <a href="https://siasetup.info/guides/renting-on-sia" target="_blank">here</a>, but I didn't see anything about this in the Getting Started docs. They should really make this clear for people up front. If I knew that going into it, I wouldn't have done any of this.</div><div><br /></div><h3 style="text-align: left;">Final Thoughts</h3><div>It's been a long 24 hours learning about Sia and getting it set up as a personal backup system. In the end, it just doesn't seem well-suited for this use case, at least not in an affordable way. I might try zipping up my directories and storing them on Sia as fewer, but larger compressed files. If that proves to be too convenient, I'll be sticking with CrashPlan for the time being.</div><div><div><br /></div></div><div><br /></div><div><br /></div></div>Ken Weinerhttp://www.blogger.com/profile/12369783173503766970noreply@blogger.com2Los Angeles, CA, USA34.0522342 -118.243684919.371520489927242 -135.8218099 48.73294791007276 -100.6655599tag:blogger.com,1999:blog-15084382.post-10901005688609403822020-09-06T16:00:00.001-07:002020-09-06T16:00:12.238-07:00Simplifying Custom Events for Google Analytics using Google Tag Manager<p>I am relatively new to using Google Tag Manager (GTM), and I am trying to figure out the best way to log Custom Events from a single page app built with React. I want these events to register in Google Analytics (GA) which I have set up already in Google Tag Manager. The kinds of events I'm planning to record are user account creation, email validation, user sign in, user sign out, and various other interactions within the application. It looks like there are various ways to trigger events based on form submissions using Google Tag Manager, but I thought it would just be simpler to manually "invoke" each event I want exactly where I want it via the GTM API.</p><p>Searching the web, this was the most useful tutorial I found: <a href="https://www.analyticsmania.com/post/google-tag-manager-custom-event-trigger/">Google Tag Manager Custom Event Trigger Explained</a> by Julius Fedorovicius. I made a spreadsheet for my app to capture all the custom events I am interested in. There were 26 of them. As I followed the tutorial, I noticed the following things I would need to do:</p><p></p><ul style="text-align: left;"><li>Create and push various Variables into the GTM Data Layer to use them in my event labels and values.</li><li>Create a new GTM Trigger for each of the 26 custom events from my spreadsheet</li><li>Create a new GTM GA Tag and associate the corresponding trigger for each of the 26 custom events from my spreadsheet</li></ul><div>This seemed like a lot of work and maintenance within GTM. I wondered if there was an easier way. Since it is possible to define the event's Category, Action, Label, and Value using variables from the Data Layer, I realized that should be able to handle all of my 26 events with just 1 new GTM Tag and Trigger along with a reusable set of custom Variables. Here's how I set it up:</div><div><br /></div><h3 style="text-align: left;">Step 1: Create Data Layer Variables for each possible GA Event field</h3><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmwNfl-NUh7Sv_-_LfmTY8DJB366CGFCNGFspkYNBghG81bHsBRI724INsQg7gaH5ufSfp5EEQkrbn-bGGCkU9rDAcOoGKBIFBLZCiSfRqp3YZpT7bzHcT4Pb_vV3osluoqhE2Tg/s1234/GTM+Data+Layer+Variables.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img alt="Google Tag Manager Custom Data Layer Variables for Google Analytics Event" border="0" data-original-height="468" data-original-width="1234" height="194" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmwNfl-NUh7Sv_-_LfmTY8DJB366CGFCNGFspkYNBghG81bHsBRI724INsQg7gaH5ufSfp5EEQkrbn-bGGCkU9rDAcOoGKBIFBLZCiSfRqp3YZpT7bzHcT4Pb_vV3osluoqhE2Tg/w512-h194/GTM+Data+Layer+Variables.png" title="Google Tag Manager Custom Data Layer Variables for Google Analytics Event" width="512" /></a></div><br /><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div>This will be used for all the possible event fields <b>Category</b>, <b>Action</b>, <b>Label</b> (optional), and <b>Value</b> (optional) to be captured from the Data Layer.</div><div><br /></div><h3 style="text-align: left;">Step 2: Create a Custom Event Trigger</h3><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0Mqu9t1UnbUVU-c5K4U8jMqH7GOSJcPntGmq3GckppF1uf_ZlclqHQsKznRIZsdKB1iU0WXkS4HugYSI0eEhjK1RAs_YUbx9hZE9S8ukPEBcjJv4nNcjIpM7_FZ97VBuhaaHGsQ/s855/GTM+Custom+Event+Trigger.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img alt="Google Tag Manager Custom Event Trigger" border="0" data-original-height="398" data-original-width="855" height="238" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0Mqu9t1UnbUVU-c5K4U8jMqH7GOSJcPntGmq3GckppF1uf_ZlclqHQsKznRIZsdKB1iU0WXkS4HugYSI0eEhjK1RAs_YUbx9hZE9S8ukPEBcjJv4nNcjIpM7_FZ97VBuhaaHGsQ/w512-h238/GTM+Custom+Event+Trigger.png" title="Google Tag Manager Custom Event Trigger" width="512" /></a></div><br /><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div>This is meant to be generic so it can be used for any Custom Event.</div><div><br /></div><h3 style="text-align: left;">Step 3: Create a Custom Event Tag and Associate with Custom Event Trigger</h3><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-HU8JJXtQjajLy4JKTqAEV3ffv5IkYyXzl6DNXGSzCA9kvr0476E3FDXYUUURprglEU4n8ESJV7tc7saePVq0EFMEaCh3lBoKzllZk_jhtUJAvhClJDicWCUwHQdwqwujkafZNg/s855/GTM+Custom+Event+GA+Tag.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img alt="Google Tag Manager Custom Event Google Analytics Tag" border="0" data-original-height="828" data-original-width="855" height="496" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-HU8JJXtQjajLy4JKTqAEV3ffv5IkYyXzl6DNXGSzCA9kvr0476E3FDXYUUURprglEU4n8ESJV7tc7saePVq0EFMEaCh3lBoKzllZk_jhtUJAvhClJDicWCUwHQdwqwujkafZNg/w512-h496/GTM+Custom+Event+GA+Tag.png" title="Google Tag Manager Custom Event Google Analytics Tag" width="512" /></a></div><br /><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div>This Google Analytics tag will be triggered by the Custom Events. Each attribute of the GA tag (Category, Action, Label, and Value) should be configured to come from the corresponding Data Layer Variable that was created in Step 1. This is what allows the same Trigger and Tag to be used for all Events. That's the whole set up!</div><div><br /></div><div>The list of Tags now only includes one Tag for Custom Events instead of one for each Custom Event. The tag list should look something like this:</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmAbmggDspDK5VVUxts8BAgsYRDv6dwgD072m8oify2eZ0uarEPBA1w54amrXPPJc6OStiRgSMMqWEGN2GzlK8649I2X4fMVmCmMQWbZ9BhxOvaO70WSYbDfTQKtF7tZhA3QPaig/s799/GTM+Tags.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img alt="Google Tag Manager Tag List" border="0" data-original-height="225" data-original-width="799" height="144" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmAbmggDspDK5VVUxts8BAgsYRDv6dwgD072m8oify2eZ0uarEPBA1w54amrXPPJc6OStiRgSMMqWEGN2GzlK8649I2X4fMVmCmMQWbZ9BhxOvaO70WSYbDfTQKtF7tZhA3QPaig/w512-h144/GTM+Tags.png" title="Google Tag Manager Tag List" width="512" /></a></div><br /><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><h3 style="text-align: left;">Pushing Events to Google Tag Manager</h3><div>Now within the application, Custom Events can be pushed to Google Tag Manager's Data Layer and the Trigger that was set up will push them into Google Analytics. The code would look something like this:</div><p></p><pre style="background: rgb(244, 245, 247); border-radius: 3px; border: 0px; color: #172b4d; font-family: SFMono-Medium, "SF Mono", "Segoe UI Mono", "Roboto Mono", "Ubuntu Mono", Menlo, Courier, monospace; font-size: 12px; line-height: 1.4; margin-bottom: 0px; margin-top: 0px; overflow-wrap: normal; overflow-x: auto; padding: 5px 10px;"><span class="p"><</span><span class="nt" style="color: navy;">script</span><span class="p">></span>
<span class="nb" style="color: #999999;">window</span><span class="p">.</span><span class="nx">dataLayer</span> <span class="o" style="font-weight: 700;">=</span> <span class="nb" style="color: #999999;">window</span><span class="p">.</span><span class="nx">dataLayer</span> <span class="o" style="font-weight: 700;">||</span> <span class="p">[];</span>
<span class="nb" style="color: #999999;">window</span><span class="p">.</span><span class="nx">dataLayer</span><span class="p">.</span><span class="nx">push</span><span class="p">({</span>
<span class="s1" style="color: #bb8844;">'event'</span><span class="o" style="font-weight: 700;">:</span> <span class="s1" style="color: #bb8844;">'Custom Event'</span><span class="p">,</span>
<span class="s1" style="color: #bb8844;">'eventCategory'</span><span class="o" style="font-weight: 700;">:</span> <span class="s1" style="color: #bb8844;">'My Event Category'</span><span class="p">,</span>
<span class="s1" style="color: #bb8844;">'eventAction'</span><span class="o" style="font-weight: 700;">:</span> <span class="s1" style="color: #bb8844;">'My Event Action'</span><span class="p">,</span>
<span class="s1" style="color: #bb8844;">'eventLabel'</span><span class="o" style="font-weight: 700;">:</span> <span class="s1" style="color: #bb8844;">'My Event Label'</span><span class="p">,</span>
<span class="s1" style="color: #bb8844;">'eventValue'</span><span class="o" style="font-weight: 700;">:</span> <span class="kc" style="font-weight: 700;">0</span>
<span class="p">});</span>
<span class="p"></</span><span class="nt" style="color: navy;">script</span><span class="p">></span></pre><p></p><h3 style="text-align: left;"><br /></h3><h3 style="text-align: left;">Final Thoughts</h3><div>Perhaps the downside of this approach is that it may be harder to adapt these events to other analytics tags I may use in the future. Maybe that is why Julius Fedorovicius's post referenced above suggested creating a new Trigger and Tag for each individual event. I was thinking about trying out <a href="https://mixpanel.com/">Mixpanel</a> next, so I will soon find out. For all you Google Tag Manager and Google Analytics Experts out there, please let me know your thoughts. </div><div><br /></div><p></p>Ken Weinerhttp://www.blogger.com/profile/12369783173503766970noreply@blogger.com0Del Rey, Los Angeles, CA34.0050173 -118.43383455.5834122733101985 -153.5900845 62.426622326689795 -83.277584500000017tag:blogger.com,1999:blog-15084382.post-76615767298091807612020-06-22T22:41:00.000-07:002020-06-22T22:50:02.938-07:00Dividing MoneyI have found a few situations that require taking an amount of money and dividing it up as evenly as possible, to the nearest cent or whole dollar, such that the individual parts exactly add up to the original amount.<div><br /></div><div>Here are a few examples of when I've needed to do this:</div><div><br /></div><div><b>Example 1:</b></div><h2 style="text-align: left;">Apportioning an Operating Expense to Multiple Real Estate Properties</h2><div>As a real estate investor that owns multiple properties, I sometimes have operating expenses that are not associated with any individual property. Since the Schedule E tax form requires all expenses to be listed on a per-property basis, it is necessary to take the expense and divide it up across the properties. As an example, let's say I spent $1025.95 on tax preparation and I have 7 properties. I would split that expense as follows:</div><div><br /></div><table border="1" bordercolor="#888" cellspacing="0" style="border-collapse: collapse; border-color: rgb(136, 136, 136); border-width: 1px;"><tbody><tr><td style="min-width: 60px;"> <span style="background-color: #c6dafc;"><b>Property</b></span></td><td style="min-width: 60px;"><span style="background-color: #c6dafc;"><b> Amount</b></span></td></tr><tr><td style="min-width: 60px;"> A</td><td style="min-width: 60px; text-align: right;"> $146.56</td></tr><tr><td> B</td><td style="text-align: right;"> $146.56</td></tr><tr><td> C</td><td style="text-align: right;"> $146.56</td></tr><tr><td> D</td><td style="text-align: right;"> $146.56</td></tr><tr><td> E</td><td style="text-align: right;"> $146.57</td></tr><tr><td> F</td><td style="text-align: right;"> $146.57</td></tr><tr><td> G</td><td style="text-align: right;"> $146.57</td></tr><tr><td> <b>Total:</b></td><td style="text-align: right;"><b> $1025.95</b></td></tr></tbody></table><div><br /></div><div>Notice that in this case I use a precision of cents.</div><div><br /></div><div><div><b>Example 2:</b></div><h2 style="text-align: left;">Distributing Cash Tips at a Gig</h2><div>As a band leader, at the end of a gig, I often need to collect the cash tips we received, total them up, and split them with the rest of my band. For example, if my jazz trio earns a total of $113 in tips, I would pay each musician as follows:</div></div><div><br /></div><div><table border="1" bordercolor="#888" cellspacing="0" style="border-collapse: collapse; border-color: rgb(136, 136, 136); border-width: 1px;"><tbody><tr><td style="min-width: 60px;"> <span style="background-color: #c6dafc;"><b>Musician</b></span></td><td style="min-width: 60px;"><span style="background-color: #c6dafc;"><b> Amount</b></span></td></tr><tr><td style="min-width: 60px;"> myself</td><td style="min-width: 60px; text-align: right;"> $37</td></tr><tr><td> bass player</td><td style="text-align: right;"> $38</td></tr><tr><td> drummer</td><td style="text-align: right;"> $38</td></tr><tr><td><b> Total:</b></td><td style="text-align: right;"><b> $113<br /></b></td></tr></tbody></table></div><div><br /></div><div>In this case, I use a precision of whole dollars since we typically don't receive any coins.</div><div><br /></div><div>These are just 2 examples, but similar division logic can be used when friends need to split the bill at a group dinner and other similar situations and the amount of money cannot be split evenly. It's not rocket science to make these calculations, but I do it often enough that I decided to make a simple web-based tool to do it for me. The tool can be found at:</div><div><br /></div><div><a href="https://divide.money/"><font size="5">https://divide.money/</font></a></div><div><br /></div><div>In this tool, simply enter an amount of money, how many parts you want to divide it into, and the precision (cents or whole dollars), and then click Divide to get the resulting amounts. Feel free to use it for all your money splitting needs! And let me know what you think of it in the comments below.</div>Ken Weinerhttp://www.blogger.com/profile/12369783173503766970noreply@blogger.com0tag:blogger.com,1999:blog-15084382.post-14956217756799093892018-04-19T16:07:00.000-07:002018-04-26T16:13:26.128-07:00Digital Advertising Cryptoscape<div style="border: 0px; color: #383838; font-family: gotham, helvetica, arial, sans-serif; font-size: 14px; line-height: 1.57143em; margin: 0px; padding: 0px;">
Many companies are working on leveraging the blockchain to solve digital advertising industry problems. I've been trying to keep track of who's doing what and how it all fits together. Inspired by the famous <a href="https://www.lumapartners.com/luma-institute/lumascapes/display-ad-tech-lumascape/">Display LUMAscape</a> from <a href="https://www.lumapartners.com/">LUMA Partners</a>, I've come up with the following Digital Advertising Cryptoscape!</div>
<div style="border: 0px; color: #383838; font-family: gotham, helvetica, arial, sans-serif; font-size: 14px; line-height: 1.57143em; margin: 0px; padding: 0px;">
<br clear="none" /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div data-mce-style="font-family: gotham, helvetica, arial, sans-serif; font-size: 14px;" style="border: 0px; color: #383838; font-family: gotham, helvetica, arial, sans-serif; font-size: 14px; line-height: 1.57143em; margin: 0px; padding: 0px;">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjw4iiZkDe2crNTyGLtfEcfRX3p2fRCyzty5n1zaUaCIbbEhxcWOAG-lCNgiSHN4cSvG7TCQvId8I70RVEAM_mkzsuXYx6C9Ozy00Btd_WsEKyjeVCWEJ-ZEc7Qd9nwVyC9ygRew/s1600/DigitalAdvertisingCryptoscape.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="Digital Advertising Cryptoscape" border="0" data-original-height="540" data-original-width="960" height="360" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjw4iiZkDe2crNTyGLtfEcfRX3p2fRCyzty5n1zaUaCIbbEhxcWOAG-lCNgiSHN4cSvG7TCQvId8I70RVEAM_mkzsuXYx6C9Ozy00Btd_WsEKyjeVCWEJ-ZEc7Qd9nwVyC9ygRew/s640/DigitalAdvertisingCryptoscape.png" title="Digital Advertising Cryptoscape" width="640" /></a></div>
<br /></div>
Here's a quick summary of each entity shown above:<br />
<h2>
Transparancy</h2>
<h3>
<a href="https://adchain.com/">adChain</a></h3>
Open protocol on the public Ethereum blockchain that allows for the building of decentralized applications for the $175 billion digital advertising ecosystem. By MetaX. adToken (ADT) is a multi-purpose token with usage properties for voting, depositing and challenging entry into the adChain Registry.<br />
<h3>
<a href="https://rebelai.com/">Rebel AI</a></h3>
Blockchain-enabled ad security solution that protects publisher identity and advertiser spend, and prevents ads from ever appearing on an unauthorized site.<br />
<h2>
DSP's</h2>
<h3>
<a href="https://hubdsp.com/">HubDSP</a></h3>
Accepts BTSR (10% off) and other cryptocurrencies.<br />
<h2>
DMP's</h2>
<h3>
<a href="https://zohem.com/">Zohem</a></h3>
Decentralized user data exchange protocol to replace DMPs like BlueKai. Zohem’s Core comprises of a common data layer to which all publishers will be able to contribute data and get rewarded for the same with Zohem Data Tokens (ZDTs)<br />
<h3>
<a href="http://madhive.com/">MadHive</a></h3>
Audience-Driven Data Solutions for OTT and AdvancedTV. Founding member of adledger.<br />
<h2>
Attribution</h2>
<h3>
<a href="http://www.mediachain.io/">MediaChain</a></h3>
Mediachain is a blockchain data solution for connecting applications to media and information about it. Attribution Engine. The best image search engine for creators. Find free, high quality images that you can share and re-use.<br />
<h2>
Exchanges</h2>
<h3>
<a href="http://adex.network/">AdEx</a></h3>
A decentralized ad exchange built on top of Ethereum smart contracts.<br />
<h3>
<a href="http://www.bitcasts.co/">Exchain</a></h3>
Blockchain and programmatic advertising platform by EnvisionX. Formerly <a href="http://bitcasts.co/">Bitcasts</a>.<br />
<h3>
<a href="https://kindads.io/">Kind Ads</a></h3>
A Decentralized Trust Protocol (the “Kind Ads Protocol”) will create an ecosystem for users, publishers, advertisers, and app partners. Currently focused on push notifications and developing a quality and reputation score for domains. No fees will be charged on dollars spent.<br />
<h3>
<a href="https://www.nyiax.com/">NYIAX</a></h3>
The world's first exchange to trade advertising contracts. Developed in partnership with Nasdaq, NYIAX combines financial trading and advertising technology in one platform to enable publishers and advertisers to buy, sell, and re-trade premium advertising inventory. As the first and only trusted, transparent, future inventory marketplace, NYIAX allows both publishers and advertisers to increase ROI and reduce costs.<br />
<h3>
<a href="https://www.xchng.io/">XCHNG</a></h3>
By Kochava. Through a smart contract IO, enables the related targeting and activation of audiences, and bolsters ad-spend efficiency and security. It will usher in a next-generation advertising system of record for all participants.<br />
<h3>
<a href="https://qchain.co/">qChain</a></h3>
Facilitating branded content, sponsorship, and influencer marketing transactions between advertisers and digital publishers or content creators<br />
<h2>
Payments</h2>
<h3>
<a href="https://www.aminopay.com/">Amino</a></h3>
Transparency-focused ad tech payment tech.<br />
<h3>
<a href="https://btsr.io/">BitTeaser</a></h3>
Use coin BTSR as a form of payment when the bill needs to be paid for programmatic advertising worldwide.<br />
<h2>
Identity</h2>
<h3>
<a href="https://www.faktor.io/">Faktor</a></h3>
A blockchain based Identity Management platform for publishers, safely connecting people to brands and content.<br />
<h2>
Monetization</h2>
<h3>
<a href="https://brave.com/">Brave Browser</a></h3>
A Chrome-based browser that blocks ads and uses Basic Attention Token (BAT) to pay users and publishers.<br />
<h3>
<a href="https://coinhive.com/">CoinHive</a></h3>
Allows publishers to mine Monero (XMR) in users' browsers.<br />
<h3>
<a href="https://jsecoin.com/en/home/">JSECoin</a></h3>
A brand new coin specifically for publishers to mine in their users' browsers.<br />
<h2>
Consortiums</h2>
<h3>
<a href="https://adledger.org/">adLedger</a></h3>
Nonprofit research and development consortium charged with implementing global technical standards and solutions for the digital media and blockchain industries.<br />
<h3>
<a href="https://iabtechlab.com/working-groups/blockchain-working-group/">IAB Tech Lab Blockchain Working Group</a></h3>
Investigates the application of blockchain technology to address challenges in the digital advertising space and to develop standards and best practices for the utilization of blockchain technology.<br />
<h2>
Additions</h2>
If you are aware of any additional organizations using the blockchain for digital advertising that belong on this cryptoscape, please leave a comment, and I will update it.<br />
<h4>
Edits</h4>
2018-04-26 Added Kind Ads.Ken Weinerhttp://www.blogger.com/profile/12369783173503766970noreply@blogger.com4tag:blogger.com,1999:blog-15084382.post-63616193678887664292017-12-19T17:59:00.001-08:002020-06-22T23:01:25.603-07:00Los Angeles Roof TV Antenna for VHF/UHF<h2>
Cutting The Cord</h2>
This year I finally <a href="https://en.wikipedia.org/wiki/Cord-cutting">cut the cord</a> and got rid of my DISH satellite TV service which saves me about $50 per month! I've had the service for many years just to get the basic local channels like CBS, ABC, NBC, and FOX. My plan was to replace DISH with a digital antenna so I could get all of those channels for free. In this post, I'll share the model of the antenna that worked for me here on the west side of Los Angeles.<br />
<h2>
Antennas</h2>
Finding the right antenna proved to be more difficult that I thought it would be. I first started with an indoor VHF/UHF antenna, the <a href="http://amzn.to/2CETAxS">NorthVu NV20 Pro AMPd</a>, that I got from <a href="https://www.tablotv.com/">Tablo</a>'s website. Tablo is an Over the Air (OTA) DVR company. Long term, I was contemplating buying one of their DVR's so I figured it would be good to get an antenna they were familiar with. With this antenna, I was able to get some UHF channels like CBS, but none of the VHF channels like FOX. I thought that maybe an indoor antenna was not powerful enough for my neighborhood in Los Angeles which is Del Rey 90066.<br />
<br />
I shopped on Amazon for a highly-rated outdoor roof antenna and purchased this <a href="http://amzn.to/2BiIXF2">1byone 85 Miles VHF/UHF</a> antenna. I borrowed a friend's ladder, got on my roof, mounted this antenna and connected it to the coax cable that was previously connected to my DISH satellite which DISH never came to retrieve. I also plugged in and connected the included power booster behind my TV. Unfortunately, I got the same result: UHF channels came in perfectly and VHF channels did not work at all. I have no idea why since the specs for this antenna clearly claim that both VHF and UHF should work. I ended up returning this antenna to Amazon for a refund.<br />
<br />
Next I started Googling for with terms like "missing VHF channels in Los Angeles" and found this web page called <a href="http://dennysantennaservice.com/los-angeles-tv-stations.html">Best TV Antenna for Los Angeles, CA Digital TV Stations</a> from an antenna vendor in NY called Denny's Antenna. The middle of this page described my exact problem:<br />
<blockquote class="tr_bq">
Note: Some Los Angeles area residents have reported problems receiving KABC 7.1 ABC, KTTV 11.1 FOX, KCOP 13.1 MYTV and KCAL 9.1 IND when using antennas other than the EZ HD or the HD Stacker. This is due to the VHF broadcast signal frequencies in use by these stations and the use of the improper antenna to receive VHF signal frequency. Many of today's antennas (do to smaller antenna size) will not receive VHF signals. The EZ HD and the HD Stacker are designed to provide excellent performance across the entire VHF/UHF frequency spectrum in use in the Los Angeles free to air broadcasting market.</blockquote>
So I immediately ordered their <a href="http://dennysantennaservice.com/ez_hd_tv_Antenna.html">EZ HD antenna</a>. It arrived at my house in just a few days. I mounted it on my roof, connected the coax cable, connected a ground wire that was also left over from the previous DISH satellite, and scanned for channels on my TV. Amazingly, it worked! I was able to receive all the local channels, both UHF and VHF. I have no idea why this antenna worked so well. To be honest, this one felt flimsy and cheaply made compared to the one I bought on Amazon.<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/proxy/AVvXsEhiCbkS_buOTmHxwj8RjNDTHq3Y0PNw3BJBfTtCE8PQNX2EQi793_SJ1umAghCfGWAm4RJr-L5xNAXESKiSg7eePbpy8JLfycfJOAuBLuBZAZN3urx8tJTJ5aPcU2sashS2xR8pXp0kEXkCiIwBMuuubFt58_Piy_h4dyLM=s423" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img alt="Denny's EZ-HD - works in LA" border="0" data-original-height="317" data-original-width="423" height="240" src="https://blogger.googleusercontent.com/img/proxy/AVvXsEhiCbkS_buOTmHxwj8RjNDTHq3Y0PNw3BJBfTtCE8PQNX2EQi793_SJ1umAghCfGWAm4RJr-L5xNAXESKiSg7eePbpy8JLfycfJOAuBLuBZAZN3urx8tJTJ5aPcU2sashS2xR8pXp0kEXkCiIwBMuuubFt58_Piy_h4dyLM=w320-h240" title="Denny's EZ-HD - works in LA" width="320" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Denny's EZ-HD - works in LA</td></tr></tbody></table><div><br />
<h2>
Channel Guide</h2>
A <a href="http://www.rabbitears.info/market.php?request=print_market&mktid=2">list of local channels</a> is easily available online, but I wanted one for my phone so I downloaded the app <a href="https://itunes.apple.com/us/app/tv-listings-by-tv24/id843259680?mt=8">TV Listings</a> by TV24. I was amazed how many channels you can get for free over the air. The TV Listings listings were pretty accurate.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://is2.mzstatic.com/image/thumb/Purple122/v4/7b/cf/57/7bcf57b7-7928-f410-9747-959ddede7198/source/392x696bb.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="696" data-original-width="392" height="320" src="http://is2.mzstatic.com/image/thumb/Purple122/v4/7b/cf/57/7bcf57b7-7928-f410-9747-959ddede7198/source/392x696bb.jpg" width="180" /></a></div>
<h2>
DVR</h2>
I look forward to being able to watch local news once in a while or a live event like the Grammy's that is hard to find online. The next thing I am going to look into is whether I want to purchase a DVR such as <a href="https://www.tablotv.com/">Tablo</a>. A lot of the shows I've been watching are on Hulu, Netflix, and Amazon to which I already subscribe. It isn't clear yet whether the DVR is necessary.</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/proxy/AVvXsEhiCbkS_buOTmHxwj8RjNDTHq3Y0PNw3BJBfTtCE8PQNX2EQi793_SJ1umAghCfGWAm4RJr-L5xNAXESKiSg7eePbpy8JLfycfJOAuBLuBZAZN3urx8tJTJ5aPcU2sashS2xR8pXp0kEXkCiIwBMuuubFt58_Piy_h4dyLM=s423" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="317" data-original-width="423" src="https://blogger.googleusercontent.com/img/proxy/AVvXsEhiCbkS_buOTmHxwj8RjNDTHq3Y0PNw3BJBfTtCE8PQNX2EQi793_SJ1umAghCfGWAm4RJr-L5xNAXESKiSg7eePbpy8JLfycfJOAuBLuBZAZN3urx8tJTJ5aPcU2sashS2xR8pXp0kEXkCiIwBMuuubFt58_Piy_h4dyLM=s320" width="320" /></a></div>Ken Weinerhttp://www.blogger.com/profile/12369783173503766970noreply@blogger.com1Los Angeles, CA 90066, USA34.0050173 -118.4338344999999933.9523613 -118.51451549999999 34.0576733 -118.35315349999999tag:blogger.com,1999:blog-15084382.post-53177702575186531502017-10-15T19:36:00.003-07:002021-03-08T00:21:00.982-08:00Chad Lefkowitz-Brown Solo Transcriptions<div class="separator" style="clear: both; text-align: center;">
<a href="https://static.wixstatic.com/media/811997_793f357b91014b8d8be5d3733fb5e380~mv2.jpg/v1/fill/w_500,h_500,q_85,usm_0.66_1.00_0.01/811997_793f357b91014b8d8be5d3733fb5e380~mv2.jpg" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="500" data-original-width="500" height="320" src="https://static.wixstatic.com/media/811997_793f357b91014b8d8be5d3733fb5e380~mv2.jpg/v1/fill/w_500,h_500,q_85,usm_0.66_1.00_0.01/811997_793f357b91014b8d8be5d3733fb5e380~mv2.jpg" width="320" /></a></div>
I am a huge fan of saxophonist <a href="https://www.chadlefkowitz-brown.com/">Chad Lefkowitz-Brown</a>. I came across one of his videos on Instagram about a year ago and I've been following him ever since.<br />
<br />
I recently purchased his book of 15 solo transcriptions by saxophonist and educator <a href="http://www.ronfix.com/">Ron Fix</a>. It's available in <a href="https://www.chadlefkowitz-brown.com/product-page/chad-lefkowitz-brown-solo-transcriptions-book-free-shipping-ships-to-usa-only">physical</a> and <a href="https://www.chadlefkowitz-brown.com/product-page/chad-lefkowitz-brown-solo-transcription-e-book-by-ron-fix">digital</a> form. It is fun to play through them and get some insight into how Chad thinks when he improvises.<br />
<br />
Interestingly, this is the first transcription book I've ever seen that covers music solely from social media! Every single one is freely available online on either Chad's <a href="https://www.youtube.com/channel/UCV17kvWvljT0Zw_5CZ4CFcA">YouTube</a> or <a href="https://www.instagram.com/chadlbsax/">Instagram</a> feed.<br />
<br />
The digital version of the book comes with audio files you can play along to, but it doesn't include links to find each video online. I combed through Instagram, YouTube, and Facebook to find each one. That's what I want to share with you in this post so you can both watch and play along. Happy practicing!<br />
<br />
They are listed below in the order they appear in the book.<br /><br />
After you listen to these, be sure to check out more of <a href="https://www.allsolos.com/soloist/5/chad-lefkowitz-brown" target="_blank">Chad LB's solos</a> on AllSolos.com.<div><br />
<h4>
All The Things You Are</h4>
<a href="https://www.instagram.com/p/BMm3wyvBkou/">Instagram - November 9, 2016</a><br />
<br />
<blockquote class="instagram-media" data-instgrm-captioned="" data-instgrm-version="7" style="background: rgb(255, 255, 255); border-radius: 3px; border: 0px; box-shadow: rgba(0, 0, 0, 0.5) 0px 0px 1px 0px, rgba(0, 0, 0, 0.15) 0px 1px 10px 0px; margin: 1px; max-width: 320px; padding: 0px; width: 99.375%;">
<div style="padding: 8px;">
<div style="background: rgb(248, 248, 248); line-height: 0; margin-top: 40px; padding: 50% 0px; text-align: center; width: 100%;">
<div style="background: url(data:image/png; display: block; height: 44px; margin: 0 auto -44px; position: relative; top: -22px; width: 44px;">
</div>
</div>
<div style="margin: 8px 0px 0px; padding: 0px 4px;">
<a href="https://www.instagram.com/p/BMm3wyvBkou/" style="color: black; font-family: arial, sans-serif; font-size: 14px; font-style: normal; font-weight: normal; line-height: 17px; overflow-wrap: break-word; text-decoration: none; word-wrap: break-word;" target="_blank">It's now more important than ever to focus on love and compassion. Here's a chorus on All The Things You Are. For next week let's pick a tune with "Love" in the title. Some of the many possibilities... I Love You, Taking A Chance On Love, There Is No Greater Love.</a></div>
<div style="color: #c9c8cd; font-family: Arial, sans-serif; font-size: 14px; line-height: 17px; margin-bottom: 0px; margin-top: 8px; overflow: hidden; padding: 8px 0px 7px; text-align: center; text-overflow: ellipsis; white-space: nowrap;">
A post shared by Chad Lefkowitz-Brown (@chadlbsax) on <time datetime="2016-11-09T23:11:22+00:00" style="font-family: Arial, sans-serif; font-size: 14px; line-height: 17px;">Nov 9, 2016 at 3:11pm PST</time></div>
</div>
</blockquote>
<script async="" defer="" src="//platform.instagram.com/en_US/embeds.js"></script>
<br />
<br />
<h4>
Body And Soul</h4>
<a href="https://www.youtube.com/watch?v=IFdRB0TzWeg">YouTube - December 8, 2015</a><br />
<br />
<div class="separator" style="clear: both; text-align: left;">
<iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/IFdRB0TzWeg/0.jpg" frameborder="0" height="266" src="https://www.youtube.com/embed/IFdRB0TzWeg?feature=player_embedded" width="320"></iframe></div>
<br />
<br />
<h4>
Caravan</h4>
<a href="https://www.instagram.com/p/BK4EcJ4hrBr/">Instagram - September 27, 2016</a><br />
<br />
<blockquote class="instagram-media" data-instgrm-captioned="" data-instgrm-version="7" style="background: rgb(255, 255, 255); border-radius: 3px; border: 0px; box-shadow: rgba(0, 0, 0, 0.5) 0px 0px 1px 0px, rgba(0, 0, 0, 0.15) 0px 1px 10px 0px; margin: 1px; max-width: 320px; padding: 0px; width: 99.375%;">
<div style="padding: 8px;">
<div style="background: rgb(248, 248, 248); line-height: 0; margin-top: 40px; padding: 50% 0px; text-align: center; width: 100%;">
<div style="background: url(data:image/png; display: block; height: 44px; margin: 0 auto -44px; position: relative; top: -22px; width: 44px;">
</div>
</div>
<div style="margin: 8px 0px 0px; padding: 0px 4px;">
<a href="https://www.instagram.com/p/BK4EcJ4hrBr/" style="color: black; font-family: arial, sans-serif; font-size: 14px; font-style: normal; font-weight: normal; line-height: 17px; overflow-wrap: break-word; text-decoration: none; word-wrap: break-word;" target="_blank">This week's Duke Ellington chorus on a standard vote went to Caravan. For next week, let's do Horace Silver! Some ideas: Nica's Dream, Sister Sadie, Song For My Father… Thanks for voting!! #caravan #dukeellington #horacesilver</a></div>
<div style="color: #c9c8cd; font-family: Arial, sans-serif; font-size: 14px; line-height: 17px; margin-bottom: 0px; margin-top: 8px; overflow: hidden; padding: 8px 0px 7px; text-align: center; text-overflow: ellipsis; white-space: nowrap;">
A post shared by Chad Lefkowitz-Brown (@chadlbsax) on <time datetime="2016-09-27T22:26:27+00:00" style="font-family: Arial, sans-serif; font-size: 14px; line-height: 17px;">Sep 27, 2016 at 3:26pm PDT</time></div>
</div>
</blockquote>
<script async="" defer="" src="//platform.instagram.com/en_US/embeds.js"></script>
<br />
<br />
<h4>
Confirmation</h4>
<a href="https://www.instagram.com/p/BIVD2o5Br2Q/">Instagram - July 26, 2016</a><br />
<br />
<blockquote class="instagram-media" data-instgrm-captioned="" data-instgrm-version="7" style="background: rgb(255, 255, 255); border-radius: 3px; border: 0px; box-shadow: rgba(0, 0, 0, 0.5) 0px 0px 1px 0px, rgba(0, 0, 0, 0.15) 0px 1px 10px 0px; margin: 1px; max-width: 320px; padding: 0px; width: 99.375%;">
<div style="padding: 8px;">
<div style="background: rgb(248, 248, 248); line-height: 0; margin-top: 40px; padding: 50% 0px; text-align: center; width: 100%;">
<div style="background: url(data:image/png; display: block; height: 44px; margin: 0 auto -44px; position: relative; top: -22px; width: 44px;">
</div>
</div>
<div style="margin: 8px 0px 0px; padding: 0px 4px;">
<a href="https://www.instagram.com/p/BIVD2o5Br2Q/" style="color: black; font-family: arial, sans-serif; font-size: 14px; font-style: normal; font-weight: normal; line-height: 17px; overflow-wrap: break-word; text-decoration: none; word-wrap: break-word;" target="_blank">Week 3 chorus on a standard, here's the "winner" with the most votes on Instagram and Facebook - Confirmation. Thanks to everyone submitting requests! For next week, let's vote now picking between the second place finishers: 26-2, Donna Lee, Bye Bye Blackbird, and Cherokee. #confirmation #26-2 #donnalee #byebyeblackbird #cherokee #johncoltrane #charlieparker #chadlefkowitzbrown</a></div>
<div style="color: #c9c8cd; font-family: Arial, sans-serif; font-size: 14px; line-height: 17px; margin-bottom: 0px; margin-top: 8px; overflow: hidden; padding: 8px 0px 7px; text-align: center; text-overflow: ellipsis; white-space: nowrap;">
A post shared by Chad Lefkowitz-Brown (@chadlbsax) on <time datetime="2016-07-26T15:05:07+00:00" style="font-family: Arial, sans-serif; font-size: 14px; line-height: 17px;">Jul 26, 2016 at 8:05am PDT</time></div>
</div>
</blockquote>
<script async="" defer="" src="//platform.instagram.com/en_US/embeds.js"></script>
<br />
<br />
<h4>
Driftin’</h4>
<a href="https://www.youtube.com/watch?v=mzSx1zWVXzk">YouTube - February 26, 2014</a><br />
<br />
<div class="separator" style="clear: both; text-align: left;">
<iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/mzSx1zWVXzk/0.jpg" frameborder="0" height="266" src="https://www.youtube.com/embed/mzSx1zWVXzk?feature=player_embedded" width="320"></iframe></div>
<br />
<br />
<h4>
For All We Know</h4>
<a href="https://www.youtube.com/watch?v=1jwcBfvN-YM">YouTube - May 17, 2013</a><br />
<br />
<div class="separator" style="clear: both; text-align: left;">
<iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/1jwcBfvN-YM/0.jpg" frameborder="0" height="266" src="https://www.youtube.com/embed/1jwcBfvN-YM?feature=player_embedded" width="320"></iframe></div>
<h4>
<br />Get Lucky</h4>
<a href="https://www.youtube.com/watch?v=DKBckJygQko">YouTube - October 9, 2013</a><br />
<br />
<div class="separator" style="clear: both; text-align: left;">
<iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/DKBckJygQko/0.jpg" frameborder="0" height="266" src="https://www.youtube.com/embed/DKBckJygQko?feature=player_embedded" width="320"></iframe></div>
<br />
<br />
<h4>
High High The Moon</h4>
<a href="https://www.instagram.com/p/BTM8lk_F7se/">Instagram - April 22, 2017</a><br />
<br />
<blockquote class="instagram-media" data-instgrm-captioned="" data-instgrm-version="7" style="background: rgb(255, 255, 255); border-radius: 3px; border: 0px; box-shadow: rgba(0, 0, 0, 0.5) 0px 0px 1px 0px, rgba(0, 0, 0, 0.15) 0px 1px 10px 0px; margin: 1px; max-width: 320px; padding: 0px; width: 99.375%;">
<div style="padding: 8px;">
<div style="background: rgb(248, 248, 248); line-height: 0; margin-top: 40px; padding: 50% 0px; text-align: center; width: 100%;">
<div style="background: url(data:image/png; display: block; height: 44px; margin: 0 auto -44px; position: relative; top: -22px; width: 44px;">
</div>
</div>
<div style="margin: 8px 0px 0px; padding: 0px 4px;">
<a href="https://www.instagram.com/p/BTM8lk_F7se/" style="color: black; font-family: arial, sans-serif; font-size: 14px; font-style: normal; font-weight: normal; line-height: 17px; overflow-wrap: break-word; text-decoration: none; word-wrap: break-word;" target="_blank">Warming up on How High The Moon (hotel volume) for the hit at Yale tonight with Adam O'Farrill and Stranger Days! @yale #yale #yaleuniversity #chadlefkowitzbrown</a></div>
<div style="color: #c9c8cd; font-family: Arial, sans-serif; font-size: 14px; line-height: 17px; margin-bottom: 0px; margin-top: 8px; overflow: hidden; padding: 8px 0px 7px; text-align: center; text-overflow: ellipsis; white-space: nowrap;">
A post shared by Chad Lefkowitz-Brown (@chadlbsax) on <time datetime="2017-04-22T21:13:02+00:00" style="font-family: Arial, sans-serif; font-size: 14px; line-height: 17px;">Apr 22, 2017 at 2:13pm PDT</time></div>
</div>
</blockquote>
<script async="" defer="" src="//platform.instagram.com/en_US/embeds.js"></script>
<br />
<br />
<h4>
Melodic Cell Lines</h4>
<a href="https://www.instagram.com/p/BSj7cailELz/">Instagram - April 6, 2017</a><br />
<br />
<blockquote class="instagram-media" data-instgrm-captioned="" data-instgrm-version="7" style="background: rgb(255, 255, 255); border-radius: 3px; border: 0px; box-shadow: rgba(0, 0, 0, 0.5) 0px 0px 1px 0px, rgba(0, 0, 0, 0.15) 0px 1px 10px 0px; margin: 1px; max-width: 320px; padding: 0px; width: 99.375%;">
<div style="padding: 8px;">
<div style="background: rgb(248, 248, 248); line-height: 0; margin-top: 40px; padding: 37.5% 0px; text-align: center; width: 100%;">
<div style="background: url(data:image/png; display: block; height: 44px; margin: 0 auto -44px; position: relative; top: -22px; width: 44px;">
</div>
</div>
<div style="margin: 8px 0px 0px; padding: 0px 4px;">
<a href="https://www.instagram.com/p/BSj7cailELz/" style="color: black; font-family: arial, sans-serif; font-size: 14px; font-style: normal; font-weight: normal; line-height: 17px; overflow-wrap: break-word; text-decoration: none; word-wrap: break-word;" target="_blank">Shedding on melodic cells 🎷🤘</a></div>
<div style="color: #c9c8cd; font-family: Arial, sans-serif; font-size: 14px; line-height: 17px; margin-bottom: 0px; margin-top: 8px; overflow: hidden; padding: 8px 0px 7px; text-align: center; text-overflow: ellipsis; white-space: nowrap;">
A post shared by Chad Lefkowitz-Brown (@chadlbsax) on <time datetime="2017-04-06T22:54:11+00:00" style="font-family: Arial, sans-serif; font-size: 14px; line-height: 17px;">Apr 6, 2017 at 3:54pm PDT</time></div>
</div>
</blockquote>
<script async="" defer="" src="//platform.instagram.com/en_US/embeds.js"></script>
<br />
<br />
<h4>
Nature Boy</h4>
<a href="https://www.youtube.com/watch?v=SPhIu1Wccqc">YouTube - July 28, 2014</a><br />
<br />
<div class="separator" style="clear: both; text-align: left;">
<iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/SPhIu1Wccqc/0.jpg" frameborder="0" height="266" src="https://www.youtube.com/embed/SPhIu1Wccqc?feature=player_embedded" width="320"></iframe></div>
<br />
<br />
<h4>
On The Sunny Side Of The Street</h4>
<a href="https://www.youtube.com/watch?v=kzgyrMLO8CY">YouTube - February 16, 2015</a><br />
<br />
<div class="separator" style="clear: both; text-align: left;">
<iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/kzgyrMLO8CY/0.jpg" frameborder="0" height="266" src="https://www.youtube.com/embed/kzgyrMLO8CY?feature=player_embedded" width="320"></iframe></div>
<br />
<br />
<h4>
Recorda Me</h4>
<a href="https://www.instagram.com/p/BJgA8YZBMlk/">Instagram - August 24, 2016</a><br />
<br />
<blockquote class="instagram-media" data-instgrm-captioned="" data-instgrm-version="7" style="background: rgb(255, 255, 255); border-radius: 3px; border: 0px; box-shadow: rgba(0, 0, 0, 0.5) 0px 0px 1px 0px, rgba(0, 0, 0, 0.15) 0px 1px 10px 0px; margin: 1px; max-width: 320px; padding: 0px; width: 99.375%;">
<div style="padding: 8px;">
<div style="background: rgb(248, 248, 248); line-height: 0; margin-top: 40px; padding: 50% 0px; text-align: center; width: 100%;">
<div style="background: url(data:image/png; display: block; height: 44px; margin: 0 auto -44px; position: relative; top: -22px; width: 44px;">
</div>
</div>
<div style="margin: 8px 0px 0px; padding: 0px 4px;">
<a href="https://www.instagram.com/p/BJgA8YZBMlk/" style="color: black; font-family: arial, sans-serif; font-size: 14px; font-style: normal; font-weight: normal; line-height: 17px; overflow-wrap: break-word; text-decoration: none; word-wrap: break-word;" target="_blank">Week 6 of a chorus (or a few) on a standard. This week's Joe Henderson vote went to Recordame. Next week let's do Wayne Shorter! Some ideas: Deluge, Footprints, Juju, Fee Fi Fo Fum... Thanks for voting!! #recordame #joehenderson #wayneshorter #chadlefkowitzbrown</a></div>
<div style="color: #c9c8cd; font-family: Arial, sans-serif; font-size: 14px; line-height: 17px; margin-bottom: 0px; margin-top: 8px; overflow: hidden; padding: 8px 0px 7px; text-align: center; text-overflow: ellipsis; white-space: nowrap;">
A post shared by Chad Lefkowitz-Brown (@chadlbsax) on <time datetime="2016-08-24T17:42:44+00:00" style="font-family: Arial, sans-serif; font-size: 14px; line-height: 17px;">Aug 24, 2016 at 10:42am PDT</time></div>
</div>
</blockquote>
<script async="" defer="" src="//platform.instagram.com/en_US/embeds.js"></script>
<br />
<br />
<h4>
Sandu</h4>
<a href="https://www.youtube.com/watch?v=L-4rIqq-WDs">YouTube - July 15, 2013</a><br />
<br />
<div class="separator" style="clear: both; text-align: left;">
<iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/L-4rIqq-WDs/0.jpg" frameborder="0" height="266" src="https://www.youtube.com/embed/L-4rIqq-WDs?feature=player_embedded" width="320"></iframe></div>
<br />
<br />
<h4>
Struttin’ With Some Barbecue</h4>
<a href="https://www.facebook.com/groups/jamoftheweekgroup/permalink/1063080493788774/">Facebook - August 4, 2016</a><br />
<a href="https://www.instagram.com/p/BIyD1rlBEjH/">Instagram - August 6, 2016</a><br />
<br />
<blockquote class="instagram-media" data-instgrm-captioned="" data-instgrm-version="7" style="background: rgb(255, 255, 255); border-radius: 3px; border: 0px; box-shadow: rgba(0, 0, 0, 0.5) 0px 0px 1px 0px, rgba(0, 0, 0, 0.15) 0px 1px 10px 0px; margin: 1px; max-width: 320px; padding: 0px; width: 99.375%;">
<div style="padding: 8px;">
<div style="background: rgb(248, 248, 248); line-height: 0; margin-top: 40px; padding: 50% 0px; text-align: center; width: 100%;">
<div style="background: url(data:image/png; display: block; height: 44px; margin: 0 auto -44px; position: relative; top: -22px; width: 44px;">
</div>
</div>
<div style="margin: 8px 0px 0px; padding: 0px 4px;">
<a href="https://www.instagram.com/p/BIyD1rlBEjH/" style="color: black; font-family: arial, sans-serif; font-size: 14px; font-style: normal; font-weight: normal; line-height: 17px; overflow-wrap: break-word; text-decoration: none; word-wrap: break-word;" target="_blank">Here's a video I posted on Facebook the other day of a Louis Armstrong tune called Struttin' with some Barbecue. #louisarmstrong #chadlefkowitzbrown</a></div>
<div style="color: #c9c8cd; font-family: Arial, sans-serif; font-size: 14px; line-height: 17px; margin-bottom: 0px; margin-top: 8px; overflow: hidden; padding: 8px 0px 7px; text-align: center; text-overflow: ellipsis; white-space: nowrap;">
A post shared by Chad Lefkowitz-Brown (@chadlbsax) on <time datetime="2016-08-06T21:22:58+00:00" style="font-family: Arial, sans-serif; font-size: 14px; line-height: 17px;">Aug 6, 2016 at 2:22pm PDT</time></div>
</div>
</blockquote>
<script async="" defer="" src="//platform.instagram.com/en_US/embeds.js"></script>
<br />
<br />
<h4>
Take The A Train</h4>
<a href="https://www.youtube.com/watch?v=9qrFqzIFTRw">YouTube - November 18, 2014</a><br />
<br />
<div class="separator" style="clear: both; text-align: left;">
<iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/9qrFqzIFTRw/0.jpg" frameborder="0" height="266" src="https://www.youtube.com/embed/9qrFqzIFTRw?feature=player_embedded" width="320"></iframe></div>
<br />
<br />
<h4>
There Is No Greater Love</h4>
<a href="https://www.instagram.com/p/BM4nXxhBKxD/">Instagram - November 16, 2016</a><br />
<br />
<blockquote class="instagram-media" data-instgrm-captioned="" data-instgrm-version="7" style="background: rgb(255, 255, 255); border-radius: 3px; border: 0px; box-shadow: rgba(0, 0, 0, 0.5) 0px 0px 1px 0px, rgba(0, 0, 0, 0.15) 0px 1px 10px 0px; margin: 1px; max-width: 320px; padding: 0px; width: 99.375%;">
<div style="padding: 8px;">
<div style="background: rgb(248, 248, 248); line-height: 0; margin-top: 40px; padding: 50% 0px; text-align: center; width: 100%;">
<div style="background: url(data:image/png; display: block; height: 44px; margin: 0 auto -44px; position: relative; top: -22px; width: 44px;">
</div>
</div>
<div style="margin: 8px 0px 0px; padding: 0px 4px;">
<a href="https://www.instagram.com/p/BM4nXxhBKxD/" style="color: black; font-family: arial, sans-serif; font-size: 14px; font-style: normal; font-weight: normal; line-height: 17px; overflow-wrap: break-word; text-decoration: none; word-wrap: break-word;" target="_blank">This week's chorus on a standard, "There Is No Greater Love," from a dressing room at the Count Basie Theater in Red Bank. Cameo from @bt0wnbr0wn. For next week let's do Dizzy Gillespie. A few ideas: Groovin' High, Night in Tunisia, Woody N' You... #chadlefkowitzbrown #dizzygillespie</a></div>
<div style="color: #c9c8cd; font-family: Arial, sans-serif; font-size: 14px; line-height: 17px; margin-bottom: 0px; margin-top: 8px; overflow: hidden; padding: 8px 0px 7px; text-align: center; text-overflow: ellipsis; white-space: nowrap;">
A post shared by Chad Lefkowitz-Brown (@chadlbsax) on <time datetime="2016-11-16T20:34:29+00:00" style="font-family: Arial, sans-serif; font-size: 14px; line-height: 17px;">Nov 16, 2016 at 12:34pm PST</time></div>
</div>
</blockquote>
<script async="" defer="" src="//platform.instagram.com/en_US/embeds.js"></script>
</div>Ken Weinerhttp://www.blogger.com/profile/12369783173503766970noreply@blogger.com1tag:blogger.com,1999:blog-15084382.post-24322075185508518222017-09-26T14:19:00.003-07:002017-09-26T14:35:46.743-07:00JavaScript Crypto-Mining with CoinHive and JSECoinIn the past, it has been difficult to mine BitCoin (BTC) with JavaScript in a web browser due to massive amount of processing power necessary. Lately, JavaScript mining solutions for other types of cryptocurrencies have come on the scene. 2 examples are <a href="https://coin-hive.com/">CoinHive</a> and <a href="https://jsecoin.com/?utm_source=referral&utm_campaign=aff14157&utm_content=kwblog">JSECoin</a>.<br />
<br />
<h3>
CoinHive</h3>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: start;">
<a href="https://coin-hive.com/media/coinhive-icon.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img alt="CoinHive" border="0" data-original-height="512" data-original-width="512" height="200" src="https://coin-hive.com/media/coinhive-icon.png" title="CoinHive" width="200" /></a></div>
CoinHive awards miners in <a href="https://getmonero.org/">Monero (XMR)</a>, a crypto currency known for its privacy as compared to BitCoin (BTC). It current trades for about $94 USD per 1 XMR. Once your account reaches the minimum payout of <span style="color: #222222; font-family: "helveticaneue" , "helvetica neue" , "helvetica" , "arial" , sans-serif; font-size: 15px;">0.5 XMR (~$47), they will transfer the Monero to a wallet that you have to setup outside of a normal coin exchange. From there, you can transfer it into an exchange wallet and then ultimately trade it for USD or BTC. CoinHive can be used as an alternative monetization source to ads. It can also be used as a CAPTCHA or gate where your user must mine some Monero before being allowed to enter a website. </span>Note that CoinHive currently takes a 30% rev share from the Monero you mine.<br />
<span style="color: #222222; font-family: "helveticaneue" , "helvetica neue" , "helvetica" , "arial" , sans-serif; font-size: 15px;"><br /></span><span style="color: #222222; font-family: "helveticaneue" , "helvetica neue" , "helvetica" , "arial" , sans-serif; font-size: 15px;">Recently some websites have been in the news for deploying CoinHive without making their users aware of it. They have since pulled it down. Here are some articles about it:</span><br />
<ul>
<li><a href="https://www.theverge.com/2017/9/26/16367620/showtime-cpu-cryptocurrency-monero-coinhive" style="font-family: HelveticaNeue, "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 15px;">Showtime websites secretly mined user CPU for cryptocurrency</a></li>
<li><a href="https://www.theregister.co.uk/2017/09/25/showtime_hit_with_coinmining_script/" style="font-family: HelveticaNeue, "Helvetica Neue", Helvetica, Arial, sans-serif;">CBS's Showtime caught mining crypto-coins in viewers' web browsers</a></li>
</ul>
<div class="separator" style="clear: both; text-align: start;">
<br /></div>
<h3>
JSECoin</h3>
<div>
<a href="https://jsecoin.com/?utm_source=referral&utm_campaign=aff14157&utm_content=kwblog" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img alt="JSECoin" border="0" data-original-height="510" data-original-width="512" height="198" src="https://jsecoin.com/wp-content/uploads/2017/09/logoSquare-512x510.png" title="JSECoin" width="200" /></a><br />
<a href="https://jsecoin.com/?utm_source=referral&utm_campaign=aff14157&utm_content=kwblog">JSECoin</a> describes itself as "cryptocurrency mined by webmasters built for everyone". JSECoins are supposed to be worth approximately $1 USD right now each, but no one knows the real value until they do an ICO after which point they will be listed on an exchange. Their ICO is planned for Q2 of 2018. Those who begin to mine JSECoin have no assurances that their rewards will be worth anything.<br />
<br /></div>
<div>
<br /></div>
<h3>
</h3>
<h3>
What the Heck</h3>
<div>
<br /></div>
<div>
Since this is all so new and interesting, I have decided to learn more about JavaScript coin mining, and the best way to do that is to jump in and try it. Therefore, I have installed CoinHive and JSECoin miner code on this blog! Consider this a warning - visiting this blog may use some of your computer's CPU until you close the page. I am curious to see what kind of a "CPM" I make to compare with the ad units I'm running. If you have any experience with JavaScript miners, please comment below.</div>
<br />Ken Weinerhttp://www.blogger.com/profile/12369783173503766970noreply@blogger.com3tag:blogger.com,1999:blog-15084382.post-30783787707597336672015-12-22T17:20:00.000-08:002015-12-22T17:23:56.943-08:00Ubuntu CUPS Driver for Google Cloud PrintOn my Ubuntu desktop computer, printing to Google Cloud Print works great when printing from Chrome. This screenshot shows how I can select my printer, the <a href="http://amzn.to/1Zohcgr" rel="nofollow" target="_blank">Brother MFC-J450DW</a>, from the printers I have previously setup in Google Cloud Print.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyBXVeiKQ5phJ2_nCbbnd_7WsB1nr6f05wrVu1hV0AVJxlCrNhIMq8PzNdZSuR7E0tUE0OKfooY5ez2O9z05sQOZe5GVWLgqJ162LIUb3eB9X-Kn1fyg48vTM102AJewjEJ6IhyA/s1600/gcp.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img alt="Google Cloud Print Printer Selection Dialog Box" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyBXVeiKQ5phJ2_nCbbnd_7WsB1nr6f05wrVu1hV0AVJxlCrNhIMq8PzNdZSuR7E0tUE0OKfooY5ez2O9z05sQOZe5GVWLgqJ162LIUb3eB9X-Kn1fyg48vTM102AJewjEJ6IhyA/s1600/gcp.png" title="Google Cloud Print Printer Selection Dialog Box" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Google Cloud Print Printer Selection Dialog Box</td></tr>
</tbody></table>
The problem is being able to select my Google Cloud Print printer from any other printer selection dialog box in Ubuntu. The answer is to setup a CUPS printer driver that knows how to print to your Google Cloud Print printer.<br />
<br />
Fortunately, Niftiest Software has made such a CUPS driver available: <a href="https://www.niftiestsoftware.com/cups-cloud-print/">CUPS Cloud Print</a>. According to their website,<br />
<blockquote class="tr_bq">
CUPS Cloud Print is a Google Cloud Print driver for UNIX-like operating systems ( Linux, Mac OS X , BSDs etc ). It allows any application which prints via CUPS to print to Google Cloud Print directly.</blockquote>
CUPS Clount Print is very easy to install on Ubuntu. You just add their Personal Package Archive (PPA), apt-get install cupscloudprint, and run the setup script, written in python. The setup script will prompt you for your Google user account. Then it generates a link which you visit in your browser. This will grant access to CUPS Cloud Print at Google and give you an authorization code. Just copy/paste that code when prompted by the setup script, choose an optional prefix for your Google Cloud Print printer names for when they show up as CUPS printers, and you're done. After this, your Google Cloud Print printers will show up in your Printers settings, and you can choose them from any Ubuntu Print dialog box.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixOj4S9mzAmn2gsQw-AIIdag7XRVMcw8gRIJVWUI2oNlghxjoUJS1QTND3_m4NE_BY_9Uwdsvp5X8OoaiQ194JEgufaXMvBgsohHTKq0hWfYILbHkB5q9hhcqE_-rlOX5nSs70_g/s1600/cups.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img alt="Ubuntu Printer Settings Dialog Box" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixOj4S9mzAmn2gsQw-AIIdag7XRVMcw8gRIJVWUI2oNlghxjoUJS1QTND3_m4NE_BY_9Uwdsvp5X8OoaiQ194JEgufaXMvBgsohHTKq0hWfYILbHkB5q9hhcqE_-rlOX5nSs70_g/s1600/cups.png" title="Ubuntu Printer Settings Dialog Box" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Ubuntu Printer Settings Dialog Box</td></tr>
</tbody></table>
<br />
Here you can see that my Google Cloud Print printer name was Brother_MFC-J450DW and I told the CUPS Cloud Print setup script to use the prefix GCP-. The prefix makes it easy to distinguish the Google Cloud Print printers from other printers you may have installed. As you can see, I don't have any other printer setup besides the Google Cloud Print printers.<br />
<div>
<br /></div>
<div>
It's nice to be able to print easily from anywhere within Ubuntu without ever having to install a proprietary printer driver. Thanks to Google Cloud Print and Niftiest Software for making this capability freely available!<br />
<br /></div>
Ken Weinerhttp://www.blogger.com/profile/12369783173503766970noreply@blogger.com0tag:blogger.com,1999:blog-15084382.post-73861757739688828352015-01-19T21:52:00.000-08:002015-01-19T21:52:46.997-08:00Send Large Files with Amazon S3 and Groovy<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxokhFjnXd2T-PCuE7YyIVhjhz7YeD8s0M7uApIOj7XFfykmTy3Znl8PGx-6fpAMIHX5sDpzbhsqcs3vSn7kXMYHcqgrBBAD4RaKXAGYFKHJOv-RiFRUm7-WOw4VO93lHsnGGsBA/s1600/send-large-files.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxokhFjnXd2T-PCuE7YyIVhjhz7YeD8s0M7uApIOj7XFfykmTy3Znl8PGx-6fpAMIHX5sDpzbhsqcs3vSn7kXMYHcqgrBBAD4RaKXAGYFKHJOv-RiFRUm7-WOw4VO93lHsnGGsBA/s1600/send-large-files.jpg" height="234" width="320" /></a></div>
<br />
Sometimes you need to send a very large files to people. You could use your email or file sharing service of choice, but they have limits. For example:<br />
<br />
Google Mail - 25 MB limit<br />
Google Drive - 100 GB limit<br />
Dropbox - 2-16 GB limit<br />
<br />
Even if your file is within the limit, you don't necessarily want to use those services each time, because it will add up, and eventually you'll run out of space in your account.<br />
<br />
You could use services that specialize in sending large files. For example:
<a href="https://www.hightail.com/">Hightail</a>, <a href="https://www.wetransfer.com/">WeTransfer</a>, <a href="http://www.dropsend.com/">DropSend</a>, etc. But, you may not trust them with your files or just don't want to bother with creating additional accounts.<br />
<br />
I came up with another solution that works well for developers like me that are familiar with using Amazon S3. With a simple script (I wrote mine in <a href="http://groovy.codehaus.org/">Groovy</a>), I can upload any file from my computer to Amazon S3 and then generate a pre-signed URL that gives access to the file for a certain period of time. This URL can be IM'd or emailed to anyone so that they can download the file before the URL expires.<br />
<br />
Here are the steps to use this script:<br />
<ol>
<li>Make sure you have an <a href="http://docs.aws.amazon.com/AmazonSimpleDB/latest/DeveloperGuide/AboutAWSAccounts.html">AWS account</a> and a <a href="http://docs.aws.amazon.com/AmazonS3/latest/gsg/CreatingABucket.html">bucket setup in S3</a>.</li>
<li>Download the script from GitHub: <a href="https://github.com/kweiner/misc/blob/master/send-large-file/UploadToS3AndGenerateSignedUrl.groovy">UploadToS3AndGenerateSignedUrl.groovy</a></li>
<li>Modify the global variables:</li>
<ul>
<li><span style="font-family: Courier New, Courier, monospace;">pathToFile</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">bucketName</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">expiresInHours</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">myAccessKeyID</span>,</li>
<li><span style="font-family: Courier New, Courier, monospace;">mySecretKey</span></li>
</ul>
<li>Run the script:</li>
<ul>
<li><span style="font-family: 'Courier New', Courier, monospace;">groovy UploadToS3AndGenerateSignedUrl.groovy</span></li>
</ul>
<li>Copy the URL that gets printed to stdout. It will look similar to this:</li>
<ul>
<li><span style="font-family: Courier New, Courier, monospace;">https://my-bucket-name.s3.amazonaws.com/myLargeFile.zip?AWSAccessKeyId=12E3AZEDFJQ6CMZW1HG5&Expires=1421887816&Signature=GFQ0LeR%2FtgWWGtXu3cJXspFtKNE%3D</span></li>
</ul>
<li>Send the URL to someone else in an email. They can click on it to download the file.</li>
<li>Optionally, use the <a href="https://console.aws.amazon.com/s3/">Amazon S3 Console</a> to remove the file from S3 once the recipient(s) have downloaded the file so that you don't get charged to have it sitting there forever.</li>
</ol>
Ken Weinerhttp://www.blogger.com/profile/12369783173503766970noreply@blogger.com0tag:blogger.com,1999:blog-15084382.post-5229238597988247362014-12-07T22:40:00.000-08:002014-12-07T22:48:51.694-08:00Using a Brother MFC-J450DW All-In-One with UbuntuAre you thinking about buying a <a href="http://www.amazon.com/gp/product/B00EANURCE/ref=as_li_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=B00EANURCE&linkCode=as2&tag=blogkw-20&linkId=XKWAEUEZ7EL7DTIB">Brother MFC-J450DW Wireless Office All-In-One Printer/Scanner/Copier/Fax Machine</a><img border="0" src="https://blogger.googleusercontent.com/img/proxy/AVvXsEi3mTeNoxHTkqEEKghSCqQHjeJf7mI3psnVu0G2h5OAkvQZSn6BSeuV2t4Jg7IHOGxdl2sWy8lbBWgFkyNs5P6Ed_ZVUG0VFv-Xydab1BkDFP7PBkzMA4dqx8jEmAvDIkC9OYyva-9koiHkXUBHVj-oT888_bPok3Y-mOoN4xW6MiT25FOdz2bKtvl9GzQqkWMP2Ee-NlLG0Vo3=" /> and wondering if it will work with your Ubuntu computer? The answer is <b>YES</b>! Brother actually includes Linux on their <a href="http://support.brother.com/g/b/oslist.aspx?c=us&lang=en&prod=mfcj450dw_us">Supported OS Page</a>. I was able to get things working on Ubuntu 14.04 LTS "Trusty Tahr".<br />
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://www.amazon.com/gp/product/B00EANURCE/ref=as_li_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=B00EANURCE&linkCode=as2&tag=blogkw-20&linkId=XKWAEUEZ7EL7DTIB" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6MZubVpjEiGiiAbZC2alBSk1tmkMTr19QgAh303xGMqQYf6M_rLPlTEVzImiFu82DDggCeiYcWfJcowY3jZssHQR5Qgd3oZ_MNAWDt5eBHoZiyucPj7G9uit6RFeSU6c3__vOrw/s1600/UbuntuLogo.png" height="72" width="320" /></a></div>
<div style="text-align: center;">
<b><span style="font-size: x-large;">+</span></b></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://www.amazon.com/gp/product/B00EANURCE/ref=as_li_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=B00EANURCE&linkCode=as2&tag=blogkw-20&linkId=XKWAEUEZ7EL7DTIB" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhANM7FiBi9xjK5kMZJGYL3iBgZBicTKoGyTfawY4iEbA9VbINqEr8kwI2FLY3WoWb4sGgx9lsSiIAgwe4pc9Aid3qHlla__GSnJR-JkATuKOmPVnhCf6TvjUO8tdZwMlqeFqFduA/s1600/mfcj450dw_us.jpg" height="186" width="320" /></a></div>
<div>
<br />
<h2>
Brother Software Installation</h2>
<div>
<br /></div>
<h3>
Driver Downloads</h3>
The CD provided with the printer contains Drivers, Utilities, and Users Manuals, but only for Windows and Macintosh computers. To get the Linux Drivers, you must visit the <a href="http://support.brother.com/g/b/downloadtop.aspx?c=us&lang=en&prod=mfcj450dw_us">MFC-J450DW Downloads Page</a>. Select Linux as the OS and Linux (deb) as the OS Version or go directly to <a href="http://support.brother.com/g/b/downloadlist.aspx?c=us&lang=en&prod=mfcj450dw_us&os=128">this page</a>. Follow directions to download and install the <b>Driver Install Tool</b>.<br />
<br />
From a terminal:<br />
<br />
<span style="background-color: #444444; color: white; font-family: Courier New, Courier, monospace;">gunzip linux-brprinter-installer-*.*.*-*.gz</span><br />
<span style="background-color: #444444; color: white; font-family: Courier New, Courier, monospace;">sudo su -</span><br />
<span style="background-color: #444444; color: white; font-family: Courier New, Courier, monospace;">bash linux-brprinter-installer-*.*.*-* MFC-J450DW</span><br />
<span style="background-color: #444444; color: white; font-family: Courier New, Courier, monospace;">Will you specify the DeviceURI? Y, 14 (Auto)</span><br />
<br />
After all this, you should be able to see your new printer:<br />
<br />
<span style="background-color: #cfe2f3;">System Settings</span> -> <span style="background-color: #cfe2f3;">Printers</span> -> <span style="background-color: #cfe2f3;">MFCJ450DW</span><br />
<br />
You should also be able to scan with the application <a href="https://apps.ubuntu.com/cat/applications/simple-scan/">Simple Scan</a> which comes with Ubuntu.<br />
<br />
<h2>
No Brother Software Installation</h2>
<div>
<br /></div>
If you would rather not install any software on your computer whatsoever, the MFC-J450DW makes this possible. I actually prefer this because it makes it easy to print and scan to and from any device you might have including Macs and iOS devices.<br />
<br />
<h3>
Google Cloud Print</h3>
Another option is to setup Google Cloud Print which lets you print from any device via your Google Account. <a href="http://www.brother.com/E-ftp/gcp/en/">Brother's Google Cloud Print Instruction Page</a> just tells you to find the right manual for your model. If you visit the <a href="http://support.brother.com/g/b/manualtop.aspx?c=us&lang=en&prod=mfcj450dw_us">Brother MFC-J450DW Manuals Page</a>, you will see the <a href="http://support.brother.com/g/b/manuallist.aspx?c=us&lang=en&prod=mfcj450dw_us&flang=English&type3=459&type2=85">Brother Google Cloud Print Guide Page</a> which let's you download the actual <a href="http://download.brother.com/welcome/doc003013/cv_mfc4510dw_eng_gcp_b.pdf">Brother Google Cloud Print Guide [PDF]</a>. To save time, just make sure you have a Google Account and then go directly to your printer's admin web interface which is accessible via a web browser at http://[PRINTER_IP_ADDRESS]/ where PRINTER_IP_ADDRESS is the address of your printer on the local network. I was able to obtain this IP address by looking at my router's list of connected clients. You can also find out via the printer's control panel by selecting <span style="background-color: #cfe2f3;">Menu</span> -> <span style="background-color: #cfe2f3;">Network</span> -> <span style="background-color: #cfe2f3;">WLAN</span> -> <span style="background-color: #cfe2f3;">TCP/IP</span> -> <span style="background-color: #cfe2f3;">IP Address</span>.<br />
<br />
The printer's Google Cloud Print admin page, at http://[PRINTER_IP_ADDRESS]/net/net/gcp.html?pageid=1084, only let's you associate the printer with one Google account. However Google let's you <a href="https://support.google.com/chromebook/answer/1241064?hl=en">share the printer</a> with other people very easily.<br />
<br />
<h3>
Scan to the Web</h3>
Another option for scanning is to use Brother Web Connect. Instructions can be found at the <a href="http://support.brother.com/g/b/manuallist.aspx?c=us&lang=en&prod=mfcj450dw_us&flang=English&type3=457&type2=85">Brother Web Connect Page</a> which lets you download the <a href="http://download.brother.com/welcome/doc100072/cv_mfc870dw_use_wcg_a.pdf">Brother Web Connect Guide [PDF]</a>. I found it very easy to setup Web Connect for <a href="https://drive.google.com/">Google Drive</a> and <a href="https://www.dropbox.com/">Dropbox</a>. Other options available that I haven't tried yet are <a href="http://picasaweb.google.com/">Picassa</a>, <a href="https://www.flickr.com/">Flickr</a>, <a href="https://www.facebook.com/">Facebook</a>, <a href="https://www.evernote.com/">Evernote</a>, <a href="https://onedrive.live.com/">Onedrive</a>, and <a href="https://www.box.com/">Box</a>. After you get it setup, you simply use the printer's control panel with <span style="background-color: #cfe2f3;">WEB</span> -> <span style="background-color: #cfe2f3;">[Service]</span> -> <span style="background-color: #cfe2f3;">[Configured Service]</span>. After scanning, the file will show up in your Configured Service in a folder called <b>From_BrotherDevice</b>. So easy!<br />
<br />
Please comment if you have any problems or other tips for people trying to get the Brother MFC-J450DW (or similar printer) working with Ubuntu.</div>
<!-- Blogger automated replacement: "https://images-blogger-opensocial.googleusercontent.com/gadgets/proxy?url=http%3A%2F%2Fwww.assoc-amazon.com%2Fe%2Fir%3Ft%3Dblogkw-20%26l%3Dbtl%26camp%3D213689%26creative%3D392969%26o%3D1%26a%3DB004HO58UW&container=blogger&gadget=a&rewriteMime=image%2F*" with "https://blogger.googleusercontent.com/img/proxy/AVvXsEi3mTeNoxHTkqEEKghSCqQHjeJf7mI3psnVu0G2h5OAkvQZSn6BSeuV2t4Jg7IHOGxdl2sWy8lbBWgFkyNs5P6Ed_ZVUG0VFv-Xydab1BkDFP7PBkzMA4dqx8jEmAvDIkC9OYyva-9koiHkXUBHVj-oT888_bPok3Y-mOoN4xW6MiT25FOdz2bKtvl9GzQqkWMP2Ee-NlLG0Vo3=" -->Ken Weinerhttp://www.blogger.com/profile/12369783173503766970noreply@blogger.com3tag:blogger.com,1999:blog-15084382.post-90146121722194904532014-11-23T23:29:00.000-08:002014-11-23T23:30:28.934-08:00Facebook Friend ClusteringMy wife is currently reading <a href="http://www.amazon.com/gp/product/0385347375/ref=as_li_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0385347375&linkCode=as2&tag=blogkw-20&linkId=3XLLRJF2MQXZYD5U">Dataclysm: Who We Are (When We Think No One's Looking)</a> and pointed me to this interesting <a href="http://dataclysm.org/relationshiptest">Relationship Test</a> tool she learned about in the book. It analyzes your Facebook friends and then shows both their connections to you and to each other. The graph assigns weight to relationships, so "cliques" of friends will cluster together. Here is the result I get:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8muTw5xM-RDOdsSX3d4dDhAwKgK7Yg9tGWptVKDqU7ojfoSNvBmvVSgvtuqIluokcJcIfE5aq4JJJHibpHR6BFREPxW1g4e7iJ1P6pXijMg7mqEriU4ZIbzrwL8upJV6YbSqZCg/s1600/fbfriends.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img alt="Ken Weiner Friend Graph" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8muTw5xM-RDOdsSX3d4dDhAwKgK7Yg9tGWptVKDqU7ojfoSNvBmvVSgvtuqIluokcJcIfE5aq4JJJHibpHR6BFREPxW1g4e7iJ1P6pXijMg7mqEriU4ZIbzrwL8upJV6YbSqZCg/s1600/fbfriends.png" height="597" title="Ken Weiner Friend Graph" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Ken Weiner's Friend Graph</td></tr>
</tbody></table>
<br />
The white circle in the center is myself. The cluster in the upper left identifies my friends from my<br />
high school, <a href="http://www.agourahighschool.net/">Agoura High School</a>. The cluster in the lower right is mostly coworkers from my previous job at <a href="http://lowermybills.com/">LowerMyBills.com</a>. The 2 less-defined clusters to the right of my high school cluster is a mix of family and <a href="http://www.ucla.edu/">college</a> friends.<br />
<br />
In addition to visualizing friend clusters, this tool also tries to identify your spouse or romantic partner using an algorithm from a paper called <a href="http://arxiv.org/pdf/1310.6753v1.pdf">Romantic Partnerships and the Dispersion of Social Ties:</a><br />
<a href="http://arxiv.org/pdf/1310.6753v1.pdf">A Network Analysis of Relationship Status on Facebook</a>. It tries to answer this question:<br />
<blockquote class="tr_bq">
Given all the connections among a person's friends, can you recognize his or her romantic partner from the network structure alone?</blockquote>
It measures something called dispersion - the extent to which two people's mutual friends are not themselves well-connected. <br />
<br />
On my network, it worked extremely well, identifying my wife as the person with whom I have the highest dispersion score (called assimilation score in this tool).<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnpQt0_nb4D1fA4Bc6ubupwCfIMdp-1Z9BD5AelF9U9yX4uRRE6RzYmvebK7Pi6fHuGvbsUM98WmHm4vmPEYdrI0yOroWyzHiIoq-QRI9zXNarGCIFOXN-KfvSzC6YlaCF9kcL7Q/s1600/assim.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img alt="Portion of my Facebook Connections Sorted by Assimilation Score" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnpQt0_nb4D1fA4Bc6ubupwCfIMdp-1Z9BD5AelF9U9yX4uRRE6RzYmvebK7Pi6fHuGvbsUM98WmHm4vmPEYdrI0yOroWyzHiIoq-QRI9zXNarGCIFOXN-KfvSzC6YlaCF9kcL7Q/s1600/assim.png" height="287" title="Portion of my Facebook Connections Sorted by Assimilation Score" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Portion of my Facebook Connections Sorted by Assimilation Score</td></tr>
</tbody></table>
<br />
This means that it is through my wife that I am connected to the most people that aren't themselves connected. This is natural, of course, because I have met my wife's high school friends, college friends, and coworkers, most of which don't know each other.<br />
<br />
There are a few people that rank high on the list that aren't actually "central" to my life. If I ignore all the people with less that 3 mutual friends, the list becomes much more meaningful and predictive of who really is central to my life.<br />
<br />
The ability to analyze my social network like this motivated me to visit Facebook and <a href="https://www.facebook.com/help/301707886595168/">Unfriend</a> acquaintances that I really never developed much of a relationship with. Now, both my Facebook news feed and Dispersion scores will be that much more meaningful!Ken Weinerhttp://www.blogger.com/profile/12369783173503766970noreply@blogger.com0tag:blogger.com,1999:blog-15084382.post-70806319136201066712014-11-16T14:31:00.000-08:002014-11-16T14:31:29.726-08:00HTTP Request Timings with cURLWhen a client makes an HTTP request, the following things happen:<br />
<br />
<ol>
<li>DNS name resolution</li>
<li>SSL/SSH/etc connect/handshake to the remote host if applicable</li>
<li>TCP connection to the remote host</li>
<li>Negotiations specific to the particular protocol(s) involved</li>
<li>Redirects if applicable</li>
<li>Content generation on remote host</li>
<li>Content transfer</li>
</ol>
<br />
Have you ever wanted to know how long each phase of an HTTP request takes?<br />
<br />
It turns out this is relatively straightforward to do with the command line tool cURL and its powerful "Write Out" option.<br />
<br />
<h3>
Write Out Option</h3>
cURL comes with an option to print out a lot of useful information related to a request. The following is taken directly from the cURL man page:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">-w, --write-out </span><format></format><br />
<br />
Defines what to display on stdout after a completed and successful operation. The format is a string that may contain plain text mixed with any number of variables. The string can be specified as "string", to get read from a particular file you specify it "@filename" and to tell curl to read the format from stdin you write "@-".<br />
<br />
The variables present in the output format will be substituted by the value or text that curl thinks fit, as described below. All variables are specified as <span style="font-family: Courier New, Courier, monospace;">%{variable_name}</span> and to output a normal % you just write them as %%. You can output a newline by using \n, a carriage return with \r and a tab space with \t.<br />
<br />
NOTE: The %-symbol is a special symbol in the win32-environment, where all occurrences of % must be doubled when using this option.<br />
<br />
The variables available are:<br />
<br />
<table border="1" cellpadding="0" cellspacing="0" dir="ltr" style="border-collapse: collapse; border: 1px solid #ccc; font-family: arial,sans,sans-serif; font-size: 13px; table-layout: fixed;"><colgroup><col width="111"></col><col width="1289"></col><col width="100"></col></colgroup><tbody>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"Variable"]" style="background-color: #efefef; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; border-top: 1px solid #000000; font-weight: bold; padding: 2px 3px 2px 3px; vertical-align: bottom;">Variable</td><td data-sheets-value="[null,2,"Description"]" style="background-color: #efefef; border-bottom: 1px solid #000000; border-right: 1px solid #000000; border-top: 1px solid #000000; font-size: 100%; font-weight: bold; padding: 2px 3px 2px 3px; vertical-align: bottom;">Description</td><td data-sheets-value="[null,2,"Since"]" style="background-color: #efefef; border-bottom: 1px solid #000000; border-right: 1px solid #000000; border-top: 1px solid #000000; font-weight: bold; padding: 2px 3px 2px 3px; vertical-align: bottom;">Since</td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"content_type"]" style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">content_type</td><td data-sheets-value="[null,2,"The Content-Type of the requested document, if there was any."]" style="background-color: white; border-bottom: 1px solid #000000; border-right: 1px solid #000000; font-size: 100%; padding: 2px 3px 2px 3px; vertical-align: bottom;">The Content-Type of the requested document, if there was any.</td><td style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;"></td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"filename_effective"]" style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">filename_effective</td><td data-sheets-value="[null,2,"The ultimate filename that curl writes out to. This is only meaningful if curl is told to write to a file with the --remote-name or --output option. It's most useful in combination with the --remote-header-name option."]" style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-right: 1px solid #000000; font-size: 100%; padding: 2px 3px 2px 3px; vertical-align: bottom;">The ultimate filename that curl writes out to. This is only meaningful if curl is told to write to a file with the --remote-name or --output option. It's most useful in combination with the --remote-header-name option.</td><td data-sheets-value="[null,2,"7.25.1"]" style="background-color: #f3f3f3; border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; font-size: 100%; padding: 2px 3px; vertical-align: bottom;">7.25.1</td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"ftp_entry_path"]" style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">ftp_entry_path</td><td data-sheets-value="[null,2,"The initial path curl ended up in when logging on to the remote FTP server."]" style="background-color: white; border-bottom: 1px solid #000000; border-right: 1px solid #000000; font-size: 100%; padding: 2px 3px 2px 3px; vertical-align: bottom;">The initial path curl ended up in when logging on to the remote FTP server.</td><td data-sheets-value="[null,2,"7.15.4"]" style="background-color: white; border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; font-size: 100%; padding: 2px 3px; vertical-align: bottom;">7.15.4</td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"http_code"]" style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">http_code</td><td data-sheets-value="[null,2,"The numerical response code that was found in the last retrieved HTTP(S) or FTP(s) transfer. In 7.18.2 the alias response_code was added to show the same info."]" style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-right: 1px solid #000000; font-size: 100%; padding: 2px 3px 2px 3px; vertical-align: bottom;">The numerical response code that was found in the last retrieved HTTP(S) or FTP(s) transfer. In 7.18.2 the alias response_code was added to show the same info.</td><td style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;"></td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"http_connect"]" style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">http_connect</td><td data-sheets-value="[null,2,"The numerical code that was found in the last response (from a proxy) to a curl CONNECT request."]" style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">The numerical code that was found in the last response (from a proxy) to a curl CONNECT request.</td><td data-sheets-value="[null,2,"7.12.4"]" style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">7.12.4</td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"local_ip"]" style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">local_ip</td><td data-sheets-value="[null,2,"The IP address of the local end of the most recently done connection - can be either IPv4 or IPv6."]" style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-right: 1px solid #000000; font-size: 100%; padding: 2px 3px 2px 3px; vertical-align: bottom;">The IP address of the local end of the most recently done connection - can be either IPv4 or IPv6.</td><td data-sheets-value="[null,2,"7.29.0"]" style="background-color: #f3f3f3; border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; font-size: 100%; padding: 2px 3px; vertical-align: bottom;">7.29.0</td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"local_port"]" style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">local_port</td><td data-sheets-value="[null,2,"The local port number of the most recently done connection."]" style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">The local port number of the most recently done connection.</td><td data-sheets-value="[null,2,"7.29.0"]" style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">7.29.0</td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"num_connects"]" style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">num_connects</td><td data-sheets-value="[null,2,"Number of new connects made in the recent transfer."]" style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-right: 1px solid #000000; font-size: 100%; padding: 2px 3px 2px 3px; vertical-align: bottom;">Number of new connects made in the recent transfer.</td><td data-sheets-value="[null,2,"7.12.3"]" style="background-color: #f3f3f3; border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; font-size: 100%; padding: 2px 3px; vertical-align: bottom;">7.12.3</td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"num_redirects"]" style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">num_redirects</td><td data-sheets-value="[null,2,"Number of redirects that were followed in the request."]" style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">Number of redirects that were followed in the request.</td><td data-sheets-value="[null,2,"7.12.3"]" style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">7.12.3</td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"redirect_url"]" style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">redirect_url</td><td data-sheets-value="[null,2,"When an HTTP request was made without -L to follow redirects, this variable will show the actual URL a redirect would take you to."]" style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-right: 1px solid #000000; font-size: 100%; padding: 2px 3px 2px 3px; vertical-align: bottom;">When an HTTP request was made without -L to follow redirects, this variable will show the actual URL a redirect would take you to.</td><td data-sheets-value="[null,2,"7.18.2"]" style="background-color: #f3f3f3; border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; font-size: 100%; padding: 2px 3px; vertical-align: bottom;">7.18.2</td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"remote_ip"]" style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">remote_ip</td><td data-sheets-value="[null,2,"The remote IP address of the most recently done connection - can be either IPv4 or IPv6."]" style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">The remote IP address of the most recently done connection - can be either IPv4 or IPv6.</td><td data-sheets-value="[null,2,"7.29.0"]" style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">7.29.0</td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"remote_port"]" style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">remote_port</td><td data-sheets-value="[null,2,"The remote port number of the most recently done connection."]" style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-right: 1px solid #000000; font-size: 100%; padding: 2px 3px 2px 3px; vertical-align: bottom;">The remote port number of the most recently done connection.</td><td data-sheets-value="[null,2,"7.29.0"]" style="background-color: #f3f3f3; border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; font-size: 100%; padding: 2px 3px; vertical-align: bottom;">7.29.0</td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"size_download"]" style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">size_download</td><td data-sheets-value="[null,2,"The total amount of bytes that were downloaded."]" style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">The total amount of bytes that were downloaded.</td><td style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;"></td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"size_header"]" style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">size_header</td><td data-sheets-value="[null,2,"The total amount of bytes of the downloaded headers."]" style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-right: 1px solid #000000; font-size: 100%; padding: 2px 3px 2px 3px; vertical-align: bottom;">The total amount of bytes of the downloaded headers.</td><td style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;"></td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"size_request"]" style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">size_request</td><td data-sheets-value="[null,2,"The total amount of bytes that were sent in the HTTP request."]" style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">The total amount of bytes that were sent in the HTTP request.</td><td style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;"></td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"size_upload"]" style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">size_upload</td><td data-sheets-value="[null,2,"The total amount of bytes that were uploaded."]" style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-right: 1px solid #000000; font-size: 100%; padding: 2px 3px 2px 3px; vertical-align: bottom;">The total amount of bytes that were uploaded.</td><td style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;"></td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"speed_download"]" style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">speed_download</td><td data-sheets-value="[null,2,"The average download speed that curl measured for the complete download. Bytes per second."]" style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">The average download speed that curl measured for the complete download. Bytes per second.</td><td style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;"></td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"speed_upload"]" style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">speed_upload</td><td data-sheets-value="[null,2,"The average upload speed that curl measured for the complete upload. Bytes per second."]" style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-right: 1px solid #000000; font-size: 100%; padding: 2px 3px 2px 3px; vertical-align: bottom;">The average upload speed that curl measured for the complete upload. Bytes per second.</td><td style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;"></td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"ssl_verify_result"]" style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">ssl_verify_result</td><td data-sheets-value="[null,2,"The result of the SSL peer certificate verification that was requested. 0 means the verification was successful."]" style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">The result of the SSL peer certificate verification that was requested. 0 means the verification was successful.</td><td data-sheets-value="[null,2,"7.19.0"]" style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">7.19.0</td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"time_appconnect"]" style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">time_appconnect</td><td data-sheets-value="[null,2,"The time, in seconds, it took from the start until the SSL/SSH/etc connect/handshake to the remote host was completed."]" style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-right: 1px solid #000000; font-size: 100%; padding: 2px 3px 2px 3px; vertical-align: bottom;">The time, in seconds, it took from the start until the SSL/SSH/etc connect/handshake to the remote host was completed.</td><td data-sheets-value="[null,2,"7.19.0"]" style="background-color: #f3f3f3; border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; font-size: 100%; padding: 2px 3px; vertical-align: bottom;">7.19.0</td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"time_connect"]" style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">time_connect</td><td data-sheets-value="[null,2,"The time, in seconds, it took from the start until the TCP connect to the remote host (or proxy) was completed."]" style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">The time, in seconds, it took from the start until the TCP connect to the remote host (or proxy) was completed.</td><td style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;"></td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"time_namelookup"]" style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">time_namelookup</td><td data-sheets-value="[null,2,"The time, in seconds, it took from the start until the name resolving was completed."]" style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-right: 1px solid #000000; font-size: 100%; padding: 2px 3px 2px 3px; vertical-align: bottom;">The time, in seconds, it took from the start until the name resolving was completed.</td><td style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;"></td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"time_pretransfer"]" style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">time_pretransfer</td><td data-sheets-value="[null,2,"The time, in seconds, it took from the start until the file transfer was just about to begin. This includes all pre-transfer commands and negotiations that are specific to the particular protocol(s) involved."]" style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">The time, in seconds, it took from the start until the file transfer was just about to begin. This includes all pre-transfer commands and negotiations that are specific to the particular protocol(s) involved.</td><td style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;"></td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"time_redirect"]" style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">time_redirect</td><td data-sheets-value="[null,2,"The time, in seconds, it took for all redirection steps include name lookup, connect, pretransfer and transfer before the final transaction was started. time_redirect shows the complete execution time for multiple redirections."]" style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-right: 1px solid #000000; font-size: 100%; padding: 2px 3px 2px 3px; vertical-align: bottom;">The time, in seconds, it took for all redirection steps include name lookup, connect, pretransfer and transfer before the final transaction was started. time_redirect shows the complete execution time for multiple redirections.</td><td data-sheets-value="[null,2,"7.12.3"]" style="background-color: #f3f3f3; border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; font-size: 100%; padding: 2px 3px; vertical-align: bottom;">7.12.3</td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"time_starttransfer"]" style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">time_starttransfer</td><td data-sheets-value="[null,2,"The time, in seconds, it took from the start until the first byte was just about to be transferred. This includes time_pretransfer and also the time the server needed to calculate the result."]" style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">The time, in seconds, it took from the start until the first byte was just about to be transferred. This includes time_pretransfer and also the time the server needed to calculate the result.</td><td style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;"></td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"time_total"]" style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">time_total</td><td data-sheets-value="[null,2,"The total time, in seconds, that the full operation lasted. The time will be displayed with millisecond resolution."]" style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-right: 1px solid #000000; font-size: 100%; padding: 2px 3px 2px 3px; vertical-align: bottom;">The total time, in seconds, that the full operation lasted. The time will be displayed with millisecond resolution.</td><td style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;"></td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"url_effective"]" style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">url_effective</td><td data-sheets-value="[null,2,"The URL that was fetched last. This is most meaningful if you've told curl to follow location: headers."]" style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">The URL that was fetched last. This is most meaningful if you've told curl to follow location: headers.</td><td style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;"></td></tr>
</tbody></table>
<br />
Here's a sample cURL command to show each one of these properties while making a request to Google's home page:<br />
<br />
<span style="background-color: #f3f3f3; font-family: Courier New, Courier, monospace;">curl -w '\ncontent_type=%{content_type}\nfilename_effective=%{filename_effective}\nftp_entry_path=%{ftp_entry_path}\nhttp_code=%{http_code}\nhttp_connect=%{http_connect}\nlocal_ip=%{local_ip}\nlocal_port=%{local_port}\nnum_connects=%{num_connects}\nnum_redirects=%{num_redirects}\nredirect_url=%{redirect_url}\nremote_ip=%{remote_ip}\nremote_port=%{remote_port}\nsize_download=%{size_download}\nsize_header=%{size_header}\nsize_request=%{size_request}\nsize_upload=%{size_upload}\nspeed_download=%{speed_download}\nspeed_upload=%{speed_upload}\nssl_verify_result=%{ssl_verify_result}\ntime_appconnect=%{time_appconnect}\ntime_connect=%{time_connect}\ntime_namelookup=%{time_namelookup}\ntime_pretransfer=%{time_pretransfer}\ntime_redirect=%{time_redirect}\ntime_starttransfer=%{time_starttransfer}\ntime_total=%{time_total}\nurl_effective=%{url_effective}\n\n' -o /dev/null -s 'https://www.google.com/'</span><br />
<br />
<div>
Where:</div>
<div>
<ul>
<li>-w shows which properties to write out</li>
<li>-o /dev/null redirects the output of the request to /dev/null</li>
<li>-s tells cURL not to show a progress bar</li>
<li>http://www.cnn.com/ is the URL we are requesting</li>
</ul>
</div>
<h3>
Timing</h3>
<div>
From the options above, the following are of interest when it comes to timing the phases of a request.</div>
<div>
<br /></div>
<div>
<table border="1" cellpadding="0" cellspacing="0" dir="ltr" style="border-collapse: collapse; border: 1px solid #ccc; font-family: arial,sans,sans-serif; font-size: 13px; table-layout: fixed;"><colgroup><col width="111"></col><col width="1289"></col><col width="100"></col></colgroup><tbody>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"time_appconnect"]" style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; border-top: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">time_appconnect</td><td data-sheets-value="[null,2,"The time, in seconds, it took from the start until the SSL/SSH/etc connect/handshake to the remote host was completed."]" style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-right: 1px solid #000000; border-top: 1px solid #000000; font-size: 100%; padding: 2px 3px 2px 3px; vertical-align: bottom;">The time, in seconds, it took from the start until the SSL/SSH/etc connect/handshake to the remote host was completed.</td><td data-sheets-value="[null,2,"7.19.0"]" style="background-color: #f3f3f3; border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(0, 0, 0); border-top-style: solid; border-top-width: 1px; font-size: 100%; padding: 2px 3px; vertical-align: bottom;">7.19.0</td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"time_connect"]" style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">time_connect</td><td data-sheets-value="[null,2,"The time, in seconds, it took from the start until the TCP connect to the remote host (or proxy) was completed."]" style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">The time, in seconds, it took from the start until the TCP connect to the remote host (or proxy) was completed.</td><td style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;"></td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"time_namelookup"]" style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">time_namelookup</td><td data-sheets-value="[null,2,"The time, in seconds, it took from the start until the name resolving was completed."]" style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-right: 1px solid #000000; font-size: 100%; padding: 2px 3px 2px 3px; vertical-align: bottom;">The time, in seconds, it took from the start until the name resolving was completed.</td><td style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;"></td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"time_pretransfer"]" style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">time_pretransfer</td><td data-sheets-value="[null,2,"The time, in seconds, it took from the start until the file transfer was just about to begin. This includes all pre-transfer commands and negotiations that are specific to the particular protocol(s) involved."]" style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">The time, in seconds, it took from the start until the file transfer was just about to begin. This includes all pre-transfer commands and negotiations that are specific to the particular protocol(s) involved.</td><td style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;"></td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"time_redirect"]" style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">time_redirect</td><td data-sheets-value="[null,2,"The time, in seconds, it took for all redirection steps include name lookup, connect, pretransfer and transfer before the final transaction was started. time_redirect shows the complete execution time for multiple redirections."]" style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-right: 1px solid #000000; font-size: 100%; padding: 2px 3px 2px 3px; vertical-align: bottom;">The time, in seconds, it took for all redirection steps include name lookup, connect, pretransfer and transfer before the final transaction was started. time_redirect shows the complete execution time for multiple redirections.</td><td data-sheets-value="[null,2,"7.12.3"]" style="background-color: #f3f3f3; border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; font-size: 100%; padding: 2px 3px; vertical-align: bottom;">7.12.3</td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"time_starttransfer"]" style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">time_starttransfer</td><td data-sheets-value="[null,2,"The time, in seconds, it took from the start until the first byte was just about to be transferred. This includes time_pretransfer and also the time the server needed to calculate the result."]" style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">The time, in seconds, it took from the start until the first byte was just about to be transferred. This includes time_pretransfer and also the time the server needed to calculate the result.</td><td style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;"></td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"time_total"]" style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;">time_total</td><td data-sheets-value="[null,2,"The total time, in seconds, that the full operation lasted. The time will be displayed with millisecond resolution."]" style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-right: 1px solid #000000; font-size: 100%; padding: 2px 3px 2px 3px; vertical-align: bottom;">The total time, in seconds, that the full operation lasted. The time will be displayed with millisecond resolution.</td><td style="background-color: #f3f3f3; border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;"></td></tr>
</tbody></table>
</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
If we consider a simple request to a non-SSL page that involves no redirects, there would be 4 main phases:</div>
<div>
<br /></div>
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvVtTgb7GXgDhqkSZ3SrBC83CWJwkcvp2OpoNkQmuC1b3MGd49FyCbKZ55RD7Hlkr0nJuyWRMBZ0KZ5msyStU6HpLtN_dkITA8SUQv4Z34OePmNd6TPbr1Ta0340lXHMbQ2OODkA/s1600/curl-phases.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img alt="HTTP Request Phases: DNS Lookup, TCP Connection, Content Generation, and Content Transfer" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvVtTgb7GXgDhqkSZ3SrBC83CWJwkcvp2OpoNkQmuC1b3MGd49FyCbKZ55RD7Hlkr0nJuyWRMBZ0KZ5msyStU6HpLtN_dkITA8SUQv4Z34OePmNd6TPbr1Ta0340lXHMbQ2OODkA/s1600/curl-phases.png" height="253" title="HTTP Request Phases" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">HTTP Request Phases<br />
<br />
<div style="text-align: left;">
<span style="font-size: small;"><br /></span></div>
<div style="text-align: left;">
<span style="font-size: small;"><br /></span></div>
<div style="text-align: left;">
<span style="font-size: small;">Let's run the following command to gather timings while loading CNN's home page:</span></div>
<div style="text-align: left;">
<span style="font-size: small;"><br /></span></div>
<div style="text-align: left;">
<span style="font-size: small;"></span><br />
<div>
<span style="font-size: small;"><span style="background-color: #f3f3f3; font-family: Courier New, Courier, monospace;">curl -w '\ntime_namelookup=%{time_namelookup}\ntime_appconnect=%{time_appconnect}\ntime_connect=%{time_connect}\ntime_redirect=%{time_redirect}\ntime_pretransfer=%{time_pretransfer}\ntime_starttransfer=%{time_starttransfer}\ntime_total=%{time_total}\n\n' -o /dev/null -s 'http://www.cnn.com/'</span></span></div>
<span style="font-size: small;">
<div>
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div>
<div>
Where:</div>
<div>
<ul>
<li>-w shows which timing properties to write out</li>
<li>-o /dev/null redirects the output of the request to /dev/null</li>
<li>-s tells cURL not to show a progress bar</li>
<li>http://www.cnn.com/ is the URL we are requesting</li>
</ul>
</div>
</div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;">This results in the following output:</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div>
<span style="background-color: #f3f3f3; font-family: Courier New, Courier, monospace;">time_namelookup=0.029</span></div>
<div>
<span style="background-color: #f3f3f3; font-family: Courier New, Courier, monospace;">time_appconnect=0.000</span></div>
<div>
<span style="background-color: #f3f3f3; font-family: Courier New, Courier, monospace;">time_connect=0.095</span></div>
<div>
<span style="background-color: #f3f3f3; font-family: Courier New, Courier, monospace;">time_redirect=0.000</span></div>
<div>
<span style="background-color: #f3f3f3; font-family: Courier New, Courier, monospace;">time_pretransfer=0.095</span></div>
<div>
<span style="background-color: #f3f3f3; font-family: Courier New, Courier, monospace;">time_starttransfer=0.166</span></div>
<div>
<span style="background-color: #f3f3f3; font-family: Courier New, Courier, monospace;">time_total=0.530</span></div>
<div>
<br /></div>
<div>
From this, we can compute the time taken in each of the 4 phases as follows:</div>
<div>
<br /></div>
<div>
DNS Lookup = DNS Lookup (29 ms) - Start (0 ms) = <b>29 milliseconds</b></div>
<div>
TCP Connection = Pre Transfer (95 ms) - DNS Lookup (29 ms) = <b>66 millseconds</b></div>
<div>
Content Generation = Start Transfer (166 ms) - Pre Transfer (95 ms) = <b>71 milliseconds</b></div>
<div>
Content Transfer = Total (530 ms) - Start Transfer (166 ms) = <b>364 milliseconds</b></div>
<div>
<br /></div>
<div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSIrUf39HwCCURZqjKMgtq_FU1QsyBV_jmsGtYk-5k_Lckc1sbEZCjnEovqX8mk_zRdW4OqnGA7EVDlk1mPT34c0EJRXNcV2gDkhzATtoI5bnR-Frsb9cAwknc5uTd8sR855Bqnw/s1600/curl-cnn.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img alt="HTTP Request to http://www.cnn.com/" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSIrUf39HwCCURZqjKMgtq_FU1QsyBV_jmsGtYk-5k_Lckc1sbEZCjnEovqX8mk_zRdW4OqnGA7EVDlk1mPT34c0EJRXNcV2gDkhzATtoI5bnR-Frsb9cAwknc5uTd8sR855Bqnw/s1600/curl-cnn.png" height="255" title="HTTP Request to http://www.cnn.com/" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="font-size: 13px; text-align: center;">HTTP Request Timings for http://www.cnn.com/</td></tr>
</tbody></table>
</div>
<div>
So there you have it! Next time a request seems slow, you can use cURL to help find out why. You can write cron-invoked scripts that invoke the cURL command, collect the timing information, and send the results to <a href="http://www.splunk.com/">Splunk</a>, <a href="http://docs.aws.amazon.com/AmazonCloudWatch/latest/DeveloperGuide/publishingMetrics.html">Amazon Cloudwatch</a>, or your favorite logging framework to get pretty graphs of data over time.</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
</span></div>
</td></tr>
</tbody></table>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
Ken Weinerhttp://www.blogger.com/profile/12369783173503766970noreply@blogger.com3tag:blogger.com,1999:blog-15084382.post-73191487682922520522012-04-17T14:36:00.000-07:002012-04-17T14:36:02.326-07:00Avoiding Spam Emails with Google Apps<div>
Employees at my startup have started complaining that their outgoing emails were landing in their recipient's Spam folders. It seems to happen more often with recipients that use Outlook. After a little research I discovered that our Google Apps and GoDaddy DNS setup was missing some key configurations: an SPF Record and DKIM Record.<br />
<br />
After making the changes described below and waiting a few hours for DNS changes to propagate, the Spam problem has been resolved!</div>
<h3>
Sender Policy Framework (SPF) Records</h3>
<div>
An SPF record is a type of DNS record that identifies which mail servers are permitted to send email on behalf of your domain. If an email message comes from a server other than the Google Apps mail servers listed in the SPF record, the recipient's mail server can reject it as spam. <a href="http://support.google.com/a/bin/answer.py?hl=en&answer=33786">More info</a>.</div>
<div>
<br /></div>
<div>
Google gives <a href="http://support.google.com/a/bin/answer.py?hl=en&answer=178723">these instructions</a> for creating an SPF record. I followed those instructions which resulted in me adding a new TXT DNS record in GoDaddy:</div>
<div>
<br /></div>
<div>
Host:<br />
<span style="background-color: #d9ead3; font-family: 'Courier New', Courier, monospace; font-size: x-small;">@</span></div>
<div>
<br />
TXT Value:<br />
<span style="background-color: #d9ead3; font-family: 'Courier New', Courier, monospace; font-size: x-small;">v=spf1 include:_spf.google.com ~all</span></div>
<h3>
DomainKeys Identified Mail (DKIM) Standard</h3>
<div>
You can add a digital "signature" to the header of mail messages sent from your domain. Recipients can check the domain signature to verify that the message really comes from your domain and that it has not been changed along the way. Google gives <a href="http://support.google.com/a/bin/answer.py?hl=en&answer=174124">these instructions</a> for getting your emails signed and verified. I followed those instructions which resulted in me adding another TXT DNS record:</div>
<div>
<br /></div>
<div>
Host:<br />
<span style="background-color: #d9ead3; font-family: 'Courier New', Courier, monospace; font-size: x-small;">google._domainkey</span><br />
<span style="background-color: #d9ead3; font-family: 'Courier New', Courier, monospace;"><br /></span></div>
<div>
TXT Value:<br />
<span style="background-color: #d9ead3;"><span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">v=DKIM1; k=rsa; p=CIGfMA0GCSqGSIb2DQEBAQAAA4GNADCBiQHKgQCj+tnMQMGMn8NfHnpDmgPa7ICUKdXdyzTlkBglZKRfEtF9msn1v/TmHZEvWFFp3KiaL2Igs7K57l+n/QJlk8Aj9C9nTGmXnzm9BL2zOQQL/zxJh9qh22bnO8uf7tM7sGHxr3z7yIkpXzA96G0inqmNb2XztXKseV4dp5jXbow4+QIDAQAB</span></span><br />
<span style="background-color: #d9ead3;"><span style="font-family: 'Courier New', Courier, monospace;"><br /></span></span></div>
<div>
I used the following services to test if the above configurations were working properly:</div>
<h3>
OpenSPF.org</h3>
<div>
The <a href="http://www.openspf.org/Tools">OpenSPF site</a> contains detailed instructions. You basically send an email to <a href="mailto:spf-test@openspf.org">spf-test@openspf.org</a>. Your email will bounce but the bounce message will contain diagnostic information. Before I made any changes, the bounced email contained:</div>
<div>
<br /></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">SPF Tests: Mail-From <span style="background-color: yellow;">Result="none"</span>: Mail From="ken@mystartup.com" HELO name="mail-vb0-f45.google.com" HELO Result="none" Remote IP="209.85.212.45"</span></div>
<div>
<br /></div>
<div>
After adding an SPF record, I got:</div>
<div>
<br /></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">SPF Tests: Mail-From <span style="background-color: yellow;">Result="pass"</span>: Mail From="ken@mystartup.com" HELO name="mail-ob0-f173.google.com" HELO Result="none" Remote IP="209.85.214.173"</span></div>
<div>
<br /></div>
<div>
After setting up DKIM, a new section appeared:</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> d=mystartup.com; s=google;</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> h=mime-version:from:date:message-id:subject:to:content-type;</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> bh=3N7Rc6NGlzUWcAIDAPH02fhMn6EQcMyaqN1zoCZpAj4=;</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> b=CB2n+ZleGjSlLH23RAvhMu56NIZULnSbc3efghykaJpeYMK5xOH2HDqzkoIk7kUWLV</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> 3xfcPK/7sABiIzhmi+RzzPaOEpUvE8kqFd9SocB3dUYmmCauB2RQIXh7qOUFFV/HTDxR</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> 23jAtjJUNX4VcdbNsmedbSwKpE30NYF49kjEY=</span></div>
</div>
<h3>
Port25.com</h3>
<div>
For this one, you send an email to <a href="mailto:check-auth@verifier.port25.com">check-auth@verifier.port25.com</a>. If you SPF record and DKIM is setup properly, you should get a reply containing this summary:</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">==========================================================</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Summary of Results</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">==========================================================</span></div>
<div>
<span style="background-color: yellow; font-family: 'Courier New', Courier, monospace; font-size: x-small;">SPF check: pass</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">DomainKeys check: neutral</span></div>
<div>
<span style="background-color: yellow; font-family: 'Courier New', Courier, monospace; font-size: x-small;">DKIM check: pass</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Sender-ID check: pass</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">SpamAssassin check: ham</span><br />
<h3>
<span style="font-family: inherit;">IsNotSpam.com</span></h3>
<span style="font-family: inherit;">This is similar to the service from Port25.com. You send an email to <a href="mailto:check@isnotspam.com">check@isnotspam.com</a> and get a similar reply.</span></div>
</div>Ken Weinerhttp://www.blogger.com/profile/12369783173503766970noreply@blogger.com0tag:blogger.com,1999:blog-15084382.post-45809909102759189602011-12-14T10:20:00.000-08:002011-12-14T10:57:27.158-08:00AutoScaling Amazon SQS Queue ProcessorsOne of my favorite things about running servers in Amazon EC2 is the ability to use AutoScaling to automatically add and remove nodes as web traffic increases and decreases. Not only does this generally save money, but it also helps prepare a system to handle traffic spikes.
<br />
<div>
<br /></div>
<div>
Recently I had some fun setting up AutoScaling for a different use case -- a cluster of machines processing messages on an Amazon SQS queue. The idea was to add and remove nodes as the number of visible messages on the queue fluctuated. Again, this keeps costs lower by only running as many nodes as are necessary to process the current workload and handles workload spikes.</div>
<div>
<br /></div>
<div>
Here are sample steps and commands that you can use for setting up AutoScaling for SQS queue processors:</div>
<div>
<br /></div>
<div>
Create an AMI for a node that will process SQS messages. The node that boots from this AMI should automatically launch one or more queue processing processes. A <a href="http://alestic.com/2009/06/ec2-user-data-scripts">user-data script</a> may be useful for this.</div>
<div>
<br /></div>
<div>
Create a Launch Configuration for the queue processor node:</div>
<div>
<br /></div>
<div>
<pre class="brush: plain">as-create-launch-config MyQueueConfig --image-id [INSERT YOUR AMI ID HERE] --instance-type c1.medium --key [INSERT YOUR KEYNAME HERE] --user-data [INSERT YOUR USER DATA SCRIPT HERE]</pre>
</div>
<div>
<br /></div>
<div>
Create an AutoScaling group for queue processors:</div>
<div>
<br /></div>
<div>
<pre class="brush: plain">as-create-auto-scaling-group MyQueueGroup --launch-configuration MyQueueConfig --availability-zones us-east-1b --min-size 1 --max-size 10</pre>
</div>
<div>
<br /></div>
<div>
<div>
Create Policies that add/remove 1 node to/from the cluster. They will be invoked when the number of messages on the queue grows excessively high or decreases to an acceptable level:</div>
<div>
<br /></div>
<div>
<pre class="brush: plain">as-put-scaling-policy MyScaleUpPolicy -g MyQueueGroup --adjustment=1 --type ChangeInCapacity</pre>
</div>
</div>
<div>
<br /></div>
<div>
<pre class="brush: plain">as-put-scaling-policy MyScaleDownPolicy -g MyQueueGroup --adjustment=-1 --type ChangeInCapacity</pre>
</div>
<div>
<br /></div>
<div>
Create Alarms to scale up/down when the number of messages on the queue grows excessively high or decreases to an acceptable level. Use the Policy ARN's returned by the previous <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">as-put-scaling-policy</span> commands.</div>
<div>
<br /></div>
<div>
<div>
<pre class="brush: plain">mon-put-metric-alarm --alarm-name MyHighMessagesAlarm --alarm-description "Scale up when number of messages on queue is high" --metric-name ApproximateNumberOfMessagesVisible --namespace AWS/SQS --statistic Average --period 60 --threshold 1000 --comparison-operator GreaterThanThreshold --dimensions QueueName=MyQueue --evaluation-periods 10 --alarm-actions [INSERT MyScaleUpPolicy ARN HERE]</pre>
</div>
</div>
<div>
<br /></div>
<div>
<pre class="brush: plain">mon-put-metric-alarm --alarm-name MyLowMessagesAlarm --alarm-description "Scale down when number of messages on queue is low" --metric-name ApproximateNumberOfMessagesVisible --namespace AWS/SQS --statistic Average --period 60 --threshold 100 --comparison-operator LessThanThreshold --dimensions QueueName=MyQueue --evaluation-periods 10 --alarm-actions [INSERT MyScaleDownPolicy ARN HERE]</pre>
</div>
<div>
<br />
In this example the Alarms cause the cluster to scale up when the number of visible messages on the queue remains above 1000 for 10 consecutive minutes and scale down when the number of visible messages falls below 100 for 10 consecutive minutes.<br />
<br />
The Policies above adjust the amount of nodes in the cluster by a specific amount, but it is also possible to specify the adjustment in terms of percentages. Using <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">--adjustment 10 --type PercentChangeInCapacity</span> would adjust the amount of nodes by 10 percent.<br />
<br />
It also would have been possible to base scaling activities on other AWS/SQS metrics such as:<br />
<ul>
<li>NumberOfMessagesSent</li>
<li>NumberOfMessagesReceived</li>
<li>NumberOfMessagesDeleted</li>
<li>NumberOfEmptyReceives</li>
<li>ApproximateNumberOfMessagesVisible</li>
<li>ApproximateNumberOfMessagesNotVisible</li>
<li>ApproximateNumberOfMessagesDelayed</li>
<li>SentMessageSize</li>
</ul>
Here are a few online references relevant to AutoScaling SQS queue processors:</div>
<div>
<div>
<ul>
<li><a href="http://aws.amazon.com/articles/1464">Auto Scaling Amazon EC2 with Amazon SQS</a></li>
<li><a href="http://docs.amazonwebservices.com/AutoScaling/latest/DeveloperGuide/index.html?US_SetUpASLBApp.html">Auto Scaling with Alarms and Load Balancing</a></li>
<li><a href="http://docs.amazonwebservices.com/AutoScaling/latest/APIReference/">Auto Scaling API Reference</a></li>
</ul>
</div>
Happy SQS AutoScaling!</div>Ken Weinerhttp://www.blogger.com/profile/12369783173503766970noreply@blogger.com5tag:blogger.com,1999:blog-15084382.post-77268115033849533542011-10-20T15:07:00.000-07:002011-10-20T15:07:05.491-07:00Online Advertising Formula ReferenceOccasionally I need to manipulate online advertising formulas to make a quick calculation. The following serves a quick cheat sheet for this purpose. Note that the term <b>Cost</b> is from the perspective of the Advertiser. The web site or publisher can translate that into <b>Revenue</b>. <br />
<h3>
CPM Campaigns</h3>
<div style="font-family: "Courier New",Courier,monospace;">
Cost = Impressions / 1000 * CPM</div>
<div style="font-family: "Courier New",Courier,monospace;">
<br /></div>
<h3>
CPC Campaigns</h3>
<div style="font-family: "Courier New",Courier,monospace;">
Cost = Impressions * CTR * CPC</div>
<div style="font-family: "Courier New",Courier,monospace;">
CPM = CTR * CPC * 1000</div>
<div style="font-family: "Courier New",Courier,monospace;">
<br /></div>
<h3>
CPA Campaigns</h3>
<div style="font-family: "Courier New",Courier,monospace;">
Cost = Impressions * CTR * AR * CPA </div>
<div style="font-family: "Courier New",Courier,monospace;">
CPM = CTR * AR * CPA * 1000</div>
<div style="font-family: "Courier New",Courier,monospace;">
<br /></div>
<br />
<table border="1" cellpadding="3" cellspacing="0">
<tbody>
<tr><th>Notation</th><th>Description</th></tr>
<tr><td>CPM</td><td>Cost Per 1000 Impressions</td></tr>
<tr><td>CPC</td><td>Cost Per Click</td></tr>
<tr><td>CPA</td><td>Cost Per Action</td></tr>
<tr><td>CTR</td><td>Click Thru Rate (Clicks / Impressions)</td></tr>
<tr><td>AR</td><td>Action Rate (Actions / Clicks)</td></tr>
</tbody></table>Ken Weinerhttp://www.blogger.com/profile/12369783173503766970noreply@blogger.com0tag:blogger.com,1999:blog-15084382.post-44243207062109226992011-07-18T21:53:00.000-07:002011-07-18T21:53:28.776-07:00Giant Ampersand - Washington/Centinela Redevelopment Part 6It's been almost 5 years since my <a href="http://blog.kenweiner.com/2007/02/washingtoncentinela-redevelopment-part_25.html">last post</a> about the corner lots of Washington and Centinela which are supposedly destined for <a href="http://www.culvercity.org/en/Government/CommunityDevelopment/Redevelopment/CurrentProjects/WashingtonCentinela">redevelopment</a>. That's because pretty much nothing has happened on those lots - until this past week.<br />
<br />
All of the sudden a 8-foot tall white wooden ampersand appeared in the middle of the lot on the north east corner. I had no idea what it meant, but I was really happy to see it. To me it meant that someone out there is thinking about this vacant plot of land.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiVFibO3nvtPxeWlHVVU-LNVwCswzH0IRyrbU9VcauGmyajtZ25n_iZZA32xjxJe9jX2Q8S_aLmOInOghkiBP37AzoYmZr0CZT3c8OJ04Lxb6Az2wxxj2TPB6shNmmCuKFAhpIhg/s1600/IMG_1313.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiVFibO3nvtPxeWlHVVU-LNVwCswzH0IRyrbU9VcauGmyajtZ25n_iZZA32xjxJe9jX2Q8S_aLmOInOghkiBP37AzoYmZr0CZT3c8OJ04Lxb6Az2wxxj2TPB6shNmmCuKFAhpIhg/s320/IMG_1313.JPG" width="320" /></a></div><br />
<br />
A little Googling produced an answer. The mysterious ampersand is a public project by Los Angeles-based artist Shannon Ebner. According to the <a href="http://www.blogger.com/"><span id="goog_375505620"></span>LAXART web site<span id="goog_375505621"></span></a><a="">:<br />
</a=""><br />
<blockquote><span class="Apple-style-span" style="font-size: large;">The ampersand is a conjoiner; it signals an incomplete thought and acknowledges that there is more to be said.</span></blockquote><br />
This is part of a Shannon Ebner <a href="http://museumpublicity.com/2011/07/16/hammer-museum-opens-shannon-ebner-exhibition/">exhibition</a> at the Hammer Museum which started July 16, 2011. Apparently this isn't the first time she's used an ampersand in her work. See <a href="http://roski.usc.edu/news/assistant-professor-shannon-eb-1.html">this photo</a> from a year ago in Milan.<br />
<br />
I've been waiting for the redevelopment on this corner to get underway since I moved to this <a href="http://www.delreync.org/">Del Rey neighborhood</a> 11 years ago. I really hope, as the giant ampersand acknowledges, that there is more to be said...Ken Weinerhttp://www.blogger.com/profile/12369783173503766970noreply@blogger.com3tag:blogger.com,1999:blog-15084382.post-86794975491683139122011-04-26T21:51:00.000-07:002011-04-26T21:51:43.151-07:00Using a Canon Pixma MX882 All-In-One with Ubuntu 10.10Are you thinking about buying a <a href="http://www.amazon.com/Canon-MX882-Wireless-Printer-4894B002/dp/B004HO58UW?ie=UTF8&tag=blogkw-20&link_code=btl&camp=213689&creative=392969" target="_blank">Canon Pixma MX882 Wireless Office All-In-One Printer</a><img alt="" border="0" height="1" src="http://www.assoc-amazon.com/e/ir?t=blogkw-20&l=btl&camp=213689&creative=392969&o=1&a=B004HO58UW" style="border: none !important; margin: 0px !important; padding: 0px !important;" width="1" /> and wondering if it will work with your Ubuntu computer? Although Canon does not make this clear in any way, the answer is <b>YES</b>!<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiF_G7tgx54xbDhSGR4fMejcNcUV7QAegRjwdqYTdSa_bTF33EwRtQPDoBgPNnnm8l75yNGoo-9woyKne81pjfEbd5VYqNH-Vuq-2Zv0EL3VpVzCvN44f_-hjGdWEzXNkQnMNfb1A/s1600/UbuntuLogo.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="50" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiF_G7tgx54xbDhSGR4fMejcNcUV7QAegRjwdqYTdSa_bTF33EwRtQPDoBgPNnnm8l75yNGoo-9woyKne81pjfEbd5VYqNH-Vuq-2Zv0EL3VpVzCvN44f_-hjGdWEzXNkQnMNfb1A/s200/UbuntuLogo.png" width="200" /></a></div><div class="separator" style="clear: both; text-align: center;"><b><span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif; font-size: 50px;">+</span></b></div><div class="separator" style="clear: both; text-align: center;"><a href="http://www.amazon.com/Canon-MX882-Wireless-Printer-4894B002/dp/B004HO58UW?ie=UTF8&tag=blogkw-20&link_code=btl&camp=213689&creative=392969" imageanchor="1" style="margin-left: 1em; margin-right: 1em;" target="_blank"><img border="0" height="131" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAhFQReDQkp1E8UZPNrEz7QyhMQH-gmfwUhGNd12J00T72X__K1hKodhqdLvscn5xIYWrs31X6TcR8diuaIivoBhTapYOTpI_xQnlZbXJS-8bn3tvXrusoJdFmAR4w2zF0qXNE-w/s200/mx882.jpg" width="200" /></a></div><br />
Instead of using software that comes on a CD with the printer, you'll have to download and install drivers yourself. They are not easy to find if you live in the US since they're only available on European and Asian Canon websites. I'll tell you how to download and install them.<br />
<h2>Printing</h2><h3>Finding and installing the drivers</h3><ol><li>Visit the <a href="http://software.canon-europe.com/software/0040867.asp">Linux IJ Printer Driver</a> page on the Canon Europe web site.</li>
<li>Click the <b>Linux IJ Printer Driver MX880 series.tar</b> link in the Downloads section to download the 7299.5 kb tarball.</li>
<li>Inside the tarball, find and unpack <b>cnijfilter-mx880series-3.50-1-deb.tar.gz</b>.</li>
<li>Inside the resulting <b>cnijfilter-mx880series-3.50-1-deb/packages</b> directory, locate and double click <b>cnijfilter-common_3.50-1_i386.deb</b> and <b>cnijfilter-mx880series_3.50-1_i386.deb</b> in that order. Ubuntu will guide you through the installation. </li>
</ol>Note: The guide that came with this driver asks you to run the <b>install.sh</b> program, but it didn't work for me. When I ran it, I got an error: <i>An error occurred. The package management system cannot be identified.</i><br />
<h3>Adding the printer</h3><ol><li>From Ubuntu's menu, select: <b>System</b>, <b>Administration</b>, then <b>Printing</b>.</li>
<li>From Printing window that opens, select <b>Add</b>.</li>
<li>After a few seconds, you should see a <b>Canon MX880</b> printer show up under <b>Network Printer</b>.</li>
<li>Select it and click <b>Forward</b>.</li>
<li>Finish entering your printer <b>Name</b>, <b>Description</b>, and <b>Location</b>.</li>
</ol><h2>Scanning</h2><h3>Finding and installing the drivers</h3><ol><li>Visit the <a href="http://software.canon-europe.com/software/0040873.asp">Linux IJ Scanner Driver</a> page on the Canon Europe web site.</li>
<li>Click the <b>Linux IJ Scanner Driver MX880 series.tar</b> link in the Downloads section to download the 3072 kb tarball.</li>
<li>Inside the tarball, find and unpack <b>scangearmp-mx880series-1.70-1-deb.tar.gz</b>.</li>
<li>Inside the resulting <b>scangearmp-mx880series-1.70-1-deb/packages</b> directory, locate and double click <b>scangearmp-common_1.70-1_i386.deb</b> and <b>scangearmp-mx880series_1.70-1_i386.deb</b> in that order. Ubuntu will guide you through the installation. </li>
</ol>Note: The guide that came with this driver asks you to run the <b>install.sh</b> program, but it didn't work for me. When I ran it, I got an error: <i>An error occurred. The package management system cannot be identified.</i><br />
<ol></ol><h3>Scan Gear MP</h3>With the drivers, an app called Scan Gear MP is also installed. This app serves as an interface to your scanner and has a Basic Mode:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZOzV50PdXzBC4OxIr4f6M0bcAKiy85geobyRDR8_n3yIhILP3pMCpvprSNamRz0gIMVLgbjqvxk0OAuxnIUYQ661otk3x-tlHHq8eCthZSQVqQ8hVKxWM1WBDGiwgursg2_0a1Q/s1600/scangear-basic.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZOzV50PdXzBC4OxIr4f6M0bcAKiy85geobyRDR8_n3yIhILP3pMCpvprSNamRz0gIMVLgbjqvxk0OAuxnIUYQ661otk3x-tlHHq8eCthZSQVqQ8hVKxWM1WBDGiwgursg2_0a1Q/s320/scangear-basic.png" width="306" /></a></div><br />
And an Advanced Mode:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjibUeWVCX-yPBDsFKliup2P8MKlnb1UAut3ic73gFSIjB-XivHtcHIPW1FSSX2YpV08768bsWGaxsGFqZPTYCGu7bkIybhebRBIglkMqtJbcRkfjEqLY5SXvdKWITSILCkxMIybg/s1600/scan-gear-advanced.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjibUeWVCX-yPBDsFKliup2P8MKlnb1UAut3ic73gFSIjB-XivHtcHIPW1FSSX2YpV08768bsWGaxsGFqZPTYCGu7bkIybhebRBIglkMqtJbcRkfjEqLY5SXvdKWITSILCkxMIybg/s320/scan-gear-advanced.png" width="306" /></a></div><br />
You can launch the app from the terminal by typing <b>scangearmp</b> and it is also available within <a href="http://www.gimp.org/">Gimp</a> by selecting <b>File</b>, <b>Create</b>,<b> Scan Gear MP...</b><br />
<b><br />
</b><br />
I have not yet figure out a way to use the scanner via <a href="https://help.ubuntu.com/community/XSane">XSane</a>. I'd love to hear comments about whether this is possible and how to do it. Without XSane support, I can't use familiar programs such as <a href="http://bobthegnome.blogspot.com/2009/12/introducing-simple-scan.html">SimpleScan</a> and <a href="http://gscan2pdf.sourceforge.net/">gscan2pdf</a>.<br />
<h3>VueScan</h3>One more thing to mention. Before I figured out Canon made drivers for this scanner, I came across a program called <a href="http://www.hamrick.com/">VueScan</a> which claimed to <a href="http://www.hamrick.com/vuescan/canon_mx880.html">support MX880 series printers</a> on Linux via the network without installing any drivers at all. It took seconds to download, launch, and see that this program could communicate with my MX882 scanner with ease! It may be worth the $79.95 if you can't get Canon's drivers to work.<br />
<br />
Happy printing, scanning, copying, and faxing!Ken Weinerhttp://www.blogger.com/profile/12369783173503766970noreply@blogger.com54tag:blogger.com,1999:blog-15084382.post-17563636252281311502011-02-03T01:02:00.000-08:002011-02-03T01:02:15.163-08:00Edit Remote EC2 Text Files with TextWranglerThis post explains how to use <a href="http://www.barebones.com/products/textwrangler/">TextWrangler</a> on a Mac to edit text files that live on a remote <a href="http://aws.amazon.com/ec2/">Amazon EC2</a> instance with <a href="http://www.ubuntu.com/">Ubuntu</a>.<br />
<br />
I assume you already know how to SSH to Amazon using an Identity File:<br />
<br />
<pre class="brush: plain">ssh -i ~ec2-keys/id_your-keypair ubuntu@ec2-public-dns-name.amazonaws.com</pre><br />
You can use a similar command to connect to your EC2 instance via SFTP:<br />
<br />
<pre class="brush: plain">sftp -o IdentityFile=eec2-keys/id_your-keypair ubuntu@ec2-public-dns-name.amazonaws.com</pre><br />
TextWrangler allows you to open a file from an SFTP server, but it doesn't allow you to configure an Identity File as you did when SSHing or SFTPing from the command line. To work around this limitation, you simply have to configure your SSH client so that it knows the Identity File you want to use. Create ~/.ssh/config if it doesn't already exist and add a line specifying your Identity File location:<br />
<br />
<pre class="brush: plain">echo 'IdentityFile ~ec2-keys/id_your-keypair' >> ~/.ssh/config
</pre><br />
Now you're ready to use TextWrangler to connect to your server and browse files. Choose: File -> Open from FTP/SFTP Server... Then enter your server publisher DNS name, check the SFTP box and enter <b>ubuntu</b> as the User name. You can leave the Password: field blank.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhd09v187iu1rliWQz8KwGbXjGUios3z5OCKv5KQTGWH8PilJSDgTdVLImB3-07SDvwOmuw7xslQ7WS2hNbFPiOCWATBOtJ3B4FeiaJyohF2lv5DmlW2dl5EeK9qNYTg1gFRK2Gcg/s1600/Picture+1.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhd09v187iu1rliWQz8KwGbXjGUios3z5OCKv5KQTGWH8PilJSDgTdVLImB3-07SDvwOmuw7xslQ7WS2hNbFPiOCWATBOtJ3B4FeiaJyohF2lv5DmlW2dl5EeK9qNYTg1gFRK2Gcg/s1600/Picture+1.png" /></a></div><br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
After you hit connect, you TextWrangler will allow you to browse the file system of your EC2 instance, choose a file, and edit it. When you save the file, it will update directly on the remote EC2 instance. That's all there is to it!Ken Weinerhttp://www.blogger.com/profile/12369783173503766970noreply@blogger.com11tag:blogger.com,1999:blog-15084382.post-47284253251241287422010-10-27T01:08:00.000-07:002010-10-27T01:15:28.795-07:00Monitor HBase & Hadoop with Ganglia on EC2<div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"><a href="http://ganglia.sourceforge.net/logo_small.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="91" src="http://ganglia.sourceforge.net/logo_small.jpg" width="200" /></a></div>This post is a recipe on setting up <a href="http://ganglia.sourceforge.net/">Ganglia</a> to monitor an <a href="http://hbase.apache.org/">HBase</a> and <a href="http://hadoop.apache.org/">Hadoop</a> cluster on the <a href="http://www.ubuntu.com/server">Ubuntu</a> OS on <a href="http://aws.amazon.com/ec2/">Amazon EC2</a>. Ganglia is a monitoring system for grids and clusters consisting of the following 3 components:<br />
<br />
<b>gmond</b><br />
A <b>G</b>anglia <b>Mon</b>itoring <b>D</b>aemon (gmond) runs on each node in the cluster and collects statistics from the node it runs on as well as other nodes in the cluster. Normally it is a <a href="http://en.wikipedia.org/wiki/Multicast">multicast</a> system where each gmond node receives data from its peers. However, since Amazon EC2 does not support multicast at this time, you must setup Ganglia Monitoring Daemons in <a href="http://en.wikipedia.org/wiki/Unicast">unicast</a> mode where each node in a cluster is configured to send its data to one pre-designated node.<br />
<br />
<b>gmetad</b><br />
A <b>G</b>anglia <b>Meta</b> <b>D</b>aemon (gmetad) runs for each grid and collects data from the Ganglia Monitoring Daemons, one from each cluster. It stores the data it collects on the file system. We'll only be configuring one grid and therefore one gmetad. We'll be running gmetad from the same node that the PHP Web Front End is installed on.<br />
<br />
<b>PHP Web Front End</b><br />
A <a href="http://www.php.net/">PHP</a> application reads the data and provides a UI to visualize the data over time with pretty graphs. <a href="http://monitor.millennium.berkeley.edu/">Example from UC Berkeley</a>.<br />
<br />
<span class="Apple-style-span" style="font-size: x-large;">Approach</span><br />
Our HBase cluster has one Master node (with Hadoop's Name Node and Job Tracker) and the rest Region Server nodes (each with a Hadoop Data Node and Task Tracker). Since we must use Ganglia in unicast mode on EC2, we need to choose one of these nodes to receive data from each of the other nodes. We'll configure each Region Server gmond to send data to the gmond running on the Master. A separate node will be used to run gmetad and the PHP web front end. The gmetad will be configured to poll the Master's gmond for aggregated cluster data.<br />
<br />
Getting the right version of Ganglia is important because of compatibility issues with Hadoop and HBase's Ganglia clients. We're using HBase 0.20.6 and Hadoop 0.20.2. Therefore, we're going to use Ganglia 3.0.7, the latest of 3.0.x at the time of writing. You could use the latest Ganglia 3.1.x if you're willing to apply the patch found in <a href="https://issues.apache.org/jira/browse/HADOOP-4675">HADOOP-4675</a> to your Hadoop installation.<br />
<br />
<span class="Apple-style-span" style="font-size: x-large;">Setting up gmond</span><br />
Add a ganglia user.<br />
<pre class="brush: plain">adduser --disabled-login --no-create-home ganglia
</pre>Download and unpack Ganglia 3.0.7.<br />
<pre class="brush: plain">wget http://downloads.sourceforge.net/project/ganglia/ganglia%20monitoring%20core/3.0.7%20%28Fossett%29/ganglia-3.0.7.tar.gz
tar -xzvf ganglia-3.0.7.tar.gz -C /opt
rm ganglia-3.0.7.tar.gz
</pre>Install dependencies<br />
<pre class="brush: plain">apt-get -y install build-essential libapr1-dev libconfuse-dev libexpat1-dev python-dev
</pre><br />
Compile and install.<br />
<pre class="brush: plain">cd /opt/ganglia-3.0.7
./configure
make && make install
</pre>Generate a default config file.<br />
<pre class="brush: plain">gmond --default_config > /etc/gmond.conf
</pre><br />
Configure /etc/gmond.conf<br />
<br />
Modify the globals.<br />
<pre class="brush: plain">globals {
user = ganglia
}
</pre>Define the cluster.<br />
<pre class="brush: plain">cluster {
name = HBase
owner = "Your Company"
latlong = "N34.02 W118.45"
url = "http://yourcompany.com/"
}
</pre>Disable multicast and define the host, the HBase master, where nodes in the cluster send data.<br />
<pre class="brush: plain">udp_send_channel {
# mcast_join = 239.2.11.71
host = master.yourcompany.com
port = 8649
ttl = 1
}
udp_recv_channel {
# mcast_join = 239.2.11.71
port = 8649
# bind = 239.2.11.71
}
</pre><br />
Run gmond:<br />
<pre class="brush: plain">gmond
</pre><br />
Note: As far as I know, there is no way to stop gmond other than killing the process.<br />
<br />
You can test each gmond node to make sure it is working. From each node:<br />
<pre class="brush: plain">telnet localhost 8649
</pre>You should see XML output.<br />
<br />
Once gmond is installed and running on each node, move on to setup gmetad.<br />
<br />
<span class="Apple-style-span" style="font-size: x-large;">Setting up gmetad</span><br />
We're going to setup a new EC2 instance to run gmetad and the PHP web front end. A <a href="http://blog.9minutesnooze.com/amazon-ec2-micro-instances-t1micro/">t1.micro</a> should be sufficient for modest clusters. gmetad will be configured to poll the gmond running on the HBase master for aggregated cluster data.<br />
<br />
Add a ganglia user.<br />
<pre class="brush: plain">adduser --disabled-login --no-create-home ganglia
</pre>Download and unpack Ganglia 3.0.7.<br />
<pre class="brush: plain">wget http://downloads.sourceforge.net/project/ganglia/ganglia%20monitoring%20core/3.0.7%20%28Fossett%29/ganglia-3.0.7.tar.gz
tar -xzvf ganglia-3.0.7.tar.gz -C /opt
rm ganglia-3.0.7.tar.gz
</pre>Install dependencies<br />
<pre class="brush: plain">apt-get -y install build-essential libapr1-dev libconfuse-dev libexpat1-dev python-dev librrd2-dev
</pre>Compile and install.<br />
<pre class="brush: plain">cd /opt/ganglia-3.0.7
./configure
make && make install
</pre>Copy the default config file.<br />
<pre class="brush: plain">cp /opt/ganglia-3.0.7/gmetad/gmetad.conf /etc/gmetad.conf
</pre><br />
Configure /etc/gmetad.conf<br />
<pre class="brush: plain">setuid_username "ganglia"
data_source "HBase" master.yourcompany.com
gridname "YourCompany"
</pre>Create directories where Ganglia will save its data.<br />
<pre class="brush: plain">mkdir /var/lib/ganglia
mkdir /var/lib/ganglia/rrds/
chown -R ganglia:ganglia /var/lib/ganglia/
</pre>Run gmetad:<br />
<pre class="brush: plain">gmetad
</pre>For troubleshooting, it might be helpful not to daemonize gmetad:<br />
<pre class="brush: plain">gmetad -d 1
</pre>Note: As far as I know, there is no way to stop gmetad other than killing the process.<br />
<br />
<span class="Apple-style-span" style="font-size: x-large;">Setting up the PHP Web Front End</span><br />
Install Apache and PHP libraries:<br />
<pre class="brush: plain">apt-get -y install rrdtool apache2 php5-mysql libapache2-mod-php5 php5-gd
</pre>Copy PHP web app into Apache's HTML directory:<br />
<pre class="brush: plain">cp -r /opt/ganglia-3.0.7/web /var/www/ganglia
</pre>Restart Apache:<br />
<pre class="brush: plain">/etc/init.d/apache2 restart
</pre><br />
You should now be able to visit the Ganglia console on http://ganglia.yourcompany.com/ganglia and see pretty graphs and charts for machine metrics like load, memory, disk use, etc.<br />
<br />
<span class="Apple-style-span" style="font-size: x-large;">Configuring Hadoop and HBase</span><br />
The next step is to configure Hadoop and HBase to start sending metrics to the master gmond. Detailed instructions are given <a href="http://wiki.apache.org/hadoop/GangliaMetrics">here</a> and <a href="http://hbase.apache.org/docs/current/metrics.html">here</a> for Hadoop and HBase respectively.<br />
<br />
Here's what we end up with inside HBase's conf/hadoop-metrics.properties:<br />
<pre class="brush: plain">hbase.class=org.apache.hadoop.metrics.ganglia.GangliaContext
hbase.period=10
hbase.servers=master.yourcompany.com:8649
jvm.class=org.apache.hadoop.metrics.ganglia.GangliaContext
jvm.period=10
jvm.servers=master.yourcompany.com:8649
rpc.class=org.apache.hadoop.metrics.ganglia.GangliaContext
rpc.period=10
rpc.servers=master.yourcompany.com:8649
</pre><br />
And inside Hadoop's conf/hadoop-metrics.properties:<br />
<pre class="brush: plain">dfs.class=org.apache.hadoop.metrics.ganglia.GangliaContext
dfs.period=10
dfs.servers=master.yourcompany.com:8649
mapred.class=org.apache.hadoop.metrics.ganglia.GangliaContext
mapred.period=10
mapred.servers=master.yourcompany.com:8649
jvm.class=org.apache.hadoop.metrics.ganglia.GangliaContext
jvm.period=10
jvm.servers=master.yourcompany.com:8649
</pre><br />
Once the hadoop-metrics.properties files are modified on all nodes in your cluster, you'll need to restart HBase and Hadoop.<br />
<br />
<span class="Apple-style-span" style="font-size: x-large;">Metrics</span><br />
After restarting, you should see the following metrics show up in Ganglia for your HBase and Hadoop cluster:<br />
<pre class="brush: plain">hbase.regionserver.blockCacheCount
hbase.regionserver.blockCacheFree
hbase.regionserver.blockCacheHitRatio
hbase.regionserver.blockCacheSize
hbase.regionserver.compactionQueueSize
hbase.regionserver.fsReadLatency_avg_time
hbase.regionserver.fsReadLatency_num_ops
hbase.regionserver.fsSyncLatency_avg_time
hbase.regionserver.fsSyncLatency_num_ops
hbase.regionserver.fsWriteLatency_avg_time
hbase.regionserver.fsWriteLatency_num_ops
hbase.regionserver.memstoreSizeMB
hbase.regionserver.regions
hbase.regionserver.requests
hbase.regionserver.storefileIndexSizeMB
hbase.regionserver.storefiles
hbase.regionserver.stores
rpc.metrics.RpcProcessingTime_avg_time
rpc.metrics.RpcProcessingTime_num_ops
rpc.metrics.RpcQueueTime_avg_time
rpc.metrics.RpcQueueTime_num_ops
rpc.metrics.addColumn_avg_time
rpc.metrics.addColumn_num_ops
rpc.metrics.checkAndPut_avg_time
rpc.metrics.checkAndPut_num_ops
rpc.metrics.close_avg_time
rpc.metrics.close_num_ops
rpc.metrics.createTable_avg_time
rpc.metrics.createTable_num_ops
rpc.metrics.deleteColumn_avg_time
rpc.metrics.deleteColumn_num_ops
rpc.metrics.deleteTable_avg_time
rpc.metrics.deleteTable_num_ops
rpc.metrics.delete_avg_time
rpc.metrics.delete_num_ops
rpc.metrics.disableTable_avg_time
rpc.metrics.disableTable_num_ops
rpc.metrics.enableTable_avg_time
rpc.metrics.enableTable_num_ops
rpc.metrics.exists_avg_time
rpc.metrics.exists_num_ops
rpc.metrics.getClosestRowBefore_avg_time
rpc.metrics.getClosestRowBefore_num_ops
rpc.metrics.getClusterStatus_avg_time
rpc.metrics.getClusterStatus_num_ops
rpc.metrics.getHServerInfo_avg_time
rpc.metrics.getHServerInfo_num_ops
rpc.metrics.getOnlineRegionsAsArray_avg_time
rpc.metrics.getOnlineRegionsAsArray_num_ops
rpc.metrics.getProtocolVersion_avg_time
rpc.metrics.getProtocolVersion_num_ops
rpc.metrics.getRegionInfo_avg_time
rpc.metrics.getRegionInfo_num_ops
rpc.metrics.getRegionsAssignment_avg_time
rpc.metrics.getRegionsAssignment_num_ops
rpc.metrics.get_avg_time
rpc.metrics.get_num_ops
rpc.metrics.incrementColumnValue_avg_time
rpc.metrics.incrementColumnValue_num_ops
rpc.metrics.isMasterRunning_avg_time
rpc.metrics.isMasterRunning_num_ops
rpc.metrics.lockRow_avg_time
rpc.metrics.lockRow_num_ops
rpc.metrics.modifyColumn_avg_time
rpc.metrics.modifyColumn_num_ops
rpc.metrics.modifyTable_avg_time
rpc.metrics.modifyTable_num_ops
rpc.metrics.next_avg_time
rpc.metrics.next_num_ops
rpc.metrics.openScanner_avg_time
rpc.metrics.openScanner_num_ops
rpc.metrics.put_avg_time
rpc.metrics.put_num_ops
rpc.metrics.regionServerReport_avg_time
rpc.metrics.regionServerReport_num_ops
rpc.metrics.regionServerStartup_avg_time
rpc.metrics.regionServerStartup_num_ops
rpc.metrics.shutdown_avg_time
rpc.metrics.shutdown_num_ops
rpc.metrics.unlockRow_avg_time
rpc.metrics.unlockRow_num_ops
dfs.datanode.blockChecksumOp_avg_time
dfs.datanode.blockChecksumOp_num_ops
dfs.datanode.blockReports_avg_time
dfs.datanode.blockReports_num_ops
dfs.datanode.block_verification_failures
dfs.datanode.blocks_read
dfs.datanode.blocks_removed
dfs.datanode.blocks_replicated
dfs.datanode.blocks_verified
dfs.datanode.blocks_written
dfs.datanode.bytes_read
dfs.datanode.bytes_written
dfs.datanode.copyBlockOp_avg_time
dfs.datanode.copyBlockOp_num_ops
dfs.datanode.heartBeats_avg_time
dfs.datanode.heartBeats_num_ops
dfs.datanode.readBlockOp_avg_time
dfs.datanode.readBlockOp_num_ops
dfs.datanode.readMetadataOp_avg_time
dfs.datanode.readMetadataOp_num_ops
dfs.datanode.reads_from_local_client
dfs.datanode.reads_from_remote_client
dfs.datanode.replaceBlockOp_avg_time
dfs.datanode.replaceBlockOp_num_ops
dfs.datanode.writeBlockOp_avg_time
dfs.datanode.writeBlockOp_num_ops
dfs.datanode.writes_from_local_client
dfs.datanode.writes_from_remote_client
jvm.metrics.gcCount
jvm.metrics.gcTimeMillis
jvm.metrics.logError
jvm.metrics.logFatal
jvm.metrics.logInfo
jvm.metrics.logWarn
jvm.metrics.memHeapCommittedM
jvm.metrics.memHeapUsedM
jvm.metrics.memNonHeapCommittedM
jvm.metrics.memNonHeapUsedM
jvm.metrics.threadsBlocked
jvm.metrics.threadsNew
jvm.metrics.threadsRunnable
jvm.metrics.threadsTerminated
jvm.metrics.threadsTimedWaiting
jvm.metrics.threadsWaiting
</pre><br />
As you can see, the metrics are incredibly useful for understanding the health of your HBase and Hadoop cluster over time.Ken Weinerhttp://www.blogger.com/profile/12369783173503766970noreply@blogger.com8tag:blogger.com,1999:blog-15084382.post-90569378903435649942009-11-30T21:52:00.000-08:002009-11-30T22:12:35.836-08:00Swivel4J - A New Java Client for SwivelAt work, we were looking for a simple way to visualize business data without having to build and host it ourselves. This led us to <a href="http://business.swivel.com/">Swivel</a> (the <span style="font-style: italic;">new Swivel</span> as they call it which is geared towards private data shared within an organization). With Swivel, we can upload our data, create pretty charts and graphs, and share them privately within our company.<br /><br />Swivel has a <a href="http://wiki.github.com/swivel/api">REST API</a> for managing the charts. Though not difficult, we found it a little unwieldy to have to use an <a href="http://hc.apache.org/httpclient-3.x/">HTTP client</a> to setup each API call. This naturally led to a small library that wrapped the REST API calls in a native Java API.<br /><br />We decided to make this library available to everyone as <a href="http://code.google.com/p/swivel4j/">Swivel4J</a> which is open source and hosted on Google Code. We hope this makes it easier for Java, Groovy, and Scala developers to get started with Swivel and promotes the use of Swivel in general.<br /><br />Please try it out and give feedback, submit patches, etc.Ken Weinerhttp://www.blogger.com/profile/12369783173503766970noreply@blogger.com0tag:blogger.com,1999:blog-15084382.post-46776858598974275592009-09-12T20:19:00.000-07:002009-09-12T21:16:52.333-07:00Amazon ELB - Capturing Client IP AddressIf you're using Amazon EC2's <a href="http://aws.amazon.com/elasticloadbalancing/">Elastic Load Balancer</a> (ELB) for load balancing web applications, you may have noticed that in your web access logs, the remote host IP address is the same for every request. The IP address you see is the private IP address of the load balancer.<br /><br />If you want to see the IP address of the client (called remote host in access log documentation), you'll need to look at the value of the <a href="http://en.wikipedia.org/wiki/X-Forwarded-For">X-Forwarded-For</a> request header which ELB populates when it forwards the request.<br /><br />This can be achieved in an Apache access log by using the syntax: <pre>%{X-Forwarded-For}i</pre>You Apache log format would then look something like this:<br /><pre class="source-code"><code>LogFormat "\"%{X-Forwarded-For}i\" %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" combined-elb<br />CustomLog log/acces_log combined-elb</code></pre>See <a href="http://httpd.apache.org/docs/1.3/mod/mod_log_config.html#formats">Apache Custom Log Formats</a><br /><br />If you're using a Tomcat application server, you could define an access log Valve like this:<br /><pre class="source-code"><code><Valve className="org.apache.catalina.valves.AccessLogValve"<br /> directory="logs" prefix="access_log." suffix=".txt"<br /> pattern="%{X-Forwarded-For}i %l %u %t &quot;%r&quot; %s %b &quot;%{Referer}i&quot; &quot;%{User-Agent}i&quot;"<br /> resolveHosts="false"/></code></pre>See <a href="http://tomcat.apache.org/tomcat-6.0-doc/config/valve.html">Tomcat 6 Valve Configuration Reference</a>.<br /><br />If you're trying to capture the client IP address within your application code, simply use whatever API you have to read the X-Forwarded-For request header. For example in Java use the HttpServletRequest:<br /><pre class="source-code"><code>String clientIpAddress = request.getHeader("X-Forwarded-For");</code></pre>instead of<pre class="source-code"><code>String clientIpAddress = request.getRemoteAddr();</code></pre>Ken Weinerhttp://www.blogger.com/profile/12369783173503766970noreply@blogger.com10tag:blogger.com,1999:blog-15084382.post-8203880726489117322009-08-31T22:49:00.000-07:002015-12-20T17:03:20.175-08:00Serving Gzipped Javascript Files from Amazon CloudFrontIt is well-known that using a <a href="http://developer.yahoo.net/blog/archives/2007/04/high_performanc_1.html">content delivery network (CDN)</a> and <a href="http://developer.yahoo.net/blog/archives/2007/07/high_performanc_3.html">compressing an HTTP response</a> with gzip can significantly improve the performance and reduce the cost of a web site. If your CDN is Amazon's <a href="http://aws.amazon.com/cloudfront/">CloudFront</a>, you'll face difficulties serving gzipped content to browsers that support it. Most web servers are able to examine the HTTP request headers sent by the browser and dynamically choose whether to deliver compressed or uncompressed content. CloudFront, however, <a href="http://developer.amazonwebservices.com/connect/thread.jspa?messageID=107725&#107725">does not yet offer this feature</a>.<br />
<br />
People have overcome this problem by manually inspecting the <i>Accept-Encoding </i>request header for a dynamically served page and writing references to either original or compressed files accordingly using a naming convention like myscript.js and myscript.js.gz for regular and compressed files respectively.<br />
<br />
If all your pages are statically served from CloudFront, however, there is no opportunity to inspect the request headers. Javascript running on a statically served page has no ability to ask the browser if it supports gzipped content. We found ourselves in this situation and resorted to the following solution to determine if the browser supports gzip:<br />
<br />
1) Create a small gzipped file, gzipcheck.js.jgz, and make it available in CloudFront. This file should contain one line of code:<br />
<pre class="brush: text">gzipEnabled = true;</pre>
<br />
2) Use the following code to attempt to load and run this file. You'll probably want to put it in the HTML HEAD section before any other Javascript code.<br />
<pre class="brush: js"><script type="text/javascript" src="gzipcheck.js.jgz">
</script>
</pre>
<br />
If the file loads, it sets a flag, gzipEnabled, that indicates whether or not the browser supports gzip.<br />
<br />
Use the result to drive a file naming convention for references to other static files. For example, you can upload and reference each compressed Javascript file with an additional .jgz extension. Why .jgz instead of .gz? Because of an <a href="http://www.webveteran.com/blog/index.php/web-coding/coldfusion/fix-for-safari-and-gzip-compressed-javascripts/">annoying limitation of Safari</a>.<br />
<br />
When you upload your files to S3/CloudFront, make sure to set the proper HTTP response headers on your files that end in .jgz:<br />
<pre class="brush: text">Content-Encoding = gzip
Content-Type = application/x-javascript
</pre>
<br />
And if you want browsers to cache your files forever (almost):<br />
<pre class="brush: text">Cache-Control = max-age=315360000
Expires = Tue, 31 Dec 2019 20:00:00 GMT
</pre>
<br />
Thanks to <a href="http://www.linkedin.com/in/ricardoe">Ricardo Rangel</a> who helped design and code this solution.<br />
<span style="background-color: yellow;"><br /></span>
<span style="background-color: yellow;"><b><u>Update</u></b></span><br />
<span style="background-color: yellow;"><b><u><br /></u></b></span>
<span style="background-color: yellow;">As of December 20, 2015, Amazon Web Services announced support for Gzipped CloudFront files! See <a href="http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/ServingCompressedFiles.html">Serving Compressed Files</a> from their developer guide.</span>Ken Weinerhttp://www.blogger.com/profile/12369783173503766970noreply@blogger.com10tag:blogger.com,1999:blog-15084382.post-79689597929952932642009-04-08T09:49:00.000-07:002009-04-10T22:43:36.393-07:00Ubuntu License Plate on the Santa Monica Freeway<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnv96VGLitvIHUZ0ghNIFyxQ1Nojz6eAdXOIB9QqrH23BKYB8M0RSwTWMS4hqBIy9rN_eopE7cTM9MKfos7SQilInF5m38PeZfUl4LHm_ENCZ7yb1Yx9Lba7XcG8Wx_Wx0Y38rAg/s1600-h/ubuntu-plate-10-fwy.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnv96VGLitvIHUZ0ghNIFyxQ1Nojz6eAdXOIB9QqrH23BKYB8M0RSwTWMS4hqBIy9rN_eopE7cTM9MKfos7SQilInF5m38PeZfUl4LHm_ENCZ7yb1Yx9Lba7XcG8Wx_Wx0Y38rAg/s400/ubuntu-plate-10-fwy.jpg" alt="" id="BLOGGER_PHOTO_ID_5322389540027660578" border="0" /></a><br />I came across this car while driving eastbound on the Santa Monica Freeway this past Saturday. Do you think the license plate is referring to the <a href="http://www.ubuntu.com/">Ubuntu Linux OS</a> or just the <a href="http://en.wikipedia.org/wiki/Ubuntu_%28philosophy%29">Ubuntu philosophy</a>?<br /><br />It also had some funny stickers and decals:<br />* <a href="http://www.amazon.com/gp/product/B0013O5VOW?ie=UTF8&tag=blogkw-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=B0013O5VOW">Evolve FISH Logo Decorative Silver Car Emblem</a><img src="http://www.assoc-amazon.com/e/ir?t=blogkw-20&l=as2&o=1&a=B0013O5VOW" alt="" style="border: medium none ! important; margin: 0px ! important;" width="1" border="0" height="1" /><br />* <a href="http://www.amazon.com/gp/product/031604041X?ie=UTF8&tag=blogkw-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=031604041X">Goodnight Bush: A Parody</a><img src="http://www.assoc-amazon.com/e/ir?t=blogkw-20&l=as2&o=1&a=031604041X" alt="" style="border: medium none ! important; margin: 0px ! important;" width="1" border="0" height="1" /><br />* <a href="http://www.zazzle.com/got_hope_bumper_sticker-128712145080642676">Got Hope Bumper Sticker</a>Ken Weinerhttp://www.blogger.com/profile/12369783173503766970noreply@blogger.com1tag:blogger.com,1999:blog-15084382.post-41377973230246405132009-01-14T21:50:00.000-08:002009-01-14T22:57:44.590-08:00Products I Can't Live Without - 2009Inspired by <a href="http://www.techcrunch.com/2009/01/04/2009-products-i-cant-live-without/">this post</a> from Michael Arrington of TechCrunch, I thought it would be interesting to make my own annual list of products and services that I can't live without. Here we go for 2009 (in the order that they came to mind):<br /><br /><a href="http://mail.google.com/">Gmail</a>, <a href="http://www.google.com/calendar/">Google Calendar</a>, <a href="http://www.rememberthemilk.com/">Remember The Milk</a>, <a href="http://www.apple.com/iphone/">iPhone</a>, <a href="http://f-spot.org/">F-Spot</a>, <a href="http://www.amazon.com/gp/product/B001D1Q7PM?ie=UTF8&tag=kenweiner&linkCode=as2&camp=1789&creative=390957&creativeASIN=B001D1Q7PM">Quicken</a><img src="http://www.assoc-amazon.com/e/ir?t=kenweiner&l=as2&o=1&a=B001D1Q7PM" alt="" style="border: medium none ! important; margin: 0px ! important;" border="0" height="1" width="1" />, <a href="http://www.google.com/reader/">Google Reader</a>, <a href="http://facebook.com/">Facebook</a>, <a href="http://sites.google.com/">Google Sites</a>, <a href="http://flickr.com/">Flickr</a>, <a href="http://itunes.com/">iTunes</a>, <a href="http://twiiter.com/">Twitter</a>, <a href="http://jungledisk.com/">Jungle Disk</a>, <a href="http://getdropbox.com/">Dropbox</a>, <a href="http://delicious.com/">Delicious</a><br /><br /><a href="http://mail.google.com/">Gmail</a><br />I use this every minute every day for both personal and work email (my company uses Google Apps for email and calendar). I just love the user interface and ease of accessing it on the web and the iPhone. Beats the hell out of Outlook for work email.<br /><br /><a href="http://www.google.com/calendar/">Google Calendar</a><br />Again, this is how I keep track of temporal events in my life both at home and at work. I love that I can get text messages with alerts for calendar events.<br /><br /><a href="http://www.rememberthemilk.com/">Remember The Milk</a><br />Ever since reading David Allan's <a href="http://www.amazon.com/gp/product/0142000280?ie=UTF8&tag=kweiner-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0142000280">Getting Things Done</a><img src="http://www.assoc-amazon.com/e/ir?t=kweiner-20&l=as2&o=1&a=0142000280" alt="" style="border: medium none ! important; margin: 0px ! important;" border="0" height="1" width="1" />, I was in search of a tool to put his ideas to work. About a year ago, I settled with Remember The Milk (RTM) and have used it ever since for task management. The user interface is outstanding and I can access it from the web and iPhone. Perhaps the best feature is that it <a href="http://www.rememberthemilk.com/services/gmail/gadget/">integrates</a> perfectly with Gmail as a "Gadget".<br /><a href="http://www.apple.com/iphone/"><br />iPhone</a><br />I don't identify with being an Apple person, but I couldn't resist the lure of the iPhone. It really adds a lot of value to my life as I can manage email, read blogs, listen to Podcasts, use Google Maps, <a href="http://www.tuaw.com/2008/07/19/iphone-101-geocaching-with-an-iphone-3g/">locate GeoCaches</a>, and even SSH to a server at work. Oh, and <a href="http://en.wikipedia.org/wiki/Visual_voicemail">visual voice mail</a> rocks!<br /><a href="http://f-spot.org/"><br />F-Spot</a><br />This <a href="http://www.gnome.org/">GNOME</a> desktop application is what I use to manage photos. It stores photo metadata in a SQLite database which I can easily access if I ever want to export the data somewhere else. It also makes it easy to upload photos to Flickr.<br /><br /><a href="http://www.amazon.com/gp/product/B001D1Q7PM?ie=UTF8&tag=kenweiner&linkCode=as2&camp=1789&creative=390957&creativeASIN=B001D1Q7PM">Quicken</a><img src="http://www.assoc-amazon.com/e/ir?t=kenweiner&l=as2&o=1&a=B001D1Q7PM" alt="" style="border: medium none ! important; margin: 0px ! important;" border="0" height="1" width="1" /><br />I have been using Quicken for years to manage my personal finances. I upgrade it to the latest version every even year, so right now I have Quicken 2008. Honestly, I would love to stop using Quicken and switch to a web-based solution, but I can't find one that is fully-featured enough for me. I just have to have the ability to create arbitrary asset accounts for my wallet (cash), reimbursements, etc. Most web-based services don't offer this yet. I've got my eye on <a href="http://www.mint.com/">Mint</a> which, I have a feeling, will get good enough for me to make the switch one day.<br /><br /><a href="http://www.google.com/reader/">Google Reader</a><br />I read a lot of blogs. I couldn't possibly keep up if I didn't use a blog reader. In late 2008, I switched from <a href="http://www.bloglines.com/">Bloglines</a> to Google Reader because the user interface for Google Reader just kept getting better and eventually it won me over. A big part of this was the excellent user interface of Google Reader on the iPhone.<br /><br /><a href="http://facebook.com">Facebook</a><br />This barely made it to my list. Maybe I could live without it, but I do find myself checking it almost daily because so many of my friends use it and somehow it makes me feel like I'm in touch with all of them without ever really talking to them :). Also, Facebook is the platform I used to develop and launch my book sharing application <a href="http://apps.new.facebook.com/we-read/">We Read</a> which continues to grow slowly, but steadily each day and recently passed 1000 users.<br /><br /><a href="http://sites.google.com/">Google Sites</a><br />This past year I finally committed to using a wiki for my family. I have been using wikis for years for work and open source software projects, and always thought it would be useful for keeping track of personal things like lists of gifts to get people, account information for utilities, financial services, and contractors, etc, etc. I tried setting up and hosting wikis like <a href="http://www.xwiki.org/">XWiki</a> and <a href="http://www.atlassian.com/software/confluence/personal-wiki.jsp">Confluence</a>, but ultimately went with the free, online Google Sites which was <a href="http://www.jot.com/">formerly JotSpot</a>.<br /><br /><a href="http://flickr.com">Flickr</a><br />I purchased the Pro Account and now use Flickr for all my online photo sharing needs. The pro account allows me to upload an unlimited amount of photos for about $25/year. My family depends on this to see the many photos I take of my son as he grows up.<br /><br /><a href="http://itunes.com">iTunes</a><br />I hate the fact that iTunes doesn't run on Linux machines, but I can't resist it because it is really the only good option for managing music and videos on an iPod. I use it daily to load up my iPhone with podcasts.<br /><a href="http://twiiter.com"><br />Twitter</a><br />I use Twitter a lot. I blame Twitter for killing my urge to blog. It is just so much easier to share things 140 characters at a time. I have Twitter linked with Facebook so that each Tweet I send out ends up updating my Facebook status.<br /><br /><a href="http://jungledisk.com">Jungle Disk</a><br />This might be one of the most important services I use. It keeps my music, videos, photos, and other important files backed up on <a href="http://aws.amazon.com/s3/">Amazon's S3</a> network. At only $.15/GB, it ends up being pretty cheap to store a lot of data. This way, if my house ever burns down or someone steals my computers, or I experience a hard disk failure, I will always be able to restore my precious data.<br /><br /><a href="http://getdropbox.com">Dropbox</a><br />I have started storing all files that I access often in a special directory on each computer (home, work, laptop, etc) called the Dropbox. Each directory gets automatically synchronized so I have easy, local, access to the files I need wherever I am. It also makes it extremely easy to share files with other people that use Dropbox.<br /><br /><a href="http://delicious.com">Delicious</a><br />I store all my bookmarks in Delicious and take advantage of its <a href="https://addons.mozilla.org/en-US/firefox/addon/3615">Firefox plugin</a> to easily tag sites and recall sites I've already tagged. I don't do a lot with the social features of Delicious like bookmark sharing, though. Maybe it's just because I don't know which of my friends use Delicious too.<br /><br />Well, there you have it! I can't wait to see how this list compares to the one I'll make in January 2010.Ken Weinerhttp://www.blogger.com/profile/12369783173503766970noreply@blogger.com3