mirror of
https://gitlab.com/news-flash/article_scraper.git
synced 2025-07-07 16:15:32 +02:00
whitespace fixes
This commit is contained in:
parent
2217c3c71a
commit
b541cd73f8
46 changed files with 3808 additions and 2111 deletions
|
@ -1,7 +1,9 @@
|
|||
<article><section id="readability-page-1"><p><strong>So finally you're <a href="http://fakehost/code/2013/testing-frontend-javascript-code-using-mocha-chai-and-sinon/" target="_blank">testing your frontend JavaScript code</a>? Great! The more you
|
||||
<article><section id="readability-page-1">
|
||||
<p><strong>So finally you're <a href="http://fakehost/code/2013/testing-frontend-javascript-code-using-mocha-chai-and-sinon/" target="_blank">testing your frontend JavaScript code</a>? Great! The more you
|
||||
write tests, the more confident you are with your code… but how much precisely?
|
||||
That's where <a href="http://en.wikipedia.org/wiki/Code_coverage" target="_blank">code coverage</a> might
|
||||
help.</strong></p>
|
||||
help.</strong>
|
||||
</p>
|
||||
<p>The idea behind code coverage is to record which parts of your code (functions,
|
||||
statements, conditionals and so on) have been executed by your test suite,
|
||||
to compute metrics out of these data and usually to provide tools for navigating
|
||||
|
@ -21,14 +23,17 @@ help.</strong></p>
|
|||
</blockquote>
|
||||
<p><strong><a href="http://blanketjs.org/" target="_blank">Blanket.js</a></strong> is an <em>easy to install, easy to configure,
|
||||
and easy to use JavaScript code coverage library that works both in-browser and
|
||||
with nodejs.</em></p>
|
||||
with nodejs.</em>
|
||||
</p>
|
||||
<p>Its use is dead easy, adding Blanket support to your Mocha test suite
|
||||
is just matter of adding this simple line to your HTML test file:</p>
|
||||
<pre><code><script src="vendor/blanket.js"
|
||||
data-cover-adapter="vendor/mocha-blanket.js"></script>
|
||||
</code></pre>
|
||||
|
||||
<p>Source files: <a href="https://raw.github.com/alex-seville/blanket/master/dist/qunit/blanket.min.js" target="_blank">blanket.js</a>,
|
||||
<a href="https://raw.github.com/alex-seville/blanket/master/src/adapters/mocha-blanket.js" target="_blank">mocha-blanket.js</a></p>
|
||||
<a href="https://raw.github.com/alex-seville/blanket/master/src/adapters/mocha-blanket.js" target="_blank">mocha-blanket.js</a>
|
||||
</p>
|
||||
<p>As an example, let's reuse the silly <code>Cow</code> example we used
|
||||
<a href="http://fakehost/code/2013/testing-frontend-javascript-code-using-mocha-chai-and-sinon/" target="_blank">in a previous episode</a>:</p>
|
||||
<pre><code>// cow.js
|
||||
|
@ -49,6 +54,7 @@ with nodejs.</em></p>
|
|||
};
|
||||
})(this);
|
||||
</code></pre>
|
||||
|
||||
<p>And its test suite, powered by Mocha and <a href="http://chaijs.com/" target="_blank">Chai</a>:</p>
|
||||
<pre><code>var expect = chai.expect;
|
||||
|
||||
|
@ -73,6 +79,7 @@ describe("Cow", function() {
|
|||
});
|
||||
});
|
||||
</code></pre>
|
||||
|
||||
<p>Let's create the HTML test file for it, featuring Blanket and its adapter
|
||||
for Mocha:</p>
|
||||
<pre><code><!DOCTYPE html>
|
||||
|
@ -97,6 +104,7 @@ describe("Cow", function() {
|
|||
</body>
|
||||
</html>
|
||||
</code></pre>
|
||||
|
||||
<p><strong>Notes</strong>:</p>
|
||||
<ul>
|
||||
<li>Notice the <code>data-cover</code> attribute we added to the script tag
|
||||
|
@ -105,7 +113,9 @@ describe("Cow", function() {
|
|||
be loaded.</li>
|
||||
</ul>
|
||||
<p>Running the tests now gives us something like this:</p>
|
||||
<p><img alt="screenshot" src="http://fakehost/static/code/2013/blanket-coverage.png"></p>
|
||||
<p>
|
||||
<img alt="screenshot" src="http://fakehost/static/code/2013/blanket-coverage.png">
|
||||
</p>
|
||||
<p>As you can see, the report at the bottom highlights that we haven't actually
|
||||
tested the case where an error is raised in case a target name is missing.
|
||||
We've been informed of that, nothing more, nothing less. We simply know
|
||||
|
@ -117,4 +127,6 @@ describe("Cow", function() {
|
|||
sessions
|
||||
and <a href="http://alexgaynor.net/2013/sep/26/effective-code-review/" target="_blank">code reviews</a> —
|
||||
but that's another story.</p>
|
||||
<p><strong>So is code coverage silver bullet? No. Is it useful? Definitely. Happy testing!</strong></p></section></article>
|
||||
<p><strong>So is code coverage silver bullet? No. Is it useful? Definitely. Happy testing!</strong>
|
||||
</p>
|
||||
</section></article>
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
<article><DIV id="readability-page-1"><article role="article"><p>For more than a decade the Web has used XMLHttpRequest (XHR) to achieve
|
||||
<article><DIV id="readability-page-1">
|
||||
<article role="article">
|
||||
<p>For more than a decade the Web has used XMLHttpRequest (XHR) to achieve
|
||||
asynchronous requests in JavaScript. While very useful, XHR is not a very
|
||||
nice API. It suffers from lack of separation of concerns. The input, output
|
||||
and state are all managed by interacting with one object, and state is
|
||||
|
@ -20,49 +22,86 @@
|
|||
</ol>
|
||||
<p>As of this writing, the Fetch API is available in Firefox 39 (currently
|
||||
Nightly) and Chrome 42 (currently dev). Github has a <a href="https://github.com/github/fetch" target="_blank">Fetch polyfill</a>.</p>
|
||||
|
||||
<h2>Feature detection</h2>
|
||||
|
||||
<p>Fetch API support can be detected by checking for <code>Headers</code>,<code>Request</code>, <code>Response</code> or <code>fetch</code> on
|
||||
the <code>window</code> or <code>worker</code> scope.</p>
|
||||
|
||||
<h2>Simple fetching</h2>
|
||||
|
||||
<p>The most useful, high-level part of the Fetch API is the <code>fetch()</code> function.
|
||||
In its simplest form it takes a URL and returns a promise that resolves
|
||||
to the response. The response is captured as a <code>Response</code> object.</p>
|
||||
<DIV><pre>fetch<span>(</span><span>"/data.json"</span><span>)</span>.<span>then</span><span>(</span><span>function</span><span>(</span>res<span>)</span><span>{</span><span>// res instanceof Response == true.</span><span>if</span><span>(</span>res.<span>ok</span><span>)</span><span>{</span>
|
||||
<DIV>
|
||||
<pre>fetch<span>(</span><span>"/data.json"</span><span>)</span>.<span>then</span><span>(</span><span>function</span><span>(</span>res<span>)</span> <span>{</span>
|
||||
<span>// res instanceof Response == true.</span>
|
||||
<span>if</span> <span>(</span>res.<span>ok</span><span>)</span> <span>{</span>
|
||||
res.<span>json</span><span>(</span><span>)</span>.<span>then</span><span>(</span><span>function</span><span>(</span>data<span>)</span> <span>{</span>
|
||||
console.<span>log</span><span>(</span>data.<span>entries</span><span>)</span><span>;</span><span>}</span><span>)</span><span>;</span><span>}</span><span>else</span><span>{</span>
|
||||
console.<span>log</span><span>(</span><span>"Looks like the response wasn't perfect, got status"</span><span>,</span> res.<span>status</span><span>)</span><span>;</span><span>}</span><span>}</span><span>,</span><span>function</span><span>(</span>e<span>)</span><span>{</span>
|
||||
console.<span>log</span><span>(</span><span>"Fetch failed!"</span><span>,</span> e<span>)</span><span>;</span><span>}</span><span>)</span><span>;</span></pre></DIV>
|
||||
console.<span>log</span><span>(</span>data.<span>entries</span><span>)</span><span>;</span>
|
||||
<span>}</span><span>)</span><span>;</span>
|
||||
<span>}</span> <span>else</span> <span>{</span>
|
||||
console.<span>log</span><span>(</span><span>"Looks like the response wasn't perfect, got status"</span><span>,</span> res.<span>status</span><span>)</span><span>;</span>
|
||||
<span>}</span>
|
||||
<span>}</span><span>,</span> <span>function</span><span>(</span>e<span>)</span> <span>{</span>
|
||||
console.<span>log</span><span>(</span><span>"Fetch failed!"</span><span>,</span> e<span>)</span><span>;</span>
|
||||
<span>}</span><span>)</span><span>;</span></pre>
|
||||
</DIV>
|
||||
<p>Submitting some parameters, it would look like this:</p>
|
||||
<DIV><pre>fetch<span>(</span><span>"http://www.example.org/submit.php"</span><span>,</span><span>{</span>
|
||||
<DIV>
|
||||
<pre>fetch<span>(</span><span>"http://www.example.org/submit.php"</span><span>,</span> <span>{</span>
|
||||
method<span>:</span> <span>"POST"</span><span>,</span>
|
||||
headers<span>:</span><span>{</span><span>"Content-Type"</span><span>:</span><span>"application/x-www-form-urlencoded"</span><span>}</span><span>,</span>
|
||||
body<span>:</span><span>"firstName=Nikhil&favColor=blue&password=easytoguess"</span><span>}</span><span>)</span>.<span>then</span><span>(</span><span>function</span><span>(</span>res<span>)</span><span>{</span><span>if</span><span>(</span>res.<span>ok</span><span>)</span><span>{</span>
|
||||
alert<span>(</span><span>"Perfect! Your settings are saved."</span><span>)</span><span>;</span><span>}</span><span>else</span><span>if</span><span>(</span>res.<span>status</span><span>==</span><span>401</span><span>)</span><span>{</span>
|
||||
alert<span>(</span><span>"Oops! You are not authorized."</span><span>)</span><span>;</span><span>}</span><span>}</span><span>,</span><span>function</span><span>(</span>e<span>)</span><span>{</span>
|
||||
alert<span>(</span><span>"Error submitting form!"</span><span>)</span><span>;</span><span>}</span><span>)</span><span>;</span></pre></DIV>
|
||||
headers<span>:</span> <span>{</span>
|
||||
<span>"Content-Type"</span><span>:</span> <span>"application/x-www-form-urlencoded"</span>
|
||||
<span>}</span><span>,</span>
|
||||
body<span>:</span> <span>"firstName=Nikhil&favColor=blue&password=easytoguess"</span>
|
||||
<span>}</span><span>)</span>.<span>then</span><span>(</span><span>function</span><span>(</span>res<span>)</span> <span>{</span>
|
||||
<span>if</span> <span>(</span>res.<span>ok</span><span>)</span> <span>{</span>
|
||||
alert<span>(</span><span>"Perfect! Your settings are saved."</span><span>)</span><span>;</span>
|
||||
<span>}</span> <span>else</span> <span>if</span> <span>(</span>res.<span>status</span> <span>==</span> <span>401</span><span>)</span> <span>{</span>
|
||||
alert<span>(</span><span>"Oops! You are not authorized."</span><span>)</span><span>;</span>
|
||||
<span>}</span>
|
||||
<span>}</span><span>,</span> <span>function</span><span>(</span>e<span>)</span> <span>{</span>
|
||||
alert<span>(</span><span>"Error submitting form!"</span><span>)</span><span>;</span>
|
||||
<span>}</span><span>)</span><span>;</span></pre>
|
||||
</DIV>
|
||||
<p>The <code>fetch()</code> function’s arguments are the same as those passed
|
||||
to the
|
||||
<br><code>Request()</code> constructor, so you may directly pass arbitrarily
|
||||
<br>
|
||||
<code>Request()</code> constructor, so you may directly pass arbitrarily
|
||||
complex requests to <code>fetch()</code> as discussed below.</p>
|
||||
|
||||
<h2>Headers</h2>
|
||||
|
||||
<p>Fetch introduces 3 interfaces. These are <code>Headers</code>, <code>Request</code> and
|
||||
<br><code>Response</code>. They map directly to the underlying HTTP concepts,
|
||||
<br>
|
||||
<code>Response</code>. They map directly to the underlying HTTP concepts,
|
||||
but have
|
||||
<br>certain visibility filters in place for privacy and security reasons,
|
||||
such as
|
||||
<br>supporting CORS rules and ensuring cookies aren’t readable by third parties.</p>
|
||||
<p>The <a href="https://fetch.spec.whatwg.org/#headers-class" target="_blank">Headers interface</a> is
|
||||
a simple multi-map of names to values:</p>
|
||||
<DIV><pre><span>var</span> content <span>=</span><span>"Hello World"</span><span>;</span><span>var</span> reqHeaders <span>=</span><span>new</span> Headers<span>(</span><span>)</span><span>;</span>
|
||||
<DIV>
|
||||
<pre><span>var</span> content <span>=</span> <span>"Hello World"</span><span>;</span>
|
||||
<span>var</span> reqHeaders <span>=</span> <span>new</span> Headers<span>(</span><span>)</span><span>;</span>
|
||||
reqHeaders.<span>append</span><span>(</span><span>"Content-Type"</span><span>,</span> <span>"text/plain"</span>
|
||||
reqHeaders.<span>append</span><span>(</span><span>"Content-Length"</span><span>,</span> content.<span>length</span>.<span>toString</span><span>(</span><span>)</span><span>)</span><span>;</span>
|
||||
reqHeaders.<span>append</span><span>(</span><span>"X-Custom-Header"</span><span>,</span><span>"ProcessThisImmediately"</span><span>)</span><span>;</span></pre></DIV>
|
||||
reqHeaders.<span>append</span><span>(</span><span>"X-Custom-Header"</span><span>,</span> <span>"ProcessThisImmediately"</span><span>)</span><span>;</span></pre>
|
||||
</DIV>
|
||||
<p>The same can be achieved by passing an array of arrays or a JS object
|
||||
literal
|
||||
<br>to the constructor:</p>
|
||||
<DIV><pre>reqHeaders <span>=</span><span>new</span> Headers<span>(</span><span>{</span><span>"Content-Type"</span><span>:</span><span>"text/plain"</span><span>,</span><span>"Content-Length"</span><span>:</span> content.<span>length</span>.<span>toString</span><span>(</span><span>)</span><span>,</span><span>"X-Custom-Header"</span><span>:</span><span>"ProcessThisImmediately"</span><span>,</span><span>}</span><span>)</span><span>;</span></pre></DIV>
|
||||
<DIV>
|
||||
<pre>reqHeaders <span>=</span> <span>new</span> Headers<span>(</span><span>{</span>
|
||||
<span>"Content-Type"</span><span>:</span> <span>"text/plain"</span><span>,</span>
|
||||
<span>"Content-Length"</span><span>:</span> content.<span>length</span>.<span>toString</span><span>(</span><span>)</span><span>,</span>
|
||||
<span>"X-Custom-Header"</span><span>:</span> <span>"ProcessThisImmediately"</span><span>,</span>
|
||||
<span>}</span><span>)</span><span>;</span></pre>
|
||||
</DIV>
|
||||
<p>The contents can be queried and retrieved:</p>
|
||||
<DIV><pre>console.<span>log</span><span>(</span>reqHeaders.<span>has</span><span>(</span><span>"Content-Type"</span><span>)</span><span>)</span><span>;</span><span>// true</span>
|
||||
<DIV>
|
||||
<pre>console.<span>log</span><span>(</span>reqHeaders.<span>has</span><span>(</span><span>"Content-Type"</span><span>)</span><span>)</span><span>;</span> <span>// true</span>
|
||||
console.<span>log</span><span>(</span>reqHeaders.<span>has</span><span>(</span><span>"Set-Cookie"</span><span>)</span><span>)</span><span>;</span> <span>// false</span>
|
||||
reqHeaders.<span>set</span><span>(</span><span>"Content-Type"</span><span>,</span> <span>"text/html"</span><span>)</span><span>;</span>
|
||||
reqHeaders.<span>append</span><span>(</span><span>"X-Custom-Header"</span><span>,</span> <span>"AnotherValue"</span><span>)</span><span>;</span>
|
||||
|
@ -71,7 +110,8 @@ console.<span>log</span><span>(</span>reqHeaders.<span>get</span><span>(</span><
|
|||
console.<span>log</span><span>(</span>reqHeaders.<span>getAll</span><span>(</span><span>"X-Custom-Header"</span><span>)</span><span>)</span><span>;</span> <span>// ["ProcessThisImmediately", "AnotherValue"]</span>
|
||||
|
||||
reqHeaders.<span>delete</span><span>(</span><span>"X-Custom-Header"</span><span>)</span><span>;</span>
|
||||
console.<span>log</span><span>(</span>reqHeaders.<span>getAll</span><span>(</span><span>"X-Custom-Header"</span><span>)</span><span>)</span><span>;</span><span>// []</span></pre></DIV>
|
||||
console.<span>log</span><span>(</span>reqHeaders.<span>getAll</span><span>(</span><span>"X-Custom-Header"</span><span>)</span><span>)</span><span>;</span> <span>// []</span></pre>
|
||||
</DIV>
|
||||
<p>Some of these operations are only useful in ServiceWorkers, but they provide
|
||||
<br>a much nicer API to Headers.</p>
|
||||
<p>Since Headers can be sent in requests, or received in responses, and have
|
||||
|
@ -98,34 +138,50 @@ console.<span>log</span><span>(</span>reqHeaders.<span>getAll</span><span>(</spa
|
|||
<p>All of the Headers methods throw TypeError if <code>name</code> is not a
|
||||
<a href="https://fetch.spec.whatwg.org/#concept-header-name" target="_blank">valid HTTP Header name</a>. The mutation operations will throw TypeError
|
||||
if there is an immutable guard. Otherwise they fail silently. For example:</p>
|
||||
<DIV><pre><span>var</span> res <span>=</span> Response.<span>error</span><span>(</span><span>)</span><span>;</span><span>try</span><span>{</span>
|
||||
res.<span>headers</span>.<span>set</span><span>(</span><span>"Origin"</span><span>,</span><span>"http://mybank.com"</span><span>)</span><span>;</span><span>}</span><span>catch</span><span>(</span>e<span>)</span><span>{</span>
|
||||
console.<span>log</span><span>(</span><span>"Cannot pretend to be a bank!"</span><span>)</span><span>;</span><span>}</span></pre></DIV>
|
||||
<DIV>
|
||||
<pre><span>var</span> res <span>=</span> Response.<span>error</span><span>(</span><span>)</span><span>;</span>
|
||||
<span>try</span> <span>{</span>
|
||||
res.<span>headers</span>.<span>set</span><span>(</span><span>"Origin"</span><span>,</span> <span>"http://mybank.com"</span><span>)</span><span>;</span>
|
||||
<span>}</span> <span>catch</span><span>(</span>e<span>)</span> <span>{</span>
|
||||
console.<span>log</span><span>(</span><span>"Cannot pretend to be a bank!"</span><span>)</span><span>;</span>
|
||||
<span>}</span></pre>
|
||||
</DIV>
|
||||
|
||||
<h2>Request</h2>
|
||||
|
||||
<p>The Request interface defines a request to fetch a resource over HTTP.
|
||||
URL, method and headers are expected, but the Request also allows specifying
|
||||
a body, a request mode, credentials and cache hints.</p>
|
||||
<p>The simplest Request is of course, just a URL, as you may do to GET a
|
||||
resource.</p>
|
||||
<DIV><pre><span>var</span> req <span>=</span><span>new</span> Request<span>(</span><span>"/index.html"</span><span>)</span><span>;</span>
|
||||
<DIV>
|
||||
<pre><span>var</span> req <span>=</span> <span>new</span> Request<span>(</span><span>"/index.html"</span><span>)</span><span>;</span>
|
||||
console.<span>log</span><span>(</span>req.<span>method</span><span>)</span><span>;</span> <span>// "GET"</span>
|
||||
console.<span>log</span><span>(</span>req.<span>url</span><span>)</span><span>;</span><span>// "http://example.com/index.html"</span></pre></DIV>
|
||||
console.<span>log</span><span>(</span>req.<span>url</span><span>)</span><span>;</span> <span>// "http://example.com/index.html"</span></pre>
|
||||
</DIV>
|
||||
<p>You may also pass a Request to the <code>Request()</code> constructor to
|
||||
create a copy.
|
||||
<br>(This is not the same as calling the <code>clone()</code> method, which
|
||||
is covered in
|
||||
<br>the “Reading bodies” section.).</p>
|
||||
<DIV><pre><span>var</span> copy <span>=</span><span>new</span> Request<span>(</span>req<span>)</span><span>;</span>
|
||||
<DIV>
|
||||
<pre><span>var</span> copy <span>=</span> <span>new</span> Request<span>(</span>req<span>)</span><span>;</span>
|
||||
console.<span>log</span><span>(</span>copy.<span>method</span><span>)</span><span>;</span> <span>// "GET"</span>
|
||||
console.<span>log</span><span>(</span>copy.<span>url</span><span>)</span><span>;</span><span>// "http://example.com/index.html"</span></pre></DIV>
|
||||
console.<span>log</span><span>(</span>copy.<span>url</span><span>)</span><span>;</span> <span>// "http://example.com/index.html"</span></pre>
|
||||
</DIV>
|
||||
<p>Again, this form is probably only useful in ServiceWorkers.</p>
|
||||
<p>The non-URL attributes of the <code>Request</code> can only be set by passing
|
||||
initial
|
||||
<br>values as a second argument to the constructor. This argument is a dictionary.</p>
|
||||
<DIV><pre><span>var</span> uploadReq <span>=</span><span>new</span> Request<span>(</span><span>"/uploadImage"</span><span>,</span><span>{</span>
|
||||
<DIV>
|
||||
<pre><span>var</span> uploadReq <span>=</span> <span>new</span> Request<span>(</span><span>"/uploadImage"</span><span>,</span> <span>{</span>
|
||||
method<span>:</span> <span>"POST"</span><span>,</span>
|
||||
headers<span>:</span><span>{</span><span>"Content-Type"</span><span>:</span><span>"image/png"</span><span>,</span><span>}</span><span>,</span>
|
||||
body<span>:</span><span>"image data"</span><span>}</span><span>)</span><span>;</span></pre></DIV>
|
||||
headers<span>:</span> <span>{</span>
|
||||
<span>"Content-Type"</span><span>:</span> <span>"image/png"</span><span>,</span>
|
||||
<span>}</span><span>,</span>
|
||||
body<span>:</span> <span>"image data"</span>
|
||||
<span>}</span><span>)</span><span>;</span></pre>
|
||||
</DIV>
|
||||
<p>The Request’s mode is used to determine if cross-origin requests lead
|
||||
to valid responses, and which properties on the response are readable.
|
||||
Legal mode values are <code>"same-origin"</code>, <code>"no-cors"</code> (default)
|
||||
|
@ -134,10 +190,14 @@ console.<span>log</span><span>(</span>copy.<span>url</span><span>)</span><span>;
|
|||
origin with this mode set, the result is simply an error. You could use
|
||||
this to ensure that
|
||||
<br>a request is always being made to your origin.</p>
|
||||
<DIV><pre><span>var</span> arbitraryUrl <span>=</span> document.<span>getElementById</span><span>(</span><span>"url-input"</span><span>)</span>.<span>value</span><span>;</span>
|
||||
<DIV>
|
||||
<pre><span>var</span> arbitraryUrl <span>=</span> document.<span>getElementById</span><span>(</span><span>"url-input"</span><span>)</span>.<span>value</span><span>;</span>
|
||||
fetch<span>(</span>arbitraryUrl<span>,</span> <span>{</span> mode<span>:</span> <span>"same-origin"</span> <span>}</span><span>)</span>.<span>then</span><span>(</span><span>function</span><span>(</span>res<span>)</span> <span>{</span>
|
||||
console.<span>log</span><span>(</span><span>"Response succeeded?"</span><span>,</span> res.<span>ok</span><span>)</span><span>;</span><span>}</span><span>,</span><span>function</span><span>(</span>e<span>)</span><span>{</span>
|
||||
console.<span>log</span><span>(</span><span>"Please enter a same-origin URL!"</span><span>)</span><span>;</span><span>}</span><span>)</span><span>;</span></pre></DIV>
|
||||
console.<span>log</span><span>(</span><span>"Response succeeded?"</span><span>,</span> res.<span>ok</span><span>)</span><span>;</span>
|
||||
<span>}</span><span>,</span> <span>function</span><span>(</span>e<span>)</span> <span>{</span>
|
||||
console.<span>log</span><span>(</span><span>"Please enter a same-origin URL!"</span><span>)</span><span>;</span>
|
||||
<span>}</span><span>)</span><span>;</span></pre>
|
||||
</DIV>
|
||||
<p>The <code>"no-cors"</code> mode captures what the web platform does by default
|
||||
for scripts you import from CDNs, images hosted on other domains, and so
|
||||
on. First, it prevents the method from being anything other than “HEAD”,
|
||||
|
@ -155,22 +215,37 @@ fetch<span>(</span>arbitraryUrl<span>,</span><span>{</span> mode<span>:</span><s
|
|||
headers is exposed in the Response, but the body is readable. For example,
|
||||
you could get a list of Flickr’s <a href="https://www.flickr.com/services/api/flickr.interestingness.getList.html" target="_blank">most interesting</a> photos
|
||||
today like this:</p>
|
||||
<DIV><pre><span>var</span> u <span>=</span><span>new</span> URLSearchParams<span>(</span><span>)</span><span>;</span>
|
||||
<DIV>
|
||||
<pre><span>var</span> u <span>=</span> <span>new</span> URLSearchParams<span>(</span><span>)</span><span>;</span>
|
||||
u.<span>append</span><span>(</span><span>'method'</span><span>,</span> <span>'flickr.interestingness.getList'</span><span>)</span><span>;</span>
|
||||
u.<span>append</span><span>(</span><span>'api_key'</span><span>,</span> <span>'<insert api key here>'</span><span>)</span><span>;</span>
|
||||
u.<span>append</span><span>(</span><span>'format'</span><span>,</span> <span>'json'</span><span>)</span><span>;</span>
|
||||
u.<span>append</span><span>(</span><span>'nojsoncallback'</span><span>,</span><span>'1'</span><span>)</span><span>;</span><span>var</span> apiCall <span>=</span> fetch<span>(</span><span>'https://api.flickr.com/services/rest?'</span><span>+</span> u<span>)</span><span>;</span>
|
||||
u.<span>append</span><span>(</span><span>'nojsoncallback'</span><span>,</span> <span>'1'</span><span>)</span><span>;</span>
|
||||
|
||||
apiCall.<span>then</span><span>(</span><span>function</span><span>(</span>response<span>)</span><span>{</span><span>return</span> response.<span>json</span><span>(</span><span>)</span>.<span>then</span><span>(</span><span>function</span><span>(</span>json<span>)</span><span>{</span><span>// photo is a list of photos.</span><span>return</span> json.<span>photos</span>.<span>photo</span><span>;</span><span>}</span><span>)</span><span>;</span><span>}</span><span>)</span>.<span>then</span><span>(</span><span>function</span><span>(</span>photos<span>)</span><span>{</span>
|
||||
<span>var</span> apiCall <span>=</span> fetch<span>(</span><span>'https://api.flickr.com/services/rest?'</span> <span>+</span> u<span>)</span><span>;</span>
|
||||
|
||||
apiCall.<span>then</span><span>(</span><span>function</span><span>(</span>response<span>)</span> <span>{</span>
|
||||
<span>return</span> response.<span>json</span><span>(</span><span>)</span>.<span>then</span><span>(</span><span>function</span><span>(</span>json<span>)</span> <span>{</span>
|
||||
<span>// photo is a list of photos.</span>
|
||||
<span>return</span> json.<span>photos</span>.<span>photo</span><span>;</span>
|
||||
<span>}</span><span>)</span><span>;</span>
|
||||
<span>}</span><span>)</span>.<span>then</span><span>(</span><span>function</span><span>(</span>photos<span>)</span> <span>{</span>
|
||||
photos.<span>forEach</span><span>(</span><span>function</span><span>(</span>photo<span>)</span> <span>{</span>
|
||||
console.<span>log</span><span>(</span>photo.<span>title</span><span>)</span><span>;</span><span>}</span><span>)</span><span>;</span><span>}</span><span>)</span><span>;</span></pre></DIV>
|
||||
console.<span>log</span><span>(</span>photo.<span>title</span><span>)</span><span>;</span>
|
||||
<span>}</span><span>)</span><span>;</span>
|
||||
<span>}</span><span>)</span><span>;</span></pre>
|
||||
</DIV>
|
||||
<p>You may not read out the “Date” header since Flickr does not allow it
|
||||
via
|
||||
<br><code>Access-Control-Expose-Headers</code>.</p>
|
||||
<DIV><pre>response.<span>headers</span>.<span>get</span><span>(</span><span>"Date"</span><span>)</span><span>;</span><span>// null</span></pre></DIV>
|
||||
<br>
|
||||
<code>Access-Control-Expose-Headers</code>.</p>
|
||||
<DIV>
|
||||
<pre>response.<span>headers</span>.<span>get</span><span>(</span><span>"Date"</span><span>)</span><span>;</span> <span>// null</span></pre>
|
||||
</DIV>
|
||||
<p>The <code>credentials</code> enumeration determines if cookies for the other
|
||||
domain are
|
||||
<br>sent to cross-origin requests. This is similar to XHR’s <code>withCredentials</code><br>flag, but tri-valued as <code>"omit"</code> (default), <code>"same-origin"</code> and <code>"include"</code>.</p>
|
||||
<br>sent to cross-origin requests. This is similar to XHR’s <code>withCredentials</code>
|
||||
<br>flag, but tri-valued as <code>"omit"</code> (default), <code>"same-origin"</code> and <code>"include"</code>.</p>
|
||||
<p>The Request object will also give the ability to offer caching hints to
|
||||
the user-agent. This is currently undergoing some <a href="https://github.com/slightlyoff/ServiceWorker/issues/585" target="_blank">security review</a>.
|
||||
Firefox exposes the attribute, but it has no effect.</p>
|
||||
|
@ -178,13 +253,16 @@ apiCall.<span>then</span><span>(</span><span>function</span><span>(</span>respon
|
|||
<br>intercepting them. There is the string <code>referrer</code>, which is
|
||||
set by the UA to be
|
||||
<br>the referrer of the Request. This may be an empty string. The other is
|
||||
<br><code>context</code> which is a rather <a href="https://fetch.spec.whatwg.org/#requestcredentials" target="_blank">large enumeration</a> defining
|
||||
<br>
|
||||
<code>context</code> which is a rather <a href="https://fetch.spec.whatwg.org/#requestcredentials" target="_blank">large enumeration</a> defining
|
||||
what sort of resource is being fetched. This could be “image” if the request
|
||||
is from an
|
||||
<img>tag in the controlled document, “worker” if it is an attempt to load a
|
||||
worker script, and so on. When used with the <code>fetch()</code> function,
|
||||
it is “fetch”.</p>
|
||||
|
||||
<h2>Response</h2>
|
||||
|
||||
<p><code>Response</code> instances are returned by calls to <code>fetch()</code>.
|
||||
They can also be created by JS, but this is only useful in ServiceWorkers.</p>
|
||||
<p>We have already seen some attributes of Response when we looked at <code>fetch()</code>.
|
||||
|
@ -222,9 +300,13 @@ apiCall.<span>then</span><span>(</span><span>function</span><span>(</span>respon
|
|||
The
|
||||
<br>idiomatic way to return a Response to an intercepted request in ServiceWorkers
|
||||
is:</p>
|
||||
<DIV><pre>addEventListener<span>(</span><span>'fetch'</span><span>,</span><span>function</span><span>(</span>event<span>)</span><span>{</span>
|
||||
<DIV>
|
||||
<pre>addEventListener<span>(</span><span>'fetch'</span><span>,</span> <span>function</span><span>(</span>event<span>)</span> <span>{</span>
|
||||
event.<span>respondWith</span><span>(</span><span>new</span> Response<span>(</span><span>"Response body"</span><span>,</span> <span>{</span>
|
||||
headers<span>:</span><span>{</span><span>"Content-Type"</span><span>:</span><span>"text/plain"</span><span>}</span><span>}</span><span>)</span><span>;</span><span>}</span><span>)</span><span>;</span></pre></DIV>
|
||||
headers<span>:</span> <span>{</span> <span>"Content-Type"</span> <span>:</span> <span>"text/plain"</span> <span>}</span>
|
||||
<span>}</span><span>)</span><span>;</span>
|
||||
<span>}</span><span>)</span><span>;</span></pre>
|
||||
</DIV>
|
||||
<p>As you can see, Response has a two argument constructor, where both arguments
|
||||
are optional. The first argument is a body initializer, and the second
|
||||
is a dictionary to set the <code>status</code>, <code>statusText</code> and <code>headers</code>.</p>
|
||||
|
@ -232,13 +314,17 @@ apiCall.<span>then</span><span>(</span><span>function</span><span>(</span>respon
|
|||
response. Similarly, <code>Response.redirect(url, status)</code> returns
|
||||
a Response resulting in
|
||||
<br>a redirect to <code>url</code>.</p>
|
||||
|
||||
<h2>Dealing with bodies</h2>
|
||||
|
||||
<p>Both Requests and Responses may contain body data. We’ve been glossing
|
||||
over it because of the various data types body may contain, but we will
|
||||
cover it in detail now.</p>
|
||||
<p>A body is an instance of any of the following types.</p>
|
||||
<ul>
|
||||
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer" target="_blank">ArrayBuffer</a></li>
|
||||
<li>
|
||||
<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer" target="_blank">ArrayBuffer</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://developer.mozilla.org/en-US/docs/Web/API/ArrayBufferView" target="_blank">ArrayBufferView</a> (Uint8Array
|
||||
and friends)</li>
|
||||
|
@ -247,7 +333,9 @@ apiCall.<span>then</span><span>(</span><span>function</span><span>(</span>respon
|
|||
<a href="https://developer.mozilla.org/en-US/docs/Web/API/File" target="_blank">File</a>
|
||||
</li>
|
||||
<li>string</li>
|
||||
<li><a href="https://url.spec.whatwg.org/#interface-urlsearchparams" target="_blank">URLSearchParams</a></li>
|
||||
<li>
|
||||
<a href="https://url.spec.whatwg.org/#interface-urlsearchparams" target="_blank">URLSearchParams</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://developer.mozilla.org/en-US/docs/Web/API/FormData" target="_blank">FormData</a> –
|
||||
currently not supported by either Gecko or Blink. Firefox expects to ship
|
||||
|
@ -257,38 +345,59 @@ apiCall.<span>then</span><span>(</span><span>function</span><span>(</span>respon
|
|||
extract their body. These all return a Promise that is eventually resolved
|
||||
with the actual content.</p>
|
||||
<ul>
|
||||
<li><code>arrayBuffer()</code></li>
|
||||
<li><code>blob()</code></li>
|
||||
<li><code>json()</code></li>
|
||||
<li><code>text()</code></li>
|
||||
<li><code>formData()</code></li>
|
||||
<li>
|
||||
<code>arrayBuffer()</code>
|
||||
</li>
|
||||
<li>
|
||||
<code>blob()</code>
|
||||
</li>
|
||||
<li>
|
||||
<code>json()</code>
|
||||
</li>
|
||||
<li>
|
||||
<code>text()</code>
|
||||
</li>
|
||||
<li>
|
||||
<code>formData()</code>
|
||||
</li>
|
||||
</ul>
|
||||
<p>This is a significant improvement over XHR in terms of ease of use of
|
||||
non-text data!</p>
|
||||
<p>Request bodies can be set by passing <code>body</code> parameters:</p>
|
||||
<DIV><pre><span>var</span> form <span>=</span><span>new</span> FormData<span>(</span>document.<span>getElementById</span><span>(</span><span>'login-form'</span><span>)</span><span>)</span><span>;</span>
|
||||
<DIV>
|
||||
<pre><span>var</span> form <span>=</span> <span>new</span> FormData<span>(</span>document.<span>getElementById</span><span>(</span><span>'login-form'</span><span>)</span><span>)</span><span>;</span>
|
||||
fetch<span>(</span><span>"/login"</span><span>,</span> <span>{</span>
|
||||
method<span>:</span> <span>"POST"</span><span>,</span>
|
||||
body<span>:</span> form
|
||||
<span>}</span><span>)</span></pre></DIV>
|
||||
<span>}</span><span>)</span></pre>
|
||||
</DIV>
|
||||
<p>Responses take the first argument as the body.</p>
|
||||
<DIV><pre><span>var</span> res <span>=</span><span>new</span> Response<span>(</span><span>new</span> File<span>(</span><span>[</span><span>"chunk"</span><span>,</span><span>"chunk"</span><span>]</span><span>,</span><span>"archive.zip"</span><span>,</span><span>{</span> type<span>:</span><span>"application/zip"</span><span>}</span><span>)</span><span>)</span><span>;</span></pre></DIV>
|
||||
<DIV>
|
||||
<pre><span>var</span> res <span>=</span> <span>new</span> Response<span>(</span><span>new</span> File<span>(</span><span>[</span><span>"chunk"</span><span>,</span> <span>"chunk"</span><span>]</span><span>,</span> <span>"archive.zip"</span><span>,</span>
|
||||
<span>{</span> type<span>:</span> <span>"application/zip"</span> <span>}</span><span>)</span><span>)</span><span>;</span></pre>
|
||||
</DIV>
|
||||
<p>Both Request and Response (and by extension the <code>fetch()</code> function),
|
||||
will try to intelligently <a href="https://fetch.spec.whatwg.org/#concept-bodyinit-extract" target="_blank">determine the content type</a>.
|
||||
Request will also automatically set a “Content-Type” header if none is
|
||||
set in the dictionary.</p>
|
||||
|
||||
<h3>Streams and cloning</h3>
|
||||
|
||||
<p>It is important to realise that Request and Response bodies can only be
|
||||
read once! Both interfaces have a boolean attribute <code>bodyUsed</code> to
|
||||
determine if it is safe to read or not.</p>
|
||||
<DIV><pre><span>var</span> res <span>=</span><span>new</span> Response<span>(</span><span>"one time use"</span><span>)</span><span>;</span>
|
||||
<DIV>
|
||||
<pre><span>var</span> res <span>=</span> <span>new</span> Response<span>(</span><span>"one time use"</span><span>)</span><span>;</span>
|
||||
console.<span>log</span><span>(</span>res.<span>bodyUsed</span><span>)</span><span>;</span> <span>// false</span>
|
||||
res.<span>text</span><span>(</span><span>)</span>.<span>then</span><span>(</span><span>function</span><span>(</span>v<span>)</span> <span>{</span>
|
||||
console.<span>log</span><span>(</span>res.<span>bodyUsed</span><span>)</span><span>;</span><span>// true</span><span>}</span><span>)</span><span>;</span>
|
||||
console.<span>log</span><span>(</span>res.<span>bodyUsed</span><span>)</span><span>;</span> <span>// true</span>
|
||||
<span>}</span><span>)</span><span>;</span>
|
||||
console.<span>log</span><span>(</span>res.<span>bodyUsed</span><span>)</span><span>;</span> <span>// true</span>
|
||||
|
||||
res.<span>text</span><span>(</span><span>)</span>.<span>catch</span><span>(</span><span>function</span><span>(</span>e<span>)</span> <span>{</span>
|
||||
console.<span>log</span><span>(</span><span>"Tried to read already consumed Response"</span><span>)</span><span>;</span><span>}</span><span>)</span><span>;</span></pre></DIV>
|
||||
console.<span>log</span><span>(</span><span>"Tried to read already consumed Response"</span><span>)</span><span>;</span>
|
||||
<span>}</span><span>)</span><span>;</span></pre>
|
||||
</DIV>
|
||||
<p>This decision allows easing the transition to an eventual <a href="https://streams.spec.whatwg.org/" target="_blank">stream-based</a> Fetch
|
||||
API. The intention is to let applications consume data as it arrives, allowing
|
||||
for JavaScript to deal with larger files like videos, and perform things
|
||||
|
@ -302,16 +411,25 @@ res.<span>text</span><span>(</span><span>)</span>.<span>catch</span><span>(</spa
|
|||
will return a clone of the object, with a ‘new’ body. <code>clone()</code> MUST
|
||||
be called before the body of the corresponding object has been used. That
|
||||
is, <code>clone()</code> first, read later.</p>
|
||||
<DIV><pre>addEventListener<span>(</span><span>'fetch'</span><span>,</span><span>function</span><span>(</span>evt<span>)</span><span>{</span><span>var</span> sheep <span>=</span><span>new</span> Response<span>(</span><span>"Dolly"</span><span>)</span><span>;</span>
|
||||
console.<span>log</span><span>(</span>sheep.<span>bodyUsed</span><span>)</span><span>;</span><span>// false</span><span>var</span> clone <span>=</span> sheep.<span>clone</span><span>(</span><span>)</span><span>;</span>
|
||||
<DIV>
|
||||
<pre>addEventListener<span>(</span><span>'fetch'</span><span>,</span> <span>function</span><span>(</span>evt<span>)</span> <span>{</span>
|
||||
<span>var</span> sheep <span>=</span> <span>new</span> Response<span>(</span><span>"Dolly"</span><span>)</span><span>;</span>
|
||||
console.<span>log</span><span>(</span>sheep.<span>bodyUsed</span><span>)</span><span>;</span> <span>// false</span>
|
||||
<span>var</span> clone <span>=</span> sheep.<span>clone</span><span>(</span><span>)</span><span>;</span>
|
||||
console.<span>log</span><span>(</span>clone.<span>bodyUsed</span><span>)</span><span>;</span> <span>// false</span>
|
||||
|
||||
clone.<span>text</span><span>(</span><span>)</span><span>;</span>
|
||||
console.<span>log</span><span>(</span>sheep.<span>bodyUsed</span><span>)</span><span>;</span> <span>// false</span>
|
||||
console.<span>log</span><span>(</span>clone.<span>bodyUsed</span><span>)</span><span>;</span> <span>// true</span>
|
||||
|
||||
evt.<span>respondWith</span><span>(</span>cache.<span>add</span><span>(</span>sheep.<span>clone</span><span>(</span><span>)</span><span>)</span>.<span>then</span><span>(</span><span>function</span><span>(</span>e<span>)</span><span>{</span><span>return</span> sheep<span>;</span><span>}</span><span>)</span><span>;</span><span>}</span><span>)</span><span>;</span></pre></DIV>
|
||||
evt.<span>respondWith</span><span>(</span>cache.<span>add</span><span>(</span>sheep.<span>clone</span><span>(</span><span>)</span><span>)</span>.<span>then</span><span>(</span><span>function</span><span>(</span>e<span>)</span> <span>{</span>
|
||||
<span>return</span> sheep<span>;</span>
|
||||
<span>}</span><span>)</span><span>;</span>
|
||||
<span>}</span><span>)</span><span>;</span></pre>
|
||||
</DIV>
|
||||
|
||||
<h2>Future improvements</h2>
|
||||
|
||||
<p>Along with the transition to streams, Fetch will eventually have the ability
|
||||
to abort running <code>fetch()</code>es and some way to report the progress
|
||||
of a fetch. These are provided by XHR, but are a little tricky to fit in
|
||||
|
@ -322,4 +440,10 @@ res.<span>text</span><span>(</span><span>)</span>.<span>catch</span><span>(</spa
|
|||
<a href="https://github.com/slightlyoff/ServiceWorker/issues" target="_blank">ServiceWorker</a>specifications.</p>
|
||||
<p>For a better web!</p>
|
||||
<p><em>The author would like to thank Andrea Marchesini, Anne van Kesteren and Ben<br>
|
||||
Kelly for helping with the specification and implementation.</em></p></article></DIV></article>
|
||||
Kelly for helping with the specification and implementation.</em>
|
||||
</p>
|
||||
|
||||
</article>
|
||||
|
||||
|
||||
</DIV></article>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<article><DIV id="readability-page-1"><article><h2>Test document title</h2>
|
||||
<article><DIV id="readability-page-1"><article>
|
||||
<h2>Test document title</h2>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
|
||||
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
|
||||
|
@ -14,4 +15,5 @@
|
|||
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
|
||||
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
|
||||
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
</p></article></DIV></article>
|
||||
</p>
|
||||
</article></DIV></article>
|
||||
|
|
|
@ -11,7 +11,9 @@
|
|||
<p>
|
||||
There are at least two major categories of information available to Facebook about non-participants like me: information from other Facebook users, and information from sites on the open web.
|
||||
</p>
|
||||
<h3><strong>Information from other Facebook users</strong></h3>
|
||||
<h3>
|
||||
<strong>Information from other Facebook users</strong>
|
||||
</h3>
|
||||
<p>
|
||||
When you sign up for Facebook, it encourages you to upload your list of contacts so that the site can "find your friends." Facebook uses this contact information to learn about people, even if those people don't agree to participate. It also links people together based on who they know, even if the shared contact hasn't agreed to this use.
|
||||
</p>
|
||||
|
@ -24,7 +26,9 @@
|
|||
<p>
|
||||
So even if you decide you need to join Facebook, remember that you might be giving the company information about someone else who didn't agree to be part of its surveillance platform.
|
||||
</p>
|
||||
<h3><strong>Information from sites on the open Web</strong></h3>
|
||||
<h3>
|
||||
<strong>Information from sites on the open Web</strong>
|
||||
</h3>
|
||||
<p>
|
||||
Nearly every website that you visit that has a "Like" button is actually encouraging your browser to tell Facebook about your browsing habits. Even if you don't click on the "Like" button, displaying it requires your browser to send a request to Facebook's servers for the "Like" button itself. That request includes <a href="https://en.wikipedia.org/wiki/HTTP_referer" target="_blank">information</a> mentioning the name of the page you are visiting and any Facebook-specific <a href="https://en.wikipedia.org/wiki/HTTP_cookie" target="_blank">cookies</a> your browser might have collected. (See <a href="https://www.facebook.com/help/186325668085084" target="_blank">Facebook's own description of this process</a>.) This is called a "third-party request."
|
||||
</p>
|
||||
|
@ -43,13 +47,17 @@
|
|||
<p>
|
||||
I'd be shocked if Facebook were not connecting those dots given the goals <a href="https://www.facebook.com/about/privacy/cookies" target="_blank">they claim for data collection</a>:
|
||||
</p>
|
||||
<blockquote><p>
|
||||
<blockquote>
|
||||
<p>
|
||||
We use the information we have to improve our advertising and measurement systems so we can show you relevant ads on and off our Services and measure the effectiveness and reach of ads and services.
|
||||
</p></blockquote>
|
||||
</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
This is, in essence, exactly what Cambridge Analytica did.
|
||||
</p>
|
||||
<h3><strong>Consent</strong></h3>
|
||||
<h3>
|
||||
<strong>Consent</strong>
|
||||
</h3>
|
||||
<p>
|
||||
Facebook and other tech companies often deflect accusations against excessive data collection by arguing "consent" — that they harvest and use data with the consent of the users involved.
|
||||
</p>
|
||||
|
@ -59,7 +67,9 @@
|
|||
<p>
|
||||
Are those of us who have explicitly avoided agreeing to the Facebook terms of service simply fair game for an industry-wide surveillance and targeting network?
|
||||
</p>
|
||||
<h3><strong>Privilege</strong></h3>
|
||||
<h3>
|
||||
<strong>Privilege</strong>
|
||||
</h3>
|
||||
<p>
|
||||
I don’t mean to critique people who have created a Facebook profile or suggest they deserve whatever they get.
|
||||
</p>
|
||||
|
@ -75,12 +85,15 @@
|
|||
<p>
|
||||
Privacy should not be a luxury good, and while I'm happy to encourage people to opt out of these subtle and socially fraught arrangements, I do not argue that anyone who has signed up has somehow relinquished concerns about their privacy. We need to evaluate privacy concerns in their full social contexts. These are not problems that can be resolved on an individual level, because of the interpersonal nature of much of this data and the complexities of the tradeoffs involved.
|
||||
</p>
|
||||
<h3><strong>Technical countermeasures</strong></h3>
|
||||
<h3>
|
||||
<strong>Technical countermeasures</strong>
|
||||
</h3>
|
||||
<p>
|
||||
While they may not solve the problem, there are some technical steps people can take to limit the scope of these surveillance practices. For example, some web browsers do not send "third-party cookies" by default, or <a href="https://wiki.mozilla.org/Thirdparty" target="_blank">they scope cookies</a> so that centralized surveillance doesn't get a single view of one user. The most privacy-preserving modern browser is <a href="https://www.torproject.org/" target="_blank">the Tor Browser</a>, which everyone should have installed and available, even if it's not the browser they choose to use every day. It limits the surveillance ability of systems that you have not signed up for to track you as you move around the web.
|
||||
</p>
|
||||
<p>
|
||||
You can also modify some browsers — for example, with plug-ins for <a href="https://requestpolicycontinued.github.io/" target="_blank">Firefox</a> and <a href="https://chrome.google.com/webstore/detail/umatrix/ogfcmafjalglgifnmanfmnieipoejdcf" target="_blank">Chrome</a> — so that they <a href="https://addons.mozilla.org/en-US/firefox/addon/umatrix/" target="_blank">do not send third-party</a><a href="https://requestpolicycontinued.github.io/" target="_blank">requests at all</a>. Firefox is also exploring even more <a href="https://addons.mozilla.org/en-US/firefox/addon/multi-account-containers/" target="_blank">privacy-preserving techniques</a><a href="https://addons.mozilla.org/en-US/firefox/addon/multi-account-containers/" target="_blank">.</a></p>
|
||||
You can also modify some browsers — for example, with plug-ins for <a href="https://requestpolicycontinued.github.io/" target="_blank">Firefox</a> and <a href="https://chrome.google.com/webstore/detail/umatrix/ogfcmafjalglgifnmanfmnieipoejdcf" target="_blank">Chrome</a> — so that they <a href="https://addons.mozilla.org/en-US/firefox/addon/umatrix/" target="_blank">do not send third-party</a> <a href="https://requestpolicycontinued.github.io/" target="_blank">requests at all</a>. Firefox is also exploring even more <a href="https://addons.mozilla.org/en-US/firefox/addon/multi-account-containers/" target="_blank">privacy-preserving techniques</a><a href="https://addons.mozilla.org/en-US/firefox/addon/multi-account-containers/" target="_blank">.</a>
|
||||
</p>
|
||||
<p>
|
||||
It can’t be denied, though, that these tools are harder to use than the web browsers most people are accustomed to, and they create barriers to some online activities. (For example, logging in to <a href="https://offcampushousing.uconn.edu/login" target="_blank">some sites</a> and accessing some <a href="https://filestore.community.support.microsoft.com/api/images/0253d8fb-b050-401a-834d-9d80a99c0b12" target="_blank">web applications</a> is impossible without third-party cookies.)
|
||||
</p>
|
||||
|
@ -90,14 +103,18 @@
|
|||
<p>
|
||||
If you are responsible for running a website, try browsing it with a third-party-blocking extension turned on. Think about how much information you're requiring your users to send to third parties as a condition for using your site. If you care about being a good steward of your visitors' data, you can re-design your website to reduce this kind of leakage.
|
||||
</p>
|
||||
<h3><strong>Opting out?</strong></h3>
|
||||
<h3>
|
||||
<strong>Opting out?</strong>
|
||||
</h3>
|
||||
<p>
|
||||
Some advertisers claim that you can "opt out" of their targeted advertising, and even offer <a href="http://optout.aboutads.info/" target="_blank">a centralized place meant to help you do so</a>. However, my experience with these tools isn't a positive one. They don't appear to work all of the time. (In a recent experiment I conducted, two advertisers’ opt-out mechanisms failed to take effect.) And while advertisers claim to allow the user to opt out of "interest-based ads," it's not clear that the opt-outs govern data collection itself, rather than just the use of the collected data for displaying ads. Moreover, opting out on their terms requires the use of third-party cookies, thereby enabling another mechanism that other advertisers can then exploit.
|
||||
</p>
|
||||
<p>
|
||||
It's also not clear how they function over time: How frequently do I need to take these steps? Do they expire? How often should I check back to make sure I’m still opted out? I'd much prefer an approach requiring me to opt <em>in</em> to surveillance and targeting.
|
||||
</p>
|
||||
<h3><strong>Fix the surveillance economy, not just Facebook</strong></h3>
|
||||
<h3>
|
||||
<strong>Fix the surveillance economy, not just Facebook</strong>
|
||||
</h3>
|
||||
<p>
|
||||
These are just a few of the mechanisms that enable online tracking. Facebook is just one culprit in this online "surveillance economy," albeit a massive one — the company owns <a href="https://www.instagram.com/" target="_blank">Instagram</a>, <a href="https://atlassolutions.com/" target="_blank">Atlas</a>, <a href="https://www.whatsapp.com/" target="_blank">WhatsApp</a>, and dozens of other internet and technology companies and services. But it’s not the only player in this space. Google’s business model also relies on this kind of surveillance, and there are dozens of smaller players as well.
|
||||
</p>
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
<p>
|
||||
Pět vítězných soutěžních duelů v řadě, během nich jediný inkasovaný gól. Čtvrté místo v lize, stejný bodový zisk jako loňský šampion Manchester City a nadšené ohlasy z tábora těch nejrenomovanějších komentátorů ostrovního fotbalu.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
West Ham je opět v kurzu, nadšené ohlasy po nedělní jasné výhře 4:1 na hřišti Aston Villy zaplnily anglický mediální prostor.
|
||||
</p>
|
||||
|
@ -21,7 +22,11 @@
|
|||
<p>
|
||||
"Klíčová věc je ta, že když udělá změny, pořád jim zůstává stejná struktura. To je něco, co pravidelně říkáme třeba o Manchesteru City. Ve hře neustále zůstává nějaká fundamentální filosofie. West Ham to má podobně a už kvůli tomu je třeba před Moyesem smeknout," přirovnává Heskey.
|
||||
</p>
|
||||
<p><em>Podívejte se na důležité momenty zápasu Aston Villa - West Ham:</em></p>
|
||||
<p>
|
||||
<em>Podívejte se na důležité momenty zápasu Aston Villa - West Ham:</em>
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
V Evropské lize má West Ham po třech zápasech plný bodový zisk. V anglickém ligovém poháru dobyl čtvrtfinále, když vyřadil oba bohaté velkokluby z Manchesteru.
|
||||
</p>
|
||||
|
@ -37,6 +42,7 @@
|
|||
<p>
|
||||
"Pořád toho odvádí strašnou spoustu mimo hlavní pozornost. Jsou to důležité věci, které je snadné přehlédnout," píše ve svém hodnocení server Claret and Hugh.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
"S Declanem Ricem vytvořil silné partnerství a udělal spoustu těžké práce. Má dobrou rozehrávku. Jediné, na co si lze stěžovat, jsou jeho občasná špatná rozhodnutí ve finální třetině hřiště," hodnotí českého středopolaře londýnský večerník Evening Standard.
|
||||
</p>
|
||||
|
@ -55,6 +61,7 @@
|
|||
<p>
|
||||
"Hraje prostě velkolepě a připomínám, že je mu stále jen dvaadvacet let," kroutí hlavou Lineker. Není sám. Ještě před pár měsíci se většina odborníků pozastavovala nad údajnou cenovkou kolem 100 milionů liber. Nyní už zaznívají hlasy o tom, jak může být i tato hranice při případném přestupu Declana Rice výrazně překročena.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
S blížícím se zimním přestupním termínem budou spekulace nabývat na síle, fanoušci Hammers ale věří, že Rice zůstane nejméně do léta. Jeho spokojenost je do očí bijící, stejně jako ochota nechat na hřišti všechno ve prospěch Clarets and Blues.
|
||||
</p>
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
<p>
|
||||
Izuku was struggling to understand how he had even managed to get here, seated before the archvillain of Japan with only a sense of dread to keep him company. All Might sat concealed in an observation room, of the firm opinion that he could only aggravate the prisoner and he sent Izuku off with a strained smile. A vague haze hovered over Izuku’s memory. It started with a simple conversation gone astray on a long drive home.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
“So, who is All For One? Do we know anything about him beyond what you told me before? He’s been imprisoned for months now.” Izuku remembered asking All Might from the backseat of the car as Detective Tsukauchi leisurely drove along a sprawling highway.
|
||||
</p>
|
||||
|
@ -89,11 +90,13 @@
|
|||
<p>
|
||||
The conversation turned to school for the rest of the way.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
It might have been curiosity or it might have been the nagging sensation that chewed at his brain for the three weeks that he researched the subject of the conversation. All For One was a cryptid. Mystical in more ways than one, he was only a rumour on a network that was two-hundred years old. There were whispers of a shadowy figure who once ruled Japan, intermingled with a string of conspiracies and fragmented events.
|
||||
</p>
|
||||
<p>
|
||||
Izuku had even braved the dark web, poking and prodding at some of the seedier elements of the world wide web. The internet had rumours, but the dark web had stories.<br></p>
|
||||
Izuku had even braved the dark web, poking and prodding at some of the seedier elements of the world wide web. The internet had rumours, but the dark web had stories.<br>
|
||||
</p>
|
||||
<p>
|
||||
An implied yakuza wrote about his grandfather who lost a fire manipulation Quirk and his sanity without any reason. His grandfather had been institutionalised, crying and repeating “he took it, he took it” until his dying days. No one could console him.
|
||||
</p>
|
||||
|
@ -136,6 +139,7 @@
|
|||
<p>
|
||||
It took another month to convince his mother, who eventually gave in once All Might provided an extremely comprehensive schedule of how the visitations and any resulting research would be carefully balanced against Izuku’s schoolwork and internship.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The day of the visit finally arrived, four months after the initial conversation, much to Izuku’s dismay.
|
||||
</p>
|
||||
|
@ -200,7 +204,8 @@
|
|||
“Care,” All For One supplied, somewhat subdued as he struggled to breathe. “You’re only here to satisfy your curiosity as to whether or not the stories were true.”
|
||||
</p>
|
||||
<p>
|
||||
Izuku nodded, scratching at his notebook with his left hand. “Yes and no, I’m actually here to ask you about how your Quirk works.” <i>For now.</i></p>
|
||||
Izuku nodded, scratching at his notebook with his left hand. “Yes and no, I’m actually here to ask you about how your Quirk works.” <i>For now.</i>
|
||||
</p>
|
||||
<p>
|
||||
Another chortle, more restrained that the last.
|
||||
</p>
|
||||
|
@ -303,7 +308,8 @@
|
|||
<p>
|
||||
Anxiety was still ebbing over Izuku after Tsukauchi had been debriefed in the car.
|
||||
</p>
|
||||
<p><i>“It seems we share a hobby.”</i> Haunted Izuku on the drive home. As if ripping someone’s Quirk from them and leaving them lying traumatised on the ground was just a fun pastime and not an act of grievous bodily harm.
|
||||
<p>
|
||||
<i>“It seems we share a hobby.”</i> Haunted Izuku on the drive home. As if ripping someone’s Quirk from them and leaving them lying traumatised on the ground was just a fun pastime and not an act of grievous bodily harm.
|
||||
</p>
|
||||
<p>
|
||||
And he’d be dealing with him again in another week.
|
||||
|
|
|
@ -1,11 +1,25 @@
|
|||
<article><div id="readability-page-1">
|
||||
<header><h4>
|
||||
<header>
|
||||
<h4>
|
||||
Biz & IT —
|
||||
</h4>
|
||||
|
||||
<h2 itemprop="description">
|
||||
Two-year-old bug exposes thousands of servers to crippling attack.
|
||||
</h2></header><div itemprop="articleBody">
|
||||
<figure><img src="https://cdn.arstechnica.net/wp-content/uploads/2015/04/server-crash-640x426.jpg" alt="Just-released Minecraft exploit makes it easy to crash game servers"><figcaption></figcaption></figure><p>
|
||||
</h2>
|
||||
<section>
|
||||
|
||||
</section>
|
||||
</header>
|
||||
<div itemprop="articleBody">
|
||||
<figure>
|
||||
<img src="https://cdn.arstechnica.net/wp-content/uploads/2015/04/server-crash-640x426.jpg" alt="Just-released Minecraft exploit makes it easy to crash game servers">
|
||||
<figcaption>
|
||||
|
||||
</figcaption>
|
||||
</figure>
|
||||
|
||||
<p>
|
||||
A flaw in the wildly popular online game <em>Minecraft</em> makes it easy for just about anyone to crash the server hosting the game, according to a computer programmer who has released proof-of-concept code that exploits the vulnerability.
|
||||
</p>
|
||||
<p>
|
||||
|
@ -21,7 +35,34 @@
|
|||
<p>
|
||||
In my case, I chose to create lists within lists, down to five levels. This is a json representation of what it looks like.
|
||||
</p>
|
||||
<div><pre><code data-lang="javascript"><span>rekt</span><span>:</span><span>{</span><span>list</span><span>:</span><span>[</span><span>list</span><span>:</span><span>[</span><span>list</span><span>:</span><span>[</span><span>list</span><span>:</span><span>[</span><span>list</span><span>:</span><span>[</span><span>list</span><span>:</span><span>[</span><span>]</span><span>list</span><span>:</span><span>[</span><span>]</span><span>list</span><span>:</span><span>[</span><span>]</span><span>list</span><span>:</span><span>[</span><span>]</span><span>...</span><span>]</span><span>...</span><span>]</span><span>...</span><span>]</span><span>...</span><span>]</span><span>...</span><span>]</span><span>...</span><span>}</span></code></pre></div>
|
||||
<div>
|
||||
<pre><code data-lang="javascript"><span>rekt</span><span>:</span> <span>{</span>
|
||||
<span>list</span><span>:</span> <span>[</span>
|
||||
<span>list</span><span>:</span> <span>[</span>
|
||||
<span>list</span><span>:</span> <span>[</span>
|
||||
<span>list</span><span>:</span> <span>[</span>
|
||||
<span>list</span><span>:</span> <span>[</span>
|
||||
<span>list</span><span>:</span> <span>[</span>
|
||||
<span>]</span>
|
||||
<span>list</span><span>:</span> <span>[</span>
|
||||
<span>]</span>
|
||||
<span>list</span><span>:</span> <span>[</span>
|
||||
<span>]</span>
|
||||
<span>list</span><span>:</span> <span>[</span>
|
||||
<span>]</span>
|
||||
<span>...</span>
|
||||
<span>]</span>
|
||||
<span>...</span>
|
||||
<span>]</span>
|
||||
<span>...</span>
|
||||
<span>]</span>
|
||||
<span>...</span>
|
||||
<span>]</span>
|
||||
<span>...</span>
|
||||
<span>]</span>
|
||||
<span>...</span>
|
||||
<span>}</span></code></pre>
|
||||
</div>
|
||||
<p>
|
||||
The root of the object, <code>rekt</code>, contains 300 lists. Each list has a list with 10 sublists, and each of those sublists has 10 of their own, up until 5 levels of recursion. That’s a total of <code>10^5 * 300 = 30,000,000</code> lists.
|
||||
</p>
|
||||
|
@ -47,5 +88,6 @@
|
|||
<p>
|
||||
Ars is asking Mojang for comment and will update this post if company officials respond.
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</div></article>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<article><DIV id="readability-page-1"><article><h2>Lorem</h2>
|
||||
<article><DIV id="readability-page-1"><article>
|
||||
<h2>Lorem</h2>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
|
||||
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
|
||||
|
@ -29,4 +30,5 @@
|
|||
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
|
||||
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
|
||||
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
</p></article></DIV></article>
|
||||
</p>
|
||||
</article></DIV></article>
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
<p>Ut enim ad minim veniam,
|
||||
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
|
||||
consequat.</p>
|
||||
|
||||
<p>Duis aute irure dolor in reprehenderit in voluptate velit esse
|
||||
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
|
||||
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
|
||||
|
@ -13,6 +14,8 @@
|
|||
<p>Tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
|
||||
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
|
||||
consequat.</p>
|
||||
|
||||
|
||||
<p>Duis aute irure dolor in reprehenderit in voluptate velit esse
|
||||
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
|
||||
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
|
||||
|
|
|
@ -19,9 +19,12 @@
|
|||
<p>Mr Obama lands in Kenya later on Friday for his first visit since becoming president. </p>
|
||||
<p>But with just 18 months left in power, he said gun control was the area where he has been "most frustrated and most stymied" since coming to power in 2009.</p>
|
||||
<p>"If you look at the number of Americans killed since 9/11 by terrorism, it's less than 100. If you look at the number that have been killed by gun violence, it's in the tens of thousands," Mr Obama said. </p>
|
||||
<figure><img src="http://ichef.bbci.co.uk/news/555/cpsprodpb/462D/production/_84456971_gettyimages-167501087.jpg" datasrc="http://ichef.bbci.co.uk/news/976/cpsprodpb/462D/production/_84456971_gettyimages-167501087.jpg" alt="Gun control campaigners protest in McPhearson Square in Washington DC - 25 April 2013" height="549" width="976"><figcaption><span>
|
||||
<figure><img src="http://ichef.bbci.co.uk/news/555/cpsprodpb/462D/production/_84456971_gettyimages-167501087.jpg" datasrc="http://ichef.bbci.co.uk/news/976/cpsprodpb/462D/production/_84456971_gettyimages-167501087.jpg" alt="Gun control campaigners protest in McPhearson Square in Washington DC - 25 April 2013" height="549" width="976">
|
||||
<figcaption>
|
||||
<span>
|
||||
The president said he would continue fighting for greater gun control laws
|
||||
</span></figcaption></figure><p>"For us not to be able to resolve that issue has been something that is distressing," he added. </p>
|
||||
</span>
|
||||
</figcaption></figure><p>"For us not to be able to resolve that issue has been something that is distressing," he added. </p>
|
||||
<p>Mr Obama has pushed for stricter gun control throughout his presidency but has been unable to secure any significant changes to the laws. </p>
|
||||
<p>After nine African-American churchgoers were killed in South Carolina in June, he admitted "politics in this town" meant there were few options available.</p>
|
||||
<figure><img src="http://ichef.bbci.co.uk/news/555/media/images/76020000/jpg/_76020974_line976.jpg" datasrc="http://ichef.bbci.co.uk/news/464/media/images/76020000/jpg/_76020974_line976.jpg" alt="line" height="2" width="464"></figure><h2>Analysis: Jon Sopel, BBC News, Washington</h2>
|
||||
|
@ -37,9 +40,12 @@
|
|||
<p>"There are going to be tensions that arise. But if you look at my daughters' generation, they have an attitude about race that's entirely different than even my generation."</p>
|
||||
<p>Talking about how he was feeling after his recent successes, he said "every president, every leader has strengths and weaknesses". </p>
|
||||
<p>"One of my strengths is I have a pretty even temperament. I don't get too high when it's high and I don't get too low when it's low," he said. </p>
|
||||
<figure><img src="http://ichef-1.bbci.co.uk/news/555/cpsprodpb/142FD/production/_84458628_shirtreuters.jpg" datasrc="http://ichef-1.bbci.co.uk/news/976/cpsprodpb/142FD/production/_84458628_shirtreuters.jpg" alt="Customer looks at Obama shirts at a stall in Nairobi's Kibera slums, 23 July 2015" height="549" width="976"><figcaption><span>
|
||||
<figure><img src="http://ichef-1.bbci.co.uk/news/555/cpsprodpb/142FD/production/_84458628_shirtreuters.jpg" datasrc="http://ichef-1.bbci.co.uk/news/976/cpsprodpb/142FD/production/_84458628_shirtreuters.jpg" alt="Customer looks at Obama shirts at a stall in Nairobi's Kibera slums, 23 July 2015" height="549" width="976">
|
||||
<figcaption>
|
||||
<span>
|
||||
Kenya is getting ready to welcome the US president
|
||||
</span></figcaption></figure><h2>Kenya trip</h2>
|
||||
</span>
|
||||
</figcaption></figure><h2>Kenya trip</h2>
|
||||
<p>Mr Obama was speaking to the BBC at the White House before departing for Kenya.</p>
|
||||
<p>His father was Kenyan and the president is expected to meet relatives in Nairobi.</p>
|
||||
<p>Mr Obama has faced criticism in the country after the US legalised gay marriage. However, in his interview, the president said he would not fall silent on the issue.</p>
|
||||
|
|
|
@ -3,26 +3,62 @@
|
|||
I've written a couple of posts in the past few months but they were all for <a href="http://blog.ioactive.com/search/label/Andrew%20Zonenberg" target="_blank">the blog at work</a> so I figured I'm long overdue for one on Silicon Exposed.</p>
|
||||
<h2>
|
||||
So what's a GreenPak?</h2>
|
||||
<br><p> Silego Technology is a fabless semiconductor company located in the SF Bay area, which makes (among other things) a line of programmable logic devices known as GreenPak. Their <a href="http://www.silego.com/products/greenpak5.html" target="_blank">5th generation parts</a> were just announced, but I started this project before that happened so I'm still targeting the <a href="http://www.silego.com/products/greenpak4.html" target="_blank">4th generation</a>.<br><br> GreenPak devices are kind of like itty bitty <a href="http://www.cypress.com/products/32-bit-arm-cortex-m-psoc" target="_blank">PSoCs</a> - they have a mixed signal fabric with an ADC, DACs, comparators, voltage references, plus a digital LUT/FF fabric and some typical digital MCU peripherals like counters and oscillators (but no CPU).<br><br> It's actually an interesting architecture - FPGAs (including some devices marketed as CPLDs) are a 2D array of LUTs connected via wires to adjacent cells, and true (product term) CPLDs are a star topology of AND-OR arrays connected by a crossbar. GreenPak, on the other hand, is a star topology of LUTs, flipflops, and analog/digital hard IP connected to a crossbar.<br><br> Without further ado, here's a block diagram showing all the cool stuff you get in the SLG46620V:</p>
|
||||
<table><tbody>
|
||||
<tr><td><a href="https://1.bp.blogspot.com/-YIPC5jkXkDE/Vy7YPSqFKWI/AAAAAAAAAxI/a7D6Ji2GxoUvcrwUkI4RLZcr2LFQEJCTACLcB/s1600/block-diagram.png" imageanchor="1" target="_blank"><img height="512" src="https://1.bp.blogspot.com/-YIPC5jkXkDE/Vy7YPSqFKWI/AAAAAAAAAxI/a7D6Ji2GxoUvcrwUkI4RLZcr2LFQEJCTACLcB/s640/block-diagram.png" width="640"></a></td></tr>
|
||||
<tr><td>SLG46620V block diagram (from device datasheet)</td></tr>
|
||||
</tbody></table>
|
||||
<br><p> Silego Technology is a fabless semiconductor company located in the SF Bay area, which makes (among other things) a line of programmable logic devices known as GreenPak. Their <a href="http://www.silego.com/products/greenpak5.html" target="_blank">5th generation parts</a> were just announced, but I started this project before that happened so I'm still targeting the <a href="http://www.silego.com/products/greenpak4.html" target="_blank">4th generation</a>.<br>
|
||||
<br> GreenPak devices are kind of like itty bitty <a href="http://www.cypress.com/products/32-bit-arm-cortex-m-psoc" target="_blank">PSoCs</a> - they have a mixed signal fabric with an ADC, DACs, comparators, voltage references, plus a digital LUT/FF fabric and some typical digital MCU peripherals like counters and oscillators (but no CPU).<br>
|
||||
<br> It's actually an interesting architecture - FPGAs (including some devices marketed as CPLDs) are a 2D array of LUTs connected via wires to adjacent cells, and true (product term) CPLDs are a star topology of AND-OR arrays connected by a crossbar. GreenPak, on the other hand, is a star topology of LUTs, flipflops, and analog/digital hard IP connected to a crossbar.<br>
|
||||
<br> Without further ado, here's a block diagram showing all the cool stuff you get in the SLG46620V:</p>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="https://1.bp.blogspot.com/-YIPC5jkXkDE/Vy7YPSqFKWI/AAAAAAAAAxI/a7D6Ji2GxoUvcrwUkI4RLZcr2LFQEJCTACLcB/s1600/block-diagram.png" imageanchor="1" target="_blank"><img height="512" src="https://1.bp.blogspot.com/-YIPC5jkXkDE/Vy7YPSqFKWI/AAAAAAAAAxI/a7D6Ji2GxoUvcrwUkI4RLZcr2LFQEJCTACLcB/s640/block-diagram.png" width="640"></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>SLG46620V block diagram (from device datasheet)</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>
|
||||
They're also tiny (the SLG46620V is a 20-pin 0.4mm pitch STQFN measuring 2x3 mm, and the lower gate count SLG46140V is a mere 1.6x2 mm) and probably the cheapest programmable logic device on the market - $0.50 in low volume and less than $0.40 in larger quantities.<br><br> The Vdd range of GreenPak4 is huge, more like what you'd expect from an MCU than an FPGA! It can run on anything from 1.8 to 5V, although performance is only specified at 1.8, 3.3, and 5V nominal voltages. There's also a dual-rail version that trades one of the GPIO pins for a second power supply pin, allowing you to interface to logic at two different voltage levels.<br><br> To support low-cost/space-constrained applications, they even have the configuration memory on die. It's one-time programmable and needs external Vpp to program (presumably Silego didn't want to waste die area on charge pumps that would only be used once) but has a SRAM programming mode for prototyping.<br><br> The best part is that the development software (GreenPak Designer) is free of charge and provided for all major operating systems including Linux! Unfortunately, the only supported design entry method is schematic entry and there's no way to write your design in a HDL.<br><br> While schematics may be fine for quick tinkering on really simple designs, they quickly get unwieldy. The nightmare of a circuit shown below is just a bunch of counters hooked up to LEDs that blink at various rates.</p>
|
||||
<table><tbody>
|
||||
<tr><td><a href="https://1.bp.blogspot.com/-k3naUT3uXao/Vy7WFac246I/AAAAAAAAAw8/mePy_ostO8QJra5ZJrbP2WGhTlJ0B_r8gCLcB/s1600/schematic-from-hell.png" imageanchor="1" target="_blank"><img height="334" src="https://1.bp.blogspot.com/-k3naUT3uXao/Vy7WFac246I/AAAAAAAAAw8/mePy_ostO8QJra5ZJrbP2WGhTlJ0B_r8gCLcB/s640/schematic-from-hell.png" width="640"></a></td></tr>
|
||||
<tr><td>Schematic from hell!</td></tr>
|
||||
</tbody></table>
|
||||
They're also tiny (the SLG46620V is a 20-pin 0.4mm pitch STQFN measuring 2x3 mm, and the lower gate count SLG46140V is a mere 1.6x2 mm) and probably the cheapest programmable logic device on the market - $0.50 in low volume and less than $0.40 in larger quantities.<br>
|
||||
<br> The Vdd range of GreenPak4 is huge, more like what you'd expect from an MCU than an FPGA! It can run on anything from 1.8 to 5V, although performance is only specified at 1.8, 3.3, and 5V nominal voltages. There's also a dual-rail version that trades one of the GPIO pins for a second power supply pin, allowing you to interface to logic at two different voltage levels.<br>
|
||||
<br> To support low-cost/space-constrained applications, they even have the configuration memory on die. It's one-time programmable and needs external Vpp to program (presumably Silego didn't want to waste die area on charge pumps that would only be used once) but has a SRAM programming mode for prototyping.<br>
|
||||
<br> The best part is that the development software (GreenPak Designer) is free of charge and provided for all major operating systems including Linux! Unfortunately, the only supported design entry method is schematic entry and there's no way to write your design in a HDL.<br>
|
||||
<br> While schematics may be fine for quick tinkering on really simple designs, they quickly get unwieldy. The nightmare of a circuit shown below is just a bunch of counters hooked up to LEDs that blink at various rates.</p>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="https://1.bp.blogspot.com/-k3naUT3uXao/Vy7WFac246I/AAAAAAAAAw8/mePy_ostO8QJra5ZJrbP2WGhTlJ0B_r8gCLcB/s1600/schematic-from-hell.png" imageanchor="1" target="_blank"><img height="334" src="https://1.bp.blogspot.com/-k3naUT3uXao/Vy7WFac246I/AAAAAAAAAw8/mePy_ostO8QJra5ZJrbP2WGhTlJ0B_r8gCLcB/s640/schematic-from-hell.png" width="640"></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Schematic from hell!</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>
|
||||
As if this wasn't enough of a problem, the largest GreenPak4 device (the SLG46620V) is split into two halves with limited routing between them, and the GUI doesn't help the user manage this complexity at all - you have to draw your schematic in two halves and add "cross connections" between them.<br><br> The icing on the cake is that schematics are a pain to diff and collaborate on. Although GreenPak schematics are XML based, which is a touch better than binary, who wants to read a giant XML diff and try to figure out what's going on in the circuit?<br><br> This isn't going to be a post on the quirks of Silego's software, though - that would be boring. As it turns out, there's one more exciting feature of these chips that I didn't mention earlier: the configuration bitstream is 100% documented in the device datasheet! This is unheard of in the programmable logic world. As Nick of Arachnid Labs <a href="http://www.arachnidlabs.com/blog/2015/03/30/greenpak/" target="_blank">says</a>, the chip is "just dying for someone to write a VHDL or Verilog compiler for it". As you can probably guess by from the title of this post, I've been busy doing exactly that.</p>
|
||||
As if this wasn't enough of a problem, the largest GreenPak4 device (the SLG46620V) is split into two halves with limited routing between them, and the GUI doesn't help the user manage this complexity at all - you have to draw your schematic in two halves and add "cross connections" between them.<br>
|
||||
<br> The icing on the cake is that schematics are a pain to diff and collaborate on. Although GreenPak schematics are XML based, which is a touch better than binary, who wants to read a giant XML diff and try to figure out what's going on in the circuit?<br>
|
||||
<br> This isn't going to be a post on the quirks of Silego's software, though - that would be boring. As it turns out, there's one more exciting feature of these chips that I didn't mention earlier: the configuration bitstream is 100% documented in the device datasheet! This is unheard of in the programmable logic world. As Nick of Arachnid Labs <a href="http://www.arachnidlabs.com/blog/2015/03/30/greenpak/" target="_blank">says</a>, the chip is "just dying for someone to write a VHDL or Verilog compiler for it". As you can probably guess by from the title of this post, I've been busy doing exactly that.</p>
|
||||
<h2>
|
||||
Great! How does it work?</h2>
|
||||
<br><p> Rather than wasting time writing a synthesizer, I decided to write a GreenPak technology library for Clifford Wolf's excellent open source synthesis tool, <a href="http://www.clifford.at/yosys/" target="_blank">Yosys</a>, and then make a place-and-route tool to turn that into a final netlist. The post-PAR netlist can then be loaded into GreenPak Designer in order to program the device.<br><br> The first step of the process is to run the "synth_greenpak4" Yosys flow on the Verilog source. This runs a generic RTL synthesis pass, then some coarse-grained extraction passes to infer shift register and counter cells from behavioral logic, and finally maps the remaining logic to LUT/FF cells and outputs a JSON-formatted netlist.<br><br> Once the design has been synthesized, my tool (named, surprisingly, gp4par) is then launched on the netlist. It begins by parsing the JSON and constructing a directed graph of cell objects in memory. A second graph, containing all of the primitives in the device and the legal connections between them, is then created based on the device specified on the command line. (As of now only the SLG46620V is supported; the SLG46621V can be added fairly easily but the SLG46140V has a slightly different microarchitecture which will require a bit more work to support.)<br><br> After the graphs are generated, each node in the netlist graph is assigned a numeric label identifying the type of cell and each node in the device graph is assigned a list of legal labels: for example, an I/O buffer site is legal for an input buffer, output buffer, or bidirectional buffer.</p>
|
||||
<table><tbody>
|
||||
<tr><td><a href="https://2.bp.blogspot.com/-kIekczO693g/Vy7dBqYifXI/AAAAAAAAAxc/hMNJBs5bedIQOrBzzkhq4gbmhR-n58EQwCLcB/s1600/graph-labels.png" imageanchor="1" target="_blank"><img height="141" src="https://2.bp.blogspot.com/-kIekczO693g/Vy7dBqYifXI/AAAAAAAAAxc/hMNJBs5bedIQOrBzzkhq4gbmhR-n58EQwCLcB/s400/graph-labels.png" width="400"></a></td></tr>
|
||||
<tr><td>Example labeling for a subset of the netlist and device graphs</td></tr>
|
||||
</tbody></table>
|
||||
<br><p> Rather than wasting time writing a synthesizer, I decided to write a GreenPak technology library for Clifford Wolf's excellent open source synthesis tool, <a href="http://www.clifford.at/yosys/" target="_blank">Yosys</a>, and then make a place-and-route tool to turn that into a final netlist. The post-PAR netlist can then be loaded into GreenPak Designer in order to program the device.<br>
|
||||
<br> The first step of the process is to run the "synth_greenpak4" Yosys flow on the Verilog source. This runs a generic RTL synthesis pass, then some coarse-grained extraction passes to infer shift register and counter cells from behavioral logic, and finally maps the remaining logic to LUT/FF cells and outputs a JSON-formatted netlist.<br>
|
||||
<br> Once the design has been synthesized, my tool (named, surprisingly, gp4par) is then launched on the netlist. It begins by parsing the JSON and constructing a directed graph of cell objects in memory. A second graph, containing all of the primitives in the device and the legal connections between them, is then created based on the device specified on the command line. (As of now only the SLG46620V is supported; the SLG46621V can be added fairly easily but the SLG46140V has a slightly different microarchitecture which will require a bit more work to support.)<br>
|
||||
<br> After the graphs are generated, each node in the netlist graph is assigned a numeric label identifying the type of cell and each node in the device graph is assigned a list of legal labels: for example, an I/O buffer site is legal for an input buffer, output buffer, or bidirectional buffer.</p>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="https://2.bp.blogspot.com/-kIekczO693g/Vy7dBqYifXI/AAAAAAAAAxc/hMNJBs5bedIQOrBzzkhq4gbmhR-n58EQwCLcB/s1600/graph-labels.png" imageanchor="1" target="_blank"><img height="141" src="https://2.bp.blogspot.com/-kIekczO693g/Vy7dBqYifXI/AAAAAAAAAxc/hMNJBs5bedIQOrBzzkhq4gbmhR-n58EQwCLcB/s400/graph-labels.png" width="400"></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Example labeling for a subset of the netlist and device graphs</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>
|
||||
The labeled nodes now need to be placed. The initial placement uses a simple greedy algorithm to create a valid (although not necessarily optimal or even routable) placement:</p>
|
||||
<ol>
|
||||
|
@ -48,7 +84,8 @@
|
|||
<li>If the score is worse, accept it with a random probability which decreases as the iteration number goes up. If the change is not accepted, restore the previous placement.</li>
|
||||
</ol>
|
||||
<p>
|
||||
After optimization, the design is checked for routability. If any edges in the netlist graph don't correspond to edges in the device graph, the user probably asked for something impossible (for example, trying to hook a flipflop's output to a comparator's reference voltage input) so fail with an error.<br><br> The design is then routed. This is quite simple due to the crossbar structure of the device. For each edge in the netlist:</p>
|
||||
After optimization, the design is checked for routability. If any edges in the netlist graph don't correspond to edges in the device graph, the user probably asked for something impossible (for example, trying to hook a flipflop's output to a comparator's reference voltage input) so fail with an error.<br>
|
||||
<br> The design is then routed. This is quite simple due to the crossbar structure of the device. For each edge in the netlist:</p>
|
||||
<ol>
|
||||
<li>If dedicated (non-fabric) routing is used for this path, configure the destination's input mux appropriately and stop.</li>
|
||||
<li>If the source and destination are in the same half of the device, configure the destination's input mux appropriately and stop.</li>
|
||||
|
@ -64,11 +101,17 @@
|
|||
<li>Some signals (such as comparator inputs and oscillator power-down controls) are generated by a shared mux and fed to many loads. If different loads require conflicting settings for the shared mux, fail with an error.</li>
|
||||
</ul>
|
||||
<p>
|
||||
If DRC passes with no errors, configure all of the individual cells in the netlist based on the HDL parameters. Fail with an error if an invalid configuration was requested.<br><br> Finally, generate the bitstream from all of the per-cell configuration and write it to a file.</p>
|
||||
If DRC passes with no errors, configure all of the individual cells in the netlist based on the HDL parameters. Fail with an error if an invalid configuration was requested.<br>
|
||||
<br> Finally, generate the bitstream from all of the per-cell configuration and write it to a file.</p>
|
||||
<h2>
|
||||
Great, let's get started!</h2>
|
||||
<p>
|
||||
If you don't already have one, you'll need to buy a <a href="http://www.silego.com/buy/index.php?main_page=product_info&products_id=388" target="_blank">GreenPak4 development kit</a>. The kit includes samples of the SLG46620V (among other devices) and a programmer/emulation board. While you're waiting for it to arrive, install <a href="http://www.silego.com/softdoc/software.html" target="_blank">GreenPak Designer</a>.<br><br> Download and install Yosys. Although Clifford is pretty good at merging my pull requests, only <a href="https://github.com/azonenberg/yosys/" target="_blank">my fork on Github</a> is guaranteed to have the most up-to-date support for GreenPak devices so don't be surprised if you can't use a bleeding-edge feature with mainline Yosys.<br><br> Download and install gp4par. You can get it from <a href="https://github.com/azonenberg/openfpga/" target="_blank">the Github repository</a>.<br><br> Write your HDL, compile with Yosys, P&R with gp4par, and import the bitstream into GreenPak Designer to program the target device. The most current gp4par manual is included in LaTeX source form in the source tree and is automatically built as part of the compile process. If you're just browsing, there's a <a href="http://thanatos.virtual.antikernel.net/unlisted/gp4-hdl.pdf" target="_blank">relatively recent PDF version</a> on my web server.<br><br> If you'd like to see the Verilog that produced the nightmare of a schematic I showed above, <a href="https://github.com/azonenberg/openfpga/blob/master/tests/greenpak4/Blinky/Blinky.v" target="_blank">here it is</a>.<br><br> Be advised that this project is still very much a work in progress and there are still a number of SLG46620V features I don't support (see the manual for exact details).</p>
|
||||
If you don't already have one, you'll need to buy a <a href="http://www.silego.com/buy/index.php?main_page=product_info&products_id=388" target="_blank">GreenPak4 development kit</a>. The kit includes samples of the SLG46620V (among other devices) and a programmer/emulation board. While you're waiting for it to arrive, install <a href="http://www.silego.com/softdoc/software.html" target="_blank">GreenPak Designer</a>.<br>
|
||||
<br> Download and install Yosys. Although Clifford is pretty good at merging my pull requests, only <a href="https://github.com/azonenberg/yosys/" target="_blank">my fork on Github</a> is guaranteed to have the most up-to-date support for GreenPak devices so don't be surprised if you can't use a bleeding-edge feature with mainline Yosys.<br>
|
||||
<br> Download and install gp4par. You can get it from <a href="https://github.com/azonenberg/openfpga/" target="_blank">the Github repository</a>.<br>
|
||||
<br> Write your HDL, compile with Yosys, P&R with gp4par, and import the bitstream into GreenPak Designer to program the target device. The most current gp4par manual is included in LaTeX source form in the source tree and is automatically built as part of the compile process. If you're just browsing, there's a <a href="http://thanatos.virtual.antikernel.net/unlisted/gp4-hdl.pdf" target="_blank">relatively recent PDF version</a> on my web server.<br>
|
||||
<br> If you'd like to see the Verilog that produced the nightmare of a schematic I showed above, <a href="https://github.com/azonenberg/openfpga/blob/master/tests/greenpak4/Blinky/Blinky.v" target="_blank">here it is</a>.<br>
|
||||
<br> Be advised that this project is still very much a work in progress and there are still a number of SLG46620V features I don't support (see the manual for exact details).</p>
|
||||
<h2>
|
||||
I love it / it segfaulted / there's a problem in the manual!</h2>
|
||||
<p>
|
||||
|
@ -76,9 +119,15 @@
|
|||
<h2>
|
||||
You're competing with Silego's IDE. Have they found out and sued you yet?</h2>
|
||||
<p>
|
||||
Nope. They're fully aware of what I'm doing and are rolling out the red carpet for me. They love the idea of a HDL flow as an alternative to schematic entry and are pretty amazed at how fast it's coming together.<br><br> After I reported a few bugs in their datasheets they decided to skip the middleman and give me direct access to the engineer who writes their documentation so that I can get faster responses. The last time I found a problem (two different parts of the datasheet contradicted each other) an updated datasheet was in my inbox and on their website by the next day. I only wish Xilinx gave me that kind of treatment!<br><br> They've even <a href="https://twitter.com/SilegoTech/status/717018987771469824" target="_blank">offered me free hardware</a> to help me add support for their latest product family, although I plan to get GreenPak4 support to a more stable state before taking them up on the offer.</p>
|
||||
Nope. They're fully aware of what I'm doing and are rolling out the red carpet for me. They love the idea of a HDL flow as an alternative to schematic entry and are pretty amazed at how fast it's coming together.<br>
|
||||
<br> After I reported a few bugs in their datasheets they decided to skip the middleman and give me direct access to the engineer who writes their documentation so that I can get faster responses. The last time I found a problem (two different parts of the datasheet contradicted each other) an updated datasheet was in my inbox and on their website by the next day. I only wish Xilinx gave me that kind of treatment!<br>
|
||||
<br> They've even <a href="https://twitter.com/SilegoTech/status/717018987771469824" target="_blank">offered me free hardware</a> to help me add support for their latest product family, although I plan to get GreenPak4 support to a more stable state before taking them up on the offer.</p>
|
||||
<h2>
|
||||
So what's next?</h2>
|
||||
<br><p> Better testing, for starters. I have to verify functionality by hand with a DMM and oscilloscope, which is time consuming.<br><br> My contact at Silego says they're going to be giving me documentation on the SRAM emulation interface soon, so I'm going to make a hardware-in-loop test platform that connects to my desktop and the Silego ZIF socket, and lets me load new bitstreams via a scriptable interface. It'll have FPGA-based digital I/O as well as an ADC and DAC on every device pin, plus an adjustable voltage regulator for power, so I can feed in arbitrary mixed-signal test waveforms and write PC-based unit tests to verify correct behavior.<br><br> Other than that, I want to finish support for the SLG46620V in the next month or two. The SLG46621V will be an easy addition since only one pin and the relevant configuration bits have changed from the 46620 (I suspect they're the same die, just bonded out differently).<br><br> Once that's done I'll have to do some more extensive work to add the SLG46140V since the architecture is a bit different (a lot of the combinatorial logic is merged into multi-function blocks). Luckily, the 46140 has a lot in common architecturally with the GreenPak5 family, so once that's done GreenPak5 will probably be a lot easier to add support for.<br><br> My thanks go out to Clifford Wolf, whitequark, the IRC users in ##openfpga, and everyone at Silego I've worked with to help make this possible. I hope that one day this project will become mature enough that Silego will ship it as an officially supported extension to GreenPak Designer, making history by becoming the first modern programmable logic vendor to ship a fully open source synthesis and P&R suite.
|
||||
<br><p> Better testing, for starters. I have to verify functionality by hand with a DMM and oscilloscope, which is time consuming.<br>
|
||||
<br> My contact at Silego says they're going to be giving me documentation on the SRAM emulation interface soon, so I'm going to make a hardware-in-loop test platform that connects to my desktop and the Silego ZIF socket, and lets me load new bitstreams via a scriptable interface. It'll have FPGA-based digital I/O as well as an ADC and DAC on every device pin, plus an adjustable voltage regulator for power, so I can feed in arbitrary mixed-signal test waveforms and write PC-based unit tests to verify correct behavior.<br>
|
||||
<br> Other than that, I want to finish support for the SLG46620V in the next month or two. The SLG46621V will be an easy addition since only one pin and the relevant configuration bits have changed from the 46620 (I suspect they're the same die, just bonded out differently).<br>
|
||||
<br> Once that's done I'll have to do some more extensive work to add the SLG46140V since the architecture is a bit different (a lot of the combinatorial logic is merged into multi-function blocks). Luckily, the 46140 has a lot in common architecturally with the GreenPak5 family, so once that's done GreenPak5 will probably be a lot easier to add support for.<br>
|
||||
<br> My thanks go out to Clifford Wolf, whitequark, the IRC users in ##openfpga, and everyone at Silego I've worked with to help make this possible. I hope that one day this project will become mature enough that Silego will ship it as an officially supported extension to GreenPak Designer, making history by becoming the first modern programmable logic vendor to ship a fully open source synthesis and P&R suite.
|
||||
</p>
|
||||
</div></article>
|
||||
|
|
|
@ -1,19 +1,52 @@
|
|||
<article><DIV id="readability-page-1">
|
||||
<DIV>
|
||||
<figure><div>
|
||||
|
||||
|
||||
|
||||
<figure>
|
||||
<div>
|
||||
<p><img itemprop="image" src="http://media.breitbart.com/media/2016/11/GettyImages-621866810-640x480.jpg" alt="Supporters of Republican presidential nominee Donald Trump cheer during election night at the New York Hilton Midtown in New York on November 9, 2016. / AFP / JIM WATSON (Photo credit should read JIM WATSON/AFP/Getty Images)" width="640" height="480"></p>
|
||||
<p>JIM WATSON/AFP/Getty Images</p>
|
||||
</div></figure><time datetime="2016-12-22T10:43:37Z">22 Dec, 2016</time><time datetime="2016-12-22T18:59:12Z">22 Dec, 2016</time>
|
||||
</div>
|
||||
</figure>
|
||||
<time datetime="2016-12-22T10:43:37Z">22 Dec, 2016</time>
|
||||
<time datetime="2016-12-22T18:59:12Z">22 Dec, 2016</time>
|
||||
</DIV>
|
||||
<div>
|
||||
<div id="EmailOptin"><p><span>SIGN UP</span> FOR OUR NEWSLETTER</p></div>
|
||||
|
||||
|
||||
<div id="EmailOptin">
|
||||
<p><span>SIGN UP</span> FOR OUR NEWSLETTER</p>
|
||||
|
||||
</div>
|
||||
<h2><span>Snopes fact checker and staff writer David Emery posted to Twitter asking if there were “any un-angry Trump supporters?”</span></h2>
|
||||
<p><span>Emery, a writer for partisan “fact-checking” website Snopes.com which soon will be in charge of labelling </span><a href="http://www.breitbart.com/tech/2016/12/15/facebook-introduce-warning-labels-stories-deemed-fake-news/" target="_blank"><span>“fake news”</span></a><span> alongside ABC News and Politifact, retweeted an article by Vulture magazine relating to the </span><a href="http://www.breitbart.com/big-hollywood/2016/11/19/boycotthamilton-trends-hamilton-cast-members-harass-mike-pence/" target="_blank"><span>protests</span></a><span> of the <em>Hamilton</em> musical following the decision by the cast of the show to make a </span><a href="http://www.breitbart.com/big-hollywood/2016/11/19/tolerance-hamilton-cast-lectures-mike-pence-broadway-stage/" target="_blank"><span>public announcement</span></a><span> to Vice-president elect Mike Pence while he watched the performance with his family.</span></p>
|
||||
<div id="EmailOptinM"><p><span>SIGN UP</span> FOR OUR NEWSLETTER</p></div>
|
||||
<div id="EmailOptinM">
|
||||
<p><span>SIGN UP</span> FOR OUR NEWSLETTER</p>
|
||||
|
||||
</div>
|
||||
<p><span>The tweet from Vulture magazine reads, “</span><a href="https://twitter.com/hashtag/Hamilton?src=hash" target="_blank" rel="noopener"><span>#Hamilton</span></a><span> Chicago show interrupted by angry Trump supporter.” Emery retweeted the story, saying, “Are there un-angry Trump supporters?”</span></p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<p><span>This isn’t the first time the Snopes.com writer has expressed anti-Trump sentiment on his Twitter page. In another tweet in which Emery links to an article that falsely attributes a quote to President-elect Trump, Emery states, “Incredibly, some people actually think they have to put words in Trump’s mouth to make him look bad.”</span></p>
|
||||
|
||||
|
||||
<p><span>Emery also retweeted an article by <em>New York</em> magazine that claimed President-elect Trump relied on lies to win during his campaign and that we now lived in a “post-truth” society. “Before long we’ll all have forgotten what it was like to live in the same universe; or maybe we already have,” Emery tweeted.</span></p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<p><span>Facebook believe that Emery, along with other Snopes writers, ABC News, and </span><a href="http://www.breitbart.com/tech/2016/12/16/flashback-weekly-standard-data-shows-politifact-has-it-out-for-republicans/" target="_blank"><span>Politifact</span></a><span> are impartial enough to label and silence what they believe to be “fake news” on social media. </span></p>
|
||||
<p><i><span>Lucas Nolan is a reporter for Breitbart Tech covering issues of free speech and online censorship. Follow him on Twitter </span></i><a href="http://twitter.com/lucasnolan_" target="_blank" rel="noopener"><i><span>@LucasNolan_</span></i></a><i><span> or email him at </span></i><a href="http://www.breitbart.com/wp-admin/blank" target="_blank"><i><span>lnolan@breitbart.com</span></i></a></p>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</DIV></article>
|
||||
|
|
|
@ -1,59 +1,116 @@
|
|||
<article><div itemprop="articleBody" id="readability-page-1">
|
||||
<p>Most people go to hotels for the pleasure of sleeping in a giant bed with clean white sheets and waking up to fresh towels in the morning.</p>
|
||||
|
||||
<p>But those towels and sheets might not be as clean as they look, according to the hotel bosses that responded to an online thread about the things hotel owners don’t want you to know.</p>
|
||||
|
||||
<p>Zeev Sharon and Michael Forrest Jones both run hotel start-ups in the US. Forrest Jones runs the start-up Beechmont Hotels Corporation, a hotel operating company that consults with hotel owners on how they can improve their business. Sharon is the CEO of Hotelied, a start-up that allows people to sign up for discounts at luxury hotels.</p>
|
||||
|
||||
<p>But even luxury hotels aren’t always cleaned as often as they should be.</p>
|
||||
|
||||
<p>Here are some of the secrets that the receptionist will never tell you when you check in, according to answers posted on <a href="https://www.quora.com/What-are-the-things-we-dont-know-about-hotel-rooms" target="_blank">Quora</a>.</p>
|
||||
|
||||
<h3> </h3>
|
||||
|
||||
<div>
|
||||
<div><p><img src="https://static.independent.co.uk/s3fs-public/styles/story_medium/public/thumbnails/image/2014/03/18/10/bandb2.jpg" alt="bandb2.jpg" title="bandb2.jpg" width="564" height="423"></p></div>
|
||||
<div>
|
||||
|
||||
<p><img src="https://static.independent.co.uk/s3fs-public/styles/story_medium/public/thumbnails/image/2014/03/18/10/bandb2.jpg" alt="bandb2.jpg" title="bandb2.jpg" width="564" height="423"></p>
|
||||
|
||||
</div>
|
||||
<p>Even posh hotels might not wash a blanket in between stays
|
||||
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<p>1. Take any blankets or duvets off the bed</p>
|
||||
|
||||
<p>Forrest Jones said that anything that comes into contact with any of the previous guest’s skin should be taken out and washed every time the room is made, but that even the fanciest hotels don’t always do so. "Hotels are getting away from comforters. Blankets are here to stay, however. But some hotels are still hesitant about washing them every day if they think they can get out of it," he said.</p>
|
||||
<div><p>Video shows bed bug infestation at New York hotel</p></div>
|
||||
<h3></h3>
|
||||
|
||||
<div>
|
||||
<div><p><img src="https://static.independent.co.uk/s3fs-public/styles/story_medium/public/thumbnails/image/2015/05/26/11/hotel-door-getty.jpg" alt="hotel-door-getty.jpg" title="hotel-door-getty.jpg" width="564" height="423"></p></div>
|
||||
|
||||
<p>Video shows bed bug infestation at New York hotel</p>
|
||||
</div>
|
||||
|
||||
<h3> </h3>
|
||||
|
||||
<div>
|
||||
<div>
|
||||
|
||||
<p><img src="https://static.independent.co.uk/s3fs-public/styles/story_medium/public/thumbnails/image/2015/05/26/11/hotel-door-getty.jpg" alt="hotel-door-getty.jpg" title="hotel-door-getty.jpg" width="564" height="423"></p>
|
||||
|
||||
</div>
|
||||
<p>Forrest Jones advised stuffing the peep hole with a strip of rolled up notepaper when not in use.
|
||||
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<p>2. Check the peep hole has not been tampered with</p>
|
||||
|
||||
<p>This is not common, but can happen, Forrest Jones said. He advised stuffing the peep hole with a strip of rolled up notepaper when not in use. When someone knocks on the door, the paper can be removed to check who is there. If no one is visible, he recommends calling the front desk immediately. “I look forward to the day when I can tell you to choose only hotels where every employee who has access to guestroom keys is subjected to a complete public records background check, prior to hire, and every year or two thereafter. But for now, I can't,” he said.</p>
|
||||
|
||||
<h3> </h3>
|
||||
|
||||
<div>
|
||||
<div><p><img src="https://static.independent.co.uk/s3fs-public/styles/story_medium/public/thumbnails/image/2013/07/31/15/luggage-3.jpg" alt="luggage-3.jpg" title="luggage-3.jpg" width="564" height="423"></p></div>
|
||||
<div>
|
||||
|
||||
<p><img src="https://static.independent.co.uk/s3fs-public/styles/story_medium/public/thumbnails/image/2013/07/31/15/luggage-3.jpg" alt="luggage-3.jpg" title="luggage-3.jpg" width="564" height="423"></p>
|
||||
|
||||
</div>
|
||||
<p>Put luggage on the floor
|
||||
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<p>3. Don’t use a wooden luggage rack</p>
|
||||
|
||||
<p>Bedbugs love wood. Even though a wooden luggage rack might look nicer and more expensive than a metal one, it’s a breeding ground for bugs. Forrest Jones says guests should put the items they plan to take from bags on other pieces of furniture and leave the bag on the floor.</p>
|
||||
|
||||
<h3> </h3>
|
||||
|
||||
<div>
|
||||
<div><p><img src="https://static.independent.co.uk/s3fs-public/styles/story_medium/public/thumbnails/image/2015/04/13/11/Lifestyle-hotels.jpg" alt="Lifestyle-hotels.jpg" title="Lifestyle-hotels.jpg" width="564" height="423"></p></div>
|
||||
<div>
|
||||
|
||||
<p><img src="https://static.independent.co.uk/s3fs-public/styles/story_medium/public/thumbnails/image/2015/04/13/11/Lifestyle-hotels.jpg" alt="Lifestyle-hotels.jpg" title="Lifestyle-hotels.jpg" width="564" height="423"></p>
|
||||
|
||||
</div>
|
||||
<p>The old rule of thumb is that for every 00 invested in a room, the hotel should charge in average daily rate
|
||||
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<p>4. Hotel rooms are priced according to how expensive they were to build</p>
|
||||
|
||||
<p>Zeev Sharon said that the old rule of thumb is that for every $1000 invested in a room, the hotel should charge $1 in average daily rate. So a room that cost $300,000 to build, should sell on average for $300/night.</p>
|
||||
|
||||
|
||||
|
||||
<h3>5. Beware the wall-mounted hairdryer</h3>
|
||||
|
||||
<p>It contains the most germs of anything in the room. Other studies have said the TV remote and bedside lamp switches are the most unhygienic. “Perhaps because it's something that's easy for the housekeepers to forget to check or to squirt down with disinfectant,” Forrest Jones said.</p>
|
||||
|
||||
<h3> </h3>
|
||||
|
||||
|
||||
|
||||
<h3>6. Mini bars almost always lose money</h3>
|
||||
|
||||
<p>Despite the snacks in the minibar seeming like the most overpriced food you have ever seen, hotel owners are still struggling to make a profit from those snacks. "Minibars almost always lose money, even when they charge $10 for a Diet Coke,” Sharon said.</p>
|
||||
|
||||
<h3> </h3>
|
||||
|
||||
<div>
|
||||
<div><p><img src="https://static.independent.co.uk/s3fs-public/styles/story_medium/public/thumbnails/image/2014/03/13/16/agenda7.jpg" alt="agenda7.jpg" title="agenda7.jpg" width="564" height="423"></p></div>
|
||||
<div>
|
||||
|
||||
<p><img src="https://static.independent.co.uk/s3fs-public/styles/story_medium/public/thumbnails/image/2014/03/13/16/agenda7.jpg" alt="agenda7.jpg" title="agenda7.jpg" width="564" height="423"></p>
|
||||
|
||||
</div>
|
||||
<p>Towels should always be cleaned between stays
|
||||
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<p>7. Always made sure the hand towels are clean when you arrive</p>
|
||||
|
||||
<p>Forrest Jones made a discovery when he was helping out with the housekeepers. “You know where you almost always find a hand towel in any recently-vacated hotel room that was occupied by a guy? On the floor, next to the bed, about halfway down, maybe a little toward the foot of the bed. Same spot in the floor, next to almost every bed occupied by a man, in every room. I'll leave the rest to your imagination,” he said.</p>
|
||||
<meta itemprop="datePublished" content="2016-05-08T10:11:51+01:00">
|
||||
<ul>
|
||||
|
@ -63,5 +120,7 @@
|
|||
<li><a itemprop="keywords" href="http://fakehost/topic/Hotels" target="_blank">Hotels</a></li>
|
||||
<li><a itemprop="keywords" href="http://fakehost/topic/Hygiene" target="_blank">Hygiene</a></li>
|
||||
</ul>
|
||||
<p><a href="http://fakehost/syndication/reuse-permision-form?url=http://www.independent.co.uk/news/business/news/seven-secrets-that-hotel-owners-dont-want-you-to-know-10506160.html" target="_blank"><img src="http://fakehost/sites/all/themes/ines_themes/independent_theme/img/reuse.png" width="25">Reuse content</a></p>
|
||||
|
||||
<p><a href="http://fakehost/syndication/reuse-permision-form?url=http://www.independent.co.uk/news/business/news/seven-secrets-that-hotel-owners-dont-want-you-to-know-10506160.html" target="_blank"><img src="http://fakehost/sites/all/themes/ines_themes/independent_theme/img/reuse.png" width="25">Reuse content</a>
|
||||
</p>
|
||||
</div></article>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<article><div id="readability-page-1">
|
||||
<div id="superlist_3758406_5547137" rel:buzz_num="1">
|
||||
<h2>The mother of a woman who took suspected diet pills bought online has described how her daughter was “literally burning up from within” moments before her death.</h2>
|
||||
|
||||
<p> <span>West Merica Police</span></p>
|
||||
</div>
|
||||
<div id="superlist_3758406_5547213" rel:buzz_num="2">
|
||||
|
@ -12,13 +13,18 @@
|
|||
</div>
|
||||
<div id="superlist_3758406_5547140">
|
||||
<div>
|
||||
<div><p><img src="http://ak-hdl.buzzfed.com/static/2015-04/21/5/enhanced/webdr12/grid-cell-2501-1429608056-15.jpg" rel:bf_image_src="http://ak-hdl.buzzfed.com/static/2015-04/21/5/enhanced/webdr12/grid-cell-2501-1429608056-15.jpg" height="412" width="203"></p></div>
|
||||
<div>
|
||||
<p><img src="http://ak-hdl.buzzfed.com/static/2015-04/21/5/enhanced/webdr12/grid-cell-2501-1429608056-15.jpg" rel:bf_image_src="http://ak-hdl.buzzfed.com/static/2015-04/21/5/enhanced/webdr12/grid-cell-2501-1429608056-15.jpg" height="412" width="203"></p>
|
||||
</div>
|
||||
<p>Facebook</p>
|
||||
</div>
|
||||
<div>
|
||||
<div><p><img src="http://ak-hdl.buzzfed.com/static/2015-04/21/5/enhanced/webdr12/grid-cell-2501-1429608057-18.jpg" rel:bf_image_src="http://ak-hdl.buzzfed.com/static/2015-04/21/5/enhanced/webdr12/grid-cell-2501-1429608057-18.jpg" height="412" width="412"></p></div>
|
||||
<div>
|
||||
<p><img src="http://ak-hdl.buzzfed.com/static/2015-04/21/5/enhanced/webdr12/grid-cell-2501-1429608057-18.jpg" rel:bf_image_src="http://ak-hdl.buzzfed.com/static/2015-04/21/5/enhanced/webdr12/grid-cell-2501-1429608057-18.jpg" height="412" width="412"></p>
|
||||
</div>
|
||||
<p>Facebook</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div id="superlist_3758406_5547284" rel:buzz_num="4">
|
||||
<p>West Mercia police <a href="https://www.westmercia.police.uk/article/9500/Warning-Issued-As-Shrewsbury-Woman-Dies-After-Taking-Suspected-Diet-Pills" target="_blank">said the tablets were believed to contain dinitrophenol</a>, known as DNP, which is a highly toxic industrial chemical. </p>
|
||||
|
@ -28,7 +34,8 @@
|
|||
</div>
|
||||
<div id="superlist_3758406_5547219" rel:buzz_num="5">
|
||||
<h2>Fiona Parry issued a plea for people to stay away from pills containing the chemical.</h2>
|
||||
<br><p>“[Eloise] just never really understood how dangerous the tablets that she took were,” she said. “Most of us don’t believe that a slimming tablet could possibly kill us.</p>
|
||||
<br>
|
||||
<p>“[Eloise] just never really understood how dangerous the tablets that she took were,” she said. “Most of us don’t believe that a slimming tablet could possibly kill us.</p>
|
||||
<p>“DNP is not a miracle slimming pill. It is a deadly toxin.”</p>
|
||||
</div>
|
||||
</div></article>
|
||||
|
|
|
@ -1,23 +1,40 @@
|
|||
<article><DIV id="readability-page-1"><article itemscope="itemscope" itemtype="https://schema.org/NewsArticle"><meta itemprop="datePublished" content="2019-04-30T13:39:00-04:00">
|
||||
<article><DIV id="readability-page-1"><article itemscope="itemscope" itemtype="https://schema.org/NewsArticle">
|
||||
<meta itemprop="datePublished" content="2019-04-30T13:39:00-04:00">
|
||||
<meta itemprop="dateModified" content="2019-04-30T13:40:00-04:00">
|
||||
<meta itemprop="mainEntityOfPage" content="https://www.citylab.com/design/2019/04/neon-signage-20th-century-history/588400/">
|
||||
<figure itemprop="image" itemscope="itemscope" itemtype="http://schema.org/ImageObject"><picture><source srcset="https://cdn.citylab.com/media/img/citylab/2019/04/mr1/940.jpg?mod=1556645448" media="(min-width: 1024px)"></source><source srcset="https://cdn.citylab.com/media/img/citylab/2019/04/mr1/lead_large.jpg?mod=1556645448" media="(min-width: 576px)"></source></picture><meta itemprop="height" content="128">
|
||||
|
||||
<figure itemprop="image" itemscope="itemscope" itemtype="http://schema.org/ImageObject">
|
||||
<picture>
|
||||
<source srcset="https://cdn.citylab.com/media/img/citylab/2019/04/mr1/940.jpg?mod=1556645448" media="(min-width: 1024px)"></source>
|
||||
<source srcset="https://cdn.citylab.com/media/img/citylab/2019/04/mr1/lead_large.jpg?mod=1556645448" media="(min-width: 576px)"></source>
|
||||
</picture>
|
||||
<meta itemprop="height" content="128">
|
||||
<meta itemprop="width" content="300">
|
||||
<meta itemprop="url" content="https://cdn.citylab.com/media/img/citylab/2019/04/mr1/300.jpg?mod=1556645448">
|
||||
<picture><source srcset="https://cdn.citylab.com/media/img/citylab/2019/04/mr1/300.jpg?mod=1556645448" media="(max-width: 575px)"></source><img src="https://cdn.citylab.com/media/img/citylab/2019/04/mr1/300.jpg?mod=1556645448" alt=""></picture><figcaption><span itemprop="caption">The Moulin Rouge cabaret in
|
||||
<picture>
|
||||
<source srcset="https://cdn.citylab.com/media/img/citylab/2019/04/mr1/300.jpg?mod=1556645448" media="(max-width: 575px)"></source>
|
||||
<img src="https://cdn.citylab.com/media/img/citylab/2019/04/mr1/300.jpg?mod=1556645448" alt="">
|
||||
|
||||
</picture>
|
||||
<figcaption>
|
||||
<span itemprop="caption">The Moulin Rouge cabaret in
|
||||
Paris</span> <span itemprop="creator">Benoit
|
||||
Tessier/Reuters</span></figcaption></figure><div>
|
||||
Tessier/Reuters</span>
|
||||
</figcaption>
|
||||
</figure>
|
||||
<div>
|
||||
<h2 itemprop="headline">
|
||||
Why Neon Is the Ultimate Symbol of the 20th Century
|
||||
</h2>
|
||||
<div><p><span><time>1:39 PM
|
||||
ET</time></span></p></div>
|
||||
|
||||
</div>
|
||||
<h2 itemprop="description">
|
||||
The once-ubiquitous form of lighting was novel when it first emerged in the early 1900s,
|
||||
though it has since come to represent decline.
|
||||
</h2>
|
||||
<section id="article-section-1"><p>
|
||||
|
||||
<section id="article-section-1">
|
||||
<p>
|
||||
In the summer of 1898, the Scottish chemist Sir William Ramsay made a discovery that
|
||||
would eventually give the Moulin Rouge in Paris, the Las Vegas Strip, and New York’s
|
||||
Times Square their perpetual nighttime glow. Using the boiling point of argon as a
|
||||
|
@ -41,6 +58,7 @@
|
|||
lack of glossy historical images. Nonetheless, de Miranda makes a convincing case for
|
||||
neon as a symbol of the grand modern ambitions of the 20th century.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
De Miranda beautifully evokes the notion of neon lighting as an icon of the 1900s in his
|
||||
introduction: “When we hear the word <em>neon</em>, an image pops into our heads: a
|
||||
|
@ -61,7 +79,11 @@
|
|||
Coco Chanel, the stream-of-consciousness poetry of Gertrude Stein, and the genre-defying
|
||||
music of Claude Debussy—all of which heralded a new age of culture for Europe and for
|
||||
the world.
|
||||
</p></section><section id="article-section-2"><p>
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section id="article-section-2">
|
||||
<p>
|
||||
Amid this artistic groundswell, Georges Claude premiered his neon lights at the <a href="https://www.mondial-paris.com/en/visiteur/auto" target="_blank">Paris Motor Show</a> in
|
||||
December 1910, captivating visitors with 40-foot-tall tubes affixed to the building’s
|
||||
exterior. The lights shone orange-red because neon, by itself, produces that color.
|
||||
|
@ -78,7 +100,11 @@
|
|||
they were adopted by cinemas and nightclubs. While Claude had a monopoly on neon
|
||||
lighting throughout the 1920s, the leaking of trade secrets and the expiration of a
|
||||
series of patents broke his hold on the rapidly expanding technology.
|
||||
</p></section><section id="article-section-3"><p>
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section id="article-section-3">
|
||||
<p>
|
||||
In the following decades, neon’s nonstop glow and vibrant colors turned ordinary
|
||||
buildings and surfaces into 24/7 billboards for businesses, large and small, that wanted
|
||||
to convey a sense of always being open. The first examples of neon in the United States
|
||||
|
@ -89,11 +115,17 @@
|
|||
At the latter event, a massive neon sign reading <span>Futurama</span>
|
||||
lit the way to a General Motors exhibition that heralded “The World of Tomorrow.”
|
||||
</p>
|
||||
<figure><picture><img alt="" data-srcset="https://cdn.theatlantic.com/assets/media/img/posts/2019/04/AP_8912060228/cbd32b0e1.jpg"></picture><figcaption>
|
||||
<figure>
|
||||
<picture>
|
||||
<img alt="" data-srcset="https://cdn.theatlantic.com/assets/media/img/posts/2019/04/AP_8912060228/cbd32b0e1.jpg">
|
||||
</picture>
|
||||
<figcaption>
|
||||
Workers remove a hammer and sickle from a neon sign that reads “Glory to Communism,”
|
||||
visible on the roof of the Communist-run electricity-board headquarters in
|
||||
Czechoslovakia in 1989. (AP)
|
||||
</figcaption></figure><p>
|
||||
</figcaption>
|
||||
</figure>
|
||||
<p>
|
||||
De Miranda points out that businesses weren’t alone in embracing neon’s ability to
|
||||
spread messages effectively. By the middle of the century, the lighting was being
|
||||
adopted for more political purposes. “In the 1960s, the Soviets deployed a vast
|
||||
|
@ -104,18 +136,26 @@
|
|||
the mass introduction of neon lighting was a way of getting citizens of Communist cities
|
||||
to see their surroundings with the pizzazz and nighttime glamour of major Western
|
||||
capitals.
|
||||
</p></section><section id="article-section-4"><p>
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section id="article-section-4">
|
||||
<p>
|
||||
Neon, around this time, began to be phased out, thanks to cheaper and less
|
||||
labor-intensive alternatives. In addition, the global economic downturn of the 1970s
|
||||
yielded a landscape in which older, flickering neon signs, which perhaps their owners
|
||||
couldn’t afford to fix or replace, came to look like symbols of decline. Where such
|
||||
signs were once sophisticated and novel, they now seemed dated and even seedy.
|
||||
</p>
|
||||
<section><h2>
|
||||
<section>
|
||||
<h2>
|
||||
Cities are changing fast. Keep up with the <b>CityLab Daily</b> newsletter.
|
||||
</h2>
|
||||
<label for="promo-email-input-email">The best way to follow issues you
|
||||
care about.</label></section><p>
|
||||
care about.</label>
|
||||
|
||||
</section>
|
||||
<p>
|
||||
De Miranda understands this evolution by zooming out and looking at the 1900s as the
|
||||
“neon century.” The author draws a parallel between the physical form of neon lights,
|
||||
which again are essentially containers for electrified gases, and that of a glass
|
||||
|
@ -125,11 +165,17 @@
|
|||
maintain a hybrid status, somewhere between junkyards and museums, not unlike European
|
||||
capitals themselves.”
|
||||
</p>
|
||||
<figure><picture><img alt="" data-srcset="https://cdn.theatlantic.com/assets/media/img/posts/2019/04/AP_945361213236/888fdd750.jpg"></picture><figcaption>
|
||||
<figure>
|
||||
<picture>
|
||||
<img alt="" data-srcset="https://cdn.theatlantic.com/assets/media/img/posts/2019/04/AP_945361213236/888fdd750.jpg">
|
||||
</picture>
|
||||
<figcaption>
|
||||
Martin Wartman, a student at Northern Kentucky University, works on a neon sign at
|
||||
the Neonworks of Cincinnati workshop connected to the American Sign Museum, in 2016.
|
||||
(John Minchillo / AP)
|
||||
</figcaption></figure><p>
|
||||
</figcaption>
|
||||
</figure>
|
||||
<p>
|
||||
Another mark of neon’s hybridity: Its obsolescence started just as some contemporary
|
||||
artists began using the lights in their sculptures. Bruce Nauman’s 1968 work <em><a href="https://www.stedelijk.nl/en/collection/1097-bruce-nauman-my-name-as-though-it-were-written-on-the-surface-of-the-moon" target="_blank">My
|
||||
Name as Though It Were Written on the Surface of the Moon</a></em> poked fun at
|
||||
|
@ -158,13 +204,24 @@
|
|||
“neonness” need not only be trapped in the past. It might also capture the mysterious
|
||||
glow of the near future—just as it did a century ago.
|
||||
</p>
|
||||
<p><em>This article originally appeared on <a href="https://www.theatlantic.com/entertainment/archive/2019/04/being-and-neonness-neon-lights-symbol-20th-century/588184/" target="_blank">The
|
||||
Atlantic</a>.</em></p></section><section data-include="css:https://cdn.citylab.com/static/a/frontend/dist/citylab/css/components/author-article.cf4e8e0b143f.css"><h4>
|
||||
<p>
|
||||
<em>This article originally appeared on <a href="https://www.theatlantic.com/entertainment/archive/2019/04/being-and-neonness-neon-lights-symbol-20th-century/588184/" target="_blank">The
|
||||
Atlantic</a>.</em>
|
||||
</p>
|
||||
</section>
|
||||
<section data-include="css:https://cdn.citylab.com/static/a/frontend/dist/citylab/css/components/author-article.cf4e8e0b143f.css">
|
||||
<h4>
|
||||
About the Author
|
||||
</h4>
|
||||
<div itemprop="author">
|
||||
<h5 itemprop="name"><a href="https://www.citylab.com/authors/sarah-archer/" target="_blank">Sarah Archer</a></h5>
|
||||
<p itemprop="description"><a href="https://www.citylab.com/authors/sarah-archer/" data-omni-click="inherit" target="_blank">Sarah Archer</a> is the author of <em>The
|
||||
<h5 itemprop="name">
|
||||
<a href="https://www.citylab.com/authors/sarah-archer/" target="_blank">Sarah Archer</a>
|
||||
</h5>
|
||||
|
||||
<p itemprop="description">
|
||||
<a href="https://www.citylab.com/authors/sarah-archer/" data-omni-click="inherit" target="_blank">Sarah Archer</a> is the author of <em>The
|
||||
Midcentury Kitchen</em>.
|
||||
</p>
|
||||
</div></section></article></DIV></article>
|
||||
</div>
|
||||
</section>
|
||||
</article></DIV></article>
|
||||
|
|
|
@ -4,8 +4,10 @@
|
|||
<span face="Lucida Handwriting " color="Maroon
|
||||
">"Bartleby the Scrivener: A Story of Wall-Street " </span>(1853) <br>
|
||||
Herman Melville</h2>
|
||||
<h2><a href="http://www.vcu.edu/engweb/webtexts/bartleby.html" target="_blank"><img src="http://fakehost/test/base/hmhome.gif" alt="To the story text without notes
|
||||
" height="38 " width="38 "></a></h2>
|
||||
<h2>
|
||||
<a href="http://www.vcu.edu/engweb/webtexts/bartleby.html" target="_blank"><img src="http://fakehost/test/base/hmhome.gif" alt="To the story text without notes
|
||||
" height="38 " width="38 "></a>
|
||||
</h2>
|
||||
<h3>Prepared by <a href="http://www.vcu.edu/engweb" target="_blank">Ann
|
||||
Woodlief,</a> Virginia Commonwealth University</h3>
|
||||
<h5>Click on text in red for hypertext notes and questions</h5>
|
||||
|
@ -274,13 +276,15 @@
|
|||
<a href="javascript:void(0);" onmouseout="nd();" target="_blank">a high green folding screen</a>, which might entirely isolate Bartleby
|
||||
from my sight, though not remove him from <a href="javascript:void(0);" onmouseout="nd();" target="_blank">my
|
||||
voice</a>. And thus, in a manner, privacy and society were
|
||||
<a href="javascript:void(0);" onmouseout="nd();" target="_blank">conjoined.</a></p>
|
||||
<a href="javascript:void(0);" onmouseout="nd();" target="_blank">conjoined.</a>
|
||||
</p>
|
||||
<p>At first Bartleby did an extraordinary quantity of writing. As if long
|
||||
<a href="javascript:void(0);" onmouseout="nd();" target="_blank">famishing</a>for something to copy, he seemed to <a href="javascript:void(0);" onmouseout="nd();" target="_blank">gorge</a> himself on my documents. There
|
||||
was no pause for digestion. He ran a day and night line, copying by sun-light
|
||||
and by candle-light. I should have been quite delighted with his application,
|
||||
had be been <a href="javascript:void(0);" onmouseout="nd();" target="_blank">cheerfully
|
||||
industrious</a>. But he wrote on silently, palely, <a href="javascript:void(0);" onmouseout="nd();" target="_blank">mechanically.</a></p>
|
||||
industrious</a>. But he wrote on silently, palely, <a href="javascript:void(0);" onmouseout="nd();" target="_blank">mechanically.</a>
|
||||
</p>
|
||||
<p>It is, of course, an indispensable part of a scrivener's business to verify
|
||||
the accuracy of his copy, word by word. Where there are two or more scriveners
|
||||
in an office, they assist each other in this examination, one reading from
|
||||
|
@ -309,7 +313,8 @@
|
|||
Imagine my surprise, nay, my consternation, when without moving from his
|
||||
privacy, Bartleby in a singularly <a href="javascript:void(0);" onmouseout="nd();" target="_blank">mild,
|
||||
firm voice</a>, replied,<a href="javascript:void(0);" onmouseout="nd();" target="_blank">"I
|
||||
would prefer not to."</a></p>
|
||||
would prefer not to."</a>
|
||||
</p>
|
||||
<p>I sat awhile in perfect silence, rallying my stunned faculties. Immediately
|
||||
it occurred to me that my ears had deceived me, or Bartleby had entirely
|
||||
misunderstood my meaning. I repeated my request in the clearest tone I
|
||||
|
@ -344,7 +349,8 @@
|
|||
group</a>.</p>
|
||||
<p>"Bartleby! quick, I am waiting."</p>
|
||||
<p>I heard a low scrape of his chair legs on the unscraped floor, and soon
|
||||
he appeared standing at the entrance of his <a href="javascript:void(0);" onmouseout="nd();" target="_blank">hermitage.</a></p>
|
||||
he appeared standing at the entrance of his <a href="javascript:void(0);" onmouseout="nd();" target="_blank">hermitage.</a>
|
||||
</p>
|
||||
<p>"What is wanted?" said he mildly.</p>
|
||||
<p>"The copies, the copies," said I hurriedly. "We are going to examine them.
|
||||
There"--and I held towards him the fourth quadruplicate.</p>
|
||||
|
@ -379,7 +385,8 @@
|
|||
it were, vaguely to surmise that, wonderful as it may be, all the justice
|
||||
and all the reason is on the other side. Accordingly, if any disinterested
|
||||
persons are present, he turns to them for some reinforcement for his own
|
||||
<a href="javascript:void(0);" onmouseout="nd();" target="_blank">faltering mind.</a></p>
|
||||
<a href="javascript:void(0);" onmouseout="nd();" target="_blank">faltering mind.</a>
|
||||
</p>
|
||||
<p>"Turkey," said I, "what do you think of this? Am I not right?"</p>
|
||||
<p>"With submission, sir," said Turkey, with his blandest tone, "I think
|
||||
that you are."</p>
|
||||
|
@ -428,7 +435,8 @@
|
|||
one of their peculiar constituents, and the final flavoring one. Now what
|
||||
was ginger? A hot, spicy thing. Was Bartleby hot and spicy? Not at all.
|
||||
Ginger, then, had no effect upon Bartleby. Probably<a href="javascript:void(0);" onmouseout="nd();" target="_blank">
|
||||
he preferred it should have none.</a></p>
|
||||
he preferred it should have none.</a>
|
||||
</p>
|
||||
<p>Nothing so aggravates an earnest person as a <a href="javascript:void(0);" onmouseout="nd();" target="_blank">passive
|
||||
resistance.</a> If the individual so resisted be of a not inhumane
|
||||
temper, and the resisting one perfectly harmless in his passivity; then,
|
||||
|
@ -528,7 +536,8 @@
|
|||
moreover, said Bartleby was never on any account to be dispatched on the
|
||||
most trivial errand of any sort; and that even if entreated to take upon
|
||||
him such a matter, it was generally understood that he would prefer not
|
||||
to--in other words, that he would refuse <a href="javascript:void(0);" onmouseout="nd();" target="_blank">point-blank.</a></p>
|
||||
to--in other words, that he would refuse <a href="javascript:void(0);" onmouseout="nd();" target="_blank">point-blank.</a>
|
||||
</p>
|
||||
<p>32 As days passed on, I became considerably reconciled to Bartleby. His
|
||||
steadiness, his freedom from all dissipation, his incessant industry (except
|
||||
when he chose to throw himself into a standing revery behind his screen),
|
||||
|
@ -612,7 +621,8 @@
|
|||
and life, at nightfall echoes with sheer vacancy, and all through Sunday
|
||||
is forlorn. And here Bartleby makes his home; sole spectator of a solitude
|
||||
which he has seen all populous--a sort of innocent and transformed <a href="javascript:void(0);" onmouseout="nd();" target="_blank">Marius
|
||||
brooding among the ruins of Carthage!</a></p>
|
||||
brooding among the ruins of Carthage!</a>
|
||||
</p>
|
||||
<p>For the <a href="javascript:void(0);" onmouseout="nd();" target="_blank">first
|
||||
time in my life</a> a feeling of overpowering stinging melancholy
|
||||
seized me. Before, I had never experienced aught but a not-unpleasing sadness.
|
||||
|
@ -676,7 +686,8 @@
|
|||
scrivener was the victim <a href="javascript:void(0);" onmouseout="nd();" target="_blank">of
|
||||
innate and incurable disorder.</a> I might give alms to his body;
|
||||
but his body did not pain him; it was his soul that suffered, and <a href="javascript:void(0);" onmouseout="nd();" target="_blank">his
|
||||
soul I could not reach.</a></p>
|
||||
soul I could not reach.</a>
|
||||
</p>
|
||||
<p>I did not accomplish the purpose of going to Trinity Church that morning.
|
||||
Somehow, <a href="javascript:void(0);" onmouseout="nd();" target="_blank">the
|
||||
things I had seen disqualified me</a> for the time from church-going.
|
||||
|
@ -699,7 +710,8 @@
|
|||
speak to you."</p>
|
||||
<p>Upon this he noiselessly slid into view.</p>
|
||||
<p>"Will you tell me, Bartleby, <a href="javascript:void(0);" onmouseout="nd();" target="_blank">where
|
||||
you were born?"</a></p>
|
||||
you were born?"</a>
|
||||
</p>
|
||||
<p>"I would prefer not to."</p>
|
||||
<p>"Will you tell me <i>anything </i>about yourself?"</p>
|
||||
<p>"I would prefer not to."</p>
|
||||
|
@ -740,7 +752,8 @@
|
|||
What is it, sir, pray, that he <i>prefers</i> not to do now?"</p>
|
||||
<p>Bartleby moved not a limb.</p>
|
||||
<p><a href="javascript:void(0);" onmouseout="nd();" target="_blank">"Mr.
|
||||
Nippers," said I, "I'd prefer that you would withdraw for the present."</a></p>
|
||||
Nippers," said I, "I'd prefer that you would withdraw for the present."</a>
|
||||
</p>
|
||||
<p>Somehow, of late I had got into the way of involuntary using this word
|
||||
"prefer" upon all sorts of not exactly suitable occasions. And I trembled
|
||||
to think that my contact with the scrivener had already and seriously affected
|
||||
|
@ -760,7 +773,8 @@
|
|||
the scrivener.</a> "What word, sir?"</p>
|
||||
<p>"I would prefer to be left alone here," said Bartleby, as if offended
|
||||
at being <a href="javascript:void(0);" onmouseout="nd();" target="_blank">mobbed
|
||||
in his privacy.</a></p>
|
||||
in his privacy.</a>
|
||||
</p>
|
||||
<p>"<i>That's</i> the word, Turkey," said I--<i>"that's</i> it."</p>
|
||||
<p>"Oh,<i> prefer</i> oh yes--queer word. I never use it myself. But, sir
|
||||
as I was saying, if he would but prefer--"</p>
|
||||
|
@ -808,7 +822,8 @@
|
|||
<p>"What!" exclaimed I; "suppose your eyes should get entirely well- better
|
||||
than ever before--would you not copy then?"</p>
|
||||
<p>"I have given up copying," he answered, and <a href="javascript:void(0);" onmouseout="nd();" target="_blank">slid
|
||||
aside.</a></p>
|
||||
aside.</a>
|
||||
</p>
|
||||
<p>He remained as ever, <a href="javascript:void(0);" onmouseout="nd();" target="_blank">a
|
||||
fixture</a> in my chamber. Nay--if that were possible--he became
|
||||
still more of a fixture than before. What was to be done? He would do nothing
|
||||
|
@ -828,7 +843,8 @@
|
|||
quit me, Bartleby," added I, "I shall see that you go not away entirely
|
||||
unprovided. Six days from this hour, remember."</p>
|
||||
<p>At the expiration of that period, I peeped behind the screen, and <a href="javascript:void(0);" onmouseout="nd();" target="_blank">lo!
|
||||
Bartleby was there.</a></p>
|
||||
Bartleby was there.</a>
|
||||
</p>
|
||||
<p>I <a href="javascript:void(0);" onmouseout="nd();" target="_blank">buttoned
|
||||
up my coat</a>, balanced myself; advanced slowly towards him,
|
||||
touched his shoulder, and said, "The time has come; you must quit this
|
||||
|
@ -1092,7 +1108,8 @@
|
|||
occupant of a naked room.</a> I stood in the entry watching him
|
||||
a moment, while something from within me upbraided me.</p>
|
||||
<p>I re-entered, with my <a href="javascript:void(0);" onmouseout="nd();" target="_blank">hand
|
||||
in my pocket--and--and my heart in my mouth.</a></p>
|
||||
in my pocket--and--and my heart in my mouth.</a>
|
||||
</p>
|
||||
<p>"Good-bye, Bartleby; I am going--good-bye, and God some way bless you;
|
||||
and take that," slipping something in his hand. But it dropped to the floor,
|
||||
and then,<a href="javascript:void(0);" onmouseout="nd();" target="_blank">--strange
|
||||
|
@ -1190,7 +1207,8 @@
|
|||
threat to try to frighten</a> his immobility into compliance.
|
||||
Despairing of all further efforts, I was precipitately leaving him, when
|
||||
a final thought occurred to me--<a href="javascript:void(0);" onmouseout="nd();" target="_blank">one
|
||||
which had not been wholly unindulged before.</a></p>
|
||||
which had not been wholly unindulged before.</a>
|
||||
</p>
|
||||
<p>"Bartleby," said I, in the kindest <a href="javascript:void(0);" onmouseout="nd();" target="_blank">tone
|
||||
I could assume</a> under such exciting circumstances, "will you
|
||||
go home with me now--not to my office, but my dwelling--and remain there
|
||||
|
@ -1225,7 +1243,8 @@
|
|||
<p>As I afterwards learned, the poor scrivener, when told that he must be
|
||||
conducted to the Tombs, offered not the slightest obstacle, but in his
|
||||
pale unmoving way, <a href="javascript:void(0);" onmouseout="nd();" target="_blank">silently
|
||||
acquiesced.</a></p>
|
||||
acquiesced.</a>
|
||||
</p>
|
||||
<p>Some of the compassionate and curious bystanders joined the party; and
|
||||
headed by one of the constables arm in arm with Bartleby, <a href="javascript:void(0);" onmouseout="nd();" target="_blank">the
|
||||
silent procession</a> filed its way through all the noise, and
|
||||
|
@ -1246,7 +1265,8 @@
|
|||
him there, standing all alone in the quietest of the yards, his face
|
||||
<a href="javascript:void(0);" onmouseout="nd();" target="_blank">towards a high wall</a>, while all around, from the narrow slits of the
|
||||
jail windows, I thought <a href="javascript:void(0);" onmouseout="nd();" target="_blank">I
|
||||
saw peering out upon him the eyes of murderers and thieves.</a></p>
|
||||
saw peering out upon him the eyes of murderers and thieves.</a>
|
||||
</p>
|
||||
<p>"Bartleby!"</p>
|
||||
<p>"<a href="javascript:void(0);" onmouseout="nd();" target="_blank">I
|
||||
know you</a>," he said, without looking round,--"and I want
|
||||
|
@ -1363,7 +1383,8 @@
|
|||
whom it would relieve, nor eats nor hungers any more; pardon for those
|
||||
who died despairing; hope for those who died unhoping; good tidings for
|
||||
those who died stifled by unrelieved calamities. <a href="javascript:void(0);" onmouseout="nd();" target="_blank">On
|
||||
errands of life, these letters speed to death.</a></p>
|
||||
errands of life, these letters speed to death.</a>
|
||||
</p>
|
||||
<p> <a href="javascript:void(0);" onmouseout="nd();" target="_blank">Ah
|
||||
Bartleby! Ah humanity</a>!</p>
|
||||
</DIV></article>
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,19 +1,48 @@
|
|||
<article><div itemprop="articleBody" data-component="lazyloadImages" id="readability-page-1">
|
||||
|
||||
|
||||
|
||||
|
||||
<figure section="shortcodeImage"><span><span itemprop="image" itemscope="" itemtype="https://schema.org/ImageObject"><img src="https://cnet1.cbsistatic.com/img/nAMdBzIE1ogVw5bOBZBaiJCt3Ro=/570x0/2014/03/21/863df5d9-e8b8-4b38-851b-5e3f77f2cf0e/mark-zuckerberg-facebook-home-10671610x407.jpg" alt="" width="570" height="0"><meta itemprop="url" content="https://cnet1.cbsistatic.com/img/nAMdBzIE1ogVw5bOBZBaiJCt3Ro=/570x0/2014/03/21/863df5d9-e8b8-4b38-851b-5e3f77f2cf0e/mark-zuckerberg-facebook-home-10671610x407.jpg">
|
||||
<meta itemprop="height" content="0">
|
||||
<meta itemprop="width" content="570"></span></span><figcaption><span><p>Facebook CEO Mark Zuckerberg, the man with the acquisition plan.</p></span><span>Photo by James Martin/CNET
|
||||
</span></figcaption></figure><p>Anyone who has ever been involved in closing a billion-dollar acquisition deal will tell you that you don't go in without a clear, well thought out plan.</p>
|
||||
<meta itemprop="width" content="570"></span></span>
|
||||
<figcaption><span><p>Facebook CEO Mark Zuckerberg, the man with the acquisition plan.</p></span><span>Photo by James Martin/CNET
|
||||
</span></figcaption>
|
||||
</figure>
|
||||
<p>Anyone who has ever been involved in closing a billion-dollar acquisition deal will tell you that you don't go in without a clear, well thought out plan.</p>
|
||||
|
||||
<p>Facebook CEO Mark Zuckerberg knows a thing or two about how to seal the deal on blockbuster buys. After all, he's the man behind his company's <a href="https://www.cnet.com/news/facebook-closes-19-billion-deal-for-whatsapp/" target="_blank">$19 billion acquisition</a> of WhatsApp, he <a href="https://www.cnet.com/news/zuckerberg-did-1-billion-instagram-deal-on-his-own/" target="_blank">personally brokered</a> its $1 billion buyout of <a href="https://www.cnet.com/news/why-facebook-plunked-down-1-billion-to-buy-instagram/" target="_blank">Instagram</a> and closed the <a href="https://www.cnet.com/news/facebook-to-buy-oculus-for-2-billion/" target="_blank">$3 billion deal</a> to buy Oculus VR.</p>
|
||||
<p>Zuckerberg offered a primer on the strategies he and his company employ when they see an attractive target during testimony Tuesday <a href="https://www.cnet.com/news/zenimax-sues-oculus-over-virtual-reality-rift-tech/" target="_blank">in a lawsuit with ZeniMax Media</a>, which accuses Oculus and Facebook of "misappropriating" trade secrets and copyright infringement. At the heart of the lawsuit is technology that helped create liftoff for virtual reality, one of the <a href="http://www.cbsnews.com/videos/the-reality-of-the-virtual-world/" target="_blank" data-component="externalLink">hottest gadget trends today.</a></p>
|
||||
<p>A key Facebook approach is building a long-term relationship with your target, Zuckerberg said at the trial. These deals don't just pop up over night, he said according to a transcript reviewed by <a href="http://www.businessinsider.com/mark-zuckerberg-explains-facebooks-acquisition-strategy-2017-1" target="_blank" data-component="externalLink">Business Insider</a>. They take time to cultivate. </p>
|
||||
<blockquote><p>I've been building relationships, at least in Instagram and the WhatsApp cases, for years with the founders and the people that are involved in these companies, which made [it] so that when it became time or when we thought it was the right time to move, we felt like we had a good amount of context and had good relationships so that we could move quickly, which was competitively important and why a lot of these acquisitions, I think, came to us instead of our competitors and ended up being very good acquisitions over time that a lot of competitors wished they had gotten instead. </p></blockquote>
|
||||
<blockquote>
|
||||
<p>I've been building relationships, at least in Instagram and the WhatsApp cases, for years with the founders and the people that are involved in these companies, which made [it] so that when it became time or when we thought it was the right time to move, we felt like we had a good amount of context and had good relationships so that we could move quickly, which was competitively important and why a lot of these acquisitions, I think, came to us instead of our competitors and ended up being very good acquisitions over time that a lot of competitors wished they had gotten instead. </p>
|
||||
</blockquote>
|
||||
<p> He also stressed the need assure your target that you have a shared vision about how you will collaborate after the deal is put to bed. Zuckerberg said this was reason Facebook was able to acquire Oculus for less than its original $4 billion asking price.</p>
|
||||
<blockquote>If this [deal] is going to happen, it's not going to be because we offer a lot of money, although we're going to have to offer a fair price for the company that is more than what they felt like they could do on their own. But they also need to feel like this was actually going to help their mission.</blockquote>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<p>When that doesn't work, Zuckerberg said scare tactics is an effective, if undesirable, way of persuading small startups that they face a better chance of survival if they have Facebook to guide their way rather than going it alone.</p>
|
||||
<blockquote>That's less my thing, but I think if you are trying to help convince people that they want to join you, helping them understand all the pain that they would have to go through to build it out independently is a valuable tactic. </blockquote>
|
||||
<p>It also pays to be weary of competing suitors for your startup, Zuckerberg said, and be willing to move fast to stave off rivals and get the deal done.</p>
|
||||
<blockquote>Often, if a company knows we're offering something, they will offer more. So being able to move quickly not only increases our chance of being able to get a deal done if we want to, but it makes it so we don't have end up having to pay a lot more because the process drags out.</blockquote>
|
||||
<p>It wasn't clear why these strategies didn't work on Snapchat CEO Evan Spiegel, who <a href="https://www.cnet.com/news/snapchat-said-to-rebuff-3-billion-offer-from-facebook/" target="_blank">famously rebuffed</a> a $3 billion takeover offer from Facebook in 2013.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<p><em><strong>Tech Enabled:</strong> CNET chronicles tech's role in providing new kinds of accessibility. Check it out <a href="https://www.cnet.com/tech-enabled/" target="_blank">here</a>.</em><em><strong><br></strong></em></p>
|
||||
<p><em><strong>Technically Literate:</strong> Original works of short fiction with unique perspectives on tech, exclusively on CNET. <a href="https://www.cnet.com/technically-literate/" target="_blank">Here</a>.</em></p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div></article>
|
||||
|
|
|
@ -1,19 +1,51 @@
|
|||
<article><div id="readability-page-1">
|
||||
|
||||
|
||||
<h2>The U.S. has long been heralded as a land of opportunity -- a place where anyone can succeed regardless of the economic class they were born into.</h2>
|
||||
<p> But a new report released on Monday by <a href="http://web.stanford.edu/group/scspi-dev/cgi-bin/" target="_blank">Stanford University's Center on Poverty and Inequality</a> calls that into question. </p>
|
||||
|
||||
<p> The report assessed poverty levels, income and wealth inequality, economic mobility and unemployment levels among 10 wealthy countries with social welfare programs. </p>
|
||||
<div id="smartassetcontainer"><p>
|
||||
<div id="smartassetcontainer">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<p>
|
||||
Powered by SmartAsset.com
|
||||
</p></div>
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<p> Among its key findings: the class you're born into matters much more in the U.S. than many of the other countries. </p>
|
||||
<p> As the <a href="http://web.stanford.edu/group/scspi-dev/cgi-bin/publications/state-union-report" target="_blank">report states</a>: "[T]he birth lottery matters more in the U.S. than in most well-off countries." </p>
|
||||
|
||||
<p> But this wasn't the only finding that suggests the U.S. isn't quite living up to its reputation as a country where everyone has an equal chance to get ahead through sheer will and hard work. </p>
|
||||
<p> <a href="http://money.cnn.com/2016/01/11/news/economy/rich-taxes/index.html?iid=EL" target="_blank"><span>Related: Rich are paying more in taxes but not as much as they used to</span></a> </p>
|
||||
|
||||
<p> The report also suggested the U.S. might not be the "jobs machine" it thinks it is, when compared to other countries. </p>
|
||||
<p> It ranked near the bottom of the pack based on the levels of unemployment among men and women of prime working age. The study determined this by taking the ratio of employed men and women between the ages of 25 and 54 compared to the total population of each country. </p>
|
||||
<p> The overall rankings of the countries were as follows:<span><br>1. Finland <span><br>2. Norway<span><br>3. Australia <span><br>4. Canada<span><br>5. Germany<span><br>6. France<span><br>7. United Kingdom <span><br>8. Italy<span><br>9. Spain<span><br>10. United States </span></span></span></span></span></span></span></span></span></span></p>
|
||||
<p> The overall rankings of the countries were as follows:<span> <br>1. Finland <span> <br>2. Norway<span> <br>3. Australia <span> <br>4. Canada<span> <br>5. Germany<span> <br>6. France<span> <br>7. United Kingdom <span> <br>8. Italy<span> <br>9. Spain<span> <br>10. United States </span></span>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</p>
|
||||
<p> The low ranking the U.S. received was due to its extreme levels of wealth and income inequality and the ineffectiveness of its "safety net" -- social programs aimed at reducing poverty. </p>
|
||||
<p> <a href="http://money.cnn.com/2016/01/05/news/economy/chicago-segregated/index.html?iid=EL" target="_blank"><span>Related: Chicago is America's most segregated city</span></a> </p>
|
||||
<p> The report concluded that the American safety net was ineffective because it provides only half the financial help people need. Additionally, the levels of assistance in the U.S. are generally lower than in other countries. </p>
|
||||
|
||||
|
||||
<p><span> CNNMoney (New York) </span> <span>First published February 1, 2016: 1:28 AM ET</span> </p>
|
||||
</div></article>
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
<article><div id="readability-page-1">
|
||||
<h2>About This Site</h2>
|
||||
<p>Daring Fireball is written and produced by John Gruber.</p>
|
||||
<p><a href="http://fakehost/graphics/author/addison-bw.jpg" target="_blank"><img src="http://fakehost/graphics/author/addison-bw-425.jpg" alt="Photograph of the author."></a><br><em>Portrait by <a href="http://superbiate.com/inquiries/" target="_blank">George Del Barrio</a></em></p>
|
||||
<p>
|
||||
<a href="http://fakehost/graphics/author/addison-bw.jpg" target="_blank"> <img src="http://fakehost/graphics/author/addison-bw-425.jpg" alt="Photograph of the author."></a>
|
||||
<br><em>Portrait by <a href="http://superbiate.com/inquiries/" target="_blank">George Del Barrio</a></em> </p>
|
||||
<h2>Mac Apps</h2>
|
||||
<ul>
|
||||
<li><a href="http://www.barebones.com/products/bbedit/" target="_blank">BBEdit</a></li>
|
||||
|
@ -15,7 +17,9 @@
|
|||
<li><a href="http://nightly.webkit.org/" target="_blank">WebKit</a></li>
|
||||
</ul>
|
||||
<h2>iPhone Apps</h2>
|
||||
<ul><li><a href="http://vesperapp.co/" target="_blank">Vesper</a></li></ul>
|
||||
<ul>
|
||||
<li><a href="http://vesperapp.co/" target="_blank">Vesper</a></li>
|
||||
</ul>
|
||||
<h2>Server Software</h2>
|
||||
<p>The Daring Fireball website is hosted by <a href="http://joyent.com/" target="_blank">Joyent</a>.</p>
|
||||
<p>Articles and links are published through <a href="http://movabletype.org/" target="_blank">Movable Type</a>. In addition to my own SmartyPants and Markdown plug-ins, Daring Fireball uses several excellent Movable Type plug-ins, including Brad Choate’s <a href="http://bradchoate.com/weblog/2003/06/24/regular-expressions" target="_blank">MT-Regex</a> and <a href="http://bradchoate.com/weblog/2004/10/20/mtifempty" target="_blank">MT-IfEmpty</a>, and <a href="http://bumppo.net/projects/amputator/" target="_blank">Nat Irons’s Amputator</a>.</p>
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,4 +1,5 @@
|
|||
<article><DIV id="readability-page-1">
|
||||
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
</p>
|
||||
|
@ -6,7 +7,9 @@
|
|||
<h2>
|
||||
Single <img>
|
||||
</h2>
|
||||
<p><img src="http://fakehost/test/base/florian-giorgio-P1U7-ZgKeOM-unsplash.jpg" alt="An image"></p>
|
||||
<p>
|
||||
<img src="http://fakehost/test/base/florian-giorgio-P1U7-ZgKeOM-unsplash.jpg" alt="An image">
|
||||
</p>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
</p>
|
||||
|
@ -14,9 +17,13 @@
|
|||
<h2>
|
||||
Single <figure>
|
||||
</h2>
|
||||
<figure><img src="http://fakehost/test/base/florian-giorgio-P1U7-ZgKeOM-unsplash.jpg" alt="An image"><figcaption>
|
||||
<figure>
|
||||
<img src="http://fakehost/test/base/florian-giorgio-P1U7-ZgKeOM-unsplash.jpg" alt="An image">
|
||||
<figcaption>
|
||||
Caption of the figure
|
||||
</figcaption></figure><p>
|
||||
</figcaption>
|
||||
</figure>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
</p>
|
||||
<hr>
|
||||
|
@ -24,9 +31,15 @@
|
|||
<ul> List of <img>
|
||||
</h2>
|
||||
<ul>
|
||||
<li><img src="http://fakehost/test/base/florian-giorgio-P1U7-ZgKeOM-unsplash.jpg" alt="An image"></li>
|
||||
<li><img src="http://fakehost/test/base/florian-giorgio-P1U7-ZgKeOM-unsplash.jpg" alt="An image"></li>
|
||||
<li><img src="http://fakehost/test/base/florian-giorgio-P1U7-ZgKeOM-unsplash.jpg" alt="An image"></li>
|
||||
<li>
|
||||
<img src="http://fakehost/test/base/florian-giorgio-P1U7-ZgKeOM-unsplash.jpg" alt="An image">
|
||||
</li>
|
||||
<li>
|
||||
<img src="http://fakehost/test/base/florian-giorgio-P1U7-ZgKeOM-unsplash.jpg" alt="An image">
|
||||
</li>
|
||||
<li>
|
||||
<img src="http://fakehost/test/base/florian-giorgio-P1U7-ZgKeOM-unsplash.jpg" alt="An image">
|
||||
</li>
|
||||
</ul>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
|
@ -36,15 +49,30 @@
|
|||
<ul> List of <figure>
|
||||
</h2>
|
||||
<ul>
|
||||
<li><figure><img src="http://fakehost/test/base/florian-giorgio-P1U7-ZgKeOM-unsplash.jpg" alt="An image"><figcaption>
|
||||
<li>
|
||||
<figure>
|
||||
<img src="http://fakehost/test/base/florian-giorgio-P1U7-ZgKeOM-unsplash.jpg" alt="An image">
|
||||
<figcaption>
|
||||
Caption of the figure
|
||||
</figcaption></figure></li>
|
||||
<li><figure><img src="http://fakehost/test/base/florian-giorgio-P1U7-ZgKeOM-unsplash.jpg" alt="An image"><figcaption>
|
||||
</figcaption>
|
||||
</figure>
|
||||
</li>
|
||||
<li>
|
||||
<figure>
|
||||
<img src="http://fakehost/test/base/florian-giorgio-P1U7-ZgKeOM-unsplash.jpg" alt="An image">
|
||||
<figcaption>
|
||||
Caption of the figure
|
||||
</figcaption></figure></li>
|
||||
<li><figure><img src="http://fakehost/test/base/florian-giorgio-P1U7-ZgKeOM-unsplash.jpg" alt="An image"><figcaption>
|
||||
</figcaption>
|
||||
</figure>
|
||||
</li>
|
||||
<li>
|
||||
<figure>
|
||||
<img src="http://fakehost/test/base/florian-giorgio-P1U7-ZgKeOM-unsplash.jpg" alt="An image">
|
||||
<figcaption>
|
||||
Caption of the figure
|
||||
</figcaption></figure></li>
|
||||
</figcaption>
|
||||
</figure>
|
||||
</li>
|
||||
</ul>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
|
|
|
@ -16,9 +16,13 @@
|
|||
Now that ATF is deployed and currently serving 9,000 async tasks scheduled per second and in use by 28 engineering teams internally, we’re glad to fill that information gap. We’ve documented Dropbox ATF thoroughly, as a reference and guide for the engineering community seeking their own async solutions.
|
||||
</p>
|
||||
</div>
|
||||
<div><P id="introduction"><h2>
|
||||
<div>
|
||||
<P id="introduction">
|
||||
<h2>
|
||||
Introduction
|
||||
</h2></P></div>
|
||||
</h2>
|
||||
</P>
|
||||
</div>
|
||||
<div>
|
||||
<p>
|
||||
Scheduling asynchronous tasks on-demand is a critical capability that powers many features and internal platforms at Dropbox. Async Task Framework (ATF) is the infrastructural system that supports this capability at Dropbox through a callback-based architecture. ATF enables developers to define callbacks, and schedule tasks that execute against these pre-defined callbacks.
|
||||
|
@ -27,73 +31,117 @@
|
|||
Since its introduction over a year ago, ATF has gone on to become an important building block in the Dropbox infrastructure, used by nearly 30 internal teams across our codebase. It currently supports 100+ use cases which require either immediate or delayed task scheduling.
|
||||
</p>
|
||||
</div>
|
||||
<div><P id="glossary"><h2>
|
||||
<div>
|
||||
<P id="glossary">
|
||||
<h2>
|
||||
Glossary
|
||||
</h2></P></div>
|
||||
</h2>
|
||||
</P>
|
||||
</div>
|
||||
<div>
|
||||
<p>
|
||||
Some basic terms repeatedly used in this post, defined as used in the context of this discussion.
|
||||
</p>
|
||||
<p><b>Lambda:</b> A callback implementing business logic.
|
||||
<p>
|
||||
<b>Lambda:</b> A callback implementing business logic.
|
||||
</p>
|
||||
<p>
|
||||
<span><b>Task:</b> Unit of execution of a lambda. Each asynchronous job scheduled with ATF is a task.</span>
|
||||
</p>
|
||||
<p>
|
||||
<span><b>Collection:</b> A labeled subset of tasks belonging to a lambda. If <span>send email</span> is implemented as a lambda, then <span>password reset email</span> and <span>marketing email</span> would be collections.</span>
|
||||
</p>
|
||||
<p>
|
||||
<span><b> Priority:</b> Labels defining priority of execution of tasks within a lambda. </span>
|
||||
</p>
|
||||
<p><span><b>Task:</b> Unit of execution of a lambda. Each asynchronous job scheduled with ATF is a task.</span></p>
|
||||
<p><span><b>Collection:</b> A labeled subset of tasks belonging to a lambda. If <span>send email</span> is implemented as a lambda, then <span>password reset email</span> and <span>marketing email</span> would be collections.</span></p>
|
||||
<p><span><b> Priority:</b> Labels defining priority of execution of tasks within a lambda. </span></p>
|
||||
</div>
|
||||
<div><P id="features"><h2>
|
||||
Features
|
||||
</h2></P></div>
|
||||
<div>
|
||||
<p><b>Task scheduling</b><br>
|
||||
<P id="features">
|
||||
<h2>
|
||||
Features
|
||||
</h2>
|
||||
</P>
|
||||
</div>
|
||||
<div>
|
||||
<p>
|
||||
<b>Task scheduling</b><br>
|
||||
Clients can schedule tasks to execute at a specified time. Tasks can be scheduled for immediate execution, or delayed to fit the use case.
|
||||
</p>
|
||||
<p><b>Priority based execution</b><br>
|
||||
<p>
|
||||
<b>Priority based execution</b><br>
|
||||
Tasks should be associated with a priority. Tasks with higher priority should get executed before tasks with a lower priority once they are ready for execution.
|
||||
</p>
|
||||
<p><b>Task gating</b><br>
|
||||
<p>
|
||||
<b>Task gating</b><br>
|
||||
ATF enables the the gating of tasks based on lambda, or a subset of tasks on a lambda based on collection. Tasks can be gated to be completely dropped or paused until a suitable time for execution.
|
||||
</p>
|
||||
<p><b>Track task status</b><br>
|
||||
<p>
|
||||
<b>Track task status</b><br>
|
||||
Clients can query the status of a scheduled task.
|
||||
</p>
|
||||
</div>
|
||||
<div><P id="system-guarantees"><h2>
|
||||
System guarantees
|
||||
</h2></P></div>
|
||||
<div>
|
||||
<p><b>At-least once task execution<br></b> The ATF system guarantees that a task is executed at least once after being scheduled. Execution is said to be complete once the user-defined callback signals task completion to the ATF system.
|
||||
<P id="system-guarantees">
|
||||
<h2>
|
||||
System guarantees
|
||||
</h2>
|
||||
</P>
|
||||
</div>
|
||||
<div>
|
||||
<p>
|
||||
<b>At-least once task execution<br></b> The ATF system guarantees that a task is executed at least once after being scheduled. Execution is said to be complete once the user-defined callback signals task completion to the ATF system.
|
||||
</p>
|
||||
<p><b>No concurrent task execution<br></b> The ATF system guarantees that at most one instance of a task will be actively executing at any given in point. This helps users write their callbacks without designing for concurrent execution of the same task from different locations.
|
||||
<p>
|
||||
<b>No concurrent task execution<br></b> The ATF system guarantees that at most one instance of a task will be actively executing at any given in point. This helps users write their callbacks without designing for concurrent execution of the same task from different locations.
|
||||
</p>
|
||||
<p><b>Isolation<br></b> Tasks in a given lambda are isolated from the tasks in other lambdas. This isolation spans across several dimensions, including worker capacity for task execution and resource use for task scheduling. Tasks on the same lambda but different priority levels are also isolated in their resource use for task scheduling.
|
||||
<p>
|
||||
<b>Isolation<br></b> Tasks in a given lambda are isolated from the tasks in other lambdas. This isolation spans across several dimensions, including worker capacity for task execution and resource use for task scheduling. Tasks on the same lambda but different priority levels are also isolated in their resource use for task scheduling.
|
||||
</p>
|
||||
<p><b>Delivery latency<br></b> 95% of tasks begin execution within five seconds from their scheduled execution time.
|
||||
<p>
|
||||
<b>Delivery latency<br></b> 95% of tasks begin execution within five seconds from their scheduled execution time.
|
||||
</p>
|
||||
<p><b>High availability for task scheduling<br></b> The ATF service is 99.9% available to accept task scheduling requests from any client.
|
||||
<p>
|
||||
<b>High availability for task scheduling<br></b> The ATF service is 99.9% available to accept task scheduling requests from any client.
|
||||
</p>
|
||||
</div>
|
||||
<div><P id="-lambda-requirements"><h2>
|
||||
<div>
|
||||
<P id="-lambda-requirements">
|
||||
<h2>
|
||||
Lambda requirements
|
||||
</h2></P></div>
|
||||
</h2>
|
||||
</P>
|
||||
</div>
|
||||
<div>
|
||||
<p>
|
||||
Following are some restrictions we place on the callback logic (lambda):
|
||||
</p>
|
||||
<p><b>Idempotence</b><br>
|
||||
<p>
|
||||
<b>Idempotence</b><br>
|
||||
A single task on a lambda can be executed multiple times within the ATF system. Developers should ensure that their lambda logic and correctness of task execution in clients are not affected by this.
|
||||
</p>
|
||||
<p><b>Resiliency</b><br>
|
||||
<p>
|
||||
<b>Resiliency</b><br>
|
||||
Worker processes which execute tasks might die at any point during task execution. ATF retries abruptly interrupted tasks, which could also be retried on different hosts. Lambda owners must design their lambdas such that retries on different hosts do not affect lambda correctness.
|
||||
</p>
|
||||
<p><b>Terminal state handling<br></b> ATF retries tasks until they are signaled to be complete from the lambda logic. Client code can mark a task as successfully completed, fatally terminated, or retriable. It is critical that lambda owners design clients to signal task completion appropriately to avoid misbehavior such as infinite retries.
|
||||
<p>
|
||||
<b>Terminal state handling<br></b> ATF retries tasks until they are signaled to be complete from the lambda logic. Client code can mark a task as successfully completed, fatally terminated, or retriable. It is critical that lambda owners design clients to signal task completion appropriately to avoid misbehavior such as infinite retries.
|
||||
</p>
|
||||
</div>
|
||||
<div><P id="architecture"><h2>
|
||||
<div>
|
||||
<P id="architecture">
|
||||
<h2>
|
||||
Architecture
|
||||
</h2></P></div>
|
||||
<div><figure><img src="http://fakehost/cms/content/dam/dropbox/tech-blog/en-us/2020/11/atf/diagrams/Techblog-ATF-720x844px-1.png" aria-hidden="false" alt="Async Task Framework (ATF) [Fig 1]" height="1688" width="1440"><figcaption>
|
||||
</h2>
|
||||
</P>
|
||||
</div>
|
||||
<div>
|
||||
<figure>
|
||||
<img src="http://fakehost/cms/content/dam/dropbox/tech-blog/en-us/2020/11/atf/diagrams/Techblog-ATF-720x844px-1.png" aria-hidden="false" alt="Async Task Framework (ATF) [Fig 1]" height="1688" width="1440">
|
||||
<figcaption>
|
||||
Async Task Framework (ATF) [Fig 1]
|
||||
</figcaption></figure></div>
|
||||
</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
<div>
|
||||
<p>
|
||||
In this section, we describe the high-level architecture of ATF and give brief description of its different components. (See Fig. 1 above.) In this section, we describe the high-level architecture of ATF and give brief description of its different components. (See Fig. 1 above.) Dropbox <a href="https://dropbox.tech/infrastructure/courier-dropbox-migration-to-grpc" target="_blank">uses gRPC</a> for remote calls and our in-house <a href="https://dropbox.tech/infrastructure/reintroducing-edgestore" target="_blank">Edgestore</a> to store tasks.
|
||||
|
@ -117,48 +165,66 @@
|
|||
<li>Heartbeat and Status Controller (HSC)<span><br></span>
|
||||
</li>
|
||||
</ul>
|
||||
<p><span><b>Frontend</b><br>
|
||||
This is the service that schedules requests via an RPC interface. The frontend accepts RPC requests from clients and schedules tasks by interacting with ATF’s task store described below.</span><br></p>
|
||||
<p><b>Task Store<br></b> ATF tasks are stored in and triggered from the task store. The task store could be any generic data store with indexed querying capability. In ATF’s case, We use our in-house metadata store Edgestore to power the task store. More details can be found in the <a href="https://paper.dropbox.com/doc/How-we-designed-Dropboxs-ATF-an-async-task-framework--A~wmq5aW48OkHns4LzkM~o6zAg-cf95JuxevqilF2iWWATj6#:uid=395988446153757833740421&h2=Data-model" target="_blank">D</a><a href="https://paper.dropbox.com/doc/How-we-designed-Dropboxs-ATF-an-async-task-framework--A~wmq5aW48OkHns4LzkM~o6zAg-cf95JuxevqilF2iWWATj6#:uid=395988446153757833740421&h2=Data-model" target="_blank">ata</a><a href="https://paper.dropbox.com/doc/How-we-designed-Dropboxs-ATF-an-async-task-framework--A~wmq5aW48OkHns4LzkM~o6zAg-cf95JuxevqilF2iWWATj6#:uid=395988446153757833740421&h2=Data-model" target="_blank">M</a><a href="https://paper.dropbox.com/doc/How-we-designed-Dropboxs-ATF-an-async-task-framework--A~wmq5aW48OkHns4LzkM~o6zAg-cf95JuxevqilF2iWWATj6#:uid=395988446153757833740421&h2=Data-model" target="_blank">odel</a> section below.
|
||||
<p>
|
||||
<span><b>Frontend</b><br>
|
||||
This is the service that schedules requests via an RPC interface. The frontend accepts RPC requests from clients and schedules tasks by interacting with ATF’s task store described below.</span><br>
|
||||
</p>
|
||||
<p><b>Store Consumer<br></b> The Store Consumer is a service that periodically polls the task store to find tasks that are ready for execution and pushes them onto the right queues, as described in the queue section below. These could be tasks that are newly ready for execution, or older tasks that are ready for execution again because they either failed in a retriable way on execution, or were dropped elsewhere within the ATF system.
|
||||
<p>
|
||||
<b>Task Store<br></b> ATF tasks are stored in and triggered from the task store. The task store could be any generic data store with indexed querying capability. In ATF’s case, We use our in-house metadata store Edgestore to power the task store. More details can be found in the <a href="https://paper.dropbox.com/doc/How-we-designed-Dropboxs-ATF-an-async-task-framework--A~wmq5aW48OkHns4LzkM~o6zAg-cf95JuxevqilF2iWWATj6#:uid=395988446153757833740421&h2=Data-model" target="_blank">D</a><a href="https://paper.dropbox.com/doc/How-we-designed-Dropboxs-ATF-an-async-task-framework--A~wmq5aW48OkHns4LzkM~o6zAg-cf95JuxevqilF2iWWATj6#:uid=395988446153757833740421&h2=Data-model" target="_blank">ata</a> <a href="https://paper.dropbox.com/doc/How-we-designed-Dropboxs-ATF-an-async-task-framework--A~wmq5aW48OkHns4LzkM~o6zAg-cf95JuxevqilF2iWWATj6#:uid=395988446153757833740421&h2=Data-model" target="_blank">M</a><a href="https://paper.dropbox.com/doc/How-we-designed-Dropboxs-ATF-an-async-task-framework--A~wmq5aW48OkHns4LzkM~o6zAg-cf95JuxevqilF2iWWATj6#:uid=395988446153757833740421&h2=Data-model" target="_blank">odel</a> section below.
|
||||
</p>
|
||||
<p>
|
||||
<b>Store Consumer<br></b> The Store Consumer is a service that periodically polls the task store to find tasks that are ready for execution and pushes them onto the right queues, as described in the queue section below. These could be tasks that are newly ready for execution, or older tasks that are ready for execution again because they either failed in a retriable way on execution, or were dropped elsewhere within the ATF system.
|
||||
</p>
|
||||
<p>
|
||||
Below is a simple walkthrough of the Store Consumer’s function:
|
||||
</p>
|
||||
</div>
|
||||
<div><pre><code>repeat every second:
|
||||
<div>
|
||||
|
||||
<pre><code>repeat every second:
|
||||
1. poll tasks ready for execution from task store
|
||||
2. push tasks onto the right queues
|
||||
3. update task statuses</code></pre></div>
|
||||
3. update task statuses</code></pre>
|
||||
</div>
|
||||
<div>
|
||||
<p>
|
||||
The Store Consumer polls tasks that failed in earlier execution attempts. This helps with the at-least-once guarantee that the ATF system provides. More details on how the Store Consumer polls new and previously failed tasks is presented in the <a href="https://paper.dropbox.com/doc/How-we-designed-Dropboxs-ATF-an-async-task-framework--A~wmq5aW48OkHns4LzkM~o6zAg-cf95JuxevqilF2iWWATj6#:uid=342792671048375002388848&h2=Lifecycle-of-a-task" target="_blank">Lifecycle of a task</a> section below.
|
||||
</p>
|
||||
<p><b>Queue<br></b> ATF uses AWS <a href="https://aws.amazon.com/sqs/" target="_blank">Simple Queue Service</a> (SQS) to queue tasks internally. These queues act as a buffer between the Store Consumer and Controllers (described below). Each <span><lambda, priority></span> pair gets a dedicated SQS queue. The total number of SQS queues used by ATF is <span>#lambdas x #priorities</span>.
|
||||
<p>
|
||||
<b>Queue<br></b> ATF uses AWS <a href="https://aws.amazon.com/sqs/" target="_blank">Simple Queue Service</a> (SQS) to queue tasks internally. These queues act as a buffer between the Store Consumer and Controllers (described below). Each <span><lambda, priority></span> pair gets a dedicated SQS queue. The total number of SQS queues used by ATF is <span>#lambdas x #priorities</span>.
|
||||
</p>
|
||||
<p><b>Controller<br></b> Worker hosts are physical hosts dedicated for task execution. Each worker host has one controller process responsible for polling tasks from SQS queues in a background thread, and then pushing them onto process local buffered queues. The Controller is only aware of the lambdas it is serving and thus polls only the limited set of necessary queues.
|
||||
<p>
|
||||
<b>Controller<br></b> Worker hosts are physical hosts dedicated for task execution. Each worker host has one controller process responsible for polling tasks from SQS queues in a background thread, and then pushing them onto process local buffered queues. The Controller is only aware of the lambdas it is serving and thus polls only the limited set of necessary queues.
|
||||
</p>
|
||||
<p>
|
||||
The Controller serves tasks from its process local queue as a response to <span>NextWork</span> RPCs. This is the layer where execution level task prioritization occurs. The Controller has different process level queues for tasks of different priorities and can thus prioritize tasks in response to <span>NextWork</span> RPCs.
|
||||
</p>
|
||||
<p><b>Executor<br></b> The Executor is a process with multiple threads, responsible for the actual task execution. Each thread within an Executor process follows this simple loop:
|
||||
<p>
|
||||
<b>Executor<br></b> The Executor is a process with multiple threads, responsible for the actual task execution. Each thread within an Executor process follows this simple loop:
|
||||
</p>
|
||||
</div>
|
||||
<div><pre><code>while True:
|
||||
<div>
|
||||
|
||||
<pre><code>while True:
|
||||
w = get_next_work()
|
||||
do_work(w)</code></pre></div>
|
||||
do_work(w)</code></pre>
|
||||
</div>
|
||||
<div>
|
||||
<p>
|
||||
Each worker host has a single Controller process and multiple executor processes. Both the Controller and Executors work in a “pull” model, in which active loops continuously long-poll for new work to be done.
|
||||
</p>
|
||||
<p><b>Heartbeat and Status Controller (HSC)</b><br>
|
||||
<p>
|
||||
<b>Heartbeat and Status Controller (HSC)</b><br>
|
||||
The HSC serves RPCs for claiming a task for execution (<span>ClaimTask</span>), setting task status after execution (<span>SetResults</span>) and heartbeats during task execution (<span>Heartbeat</span>). <span>ClaimTask</span> requests originate from the Controllers in response to <span>NextWork</span> requests. <span>Heartbeat</span> and <span>SetResults</span> requests originate from executor processes during and after task execution. The HSC interacts with the task store to update the task status on the kind of request it receives.
|
||||
</p>
|
||||
</div>
|
||||
<div><P id="data-model"><h2>
|
||||
<div>
|
||||
<P id="data-model">
|
||||
<h2>
|
||||
Data model
|
||||
</h2></P></div>
|
||||
</h2>
|
||||
</P>
|
||||
</div>
|
||||
<div>
|
||||
<p>
|
||||
ATF uses our in-house metadata store, Edgestore, as a task store. Edgestore objects can be Entities or Associations (<span>assoc</span>), each of which can have user-defined attributes. Associations are used to represent relationships between entities. Edgestore supports indexing only on attributes of associations.
|
||||
|
@ -167,9 +233,13 @@
|
|||
Based on this design, we have two kinds of ATF-related objects in Edgestore. The ATF association stores scheduling information, such as the next scheduled timestamp at which the Store Consumer should poll a given task (either for the first time or for a retry). The ATF entity stores all task related information that is used to track the task state and payload for task execution. We query on associations from the Store Consumer in a pull model to pick up tasks ready for execution.
|
||||
</p>
|
||||
</div>
|
||||
<div><P id="lifecycle-of-a-task"><h2>
|
||||
<div>
|
||||
<P id="lifecycle-of-a-task">
|
||||
<h2>
|
||||
Lifecycle of a task
|
||||
</h2></P></div>
|
||||
</h2>
|
||||
</P>
|
||||
</div>
|
||||
<div>
|
||||
<ol>
|
||||
<li>Client performs a <span>Schedule</span> RPC call to <b>Frontend</b> with task information, including execution time.
|
||||
|
@ -193,127 +263,267 @@
|
|||
<p>
|
||||
Following are the task entity and association states in ATF and their corresponding timestamp updates:
|
||||
</p>
|
||||
<table><tbody>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><p><b>Entity status</b></p></td>
|
||||
<td><p><b>Assoc status</b></p></td>
|
||||
<td><p><b>next trigger timestamp in Assoc</b></p></td>
|
||||
<td><p><b>Comment</b></p></td>
|
||||
<td>
|
||||
<p>
|
||||
<b>Entity status</b>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
<b>Assoc status</b>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
<b>next trigger timestamp in Assoc</b>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
<b>Comment</b>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><p><span>new</span></p></td>
|
||||
<td><p><span>new</span></p></td>
|
||||
<td><p><span>scheduled_timestamp</span> of the task
|
||||
</p></td>
|
||||
<td><p>
|
||||
<td>
|
||||
<p>
|
||||
<span>new</span>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
<span>new</span>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
<span>scheduled_timestamp</span> of the task
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
Pick up new tasks that are ready.
|
||||
</p></td>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><p><span>enqueued</span></p></td>
|
||||
<td><p><span>started</span></p></td>
|
||||
<td><p><span>enqueued_timestamp</span> + <span>enqueue_timeout</span></p></td>
|
||||
<td><p>
|
||||
<td>
|
||||
<p>
|
||||
<span>enqueued</span>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
<span>started</span>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
<span>enqueued_timestamp</span> + <span>enqueue_timeout</span>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
Re-enqueue task if it has been in <span>enqueued</span> state for too long. This can happen if the queue loses data or the controller goes down after polling the queue and before the task is claimed.
|
||||
</p></td>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><p><span>claimed</span></p></td>
|
||||
<td><p><span>started</span></p></td>
|
||||
<td><p><span>claimed_timestamp</span> + <span>claim_timeout</span></p></td>
|
||||
<td><p>
|
||||
<td>
|
||||
<p>
|
||||
<span>claimed</span>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
<span>started</span>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
<span>claimed_timestamp</span> + <span>claim_timeout</span>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
Re-enqueue if task is claimed but never transfered to <span>processing</span>. This can happen if Controller is down after claiming a task. Task status is changed to <span>enqueued</span> after re-enqueue.
|
||||
</p></td>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><p><span>processing</span></p></td>
|
||||
<td><p><span>started</span></p></td>
|
||||
<td><p><span>heartbeat_timestamp</span> + <span>heartbeat_timeout</span>`
|
||||
</p></td>
|
||||
<td><p>
|
||||
<td>
|
||||
<p>
|
||||
<span>processing</span>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
<span>started</span>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
<span>heartbeat_timestamp</span> + <span>heartbeat_timeout</span>`
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
Re-enqueue if task hasn’t sent <span>heartbeat</span> for too long. This can happen if Executor is down. Task status is changed to <span>enqueued</span> after re-enqueue.
|
||||
</p></td>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><p><span>retriable failure</span></p></td>
|
||||
<td><p>
|
||||
<td>
|
||||
<p>
|
||||
<span>retriable failure</span>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
started
|
||||
</p></td>
|
||||
<td><p>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
compute <span>next_timestamp</span> according to backoff logic
|
||||
</p></td>
|
||||
<td><p>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
Exponential backoff for tasks with retriable failure.
|
||||
</p></td>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><p><span>success</span></p></td>
|
||||
<td><p><span>completed</span></p></td>
|
||||
<td><p>
|
||||
<td>
|
||||
<p>
|
||||
<span>success</span>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
<span>completed</span>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
N/A
|
||||
</p></td>
|
||||
<td></td>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><p><span>fatal_failure</span></p></td>
|
||||
<td><p><span>completed</span></p></td>
|
||||
<td><p>
|
||||
<td>
|
||||
<p>
|
||||
<span>fatal_failure</span>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
<span>completed</span>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
N/A
|
||||
</p></td>
|
||||
<td></td>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>
|
||||
The store consumer polls for tasks based on the following query:
|
||||
</p>
|
||||
<p><span>assoc_status= && next_timestamp<=time.now()<br></span></p>
|
||||
<p>
|
||||
Below is the state machine that defines task state transitions: <br></p>
|
||||
<span>assoc_status= && next_timestamp<=time.now()<br></span>
|
||||
</p>
|
||||
<p>
|
||||
Below is the state machine that defines task state transitions: <br>
|
||||
</p>
|
||||
</div>
|
||||
<div><figure><img src="http://fakehost/cms/content/dam/dropbox/tech-blog/en-us/2020/11/atf/diagrams/Techblog-ATF-720x225px-2.png" aria-hidden="false" alt="Task State Transitions [Fig 2]" height="450" width="1440"></figure></div>
|
||||
<div><P id="-achieving-guarantees"><h2>
|
||||
Achieving guarantees
|
||||
</h2></P></div>
|
||||
<div>
|
||||
<p><b>At-least-once task execution<br></b> At-least-once execution is guaranteed in ATF by retrying a task until it completes execution (which is signaled by a <span>Success</span> or a <span>FatalFailure</span> state). All ATF system errors are implicitly considered retriable failures, and lambda owners have an option of marking tasks with a <span>RetriableFailure</span> state. Tasks might be dropped from the ATF execution pipeline in different parts of the system through transient RPC failures and failures on dependencies like Edgestore or SQS. These transient failures at different parts of the system do not affect the at-least-once guarantee, though, because of the system of timeouts and re-polling from Store Consumer.
|
||||
</p>
|
||||
<p><b>No concurrent task execution<br></b> Concurrent task execution is avoided through a combination of two methods in ATF. First, tasks are explicitly claimed through an exclusive task state (<span>Claimed</span>) before starting execution. Once the task execution is complete, the task status is updated to one of <span>Success</span>, <span>FatalFailure</span> or <span>RetriableFailure</span>. A task can be claimed only if its existing task state is <span>Enqueued</span> (retried tasks go to the <span>Enqueued</span> state as well once they are re-pushed onto SQS).
|
||||
<figure>
|
||||
<img src="http://fakehost/cms/content/dam/dropbox/tech-blog/en-us/2020/11/atf/diagrams/Techblog-ATF-720x225px-2.png" aria-hidden="false" alt="Task State Transitions [Fig 2]" height="450" width="1440">
|
||||
</figure>
|
||||
</div>
|
||||
<div>
|
||||
<P id="-achieving-guarantees">
|
||||
<h2>
|
||||
Achieving guarantees
|
||||
</h2>
|
||||
</P>
|
||||
</div>
|
||||
<div>
|
||||
<p>
|
||||
<b>At-least-once task execution<br></b> At-least-once execution is guaranteed in ATF by retrying a task until it completes execution (which is signaled by a <span>Success</span> or a <span>FatalFailure</span> state). All ATF system errors are implicitly considered retriable failures, and lambda owners have an option of marking tasks with a <span>RetriableFailure</span> state. Tasks might be dropped from the ATF execution pipeline in different parts of the system through transient RPC failures and failures on dependencies like Edgestore or SQS. These transient failures at different parts of the system do not affect the at-least-once guarantee, though, because of the system of timeouts and re-polling from Store Consumer.
|
||||
</p>
|
||||
<p>
|
||||
However, there might be situations where once a long running task starts execution, its heartbeats might fail repeatedly yet the task execution continues. ATF would retry this task by polling it from the store consumer because the heartbeat timeouts would’ve expired. This task can then be claimed by another worker and lead to concurrent execution. <br></p>
|
||||
<b>No concurrent task execution<br></b> Concurrent task execution is avoided through a combination of two methods in ATF. First, tasks are explicitly claimed through an exclusive task state (<span>Claimed</span>) before starting execution. Once the task execution is complete, the task status is updated to one of <span>Success</span>, <span>FatalFailure</span> or <span>RetriableFailure</span>. A task can be claimed only if its existing task state is <span>Enqueued</span> (retried tasks go to the <span>Enqueued</span> state as well once they are re-pushed onto SQS).
|
||||
</p>
|
||||
<p>
|
||||
However, there might be situations where once a long running task starts execution, its heartbeats might fail repeatedly yet the task execution continues. ATF would retry this task by polling it from the store consumer because the heartbeat timeouts would’ve expired. This task can then be claimed by another worker and lead to concurrent execution. <br>
|
||||
</p>
|
||||
<p>
|
||||
To avoid this situation, there is a termination logic in the Executor processes whereby an Executor process terminates itself as soon as three consecutive heartbeat calls fail. Each heartbeat timeout is large enough to eclipse three consecutive heartbeat failures. This ensures that the Store Consumer cannot pull such tasks before the termination logic ends them—the second method that helps achieve this guarantee.
|
||||
</p>
|
||||
<p><b>Isolation<br></b> Isolation of lambdas is achieved through dedicated worker clusters, dedicated queues, and dedicated per-lambda scheduling quotas. In addition, isolation across different priorities within the same lambda is likewise achieved through dedicated queues and scheduling bandwidth.
|
||||
<p>
|
||||
<b>Isolation<br></b> Isolation of lambdas is achieved through dedicated worker clusters, dedicated queues, and dedicated per-lambda scheduling quotas. In addition, isolation across different priorities within the same lambda is likewise achieved through dedicated queues and scheduling bandwidth.
|
||||
</p>
|
||||
<p><b>Delivery latency<br></b> ATF use cases do not require ultra-low task delivery latencies. Task delivery latencies on the order of a couple of seconds are acceptable. Tasks ready for execution are periodically polled by the Store Consumer and this period of polling largely controls the task delivery latency. Using this as a tuning lever, ATF can achieve different delivery latencies as required. Increasing poll frequency reduces task delivery latency and vice versa. Currently, we have calibrated ATF to poll for ready tasks once every two seconds.
|
||||
<p>
|
||||
<b>Delivery latency<br></b> ATF use cases do not require ultra-low task delivery latencies. Task delivery latencies on the order of a couple of seconds are acceptable. Tasks ready for execution are periodically polled by the Store Consumer and this period of polling largely controls the task delivery latency. Using this as a tuning lever, ATF can achieve different delivery latencies as required. Increasing poll frequency reduces task delivery latency and vice versa. Currently, we have calibrated ATF to poll for ready tasks once every two seconds.
|
||||
</p>
|
||||
</div>
|
||||
<div><P id="ownership-model"><h2>
|
||||
<div>
|
||||
<P id="ownership-model">
|
||||
<h2>
|
||||
Ownership model
|
||||
</h2></P></div>
|
||||
</h2>
|
||||
</P>
|
||||
</div>
|
||||
<p>
|
||||
ATF is designed to be a self-serve framework for developers at Dropbox. The design is very intentional in driving an ownership model where lambda owners own all aspects of their lambdas’ operations. To promote this, all lambda worker clusters are owned by the lambda owners. They have full control over operations on these clusters, including code deployments and capacity management. Each executor process is bound to one lambda. Owners have the option of deploying multiple lambdas on their worker clusters simply by spawning new executor processes on their hosts.
|
||||
</p>
|
||||
<div><P id="-extending-atf"><h2>
|
||||
<div>
|
||||
<P id="-extending-atf">
|
||||
<h2>
|
||||
Extending ATF
|
||||
</h2></P></div>
|
||||
</h2>
|
||||
</P>
|
||||
</div>
|
||||
<div>
|
||||
<p>
|
||||
As described above, ATF provides an infrastructural building block for scheduling asynchronous tasks. With this foundation established, ATF can be extended to support more generic use cases and provide more features as a framework. Following are some examples of what could be built as an extension to ATF.
|
||||
</p>
|
||||
<p><b>Periodic task execution<br></b> Currently, ATF is a system for one-time task scheduling. Building support for periodic task execution as an extension to this framework would be useful in unlocking new capabilities for our clients.
|
||||
</p>
|
||||
<p><b>Better support for task chaining<br></b> Currently, it is possible to chain tasks on ATF by scheduling a task onto ATF that then schedules other tasks onto ATF during its execution. Although it is possible to do this in the current ATF setup, visibility and control on this chaining is absent at the framework level. Another natural extension here would be to better support task chaining through framework-level visibility and control, to make this use case a first class concept in the ATF model.
|
||||
</p>
|
||||
<p><b>Dead letter queues for misbehaving tasks<br></b> One common source of maintenance overhead we observe on ATF is that some tasks get stuck in infinite retry loops due to occasional bugs in lambda logic. This requires manual intervention from the ATF framework owners in some cases where there are a large number of tasks stuck in such loops, occupying a lot of the scheduling bandwidth in the system. Typical manual actions in response to such a situation include pausing execution of the lambdas with misbehaving tasks, or dropping them outright.
|
||||
<p>
|
||||
<b>Periodic task execution<br></b> Currently, ATF is a system for one-time task scheduling. Building support for periodic task execution as an extension to this framework would be useful in unlocking new capabilities for our clients.
|
||||
</p>
|
||||
<p>
|
||||
One way to reduce this operational overhead and provide an easy interface for lambda owners to recover from such incidents would be to create dead letter queues filled with such misbehaving tasks. The ATF framework could impose a maximum number of retries before tasks are pushed onto the dead letter queue. We could create and expose tools that make it easy to reschedule tasks from the dead letter queue back into the ATF system, once the associated lambda bugs are fixed.<br></p>
|
||||
<b>Better support for task chaining<br></b> Currently, it is possible to chain tasks on ATF by scheduling a task onto ATF that then schedules other tasks onto ATF during its execution. Although it is possible to do this in the current ATF setup, visibility and control on this chaining is absent at the framework level. Another natural extension here would be to better support task chaining through framework-level visibility and control, to make this use case a first class concept in the ATF model.
|
||||
</p>
|
||||
<p>
|
||||
<b>Dead letter queues for misbehaving tasks<br></b> One common source of maintenance overhead we observe on ATF is that some tasks get stuck in infinite retry loops due to occasional bugs in lambda logic. This requires manual intervention from the ATF framework owners in some cases where there are a large number of tasks stuck in such loops, occupying a lot of the scheduling bandwidth in the system. Typical manual actions in response to such a situation include pausing execution of the lambdas with misbehaving tasks, or dropping them outright.
|
||||
</p>
|
||||
<p>
|
||||
One way to reduce this operational overhead and provide an easy interface for lambda owners to recover from such incidents would be to create dead letter queues filled with such misbehaving tasks. The ATF framework could impose a maximum number of retries before tasks are pushed onto the dead letter queue. We could create and expose tools that make it easy to reschedule tasks from the dead letter queue back into the ATF system, once the associated lambda bugs are fixed.<br>
|
||||
</p>
|
||||
</div>
|
||||
<div><P id="conclusion"><h2>
|
||||
<div>
|
||||
<P id="conclusion">
|
||||
<h2>
|
||||
Conclusion
|
||||
</h2></P></div>
|
||||
</h2>
|
||||
</P>
|
||||
</div>
|
||||
<p>
|
||||
We hope this post helps engineers elsewhere to develop better async task frameworks of their own. Many thanks to everyone who worked on this project: Anirudh Jayakumar, Deepak Gupta, Dmitry Kopytkov, Koundinya Muppalla, Peng Kang, Rajiv Desai, Ryan Armstrong, Steve Rodrigues, Thomissa Comellas, Xiaonan Zhang and Yuhuan Du.<br></p>
|
||||
We hope this post helps engineers elsewhere to develop better async task frameworks of their own. Many thanks to everyone who worked on this project: Anirudh Jayakumar, Deepak Gupta, Dmitry Kopytkov, Koundinya Muppalla, Peng Kang, Rajiv Desai, Ryan Armstrong, Steve Rodrigues, Thomissa Comellas, Xiaonan Zhang and Yuhuan Du.<br>
|
||||
|
||||
</p>
|
||||
</div></article>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<article><DIV id="readability-page-1">
|
||||
<div id="contentWithSidebar">
|
||||
|
||||
<p>
|
||||
Tuesday 15 October 2019 by Bradley M. Kuhn
|
||||
</p>
|
||||
|
@ -42,8 +43,15 @@
|
|||
<p>
|
||||
Posted on Tuesday 15 October 2019 at 09:11 by Bradley M. Kuhn.
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
<p><code>#include <std/disclaimer.h></code><br><code>use Standard::Disclaimer;</code><br><code>from standard import disclaimer</code><br><code>SELECT full_text FROM standard WHERE type = 'disclaimer';</code></p>
|
||||
<p>
|
||||
<code>#include <std/disclaimer.h></code><br>
|
||||
<code>use Standard::Disclaimer;</code><br>
|
||||
<code>from standard import disclaimer</code><br>
|
||||
<code>SELECT full_text FROM standard WHERE type = 'disclaimer';</code>
|
||||
</p>
|
||||
<p>
|
||||
Both previously and presently, I have been employed by and/or done work for various organizations that also have views on Free, Libre, and Open Source Software. As should be blatantly obvious, this is my website, not theirs, so please do not assume views and opinions here belong to any such organization. Since I do co-own ebb.org with my wife, it may not be so obvious that these aren't her views and opinions, either.
|
||||
</p>
|
||||
|
|
|
@ -1,12 +1,21 @@
|
|||
<article><div id="readability-page-1">
|
||||
<header><h2 itemprop="headline">
|
||||
How to Build a Terrarium </h2></header><div>
|
||||
<p>Glass cloche terrariums are not only appealing to the eye, but they also preserve a bit of nature in your home and serve as a simple, yet beautiful, piece of art. Closed terrariums are easy to care for, as they retain much of their own moisture and provide a warm environment with a consistent level of humidity. You won’t have to water the terrariums unless you see that the walls are not misting up. Small growing plants that don’t require a lot of light work best such as succulents, ferns, moss, even orchids.</p>
|
||||
<figure><img src="http://img-aws.ehowcdn.com/640/cme/photography.prod.demandstudios.com/16149374-814f-40bc-baf3-ca20f149f0ba.jpg" alt="Glass cloche terrariums" title="Glass cloche terrariums" data-credit="Lucy Akins " longdesc="http://s3.amazonaws.com/photography.prod.demandstudios.com/16149374-814f-40bc-baf3-ca20f149f0ba.jpg"></figure><figcaption> Glass cloche terrariums (Lucy Akins) </figcaption>
|
||||
</div>
|
||||
<div id="relatedContentUpper" data-module="rcp_top"><header><h3>Other People Are Reading</h3></header></div>
|
||||
<header>
|
||||
<h2 itemprop="headline">
|
||||
How to Build a Terrarium </h2>
|
||||
|
||||
|
||||
</header>
|
||||
<div>
|
||||
<p><span>What You'll Need:</span></p>
|
||||
<p>Glass cloche terrariums are not only appealing to the eye, but they also preserve a bit of nature in your home and serve as a simple, yet beautiful, piece of art. Closed terrariums are easy to care for, as they retain much of their own moisture and provide a warm environment with a consistent level of humidity. You won’t have to water the terrariums unless you see that the walls are not misting up. Small growing plants that don’t require a lot of light work best such as succulents, ferns, moss, even orchids.</p>
|
||||
<figure> <img src="http://img-aws.ehowcdn.com/640/cme/photography.prod.demandstudios.com/16149374-814f-40bc-baf3-ca20f149f0ba.jpg" alt="Glass cloche terrariums" title="Glass cloche terrariums" data-credit="Lucy Akins " longdesc="http://s3.amazonaws.com/photography.prod.demandstudios.com/16149374-814f-40bc-baf3-ca20f149f0ba.jpg"> </figure>
|
||||
<figcaption> Glass cloche terrariums (Lucy Akins) </figcaption>
|
||||
</div>
|
||||
<div id="relatedContentUpper" data-module="rcp_top">
|
||||
<header>
|
||||
<h3>Other People Are Reading</h3> </header>
|
||||
|
||||
</div>
|
||||
<div> <p><span>What You'll Need:</span></p>
|
||||
<ul>
|
||||
<li>Cloche</li>
|
||||
<li>Planter saucer, small shallow dish or desired platform</li>
|
||||
|
@ -21,74 +30,85 @@ How to Build a Terrarium </h2></header><div>
|
|||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<p><span>Step 1</span></p>
|
||||
<div> <p><span>Step 1</span></p>
|
||||
<p>Measure the circumference of your cloche and cut the foam oasis about 3/4 inch (2 cm) smaller. Place the foam oasis into a container full of water and allow to soak until it sinks to the bottom. Dig out a hole on the oasis large enough to fit your plant, being careful not to pierce all the way through to the bottom.</p>
|
||||
</div>
|
||||
<figure><img src="http://img-aws.ehowcdn.com/default/cme/photography.prod.demandstudios.com/fc249ef6-4d27-41b4-8c21-15f7a8512b50.jpg" alt="Dig a hole in the oasis." data-credit="Lucy Akins"></figure><figcaption> Dig a hole in the oasis. (Lucy Akins) </figcaption>
|
||||
<figure> <img src="http://img-aws.ehowcdn.com/default/cme/photography.prod.demandstudios.com/fc249ef6-4d27-41b4-8c21-15f7a8512b50.jpg" alt="Dig a hole in the oasis." data-credit="Lucy Akins"> </figure>
|
||||
<figcaption> Dig a hole in the oasis. (Lucy Akins) </figcaption>
|
||||
</div>
|
||||
|
||||
|
||||
<div>
|
||||
<div>
|
||||
<p><span>Step 2</span></p>
|
||||
<div> <p><span>Step 2</span></p>
|
||||
<p>Insert your plant into the hole.</p>
|
||||
</div>
|
||||
<figure><img src="http://img-aws.ehowcdn.com/default/cme/photography.prod.demandstudios.com/aae11d4d-a4aa-4251-a4d9-41023ebf6d84.jpg" alt="Orchid in foam oasis" data-credit="Lucy Akins"></figure><figcaption> Orchid in foam oasis (Lucy Akins) </figcaption>
|
||||
<figure> <img src="http://img-aws.ehowcdn.com/default/cme/photography.prod.demandstudios.com/aae11d4d-a4aa-4251-a4d9-41023ebf6d84.jpg" alt="Orchid in foam oasis" data-credit="Lucy Akins"> </figure>
|
||||
<figcaption> Orchid in foam oasis (Lucy Akins) </figcaption>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<p><span>Step 3</span></p>
|
||||
<div> <p><span>Step 3</span></p>
|
||||
<p>You can add various plants if you wish.</p>
|
||||
</div>
|
||||
<figure><img src="http://img-aws.ehowcdn.com/default/cme/photography.prod.demandstudios.com/7afdfa1e-da74-44b5-b89c-ca8123516272.jpg" alt="Various foliage" data-credit="Lucy Akins"></figure><figcaption> Various foliage (Lucy Akins) </figcaption>
|
||||
<figure> <img src="http://img-aws.ehowcdn.com/default/cme/photography.prod.demandstudios.com/7afdfa1e-da74-44b5-b89c-ca8123516272.jpg" alt="Various foliage" data-credit="Lucy Akins"> </figure>
|
||||
<figcaption> Various foliage (Lucy Akins) </figcaption>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<p><span>Step 4</span></p>
|
||||
<div> <p><span>Step 4</span></p>
|
||||
<p>Using floral pins, attach enough moss around the oasis to cover it.</p>
|
||||
</div>
|
||||
<figure><img src="http://img-aws.ehowcdn.com/default/cme/photography.prod.demandstudios.com/4f6612c0-316a-4c74-bb03-cb4e778f6d72.jpg" alt="Attach moss." data-credit="Lucy Akins"></figure><figcaption> Attach moss. (Lucy Akins) </figcaption>
|
||||
<figure> <img src="http://img-aws.ehowcdn.com/default/cme/photography.prod.demandstudios.com/4f6612c0-316a-4c74-bb03-cb4e778f6d72.jpg" alt="Attach moss." data-credit="Lucy Akins"> </figure>
|
||||
<figcaption> Attach moss. (Lucy Akins) </figcaption>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<p><span>Step 5</span></p>
|
||||
<div> <p><span>Step 5</span></p>
|
||||
<p>Gently place the cloche over the oasis. The glass may push some of the moss upward, exposing some of the foam.</p>
|
||||
</div>
|
||||
<figure><img src="http://img-aws.ehowcdn.com/default/cme/photography.prod.demandstudios.com/eeb1e0b4-e573-40a3-8db1-2c76f0b13b84.jpg" alt="Place cloche over oasis." data-credit="Lucy Akins"></figure><figcaption> Place cloche over oasis. (Lucy Akins) </figcaption>
|
||||
<figure> <img src="http://img-aws.ehowcdn.com/default/cme/photography.prod.demandstudios.com/eeb1e0b4-e573-40a3-8db1-2c76f0b13b84.jpg" alt="Place cloche over oasis." data-credit="Lucy Akins"> </figure>
|
||||
<figcaption> Place cloche over oasis. (Lucy Akins) </figcaption>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<p><span>Step 6</span></p>
|
||||
<div> <p><span>Step 6</span></p>
|
||||
<p>Simply pull down the moss with tweezers or insert more moss to fill in the empty spaces.</p>
|
||||
</div>
|
||||
<figure><img src="http://img-aws.ehowcdn.com/default/cme/photography.prod.demandstudios.com/812d4649-4152-4363-97c0-f181d02e709a.jpg" alt="Rearrange moss." data-credit="Lucy Akins"></figure><figcaption> Rearrange moss. (Lucy Akins) </figcaption>
|
||||
<figure> <img src="http://img-aws.ehowcdn.com/default/cme/photography.prod.demandstudios.com/812d4649-4152-4363-97c0-f181d02e709a.jpg" alt="Rearrange moss." data-credit="Lucy Akins"> </figure>
|
||||
<figcaption> Rearrange moss. (Lucy Akins) </figcaption>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<p><span>Step 7</span></p>
|
||||
<div> <p><span>Step 7</span></p>
|
||||
<p>You can use any platform you wish. In this case, a small saucer was used.</p>
|
||||
</div>
|
||||
<figure><img src="http://img-aws.ehowcdn.com/default/cme/photography.prod.demandstudios.com/0cb3988c-9318-47d6-bc9c-c798da1ede72.jpg" alt="Place cloche on a platform to sit on." data-credit="Lucy Akins"></figure><figcaption> Place cloche on a platform to sit on. (Lucy Akins) </figcaption>
|
||||
<figure> <img src="http://img-aws.ehowcdn.com/default/cme/photography.prod.demandstudios.com/0cb3988c-9318-47d6-bc9c-c798da1ede72.jpg" alt="Place cloche on a platform to sit on." data-credit="Lucy Akins"> </figure>
|
||||
<figcaption> Place cloche on a platform to sit on. (Lucy Akins) </figcaption>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<p><span>Step 8</span></p>
|
||||
<div> <p><span>Step 8</span></p>
|
||||
<p>This particular terrarium rests on a planter saucer and features a small white pumpkin.</p>
|
||||
</div>
|
||||
<figure><img src="http://img-aws.ehowcdn.com/640/cme/photography.prod.demandstudios.com/e3e18f0b-ab2c-4ffb-9988-a1ea63faef8b.jpg" alt="Cloche placed on a terracotta saucer" data-credit="Lucy Akins"></figure><figcaption> Cloche placed on a terracotta saucer (Lucy Akins) </figcaption>
|
||||
<figure> <img src="http://img-aws.ehowcdn.com/640/cme/photography.prod.demandstudios.com/e3e18f0b-ab2c-4ffb-9988-a1ea63faef8b.jpg" alt="Cloche placed on a terracotta saucer" data-credit="Lucy Akins"> </figure>
|
||||
<figcaption> Cloche placed on a terracotta saucer (Lucy Akins) </figcaption>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<p><span>Step 9</span></p>
|
||||
<div> <p><span>Step 9</span></p>
|
||||
<p>This particular terrarium was placed on a wood slice and a little toy squirrel was placed inside to add a little whimsy.</p>
|
||||
</div>
|
||||
<figure><img src="http://img-aws.ehowcdn.com/640/cme/photography.prod.demandstudios.com/2cd79f8d-0d16-4573-8861-e47fb74b0638.jpg" alt="Placed on a wooden slice" data-credit="Lucy Akins"></figure><figcaption> Placed on a wooden slice (Lucy Akins) </figcaption>
|
||||
<figure> <img src="http://img-aws.ehowcdn.com/640/cme/photography.prod.demandstudios.com/2cd79f8d-0d16-4573-8861-e47fb74b0638.jpg" alt="Placed on a wooden slice" data-credit="Lucy Akins"> </figure>
|
||||
<figcaption> Placed on a wooden slice (Lucy Akins) </figcaption>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<p><span>Finished Terrarium</span></p>
|
||||
<div> <p><span>Finished Terrarium</span></p>
|
||||
<p>Displayed alone or in a group, these pretty arrangements allow you to add a little nature to your decor or tablescape.</p>
|
||||
</div>
|
||||
<figure><img src="http://img-aws.ehowcdn.com/640/cme/photography.prod.demandstudios.com/78670312-8636-4c42-a75c-3029f7aa6c73.jpg" alt="Cloche terrarium" data-credit="Lucy Akins"></figure><figcaption> Cloche terrarium (Lucy Akins) </figcaption>
|
||||
<figure> <img src="http://img-aws.ehowcdn.com/640/cme/photography.prod.demandstudios.com/78670312-8636-4c42-a75c-3029f7aa6c73.jpg" alt="Cloche terrarium" data-credit="Lucy Akins"> </figure>
|
||||
<figcaption> Cloche terrarium (Lucy Akins) </figcaption>
|
||||
</div>
|
||||
<section id="FeaturedTombstone" data-module="rcp_tombstone"><h2>Featured</h2></section>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section id="FeaturedTombstone" data-module="rcp_tombstone">
|
||||
<h2>Featured</h2>
|
||||
|
||||
</section>
|
||||
</div></article>
|
||||
|
|
|
@ -1,58 +1,151 @@
|
|||
<article><DIV id="readability-page-1">
|
||||
<div data-type="AuthorProfile">
|
||||
<div><p><a id="img-follow-tip" href="http://fakehost/contributor/gina_robertsgrey/" target="_blank"><img src="http://img-aws.ehowcdn.com/60x60/cme/cme_public_images/www_demandstudios_com/sitelife.studiod.com/ver1.0/Content/images/store/9/2/d9dd6f61-b183-4893-927f-5b540e45be91.Small.jpg" data-failover="//img-aws.ehowcdn.com/60x60/ehow-cdn-assets/test15/media/images/authors/missing-author-image.png" onerror="var failover = this.getAttribute('data-failover');
|
||||
<div>
|
||||
<p><a id="img-follow-tip" href="http://fakehost/contributor/gina_robertsgrey/" target="_blank">
|
||||
<img src="http://img-aws.ehowcdn.com/60x60/cme/cme_public_images/www_demandstudios_com/sitelife.studiod.com/ver1.0/Content/images/store/9/2/d9dd6f61-b183-4893-927f-5b540e45be91.Small.jpg" data-failover="//img-aws.ehowcdn.com/60x60/ehow-cdn-assets/test15/media/images/authors/missing-author-image.png" onerror="var failover = this.getAttribute('data-failover');
|
||||
if (failover) failover = failover.replace(/^https?:/,'');
|
||||
var src = this.src ? this.src.replace(/^https?:/,'') : '';
|
||||
if (src != failover){
|
||||
this.src = failover;
|
||||
}"></a></p></div>
|
||||
<p><time datetime="2016-09-14T07:07:00-04:00" itemprop="dateModified">Last updated September 14, 2016</time></p>
|
||||
}"> </a></p>
|
||||
</div>
|
||||
<div><article data-type="article"><div>
|
||||
|
||||
<p><time datetime="2016-09-14T07:07:00-04:00" itemprop="dateModified">Last updated September 14, 2016</time>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
<div>
|
||||
<article data-type="article">
|
||||
<div>
|
||||
<div>
|
||||
<p>Graduation parties are a great way to commemorate the years of hard work teens and college co-eds devote to education. They’re also costly for mom and dad.</p>
|
||||
<p>The average cost of a graduation party in 2013 was a whopping $1,200, according to Graduationparty.com; $700 of that was allocated for food. However that budget was based on Midwestern statistics, and parties in urban areas like New York City are thought to have a much higher price tag.</p>
|
||||
<p>Thankfully, there are plenty of creative ways to trim a little grad party fat without sacrificing any of the fun or celebratory spirit.</p>
|
||||
</div>
|
||||
<figure><img src="http://img-aws.ehowcdn.com/640/cme/cme_public_images/www_ehow_com/cdn-write.demandstudios.com/upload/image/2F/86/5547EF62-EAF5-4256-945D-0496F61C862F/5547EF62-EAF5-4256-945D-0496F61C862F.jpg" alt="Graduation" title="Graduation" data-credit="Mike Watson Images/Moodboard/Getty " longdesc="http://s3.amazonaws.com/cme_public_images/www_ehow_com/cdn-write.demandstudios.com/upload/image/2F/86/5547EF62-EAF5-4256-945D-0496F61C862F/5547EF62-EAF5-4256-945D-0496F61C862F.jpg" data-pin-ehow-hover="true" data-pin-no-hover="true"></figure><figcaption>
|
||||
<figure>
|
||||
<img src="http://img-aws.ehowcdn.com/640/cme/cme_public_images/www_ehow_com/cdn-write.demandstudios.com/upload/image/2F/86/5547EF62-EAF5-4256-945D-0496F61C862F/5547EF62-EAF5-4256-945D-0496F61C862F.jpg" alt="Graduation" title="Graduation" data-credit="Mike Watson Images/Moodboard/Getty " longdesc="http://s3.amazonaws.com/cme_public_images/www_ehow_com/cdn-write.demandstudios.com/upload/image/2F/86/5547EF62-EAF5-4256-945D-0496F61C862F/5547EF62-EAF5-4256-945D-0496F61C862F.jpg" data-pin-ehow-hover="true" data-pin-no-hover="true">
|
||||
</figure>
|
||||
<figcaption>
|
||||
(Mike Watson Images/Moodboard/Getty)
|
||||
</figcaption>
|
||||
</div>
|
||||
<span><span><div>
|
||||
|
||||
|
||||
<span>
|
||||
<span>
|
||||
<div>
|
||||
<p><span><p>Parties hosted at restaurants, clubhouses and country clubs eliminate the need to spend hours cleaning up once party guests have gone home. But that convenience comes with a price tag. A country club may charge as much as $2,000 for room rental and restaurant food and beverage will almost always cost more than food prepped and served at home.</p></span> </p>
|
||||
<figure><img src="http://img-aws.ehowcdn.com/640/cme/cme_public_images/www_ehow_com/cdn-write.demandstudios.com/upload/image/FE/CB/121569D2-6984-4B2F-83C4-9D2D9A27CBFE/121569D2-6984-4B2F-83C4-9D2D9A27CBFE.jpg" alt="Save money hosting the party at home." data-credit="Thomas Jackson/Digital Vision/Getty Images" data-pin-ehow-hover="true" data-pin-no-hover="true"></figure><figcaption>
|
||||
<figure>
|
||||
<img src="http://img-aws.ehowcdn.com/640/cme/cme_public_images/www_ehow_com/cdn-write.demandstudios.com/upload/image/FE/CB/121569D2-6984-4B2F-83C4-9D2D9A27CBFE/121569D2-6984-4B2F-83C4-9D2D9A27CBFE.jpg" alt="Save money hosting the party at home." data-credit="Thomas Jackson/Digital Vision/Getty Images" data-pin-ehow-hover="true" data-pin-no-hover="true">
|
||||
</figure>
|
||||
<figcaption>
|
||||
Thomas Jackson/Digital Vision/Getty Images </figcaption>
|
||||
</div></span></span><span><span><div>
|
||||
</div>
|
||||
</span>
|
||||
</span>
|
||||
<span>
|
||||
<span>
|
||||
<div>
|
||||
<p><span><p>Instead of hiring a DJ, use your iPod or Smartphone to spin the tunes. Both easily hook up to most speakers or mp3 compatible docks to play music from your music library. Or download Pandora, the free online radio app, and play hours of music for free.</p>
|
||||
<p>Personalize the music with a playlist of the grad’s favorite songs or songs that were big hits during his or her years in school.</p></span> </p>
|
||||
<figure><img src="http://img-aws.ehowcdn.com/640/cme/cme_public_images/www_ehow_com/cdn-write.demandstudios.com/upload/image/DF/FC/A05B0252-BD73-4BC7-A09A-96F0A504FCDF/A05B0252-BD73-4BC7-A09A-96F0A504FCDF.jpg" alt="Online radio can take the place of a hired DJ." data-credit="Spencer Platt/Getty Images News/Getty Images" data-pin-ehow-hover="true" data-pin-no-hover="true"></figure><figcaption>
|
||||
<figure>
|
||||
<img src="http://img-aws.ehowcdn.com/640/cme/cme_public_images/www_ehow_com/cdn-write.demandstudios.com/upload/image/DF/FC/A05B0252-BD73-4BC7-A09A-96F0A504FCDF/A05B0252-BD73-4BC7-A09A-96F0A504FCDF.jpg" alt="Online radio can take the place of a hired DJ." data-credit="Spencer Platt/Getty Images News/Getty Images" data-pin-ehow-hover="true" data-pin-no-hover="true">
|
||||
</figure>
|
||||
<figcaption>
|
||||
Spencer Platt/Getty Images News/Getty Images </figcaption>
|
||||
</div></span></span><span><span><div>
|
||||
</div>
|
||||
</span>
|
||||
</span>
|
||||
<span>
|
||||
<span>
|
||||
<div>
|
||||
<p><span><p>Avoid canned drinks, which guests often open, but don't finish. Serve pitchers of tap water with lemon and cucumber slices or sliced strawberries for an interesting and refreshing flavor. Opt for punches and non-alcoholic drinks for high school graduates that allow guests to dole out the exact amount they want to drink.</p></span> </p>
|
||||
<figure><img src="http://img-aws.ehowcdn.com/640/cme/cme_public_images/www_ehow_com/cdn-write.demandstudios.com/upload/image/EB/DB/8A04CCA7-3255-4225-B59A-C41441F8DBEB/8A04CCA7-3255-4225-B59A-C41441F8DBEB.jpg" alt="Serve drinks in pitchers, not in cans." data-credit="evgenyb/iStock/Getty Images" data-pin-ehow-hover="true" data-pin-no-hover="true"></figure><figcaption>
|
||||
<figure>
|
||||
<img src="http://img-aws.ehowcdn.com/640/cme/cme_public_images/www_ehow_com/cdn-write.demandstudios.com/upload/image/EB/DB/8A04CCA7-3255-4225-B59A-C41441F8DBEB/8A04CCA7-3255-4225-B59A-C41441F8DBEB.jpg" alt="Serve drinks in pitchers, not in cans." data-credit="evgenyb/iStock/Getty Images" data-pin-ehow-hover="true" data-pin-no-hover="true">
|
||||
</figure>
|
||||
<figcaption>
|
||||
evgenyb/iStock/Getty Images </figcaption>
|
||||
</div></span></span><span><span><div>
|
||||
</div>
|
||||
|
||||
</span>
|
||||
</span>
|
||||
<span>
|
||||
<span>
|
||||
<div>
|
||||
<p><span><p>Instead of inviting everyone you – and the graduate – know or ever knew, scale back the guest list. Forgo inviting guests that you or your grad haven't seen for eons. There is no reason to provide provisions for people who are essentially out of your lives. Sticking to a small, but personal, guest list allows more time to mingle with loved ones during the party, too.</p></span> </p>
|
||||
<figure><img src="http://img-aws.ehowcdn.com/640/cme/cme_public_images/www_ehow_com/cdn-write.demandstudios.com/upload/image/94/10/08035476-0167-4A03-AADC-13A7E7AA1094/08035476-0167-4A03-AADC-13A7E7AA1094.jpg" alt="Limit guests to those close to the graduate." data-credit="Kane Skennar/Photodisc/Getty Images" data-pin-ehow-hover="true" data-pin-no-hover="true"></figure><figcaption>
|
||||
<figure>
|
||||
<img src="http://img-aws.ehowcdn.com/640/cme/cme_public_images/www_ehow_com/cdn-write.demandstudios.com/upload/image/94/10/08035476-0167-4A03-AADC-13A7E7AA1094/08035476-0167-4A03-AADC-13A7E7AA1094.jpg" alt="Limit guests to those close to the graduate." data-credit="Kane Skennar/Photodisc/Getty Images" data-pin-ehow-hover="true" data-pin-no-hover="true">
|
||||
</figure>
|
||||
<figcaption>
|
||||
Kane Skennar/Photodisc/Getty Images </figcaption>
|
||||
</div></span></span><span><span><div>
|
||||
</div>
|
||||
</span>
|
||||
</span>
|
||||
<span>
|
||||
<span>
|
||||
<div>
|
||||
<p><span><p>See if your grad and his best friend, girlfriend or close family member would consider hosting a joint party. You can split some of the expenses, especially when the two graduates share mutual friends. You'll also have another parent to bounce ideas off of and to help you stick to your budget when you're tempted to splurge.</p></span> </p>
|
||||
<figure><img src="http://img-aws.ehowcdn.com/640/cme/cme_public_images/www_ehow_com/cdn-write.demandstudios.com/upload/image/06/49/4AD62696-FC95-4DA2-8351-42740C7B4906/4AD62696-FC95-4DA2-8351-42740C7B4906.jpg" alt="Throw a joint bash for big savings." data-credit="Mike Watson Images/Moodboard/Getty" data-pin-ehow-hover="true" data-pin-no-hover="true"></figure><figcaption>
|
||||
<figure>
|
||||
<img src="http://img-aws.ehowcdn.com/640/cme/cme_public_images/www_ehow_com/cdn-write.demandstudios.com/upload/image/06/49/4AD62696-FC95-4DA2-8351-42740C7B4906/4AD62696-FC95-4DA2-8351-42740C7B4906.jpg" alt="Throw a joint bash for big savings." data-credit="Mike Watson Images/Moodboard/Getty" data-pin-ehow-hover="true" data-pin-no-hover="true">
|
||||
</figure>
|
||||
<figcaption>
|
||||
Mike Watson Images/Moodboard/Getty </figcaption>
|
||||
</div></span></span><span><span><div>
|
||||
</div>
|
||||
</span>
|
||||
</span>
|
||||
<span>
|
||||
<span>
|
||||
<div>
|
||||
<p><span><p>Skip carving stations of prime rib and jumbo shrimp as appetizers, especially for high school graduation parties. Instead, serve some of the graduate's favorite side dishes that are cost effective, like a big pot of spaghetti with breadsticks. Opt for easy and simple food such as pizza, finger food and mini appetizers. </p>
|
||||
<p>Avoid pre-packaged foods and pre-made deli platters. These can be quite costly. Instead, make your own cheese and deli platters for less than half the cost of pre-made.</p></span> </p>
|
||||
<figure><img src="http://img-aws.ehowcdn.com/640/cme/cme_public_images/www_ehow_com/cdn-write.demandstudios.com/upload/image/D0/51/B6AED06C-5E19-4A26-9AAD-0E175F6251D0/B6AED06C-5E19-4A26-9AAD-0E175F6251D0.jpg" alt="Cost effective appetizers are just as satisfying as pre-made deli platters." data-credit="Mark Stout/iStock/Getty Images" data-pin-ehow-hover="true" data-pin-no-hover="true"></figure><figcaption>
|
||||
Mark Stout/iStock/Getty Images </figcaption>
|
||||
</div></span></span><span><span><div>
|
||||
<p><span><p>Instead of an evening dinner party, host a grad lunch or all appetizers party. Brunch and lunch fare or finger food costs less than dinner. Guests also tend to consume less alcohol in the middle of the day, which keeps cost down.</p></span></p>
|
||||
<figure><img src="http://img-aws.ehowcdn.com/640/cme/cme_public_images/www_ehow_com/cdn-write.demandstudios.com/upload/image/35/B4/DD5FD05A-B631-4AFE-BC8F-FDACAD1EB435/DD5FD05A-B631-4AFE-BC8F-FDACAD1EB435.jpg" alt="A brunch gathering will cost less than a dinner party." data-credit="Mark Stout/iStock/Getty Images" data-pin-ehow-hover="true" data-pin-no-hover="true"></figure><figcaption>
|
||||
<figure>
|
||||
<img src="http://img-aws.ehowcdn.com/640/cme/cme_public_images/www_ehow_com/cdn-write.demandstudios.com/upload/image/D0/51/B6AED06C-5E19-4A26-9AAD-0E175F6251D0/B6AED06C-5E19-4A26-9AAD-0E175F6251D0.jpg" alt="Cost effective appetizers are just as satisfying as pre-made deli platters." data-credit="Mark Stout/iStock/Getty Images" data-pin-ehow-hover="true" data-pin-no-hover="true">
|
||||
</figure>
|
||||
<figcaption>
|
||||
Mark Stout/iStock/Getty Images </figcaption>
|
||||
</div>
|
||||
<div id="relatedContentUpper" data-module="rcp_top"><header><h3>Other People Are Reading</h3></header></div></span></span><span><span><div>
|
||||
</span>
|
||||
</span>
|
||||
<span>
|
||||
<span>
|
||||
<div>
|
||||
<p><span><p>Instead of an evening dinner party, host a grad lunch or all appetizers party. Brunch and lunch fare or finger food costs less than dinner. Guests also tend to consume less alcohol in the middle of the day, which keeps cost down.</p></span> </p>
|
||||
<figure>
|
||||
<img src="http://img-aws.ehowcdn.com/640/cme/cme_public_images/www_ehow_com/cdn-write.demandstudios.com/upload/image/35/B4/DD5FD05A-B631-4AFE-BC8F-FDACAD1EB435/DD5FD05A-B631-4AFE-BC8F-FDACAD1EB435.jpg" alt="A brunch gathering will cost less than a dinner party." data-credit="Mark Stout/iStock/Getty Images" data-pin-ehow-hover="true" data-pin-no-hover="true">
|
||||
</figure>
|
||||
<figcaption>
|
||||
Mark Stout/iStock/Getty Images </figcaption>
|
||||
</div>
|
||||
<div id="relatedContentUpper" data-module="rcp_top">
|
||||
<header>
|
||||
<h3>Other People Are Reading</h3>
|
||||
</header>
|
||||
|
||||
</div>
|
||||
|
||||
</span>
|
||||
</span>
|
||||
<span>
|
||||
<span>
|
||||
<div>
|
||||
<p><span><p>Decorate your party in the graduate's current school colors or the colors of the school he or she will be headed to next. Décor that is not specifically graduation-themed may cost a bit less, and any leftovers can be re-used for future parties, picnics and events.</p></span> </p>
|
||||
<figure><img src="http://img-aws.ehowcdn.com/640/cme/cme_public_images/www_ehow_com/cdn-write.demandstudios.com/upload/image/A1/FA/2C368B34-8F6A-45F6-9DFC-0B0C4E33FAA1/2C368B34-8F6A-45F6-9DFC-0B0C4E33FAA1.jpg" alt="Theme the party by color without graduation-specific decor." data-credit="jethuynh/iStock/Getty Images" data-pin-ehow-hover="true" data-pin-no-hover="true"></figure><figcaption>
|
||||
<figure>
|
||||
<img src="http://img-aws.ehowcdn.com/640/cme/cme_public_images/www_ehow_com/cdn-write.demandstudios.com/upload/image/A1/FA/2C368B34-8F6A-45F6-9DFC-0B0C4E33FAA1/2C368B34-8F6A-45F6-9DFC-0B0C4E33FAA1.jpg" alt="Theme the party by color without graduation-specific decor." data-credit="jethuynh/iStock/Getty Images" data-pin-ehow-hover="true" data-pin-no-hover="true">
|
||||
</figure>
|
||||
<figcaption>
|
||||
jethuynh/iStock/Getty Images </figcaption>
|
||||
</div></span></span><h2><a target="_blank" href="https://www.google.com/adsense/support/bin/request.py?contact=abg_afc&url=http://ehow.com/&hl=en&client=ehow&gl=US">Related Searches</a></h2>
|
||||
<p>Promoted By Zergnet</p></article></div>
|
||||
</div>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
|
||||
<h2>
|
||||
<a target="_blank" href="https://www.google.com/adsense/support/bin/request.py?contact=abg_afc&url=http://ehow.com/&hl=en&client=ehow&gl=US">Related Searches</a>
|
||||
</h2>
|
||||
|
||||
|
||||
<p>Promoted By Zergnet</p>
|
||||
|
||||
</article>
|
||||
</div>
|
||||
</DIV></article>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<article><DIV id="readability-page-1"><article><h2>Lorem</h2>
|
||||
<article><DIV id="readability-page-1"><article>
|
||||
<h2>Lorem</h2>
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
|
||||
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
|
||||
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
|
||||
|
@ -7,7 +8,10 @@
|
|||
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
|
||||
<h2>Videos</h2>
|
||||
<p>At root</p>
|
||||
<iframe width="100%" height="100%" src="https://www.youtube.com/embed/LtOGa5M8AuU" frameborder="0" allowfullscreen=""></iframe><iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/LtOGa5M8AuU" frameborder="0" allowfullscreen=""></iframe><iframe src="https://player.vimeo.com/video/32246206?color=ffffff+title=0+byline=0+portrait=0" width="500" height="281" frameborder="0" webkitallowfullscreen="" mozallowfullscreen="" allowfullscreen=""></iframe><p>In a paragraph</p>
|
||||
<iframe width="100%" height="100%" src="https://www.youtube.com/embed/LtOGa5M8AuU" frameborder="0" allowfullscreen=""></iframe>
|
||||
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/LtOGa5M8AuU" frameborder="0" allowfullscreen=""></iframe>
|
||||
<iframe src="https://player.vimeo.com/video/32246206?color=ffffff+title=0+byline=0+portrait=0" width="500" height="281" frameborder="0" webkitallowfullscreen="" mozallowfullscreen="" allowfullscreen=""></iframe>
|
||||
<p>In a paragraph</p>
|
||||
<p><iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/LtOGa5M8AuU" frameborder="0" allowfullscreen=""></iframe></p>
|
||||
<p>In a div</p>
|
||||
<div><iframe width="100%" height="100%" src="https://www.youtube.com/embed/LtOGa5M8AuU" frameborder="0" allowfullscreen=""></iframe></div>
|
||||
|
@ -18,4 +22,5 @@
|
|||
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
|
||||
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
|
||||
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
</p></article></DIV></article>
|
||||
</p>
|
||||
</article></DIV></article>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<article><DIV id="readability-page-1">
|
||||
<div><p>The <a href="https://www.engadget.com/2017/06/13/the-xbox-one-x-is-aspirational-in-the-purest-sense-of-the-word/" target="_blank">Xbox
|
||||
<div>
|
||||
<p>The <a href="https://www.engadget.com/2017/06/13/the-xbox-one-x-is-aspirational-in-the-purest-sense-of-the-word/" target="_blank">Xbox
|
||||
One X</a> is the ultimate video game system. It sports
|
||||
more horsepower than any system ever. And it plays more
|
||||
titles in native 4K than <a href="https://www.engadget.com/2016/11/07/sony-playstation-4-pro-review/" target="_blank">Sony's
|
||||
|
@ -12,12 +13,24 @@
|
|||
more to play the console's exclusive titles in 4K.
|
||||
Everyone else might be better off waiting, or opting for
|
||||
the $279 <a href="https://www.engadget.com/2016/08/02/xbox-one-s-review/" target="_blank">Xbox
|
||||
One S</a>. </p></div>
|
||||
<section><h4> Gallery: Xbox One
|
||||
One S</a>. </p>
|
||||
</div>
|
||||
<section>
|
||||
<h4> Gallery: Xbox One
|
||||
X | 14 Photos </h4>
|
||||
<div data-behavior="lightbox_trigger" data-engadget-slideshow-id="803271" data-eng-bang='{"gallery":803271,"slide":7142088,"index":0}' data-eng-mn="93511844"><p><a href="http://fakehost/test/base/#" data-index="0" data-engadget-slide-id="7142088" data-eng-bang='{"gallery":803271,"slide":7142088,"index":0}' target="_blank"><img src="https://o.aolcdn.com/images/dims?thumbnail=980%2C653&quality=80&image_uri=https%3A%2F%2Fs.blogcdn.com%2Fslideshows%2Fimages%2Fslides%2F714%2F208%2F8%2FS7142088%2Fslug%2Fl%2Fxbox-one-x-review-gallery-1-1.jpg&client=cbc79c14efcebee57402&signature=9bb08b52e12de8e4060f863a52c613489529818d"></a></p></div></section><div>
|
||||
<div data-behavior="lightbox_trigger" data-engadget-slideshow-id="803271" data-eng-bang='{"gallery":803271,"slide":7142088,"index":0}' data-eng-mn="93511844">
|
||||
<p><a href="http://fakehost/test/base/#" data-index="0" data-engadget-slide-id="7142088" data-eng-bang='{"gallery":803271,"slide":7142088,"index":0}' target="_blank">
|
||||
<img src="https://o.aolcdn.com/images/dims?thumbnail=980%2C653&quality=80&image_uri=https%3A%2F%2Fs.blogcdn.com%2Fslideshows%2Fimages%2Fslides%2F714%2F208%2F8%2FS7142088%2Fslug%2Fl%2Fxbox-one-x-review-gallery-1-1.jpg&client=cbc79c14efcebee57402&signature=9bb08b52e12de8e4060f863a52c613489529818d">
|
||||
</a></p>
|
||||
|
||||
</div>
|
||||
</section><div>
|
||||
|
||||
|
||||
<div>
|
||||
<div><ul>
|
||||
<div>
|
||||
|
||||
<ul>
|
||||
<li>Most
|
||||
powerful hardware ever in a home console
|
||||
</li>
|
||||
|
@ -27,8 +40,11 @@
|
|||
<li>4K Blu-ray
|
||||
drive is great for movie fans
|
||||
</li>
|
||||
</ul></div>
|
||||
<div><ul>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
<ul>
|
||||
<li>Expensive
|
||||
</li>
|
||||
<li>Not worth
|
||||
|
@ -37,15 +53,20 @@
|
|||
<li>Still no VR
|
||||
support
|
||||
</li>
|
||||
</ul></div>
|
||||
</ul>
|
||||
</div>
|
||||
<div><p>As promised, the Xbox One X is the
|
||||
</div>
|
||||
<div>
|
||||
|
||||
<p>As promised, the Xbox One X is the
|
||||
most powerful game console ever. In practice, though, it
|
||||
really just puts Microsoft on equal footing with Sony’s
|
||||
PlayStation 4 Pro. 4K/HDR enhanced games look great, but
|
||||
it’s lack of VR is disappointing in 2017.</p></div>
|
||||
it’s lack of VR is disappointing in 2017.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
<div>
|
||||
<h3>Hardware</h3>
|
||||
<p><img data-credit="Devindra Hardawar/AOL" data-mep="2181678" src="https://o.aolcdn.com/images/dims?crop=1600%2C1067%2C0%2C0&quality=85&format=jpg&resize=1600%2C1067&image_uri=http%3A%2F%2Fo.aolcdn.com%2Fhss%2Fstorage%2Fmidas%2F93beb86758ae1cf95721699e1e006e35%2F205826074%2FXbox%2BOne%2BX%2Breview%2Bgallery%2B7.jpg&client=a1acac3e1b3290917d92&signature=c0f2d36259c2c1decfb60aae364527cda2560d4a" alt=""></p>
|
||||
|
@ -77,7 +98,12 @@
|
|||
Kinect around, you'll need to use a USB adapter to
|
||||
plug it in.</p>
|
||||
</div>
|
||||
<div data-engadget-breakout-type="image"><figure><img src="https://o.aolcdn.com/images/dims?resize=980%2C640&quality=100&image_uri=https%3A%2F%2Fo.aolcdn.com%2Fimages%2Fdims%3Fcrop%3D1599%252C1043%252C0%252C0%26quality%3D85%26format%3Djpg%26resize%3D1600%252C1043%26image_uri%3Dhttp%253A%252F%252Fo.aolcdn.com%252Fhss%252Fstorage%252Fmidas%252F8b98ec8f6649158fe7448ac2f2695ac5%252F205826072%252FXbox%252BOne%252BX%252Breview%252Bgallery%252B6.jpg%26client%3Da1acac3e1b3290917d92%26signature%3D353dad1308f98c2c9dfc82c58a540a8b2f1fe63c&client=cbc79c14efcebee57402&signature=60b7c061460d0d45f5d367b8a9c62978af6b76ce"><figcaption><span>Devindra Hardawar/AOL</span></figcaption></figure></div>
|
||||
<div data-engadget-breakout-type="image">
|
||||
<figure><img src="https://o.aolcdn.com/images/dims?resize=980%2C640&quality=100&image_uri=https%3A%2F%2Fo.aolcdn.com%2Fimages%2Fdims%3Fcrop%3D1599%252C1043%252C0%252C0%26quality%3D85%26format%3Djpg%26resize%3D1600%252C1043%26image_uri%3Dhttp%253A%252F%252Fo.aolcdn.com%252Fhss%252Fstorage%252Fmidas%252F8b98ec8f6649158fe7448ac2f2695ac5%252F205826072%252FXbox%252BOne%252BX%252Breview%252Bgallery%252B6.jpg%26client%3Da1acac3e1b3290917d92%26signature%3D353dad1308f98c2c9dfc82c58a540a8b2f1fe63c&client=cbc79c14efcebee57402&signature=60b7c061460d0d45f5d367b8a9c62978af6b76ce">
|
||||
<figcaption><span>Devindra Hardawar/AOL</span>
|
||||
</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
<div>
|
||||
<p>The console's controller hasn't changed since its
|
||||
last mini-upgrade with the Xbox One S. That revision
|
||||
|
@ -92,7 +118,12 @@
|
|||
has rechargeable controllers.</p>
|
||||
<h3>In use</h3>
|
||||
</div>
|
||||
<div data-engadget-breakout-type="image"><figure><img src="https://o.aolcdn.com/images/dims?resize=980%2C640&quality=100&image_uri=https%3A%2F%2Fo.aolcdn.com%2Fimages%2Fdims%3Fcrop%3D1600%252C900%252C0%252C0%26quality%3D85%26format%3Djpg%26resize%3D1600%252C900%26image_uri%3Dhttp%253A%252F%252Fo.aolcdn.com%252Fhss%252Fstorage%252Fmidas%252F1885534bd201fc37481b806645c1fc8b%252F205828119%252FXbox%252Bone%252BX%252Bscreenshot%252Bgallery%252B8.jpg%26client%3Da1acac3e1b3290917d92%26signature%3Df63cf67c88b37fd9424855984e45f6b950c8c11a&client=cbc79c14efcebee57402&signature=0adca80fc8ee26a7353be639082881450a5ad49f"><figcaption><span>Devindra Hardawar/AOL</span></figcaption></figure></div>
|
||||
<div data-engadget-breakout-type="image">
|
||||
<figure><img src="https://o.aolcdn.com/images/dims?resize=980%2C640&quality=100&image_uri=https%3A%2F%2Fo.aolcdn.com%2Fimages%2Fdims%3Fcrop%3D1600%252C900%252C0%252C0%26quality%3D85%26format%3Djpg%26resize%3D1600%252C900%26image_uri%3Dhttp%253A%252F%252Fo.aolcdn.com%252Fhss%252Fstorage%252Fmidas%252F1885534bd201fc37481b806645c1fc8b%252F205828119%252FXbox%252Bone%252BX%252Bscreenshot%252Bgallery%252B8.jpg%26client%3Da1acac3e1b3290917d92%26signature%3Df63cf67c88b37fd9424855984e45f6b950c8c11a&client=cbc79c14efcebee57402&signature=0adca80fc8ee26a7353be639082881450a5ad49f">
|
||||
<figcaption><span>Devindra Hardawar/AOL</span>
|
||||
</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
<div>
|
||||
<p>You won't find any major differences between the One
|
||||
X and the last Xbox at first — aside from a more
|
||||
|
@ -125,7 +156,12 @@
|
|||
times were on-par with what I've seen with the game
|
||||
on the Xbox One S.</p>
|
||||
</div>
|
||||
<div data-engadget-breakout-type="e2ehero"><figure><img src="https://o.aolcdn.com/images/dims?crop=1600%2C900%2C0%2C0&quality=85&format=jpg&resize=1600%2C900&image_uri=http%3A%2F%2Fo.aolcdn.com%2Fhss%2Fstorage%2Fmidas%2F8352a8a14e88e2ca2ba5be4d8381a055%2F205828115%2FXbox%2Bone%2BX%2Bscreenshot%2Bgallery%2B1.jpg&client=a1acac3e1b3290917d92&signature=d2ccb22e0eaabeb05bfe46e83dbe26fd07f01da8"></figure></div>
|
||||
<div data-engadget-breakout-type="e2ehero">
|
||||
|
||||
<figure><img src="https://o.aolcdn.com/images/dims?crop=1600%2C900%2C0%2C0&quality=85&format=jpg&resize=1600%2C900&image_uri=http%3A%2F%2Fo.aolcdn.com%2Fhss%2Fstorage%2Fmidas%2F8352a8a14e88e2ca2ba5be4d8381a055%2F205828115%2FXbox%2Bone%2BX%2Bscreenshot%2Bgallery%2B1.jpg&client=a1acac3e1b3290917d92&signature=d2ccb22e0eaabeb05bfe46e83dbe26fd07f01da8">
|
||||
|
||||
</figure>
|
||||
</div>
|
||||
<div>
|
||||
<p>You can also play in Performance mode, which bumps
|
||||
the frame rate up to 60FPS and uses higher quality
|
||||
|
@ -150,10 +186,20 @@
|
|||
but there were clearly plenty of graphics settings
|
||||
it couldn't take advantage of, in particular higher
|
||||
levels of bloom lighting and shadow detail.</p>
|
||||
|
||||
</div>
|
||||
<section data-engadget-breakout-type="gallery"><h3> Gallery: Xbox
|
||||
|
||||
<section data-engadget-breakout-type="gallery">
|
||||
<h3> Gallery: Xbox
|
||||
One X screenshots | 9 Photos </h3>
|
||||
<div data-behavior="lightbox_trigger" data-engadget-slideshow-id="803330" data-eng-bang='{"gallery":803330,"slide":7142924}' data-eng-mn="93511844"><p><a href="http://fakehost/test/base/#" data-index="0" data-engadget-slide-id="7142924" data-eng-bang='{"gallery":803330,"slide":7142924}' target="_blank"><img src="https://o.aolcdn.com/images/dims?thumbnail=980%2C653&quality=80&image_uri=https%3A%2F%2Fs.blogcdn.com%2Fslideshows%2Fimages%2Fslides%2F714%2F292%2F4%2FS7142924%2Fslug%2Fl%2Fxbox-one-x-screenshot-gallery-2-1.jpg&client=cbc79c14efcebee57402&signature=38c95635c7aad58a8a48038e05589f5cf35b1e28"></a></p></div></section><div>
|
||||
<div data-behavior="lightbox_trigger" data-engadget-slideshow-id="803330" data-eng-bang='{"gallery":803330,"slide":7142924}' data-eng-mn="93511844">
|
||||
<p><a href="http://fakehost/test/base/#" data-index="0" data-engadget-slide-id="7142924" data-eng-bang='{"gallery":803330,"slide":7142924}' target="_blank">
|
||||
<img src="https://o.aolcdn.com/images/dims?thumbnail=980%2C653&quality=80&image_uri=https%3A%2F%2Fs.blogcdn.com%2Fslideshows%2Fimages%2Fslides%2F714%2F292%2F4%2FS7142924%2Fslug%2Fl%2Fxbox-one-x-screenshot-gallery-2-1.jpg&client=cbc79c14efcebee57402&signature=38c95635c7aad58a8a48038e05589f5cf35b1e28">
|
||||
</a></p>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
<div>
|
||||
<p><em>Killer Instinct</em> and <em>Super Lucky's
|
||||
Tale</em> run in 4K at a smooth 60FPS. They both
|
||||
looked and played better than their standard
|
||||
|
@ -186,7 +232,12 @@
|
|||
Basically, don't expect your entire 360 library to
|
||||
get enhanced.</p>
|
||||
</div>
|
||||
<div data-engadget-breakout-type="e2ehero"><figure><img src="https://o.aolcdn.com/images/dims?crop=1600%2C900%2C0%2C0&quality=85&format=jpg&resize=1600%2C900&image_uri=http%3A%2F%2Fo.aolcdn.com%2Fhss%2Fstorage%2Fmidas%2Facb08903fbe26ad77b80db8c8e7e8fb1%2F205828118%2FXbox%2Bone%2BX%2Bscreenshot%2Bgallery%2B7.jpg&client=a1acac3e1b3290917d92&signature=21630fa5ec6d8fdce2c35f7e1f652636a2d8efe7"></figure></div>
|
||||
<div data-engadget-breakout-type="e2ehero">
|
||||
|
||||
<figure><img src="https://o.aolcdn.com/images/dims?crop=1600%2C900%2C0%2C0&quality=85&format=jpg&resize=1600%2C900&image_uri=http%3A%2F%2Fo.aolcdn.com%2Fhss%2Fstorage%2Fmidas%2Facb08903fbe26ad77b80db8c8e7e8fb1%2F205828118%2FXbox%2Bone%2BX%2Bscreenshot%2Bgallery%2B7.jpg&client=a1acac3e1b3290917d92&signature=21630fa5ec6d8fdce2c35f7e1f652636a2d8efe7">
|
||||
|
||||
</figure>
|
||||
</div>
|
||||
<div>
|
||||
<p>Even if a game isn't specifically tuned for the new
|
||||
console, Microsoft says you might still see some
|
||||
|
@ -204,7 +255,9 @@
|
|||
capable HDR 10 standard. That makes sense since it's
|
||||
more widely supported, but it would have been nice
|
||||
to see Dolby's, too.</p>
|
||||
<p><iframe allowfullscreen="" frameborder="0" gesture="media" height="100%" src="https://www.youtube.com/embed/c8aFcHFu8QM" width="100%"></iframe></p>
|
||||
<p>
|
||||
<iframe allowfullscreen="" frameborder="0" gesture="media" height="100%" src="https://www.youtube.com/embed/c8aFcHFu8QM" width="100%"></iframe>
|
||||
</p>
|
||||
<p>And speaking of Dolby technology, Microsoft is also
|
||||
highlighting Atmos support on the One X, just like
|
||||
it did with the One S. The company's app lets you
|
||||
|
@ -229,7 +282,12 @@
|
|||
PlayStation VR.</p>
|
||||
<h3>Pricing and the competition</h3>
|
||||
</div>
|
||||
<div data-engadget-breakout-type="image"><figure><img src="https://o.aolcdn.com/images/dims?resize=980%2C640&quality=100&image_uri=https%3A%2F%2Fo.aolcdn.com%2Fimages%2Fdims%3Fcrop%3D1600%252C1027%252C0%252C0%26quality%3D85%26format%3Djpg%26resize%3D1600%252C1027%26image_uri%3Dhttp%253A%252F%252Fo.aolcdn.com%252Fhss%252Fstorage%252Fmidas%252Fa2c8ba1caccdbb9e0559797e5141eafd%252F205826078%252FXbox%252BOne%252BX%252Breview%252Bgallery%252B11.jpg%26client%3Da1acac3e1b3290917d92%26signature%3Da11bcddced805c6e3698f8ce0494102aef057265&client=cbc79c14efcebee57402&signature=1e9bd192add2772bc842a34e67b7572cfd1b265a"><figcaption><span>Devindra Hardawar/AOL</span></figcaption></figure></div>
|
||||
<div data-engadget-breakout-type="image">
|
||||
<figure><img src="https://o.aolcdn.com/images/dims?resize=980%2C640&quality=100&image_uri=https%3A%2F%2Fo.aolcdn.com%2Fimages%2Fdims%3Fcrop%3D1600%252C1027%252C0%252C0%26quality%3D85%26format%3Djpg%26resize%3D1600%252C1027%26image_uri%3Dhttp%253A%252F%252Fo.aolcdn.com%252Fhss%252Fstorage%252Fmidas%252Fa2c8ba1caccdbb9e0559797e5141eafd%252F205826078%252FXbox%252BOne%252BX%252Breview%252Bgallery%252B11.jpg%26client%3Da1acac3e1b3290917d92%26signature%3Da11bcddced805c6e3698f8ce0494102aef057265&client=cbc79c14efcebee57402&signature=1e9bd192add2772bc842a34e67b7572cfd1b265a">
|
||||
<figcaption><span>Devindra Hardawar/AOL</span>
|
||||
</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
<div>
|
||||
<p>The biggest knock against the Xbox One X is its $500
|
||||
price. The PS4 Pro launched at $400 last year, and
|
||||
|
@ -272,5 +330,7 @@
|
|||
that will matter. It's exactly what the company
|
||||
promised: the fastest game console ever made.</p>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</DIV></article>
|
||||
|
|
|
@ -1,17 +1,28 @@
|
|||
<article><div id="readability-page-1"><article id="post-997"><div>
|
||||
<article><div id="readability-page-1">
|
||||
<article id="post-997">
|
||||
|
||||
<div>
|
||||
<h3>
|
||||
Highlights
|
||||
</h3>
|
||||
<ul>
|
||||
<li><a href="https://blog.mozilla.org/blog/2020/12/15/our-year-in-review-how-weve-kept-firefox-working-for-you-in-2020/" target="_blank">Here’s our Firefox Year in Review!</a></li>
|
||||
<li><a href="https://blog.mozilla.org/performance/2020/12/15/2020-year-in-review/" target="_blank">Here’s our Performance Year in Review!</a></li>
|
||||
<li>
|
||||
<a href="https://blog.mozilla.org/blog/2020/12/15/our-year-in-review-how-weve-kept-firefox-working-for-you-in-2020/" target="_blank">Here’s our Firefox Year in Review!</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://blog.mozilla.org/performance/2020/12/15/2020-year-in-review/" target="_blank">Here’s our Performance Year in Review!</a>
|
||||
</li>
|
||||
<li>We’ve just landed <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1553982" target="_blank">Bug 1553982</a>, which aims to prevent starting an update while another Firefox instance is running (the cause of that about:restartrequired error page you may have seen).
|
||||
<ul><li><div id="attachment_994">
|
||||
<ul>
|
||||
<li>
|
||||
<div id="attachment_994">
|
||||
<p><a href="https://3sgkpvh31s44756j71xlti9b-wpengine.netdna-ssl.com/files/2020/12/headlines85_0.png" target="_blank"><img aria-describedby="caption-attachment-994" loading="lazy" src="https://3sgkpvh31s44756j71xlti9b-wpengine.netdna-ssl.com/files/2020/12/headlines85_0.png" alt='The about:restartrequired error page, saying "Sorry. We just need to do one small thing to keep going. Nightly has just been updated in the background. Click Restart Nightly to complete the update. We will restore all your pages, windows and tabs afterwards, so you can be on your way quickly.", followed by a button to restart Nightly.' width="1600" height="805"></a></p>
|
||||
<p id="caption-attachment-994">
|
||||
Users who run multiple user profiles concurrently will probably see this less!
|
||||
</p>
|
||||
</div></li></ul>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Also just about to land is <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=353804" target="_blank">Bug 353804</a>, which provides some support for downloading new updates when we already have an update downloaded but haven’t installed it yet. That should prevent many cases of restarting to finish an update and then immediately being notified about another one.
|
||||
</li>
|
||||
|
@ -24,8 +35,10 @@
|
|||
<li>Firefox now supports printing non-contiguous page ranges (e.g. 1-3, 6, 7) – <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=499640" target="_blank">Bug 499640</a>
|
||||
</li>
|
||||
<li>DevTools and Marionette are now fully Fission compatible! Congratulations to those teams!
|
||||
<ul><li>Reminder: Nightly users can help us test Fission by enabling it in about:preferences#experimental, and <a href="https://bugzilla.mozilla.org/enter_bug.cgi?assigned_to=nobody%40mozilla.org&blocked=1561396&bug_ignored=0&bug_severity=--&bug_status=NEW&bug_type=defect&cf_a11y_review_project_flag=---&cf_fission_milestone=---&cf_fx_iteration=---&cf_fx_points=---&cf_root_cause=---&cf_status_firefox83=---&cf_status_firefox84=---&cf_status_firefox85=---&cf_status_firefox86=---&cf_status_firefox_esr78=---&cf_status_thunderbird_esr78=---&cf_tracking_firefox84=---&cf_tracking_firefox85=---&cf_tracking_firefox86=---&cf_tracking_firefox_esr78=---&cf_tracking_firefox_relnote=---&cf_tracking_firefox_sumo=---&cf_tracking_thunderbird_esr78=---&cf_webcompat_priority=---&component=DOM%3A%20Navigation&contenttypemethod=list&contenttypeselection=text%2Fplain&defined_groups=1&filed_via=standard_form&flag_type-203=X&flag_type-37=X&flag_type-41=X&flag_type-607=X&flag_type-721=X&flag_type-737=X&flag_type-787=X&flag_type-799=X&flag_type-800=X&flag_type-803=X&flag_type-846=X&flag_type-855=X&flag_type-863=X&flag_type-864=X&flag_type-930=X&flag_type-936=X&flag_type-937=X&flag_type-945=X&form_name=enter_bug&maketemplate=Remember%20values%20as%20bookmarkable%20template&op_sys=Unspecified&priority=--&product=Core&rep_platform=Unspecified&target_milestone=---&version=unspecified" target="_blank">filing bugs here</a>
|
||||
</li></ul>
|
||||
<ul>
|
||||
<li>Reminder: Nightly users can help us test Fission by enabling it in about:preferences#experimental, and <a href="https://bugzilla.mozilla.org/enter_bug.cgi?assigned_to=nobody%40mozilla.org&blocked=1561396&bug_ignored=0&bug_severity=--&bug_status=NEW&bug_type=defect&cf_a11y_review_project_flag=---&cf_fission_milestone=---&cf_fx_iteration=---&cf_fx_points=---&cf_root_cause=---&cf_status_firefox83=---&cf_status_firefox84=---&cf_status_firefox85=---&cf_status_firefox86=---&cf_status_firefox_esr78=---&cf_status_thunderbird_esr78=---&cf_tracking_firefox84=---&cf_tracking_firefox85=---&cf_tracking_firefox86=---&cf_tracking_firefox_esr78=---&cf_tracking_firefox_relnote=---&cf_tracking_firefox_sumo=---&cf_tracking_thunderbird_esr78=---&cf_webcompat_priority=---&component=DOM%3A%20Navigation&contenttypemethod=list&contenttypeselection=text%2Fplain&defined_groups=1&filed_via=standard_form&flag_type-203=X&flag_type-37=X&flag_type-41=X&flag_type-607=X&flag_type-721=X&flag_type-737=X&flag_type-787=X&flag_type-799=X&flag_type-800=X&flag_type-803=X&flag_type-846=X&flag_type-855=X&flag_type-863=X&flag_type-864=X&flag_type-930=X&flag_type-936=X&flag_type-937=X&flag_type-945=X&form_name=enter_bug&maketemplate=Remember%20values%20as%20bookmarkable%20template&op_sys=Unspecified&priority=--&product=Core&rep_platform=Unspecified&target_milestone=---&version=unspecified" target="_blank">filing bugs here</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<h3>
|
||||
|
@ -34,9 +47,13 @@
|
|||
<h4>
|
||||
Introductions/Shout-Outs
|
||||
</h4>
|
||||
<ul><li>[harry] Amy Churchwell joins the Search & Navigation team today. She transferred internally from Marketing Engineering. Welcome Amy!
|
||||
</li></ul>
|
||||
<h4><a href="https://bugzilla.mozilla.org/buglist.cgi?title=Resolved%20bugs%20(excluding%20employees)&quicksearch=1647931%2C1649618%2C1650645%2C1652412%2C1654217%2C1664768%2C1666831%2C1667061%2C1671579%2C1674806%2C1678173%2C1678372%2C1678616%2C1678865%2C1678866%2C1679252%2C1679412%2C1680931%2C1681213%2C1681554%2C1681642%2C1681948" target="_blank">Resolved bugs (excluding employees)</a></h4>
|
||||
<ul>
|
||||
<li>[harry] Amy Churchwell joins the Search & Navigation team today. She transferred internally from Marketing Engineering. Welcome Amy!
|
||||
</li>
|
||||
</ul>
|
||||
<h4>
|
||||
<a href="https://bugzilla.mozilla.org/buglist.cgi?title=Resolved%20bugs%20(excluding%20employees)&quicksearch=1647931%2C1649618%2C1650645%2C1652412%2C1654217%2C1664768%2C1666831%2C1667061%2C1671579%2C1674806%2C1678173%2C1678372%2C1678616%2C1678865%2C1678866%2C1679252%2C1679412%2C1680931%2C1681213%2C1681554%2C1681642%2C1681948" target="_blank">Resolved bugs (excluding employees)</a>
|
||||
</h4>
|
||||
<h4>
|
||||
Fixed more than one bug
|
||||
</h4>
|
||||
|
@ -70,14 +87,17 @@
|
|||
<h5>
|
||||
Addon Manager & about:addons
|
||||
</h5>
|
||||
<ul><li>Starting from Firefox 85, Mozilla-signed privileged addons can be installed from a third party website without triggering the “third party addon install doorhanger” (and without having to add new “install” site permission for those hosts, <a href="https://searchfox.org/mozilla-central/rev/23c25cd32a1e87095301273937b4ee162f41e860/browser/app/permissions#24-25" target="_blank">e.g. as we had to do for fpn.firefox.com</a>) – <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1681331" target="_blank">Bug 1681331</a>
|
||||
</li></ul>
|
||||
<ul>
|
||||
<li>Starting from Firefox 85, Mozilla-signed privileged addons can be installed from a third party website without triggering the “third party addon install doorhanger” (and without having to add new “install” site permission for those hosts, <a href="https://searchfox.org/mozilla-central/rev/23c25cd32a1e87095301273937b4ee162f41e860/browser/app/permissions#24-25" target="_blank">e.g. as we had to do for fpn.firefox.com</a>) – <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1681331" target="_blank">Bug 1681331</a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li>Fixed addon startup issue when an extension sideloaded in the profile is updated on disk (<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1664144" target="_blank">Bug 1664144</a>)
|
||||
</li>
|
||||
<li>Some more small about:addons cleanup from ntim (<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1678173" target="_blank">Bug 1678173</a>, <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1678865" target="_blank">Bug 1678865</a>, <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1678866" target="_blank">Bug 1678866</a>). Thanks a lot, ntim!
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h5>
|
||||
WebExtensions Framework
|
||||
</h5>
|
||||
|
@ -96,37 +116,50 @@
|
|||
<ul>
|
||||
<li>
|
||||
<b>DevTools Fission</b> <b>M2</b> – Making DevTools Fission compatible DONE.
|
||||
<ul><li><div id="attachment_995">
|
||||
<ul>
|
||||
<li>
|
||||
<div id="attachment_995">
|
||||
<p><a href="https://3sgkpvh31s44756j71xlti9b-wpengine.netdna-ssl.com/files/2020/12/headlines85_1.png" target="_blank"><img aria-describedby="caption-attachment-995" loading="lazy" src="https://3sgkpvh31s44756j71xlti9b-wpengine.netdna-ssl.com/files/2020/12/headlines85_1.png" alt="A table showing the total number of remaining bugs for the MVP to make the DevTools Fission-compatible." width="1600" height="192"></a></p>
|
||||
<p id="caption-attachment-995">
|
||||
Our DevTools are ready for Fission (out-of-process iframes)!
|
||||
</p>
|
||||
</div></li></ul>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<b>Marionette Fission</b> – Making Marionette Fission compatible DONE
|
||||
<ul><li><div id="attachment_996">
|
||||
<ul>
|
||||
<li>
|
||||
<div id="attachment_996">
|
||||
<p><a href="https://3sgkpvh31s44756j71xlti9b-wpengine.netdna-ssl.com/files/2020/12/headlines85_2.png" target="_blank"><img aria-describedby="caption-attachment-996" loading="lazy" src="https://3sgkpvh31s44756j71xlti9b-wpengine.netdna-ssl.com/files/2020/12/headlines85_2.png" alt="A table showing the total number of remaining bugs for the MVP to make Marionette Fission-compatible." width="1600" height="189"></a></p>
|
||||
<p id="caption-attachment-996">
|
||||
Marionette, the framework that allows Firefox to be tested with automation, is now Fission compatible too!
|
||||
</p>
|
||||
</div></li></ul>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<h4>
|
||||
Fission
|
||||
</h4>
|
||||
<ul><li>Neil has patches up to <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1682442" target="_blank">improve the behaviour of the tab unloader</a>, and <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1644911" target="_blank">show UI when subframes crash</a>
|
||||
</li></ul>
|
||||
<ul>
|
||||
<li>Neil has patches up to <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1682442" target="_blank">improve the behaviour of the tab unloader</a>, and <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1644911" target="_blank">show UI when subframes crash</a>
|
||||
</li>
|
||||
</ul>
|
||||
<h4>
|
||||
Installer & Updater
|
||||
</h4>
|
||||
<ul><li>Background updater work is also proceeding, with <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1676296" target="_blank">Bug 1676296</a> landing last week to support managing scheduled tasks in Gecko, and more development still also happening on the background task framework.
|
||||
</li></ul>
|
||||
<ul>
|
||||
<li>Background updater work is also proceeding, with <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1676296" target="_blank">Bug 1676296</a> landing last week to support managing scheduled tasks in Gecko, and more development still also happening on the background task framework.
|
||||
</li>
|
||||
</ul>
|
||||
<h4>
|
||||
New Tab Page and Pocket
|
||||
</h4>
|
||||
<ul><li>We’re running three experiments:
|
||||
<ul>
|
||||
<li>We’re running three experiments:
|
||||
<ul>
|
||||
<li>Newtab Pocket stories in AU and NZ
|
||||
</li>
|
||||
|
@ -135,8 +168,11 @@
|
|||
<li>We’re testing some changes to newtab story personalization
|
||||
</li>
|
||||
</ul>
|
||||
</li></ul>
|
||||
<h4><a href="https://wiki.mozilla.org/Toolkit:Password_Manager" target="_blank">Password Manager</a></h4>
|
||||
</li>
|
||||
</ul>
|
||||
<h4>
|
||||
<a href="https://wiki.mozilla.org/Toolkit:Password_Manager" target="_blank">Password Manager</a>
|
||||
</h4>
|
||||
<ul>
|
||||
<li>Dimi fixed <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1677710" target="_blank">Bug 1677710</a> The password manager code triggers main thread sqlite disk I/O off of the gather-telemetry notification
|
||||
</li>
|
||||
|
@ -186,9 +222,15 @@
|
|||
</li>
|
||||
<li>florian has some new visualization variations up for the BHR dashboard
|
||||
<ul>
|
||||
<li><a href="http://queze.net/bhr/test/#showFrames=1" target="_blank">showFrames</a></li>
|
||||
<li><a href="http://queze.net/bhr/test/#showFrames=1&onlyXulLeaf=1" target="_blank">onlyXulLeaf</a></li>
|
||||
<li><a href="http://queze.net/bhr/test/#showFrames=1&onlyXulLeaf=1&skipKnownBugs=1" target="_blank">skipKnownBugs</a></li>
|
||||
<li>
|
||||
<a href="http://queze.net/bhr/test/#showFrames=1" target="_blank">showFrames</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="http://queze.net/bhr/test/#showFrames=1&onlyXulLeaf=1" target="_blank">onlyXulLeaf</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="http://queze.net/bhr/test/#showFrames=1&onlyXulLeaf=1&skipKnownBugs=1" target="_blank">skipKnownBugs</a>
|
||||
</li>
|
||||
<li>This BHR dashboard helped identify a hang caused by the password manager code, <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1677710" target="_blank">which has been recently fixed</a>! Thanks, dimi!
|
||||
</li>
|
||||
</ul>
|
||||
|
@ -212,11 +254,21 @@
|
|||
</li>
|
||||
<li>In progress:
|
||||
<ul>
|
||||
<li><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1677080" target="_blank">Bug 1677080 – Fullscreen PiP window is affected by switching video source</a></li>
|
||||
<li><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1677107" target="_blank">Bug 1677107 – Add Telemetry for tracking multiple PiP support usage</a></li>
|
||||
<li><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1681796" target="_blank">Bug 1681796 – Prevent superfluous PictureInPictureParent actors from being associated with each tab</a></li>
|
||||
<li><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1680796" target="_blank">Bug 1680796 – Ensure that the tab’s Toolkit:PictureInPicture actor is destroyed before moving to next test</a></li>
|
||||
<li><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1678390" target="_blank">Bug 1678390 – Prevent Picture-in-Picture windows from opening on top of one another</a></li>
|
||||
<li>
|
||||
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1677080" target="_blank">Bug 1677080 – Fullscreen PiP window is affected by switching video source</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1677107" target="_blank">Bug 1677107 – Add Telemetry for tracking multiple PiP support usage</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1681796" target="_blank">Bug 1681796 – Prevent superfluous PictureInPictureParent actors from being associated with each tab</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1680796" target="_blank">Bug 1680796 – Ensure that the tab’s Toolkit:PictureInPicture actor is destroyed before moving to next test</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1678390" target="_blank">Bug 1678390 – Prevent Picture-in-Picture windows from opening on top of one another</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
@ -237,4 +289,7 @@
|
|||
<li>Fixed a bug where search engines were being re-added on startup after their removal, when using a language pack (<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1675624" target="_blank">Bug 1675624</a>)
|
||||
</li>
|
||||
</ul>
|
||||
</div></article></div></article>
|
||||
</div>
|
||||
|
||||
</article>
|
||||
</div></article>
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
<p>
|
||||
Na ocasião, Tite e outros representantes do Corinthians <a href="https://www1.folha.uol.com.br/poder/1124743-corinthians-leva-a-taca-da-libertadores-para-lula.shtml" target="_blank">foram ao Instituto Lula para mostrar a taça</a> original da Libertadores ao ex-presidente.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
O assunto foi levantado porque recentemente Tite foi questionado se aceitaria um encontro da seleção brasileira com Bolsonaro em uma conquista de título ou <a href="https://www1.folha.uol.com.br/esporte/2018/12/selecao-brasileira-jogara-duas-vezes-em-sao-paulo-na-copa-america.shtml" target="_blank">antes da Copa América de 2019</a>, por exemplo. O treinador deixou claro que preferiria evitar esse tipo de formalidade.
|
||||
</p>
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
<article><div id="readability-page-1">
|
||||
|
||||
|
||||
|
||||
<p> 翱翔于距地球数千公里的太空中,进入广袤漆黑的未知领域,是一项艰苦卓绝的工作。这让人感到巨大压力和极度恐慌。那么,为什么不能让宇航员来一杯“地球末日”鸡尾酒来放松一下?</p>
|
||||
<p> 不幸的是,对于希望能喝上一杯的太空探险者,那些将他们送上太空的政府机构普遍禁止他们染指包括酒在内的含酒精饮料。</p>
|
||||
<p> 但是,很快普通人都会有机会向人类“最终的边疆”出发——以平民化旅行的形式,去探索和殖民火星。确实,火星之旅将是一次令人感到痛苦的旅行,可能一去不复返并要几年时间才能完成,但是否应该允许参与者在旅程中痛饮一番?或至少携带能在火星上发酵自制酒精饮料的设备?</p>
|
||||
<p><img id="45395168" alt="(Credit: Nasa)" src="http://imgtech.gmw.cn/attachement/jpg/site2/20170310/448a5bc1e2861a2c4e5929.jpg" title="宇航员在太空中喝酒会怎么样?后果很严重"></p>
|
||||
<p><span face="楷体"> 图注:巴兹?奥尔德林(Buzz Aldrin)可能是第二个在月球上行走的人,但他是第一个在月球上喝酒的人</span></p>
|
||||
<p>
|
||||
<span face="楷体"> 图注:巴兹?奥尔德林(Buzz Aldrin)可能是第二个在月球上行走的人,但他是第一个在月球上喝酒的人</span>
|
||||
</p>
|
||||
<p> 事实是,历史上酒与太空探险有一种复杂的关系。让我们来看看喝了酒的航天员究竟会发生什么—— 如果我们开始给予进入太空的人类更大的自由度,又可能会发生什么。</p>
|
||||
<p> 人们普遍认为,当一个人所处的海拔越高,喝醉后会越容易感到头昏。因此,人们自然地想到,当人身处地球轨道上时,饮酒会对人体有更强烈的致眩作用。但这种说法可能不是正确的。</p>
|
||||
<p> 事实上,有证据表明,早在上世纪八十年代就澄清了这一传言。1985年,美国联邦航空管理局(UFAA)开展了一项研究,以验证人在不同的海拔高度饮酒,是否会影响执行复杂任务时的表现和酒精测定仪的读数。</p>
|
||||
|
@ -16,7 +21,9 @@
|
|||
<p> 美国宇航局约翰逊航天中心发言人丹尼尔·霍特(Daniel Huot)表示:“国际空间站上的宇航员不允许喝酒。在国际空间站上,酒精和其它挥发性化合物的使用受到控制,因为它们的挥发物可能对该站的水回收系统产生影响。”</p>
|
||||
<p> 为此,国际空间站上的宇航员甚至没有被提供含有酒精的产品,例如漱口水、香水或须后水。如果在国际空间站上饮酒狂欢,溢出的啤酒也可能存在损坏设备的风险。</p>
|
||||
<p><img id="45395150" alt="(Credit: iStock)" src="http://imgtech.gmw.cn/attachement/jpg/site2/20170310/448a5bc1e2861a2c4e592a.jpg" title="宇航员在太空中喝酒会怎么样?后果很严重"></p>
|
||||
<p><span face="楷体"> 图注:测试表明,有关人在高空中喝酒更容易醉的传言是不正确的</span></p>
|
||||
<p>
|
||||
<span face="楷体"> 图注:测试表明,有关人在高空中喝酒更容易醉的传言是不正确的</span>
|
||||
</p>
|
||||
<p> 然后是责任的问题。我们不允许汽车司机或飞机飞行员喝醉后驾驶,所以并不奇怪同样的规则适用于国际空间站上的宇航员。毕竟国际空间站的造价高达1500亿美元,而且在接近真空的太空中其运行速度达到了每小时27680公里。</p>
|
||||
<p> 然而,2007年,美国宇航局(NASA)成立了一个负责调查宇航员健康状况的独立小组,称历史上该机构至少有两名宇航员在即将飞行前喝了大量的酒,但仍然被允许飞行。Nasa安全负责人随后的审查发现并没有证据支持这一指控。宇航员在飞行前12小时是严禁饮酒的,因为他们需要充分的思维能力和清醒的意识。</p>
|
||||
<p> 出台这一规则的原因很清楚。在1985年UFAA开展的关于酒精在不同海拔高度影响的研究中,研究人员得出结论,酒精的影响与海拔高度无关。无论参与测试的人员在什么海拔高度喝酒,其酒精测量仪的读数都是一样的。他们的行为表现受到的影响也相同,但如果提供给测试人员的是安慰剂,则身处高空比身处海平面的行为表现要更差一些。这表明,无论是否摄入酒精,海拔高度可能对心理表现有轻微的影响。</p>
|
||||
|
@ -33,11 +40,18 @@
|
|||
<p> 相比之下,执行登陆火星任务的人将远离家乡几年,而不是几个月,因此可能会有人提出有关禁止饮酒的规定可以放松一些。</p>
|
||||
<p> 然而,像戴夫?汉森这样的专家认为,继续禁止饮酒并没有什么害处。除了实际的安全问题,饮酒还可能有其它挑战。汉森认为,地球人存在许多社会文化方面的差异,而且人连续几年时间呆在一个狭小的空间里,很容易突然发怒,这些因素都使饮酒问题变得很棘手。</p>
|
||||
<p><img id="45395153" alt="(Credit: David Frohman/Peachstate Historical Consulting Inc)" src="http://imgtech.gmw.cn/attachement/jpg/site2/20170310/448a5bc1e2861a2c4e592d.jpg" title="宇航员在太空中喝酒会怎么样?后果很严重"> </p>
|
||||
<p><span face="楷体"> 图注:奥尔德林的圣餐杯回到了地球上</span></p>
|
||||
<p>
|
||||
<span face="楷体"> 图注:奥尔德林的圣餐杯回到了地球上</span>
|
||||
</p>
|
||||
<p> 他说:“这是一个政治问题,也是一个文化方面的问题,但不是一个科学上的问题。这将是未来一个可能产生冲突领域,因为人们具有不同的文化背景,他们对饮酒的态度不同。”他进一步指出,如果你与穆斯林、摩门教徒或禁酒主义者分配在同一间宿舍怎么办?面对未来人们可能在一个没有期限的时间内呆在一个有限的空间里,需要“尽早解决”如何协调不同文化观点的问题。</p>
|
||||
<p><ins></ins> 所以,当宇航员在地球轨道上时,将还不得不满足于通过欣赏外面的景色来振作精神,而不要指望沉溺于烈酒中。我们留在地球上的人,则可以准备好适量的香槟酒,以迎接他们的归来。</p>
|
||||
<p> 原标题:他晚于阿姆斯特朗登月 却是首个敢在月球喝酒的人</p>
|
||||
<p><strong> 出品︱网易科学人栏目组 胖胖</strong></p>
|
||||
<p><strong> 作者︱春春</strong><a href="http://www.gmw.cn/" target="_blank"><img src="https://img.gmw.cn/pic/content_logo.png" title="返回光明网首页"></a></p>
|
||||
<p><strong> 作者︱春春</strong>
|
||||
<a href="http://www.gmw.cn/" target="_blank"><img src="https://img.gmw.cn/pic/content_logo.png" title="返回光明网首页"></a>
|
||||
</p>
|
||||
|
||||
<p>[责任编辑:肖春芳]</p>
|
||||
|
||||
|
||||
</div></article>
|
||||
|
|
|
@ -1,33 +1,61 @@
|
|||
<article><section data-type="chapter" id="readability-page-1" role="main"><h2>
|
||||
<article><section data-type="chapter" id="readability-page-1" role="main">
|
||||
<h2>
|
||||
Monitoring Distributed Systems
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
Google’s SRE teams have some basic principles and best practices for building successful monitoring and alerting systems. This chapter offers guidelines for what issues should interrupt a human via a page, and how to deal with issues that aren’t serious enough to trigger a page.
|
||||
</p>
|
||||
<section data-type="sect1" id="definitions-2ksZhN"><h2>
|
||||
<section data-type="sect1" id="definitions-2ksZhN">
|
||||
<h2>
|
||||
Definitions
|
||||
</h2>
|
||||
<p>There’s no uniformly shared vocabulary for discussing all topics related to monitoring. Even within Google, usage of the following terms varies, but the most common interpretations are listed here.
|
||||
<p>
|
||||
There’s no uniformly shared vocabulary for discussing all topics related to monitoring. Even within Google, usage of the following terms varies, but the most common interpretations are listed here.
|
||||
</p>
|
||||
<dl>
|
||||
<dd><p>
|
||||
|
||||
<dd>
|
||||
<p>
|
||||
Collecting, processing, aggregating, and displaying real-time quantitative data about a system, such as query counts and types, error counts and types, processing times, and server lifetimes.
|
||||
</p></dd>
|
||||
<dd><p>Monitoring based on metrics exposed by the internals of the system, including logs, interfaces like the Java Virtual Machine Profiling Interface, or an HTTP handler that emits internal statistics.
|
||||
</p></dd>
|
||||
<dd><p>Testing externally visible behavior as a user would see it.
|
||||
</p></dd>
|
||||
<dd><p>An application (usually web-based) that provides a summary view of a service’s core metrics. A dashboard may have filters, selectors, and so on, but is prebuilt to expose the metrics most important to its users. The dashboard might also display team information such as ticket queue length, a list of high-priority bugs, the current on-call engineer for a given area of responsibility, or recent pushes.
|
||||
</p></dd>
|
||||
<dd><p>A notification intended to be read by a human and that is pushed to a system such as a bug or ticket queue, an email alias, or a pager. Respectively, these alerts are classified as <em>tickets</em>, <em>email alerts</em>,<sup><a data-type="noteref" id="id-LvQuvtYS7UvI8h4-marker" href="http://fakehost/test/base/#id-LvQuvtYS7UvI8h4" target="_blank">22</a></sup> and <em>pages</em>.
|
||||
</p></dd>
|
||||
<dd><p>A defect in a software or human system that, if repaired, instills confidence that this event won’t happen again in the same way. A given incident might have multiple root causes: for example, perhaps it was caused by a combination of insufficient process automation, software that crashed on bogus input, <em>and</em> insufficient testing of the script used to generate the configuration. Each of these factors might stand alone as a root cause, and each should be repaired.
|
||||
</p></dd>
|
||||
</p>
|
||||
</dd>
|
||||
|
||||
<dd>
|
||||
<p>
|
||||
Monitoring based on metrics exposed by the internals of the system, including logs, interfaces like the Java Virtual Machine Profiling Interface, or an HTTP handler that emits internal statistics.
|
||||
</p>
|
||||
</dd>
|
||||
|
||||
<dd>
|
||||
<p>
|
||||
Testing externally visible behavior as a user would see it.
|
||||
</p>
|
||||
</dd>
|
||||
|
||||
<dd>
|
||||
<p>
|
||||
An application (usually web-based) that provides a summary view of a service’s core metrics. A dashboard may have filters, selectors, and so on, but is prebuilt to expose the metrics most important to its users. The dashboard might also display team information such as ticket queue length, a list of high-priority bugs, the current on-call engineer for a given area of responsibility, or recent pushes.
|
||||
</p>
|
||||
</dd>
|
||||
|
||||
<dd>
|
||||
<p>
|
||||
A notification intended to be read by a human and that is pushed to a system such as a bug or ticket queue, an email alias, or a pager. Respectively, these alerts are classified as <em>tickets</em>, <em>email alerts</em>,<sup><a data-type="noteref" id="id-LvQuvtYS7UvI8h4-marker" href="http://fakehost/test/base/#id-LvQuvtYS7UvI8h4" target="_blank">22</a></sup> and <em>pages</em>.
|
||||
</p>
|
||||
</dd>
|
||||
|
||||
<dd>
|
||||
<p>
|
||||
A defect in a software or human system that, if repaired, instills confidence that this event won’t happen again in the same way. A given incident might have multiple root causes: for example, perhaps it was caused by a combination of insufficient process automation, software that crashed on bogus input, <em>and</em> insufficient testing of the script used to generate the configuration. Each of these factors might stand alone as a root cause, and each should be repaired.
|
||||
</p>
|
||||
</dd>
|
||||
<dt id="node-and-machine">
|
||||
Node and machine
|
||||
</dt>
|
||||
<dd>
|
||||
<p>Used interchangeably to indicate a single instance of a running kernel in either a physical server, virtual machine, or container. There might be multiple <em>services</em> worth monitoring on a single machine. The services may either be:
|
||||
<p>
|
||||
Used interchangeably to indicate a single instance of a running kernel in either a physical server, virtual machine, or container. There might be multiple <em>services</em> worth monitoring on a single machine. The services may either be:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Related to each other: for example, a caching server and a web server
|
||||
|
@ -36,29 +64,52 @@
|
|||
</li>
|
||||
</ul>
|
||||
</dd>
|
||||
<dd><p>
|
||||
|
||||
<dd>
|
||||
<p>
|
||||
Any change to a service’s running software or its configuration.
|
||||
</p></dd>
|
||||
</dl></section><section data-type="sect1" id="why-monitor-pWsBTZ"><h2>
|
||||
</p>
|
||||
</dd>
|
||||
</dl>
|
||||
</section>
|
||||
<section data-type="sect1" id="why-monitor-pWsBTZ">
|
||||
<h2>
|
||||
Why Monitor?
|
||||
</h2>
|
||||
<p>There are many reasons to monitor a system, including:
|
||||
<p>
|
||||
There are many reasons to monitor a system, including:
|
||||
</p>
|
||||
<dl>
|
||||
<dd><p>
|
||||
|
||||
<dd>
|
||||
<p>
|
||||
How big is my database and how fast is it growing? How quickly is my daily-active user count growing?
|
||||
</p></dd>
|
||||
<dd><p>
|
||||
</p>
|
||||
</dd>
|
||||
|
||||
<dd>
|
||||
<p>
|
||||
Are queries faster with Acme Bucket of Bytes 2.72 versus Ajax DB 3.14? How much better is my memcache hit rate with an extra node? Is my site slower than it was last week?
|
||||
</p></dd>
|
||||
<dd><p>
|
||||
</p>
|
||||
</dd>
|
||||
|
||||
<dd>
|
||||
<p>
|
||||
Something is broken, and somebody needs to fix it right now! Or, something might break soon, so somebody should look soon.
|
||||
</p></dd>
|
||||
<dd><p>Dashboards should answer basic questions about your service, and normally include some form of the four golden signals (discussed in <a data-type="xref" href="http://fakehost/test/base/#xref_monitoring_golden-signals" target="_blank">The Four Golden Signals</a>).
|
||||
</p></dd>
|
||||
<dd><p>
|
||||
</p>
|
||||
</dd>
|
||||
|
||||
<dd>
|
||||
<p>
|
||||
Dashboards should answer basic questions about your service, and normally include some form of the four golden signals (discussed in <a data-type="xref" href="http://fakehost/test/base/#xref_monitoring_golden-signals" target="_blank">The Four Golden Signals</a>).
|
||||
</p>
|
||||
</dd>
|
||||
|
||||
<dd>
|
||||
<p>
|
||||
Our latency just shot up; what else happened around the same time?
|
||||
</p></dd>
|
||||
</p>
|
||||
</dd>
|
||||
</dl>
|
||||
<p>
|
||||
System monitoring is also helpful in supplying raw input into business analytics and in facilitating analysis of security breaches. Because this book focuses on the engineering domains in which SRE has particular expertise, we won’t discuss these applications of monitoring here.
|
||||
|
@ -68,24 +119,34 @@
|
|||
</p>
|
||||
<p>
|
||||
Paging a human is a quite expensive use of an employee’s time. If an employee is at work, a page interrupts their workflow. If the employee is at home, a page interrupts their personal time, and perhaps even their sleep. When pages occur too frequently, employees second-guess, skim, or even ignore incoming alerts, sometimes even ignoring a "real" page that’s masked by the noise. Outages can be prolonged because other noise interferes with a rapid diagnosis and fix. Effective alerting systems have good signal and very low noise.
|
||||
</p></section><section data-type="sect1" id="setting-reasonable-expectations-for-monitoring-o8svcM"><h2>
|
||||
</p>
|
||||
</section>
|
||||
<section data-type="sect1" id="setting-reasonable-expectations-for-monitoring-o8svcM">
|
||||
<h2>
|
||||
Setting Reasonable Expectations for Monitoring
|
||||
</h2>
|
||||
<p>Monitoring a complex application is a significant engineering endeavor in and of itself. Even with substantial existing infrastructure for instrumentation, collection, display, and alerting in place, a Google SRE team with 10–12 members typically has one or sometimes two members whose primary assignment is to build and maintain monitoring systems for their service. This number has decreased over time as we generalize and centralize common monitoring infrastructure, but every SRE team typically has at least one “monitoring person.” (That being said, while it can be fun to have access to traffic graph dashboards and the like, SRE teams carefully avoid any situation that requires someone to “stare at a screen to watch for problems.”)
|
||||
<p>
|
||||
Monitoring a complex application is a significant engineering endeavor in and of itself. Even with substantial existing infrastructure for instrumentation, collection, display, and alerting in place, a Google SRE team with 10–12 members typically has one or sometimes two members whose primary assignment is to build and maintain monitoring systems for their service. This number has decreased over time as we generalize and centralize common monitoring infrastructure, but every SRE team typically has at least one “monitoring person.” (That being said, while it can be fun to have access to traffic graph dashboards and the like, SRE teams carefully avoid any situation that requires someone to “stare at a screen to watch for problems.”)
|
||||
</p>
|
||||
<p>In general, Google has trended toward simpler and faster monitoring systems, with better tools for <em>post hoc</em> analysis. We avoid "magic" systems that try to learn thresholds or automatically detect causality. Rules that detect unexpected changes in end-user request rates are one counterexample; while these rules are still kept as simple as possible, they give a very quick detection of a very simple, specific, severe anomaly. Other uses of monitoring data such as capacity planning and traffic prediction can tolerate more fragility, and thus, more complexity. Observational experiments conducted over a very long time horizon (months or years) with a low sampling rate (hours or days) can also often tolerate more fragility because occasional missed samples won’t hide a long-running trend.
|
||||
<p>
|
||||
In general, Google has trended toward simpler and faster monitoring systems, with better tools for <em>post hoc</em> analysis. We avoid "magic" systems that try to learn thresholds or automatically detect causality. Rules that detect unexpected changes in end-user request rates are one counterexample; while these rules are still kept as simple as possible, they give a very quick detection of a very simple, specific, severe anomaly. Other uses of monitoring data such as capacity planning and traffic prediction can tolerate more fragility, and thus, more complexity. Observational experiments conducted over a very long time horizon (months or years) with a low sampling rate (hours or days) can also often tolerate more fragility because occasional missed samples won’t hide a long-running trend.
|
||||
</p>
|
||||
<p>Google SRE has experienced only limited success with complex dependency hierarchies. We seldom use rules such as, "If I know the database is slow, alert for a slow database; otherwise, alert for the website being generally slow." Dependency-reliant rules usually pertain to very stable parts of our system, such as our system for draining user traffic away from a datacenter. For example, "If a datacenter is drained, then don’t alert me on its latency" is one common datacenter alerting rule. Few teams at Google maintain complex dependency hierarchies because our infrastructure has a steady rate of continuous refactoring.
|
||||
<p>
|
||||
Google SRE has experienced only limited success with complex dependency hierarchies. We seldom use rules such as, "If I know the database is slow, alert for a slow database; otherwise, alert for the website being generally slow." Dependency-reliant rules usually pertain to very stable parts of our system, such as our system for draining user traffic away from a datacenter. For example, "If a datacenter is drained, then don’t alert me on its latency" is one common datacenter alerting rule. Few teams at Google maintain complex dependency hierarchies because our infrastructure has a steady rate of continuous refactoring.
|
||||
</p>
|
||||
<p>
|
||||
Some of the ideas described in this chapter are still aspirational: there is always room to move more rapidly from symptom to root cause(s), especially in ever-changing systems. So while this chapter sets out some goals for monitoring systems, and some ways to achieve these goals, it’s important that monitoring systems—especially the critical path from the onset of a production problem, through a page to a human, through basic triage and deep debugging—be kept simple and comprehensible by everyone on the team.
|
||||
</p>
|
||||
<p>
|
||||
Similarly, to keep noise low and signal high, the elements of your monitoring system that direct to a pager need to be very simple and robust. Rules that generate alerts for humans should be simple to understand and represent a clear failure.
|
||||
</p></section><section data-type="sect1" id="symptoms-versus-causes-g0sEi4"><h2>
|
||||
</p>
|
||||
</section>
|
||||
<section data-type="sect1" id="symptoms-versus-causes-g0sEi4">
|
||||
<h2>
|
||||
Symptoms Versus Causes
|
||||
</h2>
|
||||
<p>Your monitoring system should address two questions: what’s broken, and why?
|
||||
<p>
|
||||
Your monitoring system should address two questions: what’s broken, and why?
|
||||
</p>
|
||||
<p>
|
||||
The "what’s broken" indicates the symptom; the "why" indicates a (possibly intermediate) cause. <a data-type="xref" href="http://fakehost/test/base/#table_monitoring_symptoms" target="_blank">Table 6-1</a> lists some hypothetical symptoms and corresponding causes.
|
||||
|
@ -94,43 +155,77 @@
|
|||
<caption>
|
||||
<span>Table 6-1.</span> Example symptoms and causes
|
||||
</caption>
|
||||
<thead><tr>
|
||||
<th><strong>Symptom</strong></th>
|
||||
<th><strong>Cause</strong></th>
|
||||
</tr></thead>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<strong>Symptom</strong>
|
||||
</th>
|
||||
<th>
|
||||
<strong>Cause</strong>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><p><strong>I’m serving HTTP 500s or 404s</strong></p></td>
|
||||
<td><p>
|
||||
<td>
|
||||
<p>
|
||||
<strong>I’m serving HTTP 500s or 404s</strong>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
Database servers are refusing connections
|
||||
</p></td>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><p><strong>My responses are slow</strong></p></td>
|
||||
<td><p>
|
||||
<td>
|
||||
<p>
|
||||
<strong>My responses are slow</strong>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
CPUs are overloaded by a bogosort, or an Ethernet cable is crimped under a rack, visible as partial packet loss
|
||||
</p></td>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><p><strong>Users in Antarctica aren’t receiving animated cat GIFs</strong></p></td>
|
||||
<td><p>
|
||||
<td>
|
||||
<p>
|
||||
<strong>Users in Antarctica aren’t receiving animated cat GIFs</strong>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
Your Content Distribution Network hates scientists and felines, and thus blacklisted some client IPs
|
||||
</p></td>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><p><strong>Private content is world-readable</strong></p></td>
|
||||
<td><p>
|
||||
<td>
|
||||
<p>
|
||||
<strong>Private content is world-readable</strong>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
A new software push caused ACLs to be forgotten and allowed all requests
|
||||
</p></td>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>
|
||||
"What" versus "why" is one of the most important distinctions in writing good monitoring with maximum signal and minimum noise.
|
||||
</p></section><section data-type="sect1" id="black-box-versus-white-box-q8sJuw"><h2>
|
||||
</p>
|
||||
</section>
|
||||
<section data-type="sect1" id="black-box-versus-white-box-q8sJuw">
|
||||
<h2>
|
||||
Black-Box Versus White-Box
|
||||
</h2>
|
||||
<p>We combine heavy use of white-box monitoring with modest but critical uses of black-box monitoring. The simplest way to think about black-box monitoring versus white-box monitoring is that black-box monitoring is symptom-oriented and represents active—not predicted—problems: "The system isn’t working correctly, right now." White-box monitoring depends on the ability to inspect the innards of the system, such as logs or HTTP endpoints, with instrumentation. White-box monitoring therefore allows detection of imminent problems, failures masked by retries, and so forth.
|
||||
<p>
|
||||
We combine heavy use of white-box monitoring with modest but critical uses of black-box monitoring. The simplest way to think about black-box monitoring versus white-box monitoring is that black-box monitoring is symptom-oriented and represents active—not predicted—problems: "The system isn’t working correctly, right now." White-box monitoring depends on the ability to inspect the innards of the system, such as logs or HTTP endpoints, with instrumentation. White-box monitoring therefore allows detection of imminent problems, failures masked by retries, and so forth.
|
||||
</p>
|
||||
<p>
|
||||
Note that in a multilayered system, one person’s symptom is another person’s cause. For example, suppose that a database’s performance is slow. Slow database reads are a symptom for the database SRE who detects them. However, for the frontend SRE observing a slow website, the same slow database reads are a cause. Therefore, white-box monitoring is sometimes symptom-oriented, and sometimes cause-oriented, depending on just how informative your white-box is.
|
||||
|
@ -140,20 +235,38 @@
|
|||
</p>
|
||||
<p>
|
||||
For paging, black-box monitoring has the key benefit of forcing discipline to only nag a human when a problem is both already ongoing and contributing to real symptoms. On the other hand, for not-yet-occurring but imminent problems, black-box monitoring is fairly useless.
|
||||
</p></section><section data-type="sect1" id="xref_monitoring_golden-signals"><h2>
|
||||
</p>
|
||||
</section>
|
||||
<section data-type="sect1" id="xref_monitoring_golden-signals">
|
||||
<h2>
|
||||
The Four Golden Signals
|
||||
</h2>
|
||||
<p>The four golden signals of monitoring are latency, traffic, errors, and saturation. If you can only measure four metrics of your user-facing system, focus on these four.
|
||||
<p>
|
||||
The four golden signals of monitoring are latency, traffic, errors, and saturation. If you can only measure four metrics of your user-facing system, focus on these four.
|
||||
</p>
|
||||
<dl>
|
||||
<dd><p>The time it takes to service a request. It’s important to distinguish between the latency of successful requests and the latency of failed requests. For example, an HTTP 500 error triggered due to loss of connection to a database or other critical backend might be served very quickly; however, as an HTTP 500 error indicates a failed request, factoring 500s into your overall latency might result in misleading calculations. On the other hand, a slow error is even worse than a fast error! Therefore, it’s important to track error latency, as opposed to just filtering out errors.
|
||||
</p></dd>
|
||||
<dd><p>A measure of how much demand is being placed on your system, measured in a high-level system-specific metric. For a web service, this measurement is usually HTTP requests per second, perhaps broken out by the nature of the requests (e.g., static versus dynamic content). For an audio streaming system, this measurement might focus on network I/O rate or concurrent sessions. For a key-value storage system, this measurement might be transactions and retrievals per <span>second</span>.
|
||||
</p></dd>
|
||||
<dd><p>The rate of requests that fail, either explicitly (e.g., HTTP 500s), implicitly (for example, an HTTP 200 success response, but coupled with the wrong content), or by policy (for example, "If you committed to one-second response times, any request over one second is an error"). Where protocol response codes are insufficient to express all failure conditions, secondary (internal) protocols may be necessary to track partial failure modes. Monitoring these cases can be drastically different: catching HTTP 500s at your load balancer can do a decent job of catching all completely failed requests, while only end-to-end system tests can detect that you’re serving the wrong content.
|
||||
</p></dd>
|
||||
|
||||
<dd>
|
||||
<p>How "full" your service is. A measure of your system fraction, emphasizing the resources that are most constrained (e.g., in a memory-constrained system, show memory; in an I/O-constrained system, show I/O). Note that many systems degrade in performance before they achieve 100% utilization, so having a utilization target is essential.
|
||||
<p>
|
||||
The time it takes to service a request. It’s important to distinguish between the latency of successful requests and the latency of failed requests. For example, an HTTP 500 error triggered due to loss of connection to a database or other critical backend might be served very quickly; however, as an HTTP 500 error indicates a failed request, factoring 500s into your overall latency might result in misleading calculations. On the other hand, a slow error is even worse than a fast error! Therefore, it’s important to track error latency, as opposed to just filtering out errors.
|
||||
</p>
|
||||
</dd>
|
||||
|
||||
<dd>
|
||||
<p>
|
||||
A measure of how much demand is being placed on your system, measured in a high-level system-specific metric. For a web service, this measurement is usually HTTP requests per second, perhaps broken out by the nature of the requests (e.g., static versus dynamic content). For an audio streaming system, this measurement might focus on network I/O rate or concurrent sessions. For a key-value storage system, this measurement might be transactions and retrievals per <span>second</span>.
|
||||
</p>
|
||||
</dd>
|
||||
|
||||
<dd>
|
||||
<p>
|
||||
The rate of requests that fail, either explicitly (e.g., HTTP 500s), implicitly (for example, an HTTP 200 success response, but coupled with the wrong content), or by policy (for example, "If you committed to one-second response times, any request over one second is an error"). Where protocol response codes are insufficient to express all failure conditions, secondary (internal) protocols may be necessary to track partial failure modes. Monitoring these cases can be drastically different: catching HTTP 500s at your load balancer can do a decent job of catching all completely failed requests, while only end-to-end system tests can detect that you’re serving the wrong content.
|
||||
</p>
|
||||
</dd>
|
||||
|
||||
<dd>
|
||||
<p>
|
||||
How "full" your service is. A measure of your system fraction, emphasizing the resources that are most constrained (e.g., in a memory-constrained system, show memory; in an I/O-constrained system, show I/O). Note that many systems degrade in performance before they achieve 100% utilization, so having a utilization target is essential.
|
||||
</p>
|
||||
<p>
|
||||
In complex systems, saturation can be supplemented with higher-level load measurement: can your service properly handle double the traffic, handle only 10% more traffic, or handle even less traffic than it currently receives? For very simple services that have no parameters that alter the complexity of the request (e.g., "Give me a nonce" or "I need a globally unique monotonic integer") that rarely change configuration, a static value from a load test might be adequate. As discussed in the previous paragraph, however, most services need to use indirect signals like CPU utilization or network bandwidth that have a known upper bound. Latency increases are often a leading indicator of saturation. Measuring your 99th percentile response time over some small window (e.g., one minute) can give a very early signal of saturation.
|
||||
|
@ -165,17 +278,25 @@
|
|||
</dl>
|
||||
<p>
|
||||
If you measure all four golden signals and page a human when one signal is problematic (or, in the case of saturation, nearly problematic), your service will be at least decently covered by monitoring.
|
||||
</p></section><section data-type="sect1" id="worrying-about-your-tail-or-instrumentation-and-performance-Yms9Ck"><h2>
|
||||
</p>
|
||||
</section>
|
||||
<section data-type="sect1" id="worrying-about-your-tail-or-instrumentation-and-performance-Yms9Ck">
|
||||
<h2>
|
||||
Worrying About Your Tail (or, Instrumentation and Performance)
|
||||
</h2>
|
||||
<p>When building a monitoring system from scratch, it’s tempting to design a system based upon the mean of some quantity: the mean latency, the mean CPU usage of your nodes, or the mean fullness of your databases. The danger presented by the latter two cases is obvious: CPUs and databases can easily be utilized in a very imbalanced way. The same holds for latency. If you run a web service with an average latency of 100 ms at 1,000 requests per second, 1% of requests might easily take 5 seconds.<sup><a data-type="noteref" id="id-QQLuAIXFxCz-marker" href="http://fakehost/test/base/#id-QQLuAIXFxCz" target="_blank">23</a></sup> If your users depend on several such web services to render their page, the 99th percentile of one backend can easily become the median response of your <span>frontend</span>.
|
||||
<p>
|
||||
When building a monitoring system from scratch, it’s tempting to design a system based upon the mean of some quantity: the mean latency, the mean CPU usage of your nodes, or the mean fullness of your databases. The danger presented by the latter two cases is obvious: CPUs and databases can easily be utilized in a very imbalanced way. The same holds for latency. If you run a web service with an average latency of 100 ms at 1,000 requests per second, 1% of requests might easily take 5 seconds.<sup><a data-type="noteref" id="id-QQLuAIXFxCz-marker" href="http://fakehost/test/base/#id-QQLuAIXFxCz" target="_blank">23</a></sup> If your users depend on several such web services to render their page, the 99th percentile of one backend can easily become the median response of your <span>frontend</span>.
|
||||
</p>
|
||||
<p>
|
||||
The simplest way to differentiate between a slow average and a very slow "tail" of requests is to collect request counts bucketed by latencies (suitable for rendering a histogram), rather than actual latencies: how many requests did I serve that took between 0 ms and 10 ms, between 10 ms and 30 ms, between 30 ms and 100 ms, between 100 ms and 300 ms, and so on? Distributing the histogram boundaries approximately exponentially (in this case by factors of roughly 3) is often an easy way to visualize the distribution of your requests.
|
||||
</p></section><section data-type="sect1" id="choosing-an-appropriate-resolution-for-measurements-vJsBsE"><h2>
|
||||
</p>
|
||||
</section>
|
||||
<section data-type="sect1" id="choosing-an-appropriate-resolution-for-measurements-vJsBsE">
|
||||
<h2>
|
||||
Choosing an Appropriate Resolution for Measurements
|
||||
</h2>
|
||||
<p>Different aspects of a system should be measured with different levels of granularity. For example:
|
||||
<p>
|
||||
Different aspects of a system should be measured with different levels of granularity. For example:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Observing CPU load over the time span of a minute won’t reveal even quite long-lived spikes that drive high tail latencies.
|
||||
|
@ -198,10 +319,14 @@
|
|||
</ol>
|
||||
<p>
|
||||
This strategy allows you to observe brief CPU hotspots without incurring very high cost due to collection and retention.
|
||||
</p></section><section data-type="sect1" id="as-simple-as-possible-no-simpler-lqskHx"><h2>
|
||||
</p>
|
||||
</section>
|
||||
<section data-type="sect1" id="as-simple-as-possible-no-simpler-lqskHx">
|
||||
<h2>
|
||||
As Simple as Possible, No Simpler
|
||||
</h2>
|
||||
<p>Piling all these requirements on top of each other can add up to a very complex monitoring system—your system might end up with the following levels of complexity:
|
||||
<p>
|
||||
Piling all these requirements on top of each other can add up to a very complex monitoring system—your system might end up with the following levels of complexity:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Alerts on different latency thresholds, at different percentiles, on all kinds of different metrics
|
||||
|
@ -227,13 +352,18 @@
|
|||
</ul>
|
||||
<p>
|
||||
In Google’s experience, basic collection and aggregation of metrics, paired with alerting and dashboards, has worked well as a relatively standalone system. (In fact Google’s monitoring system is broken up into several binaries, but typically people learn about all aspects of these binaries.) It can be tempting to combine monitoring with other aspects of inspecting complex systems, such as detailed system profiling, single-process debugging, tracking details about exceptions or crashes, load testing, log collection and analysis, or traffic inspection. While most of these subjects share commonalities with basic monitoring, blending together too many results in overly complex and fragile systems. As in many other aspects of software engineering, maintaining distinct systems with clear, simple, loosely coupled points of integration is a better strategy (for example, using web APIs for pulling summary data in a format that can remain constant over an extended period of time).
|
||||
</p></section><section data-type="sect1" id="tying-these-principles-together-nqsJfw"><h2>
|
||||
</p>
|
||||
</section>
|
||||
<section data-type="sect1" id="tying-these-principles-together-nqsJfw">
|
||||
<h2>
|
||||
Tying These Principles Together
|
||||
</h2>
|
||||
<p>
|
||||
The principles discussed in this chapter can be tied together into a philosophy on monitoring and alerting that’s widely endorsed and followed within Google SRE teams. While this monitoring philosophy is a bit aspirational, it’s a good starting point for writing or reviewing a new alert, and it can help your organization ask the right questions, regardless of the size of your organization or the complexity of your service or system.
|
||||
</p>
|
||||
<p>When creating rules for monitoring and alerting, asking the following questions can help you avoid false positives and pager burnout:<sup><a data-type="noteref" id="id-a82udF8IBfx-marker" href="http://fakehost/test/base/#id-a82udF8IBfx" target="_blank">24</a></sup></p>
|
||||
<p>
|
||||
When creating rules for monitoring and alerting, asking the following questions can help you avoid false positives and pager burnout:<sup><a data-type="noteref" id="id-a82udF8IBfx-marker" href="http://fakehost/test/base/#id-a82udF8IBfx" target="_blank">24</a></sup>
|
||||
</p>
|
||||
<ul>
|
||||
<li>Does this rule detect <em>an otherwise undetected condition</em> that is urgent, actionable, and actively or imminently user-visible?<sup><a data-type="noteref" id="id-0vYuEFpSjSMtLfG-marker" href="http://fakehost/test/base/#id-0vYuEFpSjSMtLfG" target="_blank">25</a></sup>
|
||||
</li>
|
||||
|
@ -246,7 +376,8 @@
|
|||
<li>Are other people getting paged for this issue, therefore rendering at least one of the pages unnecessary?
|
||||
</li>
|
||||
</ul>
|
||||
<p>These questions reflect a fundamental philosophy on pages and pagers:
|
||||
<p>
|
||||
These questions reflect a fundamental philosophy on pages and pagers:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Every time the pager goes off, I should be able to react with a sense of urgency. I can only react with a sense of urgency a few times a day before I become fatigued.
|
||||
|
@ -260,15 +391,22 @@
|
|||
</ul>
|
||||
<p>
|
||||
Such a perspective dissipates certain distinctions: if a page satisfies the preceding four bullets, it’s irrelevant whether the page is triggered by white-box or black-box monitoring. This perspective also amplifies certain distinctions: it’s better to spend much more effort on catching symptoms than causes; when it comes to causes, only worry about very definite, very imminent causes.
|
||||
</p></section><section data-type="sect1" id="monitoring-for-the-long-term-NbsNS8"><h2>
|
||||
</p>
|
||||
</section>
|
||||
<section data-type="sect1" id="monitoring-for-the-long-term-NbsNS8">
|
||||
<h2>
|
||||
Monitoring for the Long Term
|
||||
</h2>
|
||||
<p>In modern production systems, monitoring systems track an ever-evolving system with changing software architecture, load characteristics, and performance targets. An alert that’s currently exceptionally rare and hard to automate might become frequent, perhaps even meriting a hacked-together script to resolve it. At this point, someone should find and eliminate the root causes of the problem; if such resolution isn’t possible, the alert response deserves to be fully automated.
|
||||
<p>
|
||||
In modern production systems, monitoring systems track an ever-evolving system with changing software architecture, load characteristics, and performance targets. An alert that’s currently exceptionally rare and hard to automate might become frequent, perhaps even meriting a hacked-together script to resolve it. At this point, someone should find and eliminate the root causes of the problem; if such resolution isn’t possible, the alert response deserves to be fully automated.
|
||||
</p>
|
||||
<p>
|
||||
It’s important that decisions about monitoring be made with long-term goals in mind. Every page that happens today distracts a human from improving the system for tomorrow, so there is often a case for taking a short-term hit to availability or performance in order to improve the long-term outlook for the system. Let’s take a look at two case studies that illustrate this trade-off.
|
||||
</p>
|
||||
<section data-type="sect2" id="bigtable-sre-a-tale-of-over-alerting-dbsXtjSM"><p>Google’s internal infrastructure is typically offered and measured against a service level objective (SLO; see <a data-type="xref" href="http://fakehost/sre/sre-book/chapters/service-level-objectives" target="_blank">Service Level Objectives</a>). Many years ago, the Bigtable service’s SLO was based on a synthetic well-behaved client’s mean performance. Because of problems in Bigtable and lower layers of the storage stack, the mean performance was driven by a "large" tail: the worst 5% of requests were often significantly slower than the rest.
|
||||
<section data-type="sect2" id="bigtable-sre-a-tale-of-over-alerting-dbsXtjSM">
|
||||
|
||||
<p>
|
||||
Google’s internal infrastructure is typically offered and measured against a service level objective (SLO; see <a data-type="xref" href="http://fakehost/sre/sre-book/chapters/service-level-objectives" target="_blank">Service Level Objectives</a>). Many years ago, the Bigtable service’s SLO was based on a synthetic well-behaved client’s mean performance. Because of problems in Bigtable and lower layers of the storage stack, the mean performance was driven by a "large" tail: the worst 5% of requests were often significantly slower than the rest.
|
||||
</p>
|
||||
<p>
|
||||
Email alerts were triggered as the SLO approached, and paging alerts were triggered when the SLO was exceeded. Both types of alerts were firing voluminously, consuming unacceptable amounts of engineering time: the team spent significant amounts of time triaging the alerts to find the few that were really actionable, and we often missed the problems that actually affected users, because so few of them did. Many of the pages were non-urgent, due to well-understood problems in the infrastructure, and had either rote responses or received no response.
|
||||
|
@ -278,7 +416,12 @@
|
|||
</p>
|
||||
<p>
|
||||
This strategy gave us enough breathing room to actually fix the longer-term problems in Bigtable and the lower layers of the storage stack, rather than constantly fixing tactical problems. On-call engineers could actually accomplish work when they weren’t being kept up by pages at all hours. Ultimately, temporarily backing off on our alerts allowed us to make faster progress toward a better service.
|
||||
</p></section><section data-type="sect2" id="gmail-predictable-scriptable-responses-from-humans-BVs1h4SD"><p>In the very early days of Gmail, the service was built on a retrofitted distributed process management system called Workqueue, which was originally created for batch processing of pieces of the search index. Workqueue was "adapted" to long-lived processes and subsequently applied to Gmail, but certain bugs in the relatively opaque codebase in the scheduler proved hard to beat.
|
||||
</p>
|
||||
</section>
|
||||
<section data-type="sect2" id="gmail-predictable-scriptable-responses-from-humans-BVs1h4SD">
|
||||
|
||||
<p>
|
||||
In the very early days of Gmail, the service was built on a retrofitted distributed process management system called Workqueue, which was originally created for batch processing of pieces of the search index. Workqueue was "adapted" to long-lived processes and subsequently applied to Gmail, but certain bugs in the relatively opaque codebase in the scheduler proved hard to beat.
|
||||
</p>
|
||||
<p>
|
||||
At that time, the Gmail monitoring was structured such that alerts fired when individual tasks were “de-scheduled” by Workqueue. This setup was less than ideal because even at that time, Gmail had many, many thousands of tasks, each task representing a fraction of a percent of our users. We cared deeply about providing a good user experience for Gmail users, but such an alerting setup was unmaintainable.
|
||||
|
@ -290,8 +433,18 @@
|
|||
This kind of tension is common within a team, and often reflects an underlying mistrust of the team’s self-discipline: while some team members want to implement a “hack” to allow time for a proper fix, others worry that a hack will be forgotten or that the proper fix will be deprioritized indefinitely. This concern is credible, as it’s easy to build layers of unmaintainable technical debt by patching over problems instead of making real fixes. Managers and technical leaders play a key role in implementing true, long-term fixes by supporting and prioritizing potentially time-consuming long-term fixes even when the initial “pain” of paging subsides.
|
||||
</p>
|
||||
<p>
|
||||
Pages with rote, algorithmic responses should be a red flag. Unwillingness on the part of your team to automate such pages implies that the team lacks confidence that they can clean up their technical debt. This is a major problem worth escalating.</p></section><section data-type="sect2" id="the-long-run-MQsWTMS7"><p>A common theme connects the previous examples of Bigtable and Gmail: a tension between short-term and long-term availability. Often, sheer force of effort can help a rickety system achieve high availability, but this path is usually short-lived and fraught with burnout and dependence on a small number of heroic team members. Taking a controlled, short-term decrease in availability is often a painful, but strategic trade for the long-run stability of the system. It’s important not to think of every page as an event in isolation, but to consider whether the overall <em>level</em> of paging leads toward a healthy, appropriately available system with a healthy, viable team and long-term outlook. We review statistics about page frequency (usually expressed as incidents per shift, where an incident might be composed of a few related pages) in quarterly reports with management, ensuring that decision makers are kept up to date on the pager load and overall health of their teams.
|
||||
</p></section></section><section data-type="sect1" id="conclusion-8ksvFj"><h2>
|
||||
Pages with rote, algorithmic responses should be a red flag. Unwillingness on the part of your team to automate such pages implies that the team lacks confidence that they can clean up their technical debt. This is a major problem worth escalating.
|
||||
</p>
|
||||
</section>
|
||||
<section data-type="sect2" id="the-long-run-MQsWTMS7">
|
||||
|
||||
<p>
|
||||
A common theme connects the previous examples of Bigtable and Gmail: a tension between short-term and long-term availability. Often, sheer force of effort can help a rickety system achieve high availability, but this path is usually short-lived and fraught with burnout and dependence on a small number of heroic team members. Taking a controlled, short-term decrease in availability is often a painful, but strategic trade for the long-run stability of the system. It’s important not to think of every page as an event in isolation, but to consider whether the overall <em>level</em> of paging leads toward a healthy, appropriately available system with a healthy, viable team and long-term outlook. We review statistics about page frequency (usually expressed as incidents per shift, where an incident might be composed of a few related pages) in quarterly reports with management, ensuring that decision makers are kept up to date on the pager load and overall health of their teams.
|
||||
</p>
|
||||
</section>
|
||||
</section>
|
||||
<section data-type="sect1" id="conclusion-8ksvFj">
|
||||
<h2>
|
||||
Conclusion
|
||||
</h2>
|
||||
<p>
|
||||
|
@ -299,4 +452,7 @@
|
|||
</p>
|
||||
<p>
|
||||
Over the long haul, achieving a successful on-call rotation and product includes choosing to alert on symptoms or imminent real problems, adapting your targets to goals that are actually achievable, and making sure that your monitoring supports rapid diagnosis.
|
||||
</p></section></section></article>
|
||||
</p>
|
||||
</section>
|
||||
|
||||
</section></article>
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,8 +1,34 @@
|
|||
<article><div id="readability-page-1">
|
||||
<figure><img src="http://3.f.ix.de/scale/geometry/600/q75/imgs/18/1/4/6/2/3/5/1/Barcode-Scanner-With-Border-fc08c913da5cea5d.jpeg"><figcaption><p>1Password scannt auch QR-Codes.</p>
|
||||
<p>(Bild: Hersteller)</p></figcaption></figure><p><strong>Das in der iOS-Version bereits enthaltene TOTP-Feature ist nun auch für OS X 10.10 verfügbar. Zudem gibt es neue Zusatzfelder in der Datenbank und weitere Verbesserungen.</strong></p>
|
||||
|
||||
|
||||
<figure>
|
||||
<img src="http://3.f.ix.de/scale/geometry/600/q75/imgs/18/1/4/6/2/3/5/1/Barcode-Scanner-With-Border-fc08c913da5cea5d.jpeg">
|
||||
|
||||
<figcaption>
|
||||
|
||||
<p>1Password scannt auch QR-Codes.</p>
|
||||
|
||||
|
||||
<p>(Bild: Hersteller)</p>
|
||||
|
||||
</figcaption>
|
||||
|
||||
</figure>
|
||||
|
||||
|
||||
|
||||
<p><strong>Das in der iOS-Version bereits enthaltene TOTP-Feature ist nun auch für OS X 10.10 verfügbar. Zudem gibt es neue Zusatzfelder in der Datenbank und weitere Verbesserungen.</strong></p>
|
||||
<p><a rel="external" target="_blank" href="https://itunes.apple.com/de/app/1password-password-manager/id443987910">AgileBits hat Version 5.3 seines bekannten Passwortmanagers 1Password für OS X freigegeben.</a> Mit dem Update wird eine praktische Funktion nachgereicht, die <a href="http://fakehost/mac-and-i/meldung/Passwortmanager-1Password-mit-groesseren-Updates-fuer-OS-X-und-iOS-2529204.html" target="_blank">die iOS-Version der Anwendung bereits seit längerem beherrscht</a>: Das direkte Erstellen von Einmal-Passwörtern. Unterstützt wird dabei der <a rel="external" target="_blank" href="https://blog.agilebits.com/2015/01/26/totp-for-1password-users/">TOTP-Standard</a> (Time-Based One-Time Passwords), den unter anderem Firmen wie Evernote, Dropbox oder Google einsetzen, um ihre Zugänge besser abzusichern. Neben Account und regulärem Passwort wird dabei dann ein Zusatzcode verlangt, der nur kurze Zeit gilt.</p>
|
||||
<p>Zur TOTP-Nutzung muss zunächst ein Startwert an 1Password übergeben werden. Das geht unter anderem per QR-Code, den die App über ein neues Scanfenster selbst einlesen kann – etwa aus dem Webbrowser. Eine Einführung in die Technik gibt <a rel="external" target="_blank" href="http://1pw.ca/TOTPvideoMac">ein kurzes Video</a>. Die TOTP-Unterstützung in 1Password erlaubt es, auf ein zusätzliches Gerät (z.B. ein iPhone) neben dem Mac zu verzichten, das den Code liefert – was allerdings auch die Sicherheit verringert, weil es keinen "echten" zweiten Faktor mehr gibt.</p>
|
||||
<p>Update 5.3 des Passwortmanagers liefert auch noch weitere Verbesserungen. So gibt es die Möglichkeit, FaceTime-Audio- oder Skype-Anrufe aus 1Password zu starten, die Zahl der Zusatzfelder in der Datenbank wurde erweitert und der Umgang mit unterschiedlichen Zeitzonen klappt besser. Die Engine zur Passworteingabe im Browser soll beschleunigt worden sein.</p>
|
||||
<p>1Password kostet aktuell knapp 50 Euro im Mac App Store und setzt in seiner aktuellen Version mindestens OS X 10.10 voraus.<span>(<a title="Ben Schwan" href="mailto:bsc@heise.de" target="_blank">bsc</a>)</span><br></p>
|
||||
<p>1Password kostet aktuell knapp 50 Euro im Mac App Store und setzt in seiner aktuellen Version mindestens OS X 10.10 voraus.
|
||||
|
||||
|
||||
|
||||
<span>(<a title="Ben Schwan" href="mailto:bsc@heise.de" target="_blank">bsc</a>)</span>
|
||||
<br>
|
||||
|
||||
|
||||
</p>
|
||||
|
||||
</div></article>
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
<article><div id="readability-page-1">
|
||||
<div>
|
||||
<p><img data-src="http://api.news.com.au/content/1.0/heraldsun/images/1227261885862?format=jpg&group=iphone&size=medium" alt="A new Bill would require telecommunications service providers to store so-called ‘metadat"></p>
|
||||
<p><span id="imgCaption">A new Bill would require telecommunications service providers to store so-called ‘metadata’ for two years.</span><span><em>Source:</em>
|
||||
Supplied</span></p>
|
||||
<p><img data-src="http://api.news.com.au/content/1.0/heraldsun/images/1227261885862?format=jpg&group=iphone&size=medium" alt="A new Bill would require telecommunications service providers to store so-called ‘metadat">
|
||||
</p>
|
||||
<p>
|
||||
<span id="imgCaption">A new Bill would require telecommunications service providers to store so-called ‘metadata’ for two years.</span>
|
||||
<span><em>Source:</em>
|
||||
Supplied</span>
|
||||
</p>
|
||||
</div>
|
||||
<p><strong>
|
||||
A HIGH-powered federal government team has been doing the rounds of media organisations in the past few days in an attempt to allay concerns about the impact of new surveillance legislation on press freedom. It failed.
|
||||
|
@ -10,6 +14,9 @@
|
|||
<p>The roadshow featured the Prime Minister’s national security adviser, Andrew Shearer, Justin Bassi, who advises Attorney-General George Brandis on crime and security matters, and Australian Federal Police Commissioner Andrew Colvin. Staffers from the office of Communications Minister Malcolm Turnbull also took part.</p>
|
||||
<p>They held meetings with executives from News Corporation and Fairfax, representatives of the TV networks, the ABC top brass and a group from the media union and the Walkley journalism foundation. I was involved as a member of the Walkley board.</p>
|
||||
<p>The initiative, from Tony Abbott’s office, is evidence that the Government has been alarmed by the strength of criticism from media of the Data Retention Bill it wants passed before Parliament rises in a fortnight. Bosses, journalists, even the Press Council, are up in arms, not only over this measure, but also over aspects of two earlier pieces of national security legislation that interfere with the ability of the media to hold government to account.</p>
|
||||
|
||||
|
||||
|
||||
<div id="read-more">
|
||||
<p>The Bill would require telecommunications service providers to store so-called “metadata” — the who, where, when and how of a communication, but not its content — for two years so security and law enforcement agencies can access it without warrant. Few would argue against the use of such material to catch criminals or terrorists. But, as Parliament’s Joint Committee on Intelligence and Security has pointed out, it would also be used “for the purpose of determining the identity of a journalist’s sources”.</p>
|
||||
<p>And that should ring warning bells for anyone genuinely concerned with the health of our democracy. Without the ability to protect the identity of sources, journalists would be greatly handicapped in exposing corruption, dishonesty, waste, incompetence and misbehaviour by public officials.</p>
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
<article><DIV id="readability-page-1">
|
||||
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
|
||||
</p>
|
||||
<h2>
|
||||
Secondary header
|
||||
</h2>
|
||||
|
||||
<h2>
|
||||
Third header
|
||||
</h2>
|
||||
|
||||
</DIV></article>
|
||||
|
|
|
@ -1,107 +1,293 @@
|
|||
<article><DIV id="readability-page-1">
|
||||
<td>
|
||||
<table><tbody><tr>
|
||||
<td><img src="http://fakehost/366/logo_bana/corner_1.gif" width="7" height="7"></td>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<img src="http://fakehost/366/logo_bana/corner_1.gif" width="7" height="7">
|
||||
</td>
|
||||
<td></td>
|
||||
<td><img src="http://fakehost/366/logo_bana/corner_2.gif" width="7" height="7"></td>
|
||||
</tr></tbody></table>
|
||||
<table><tbody>
|
||||
<tr><td></td></tr>
|
||||
<tr><td></td></tr>
|
||||
</tbody></table>
|
||||
<td>
|
||||
<img src="http://fakehost/366/logo_bana/corner_2.gif" width="7" height="7">
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
<td>
|
||||
<p><a href="http://fakehost/index.html" target="_blank">福娘童話集</a> > <a href="http://fakehost/test/index.html" target="_blank">きょうのイソップ童話</a> > <a href="http://fakehost/test/itiran/01gatu.htm" target="_blank">1月のイソップ童話</a> > 欲張りなイヌ
|
||||
<p>
|
||||
<a href="http://fakehost/index.html" target="_blank">福娘童話集</a> > <a href="http://fakehost/test/index.html" target="_blank">きょうのイソップ童話</a> > <a href="http://fakehost/test/itiran/01gatu.htm" target="_blank">1月のイソップ童話</a> > 欲張りなイヌ
|
||||
</p>
|
||||
<p><span color="#FF0000" size="+2">元旦のイソップ童話</span><br><br><br><br><img src="http://fakehost/gazou/pc_gazou/aesop/aesop052.jpg" alt="よくばりなイヌ" width="480" height="360"><br><br><br><br>
|
||||
欲張りなイヌ<br><br><br><br><a href="http://hukumusume.com/douwa/English/aesop/01/01_j.html" target="_blank">ひらがな</a> ←→ <a href="http://hukumusume.com/douwa/English/aesop/01/01_j&E.html" target="_blank">日本語・英語</a> ←→ <a href="http://hukumusume.com/douwa/English/aesop/01/01_E.html" target="_blank">English</a></p>
|
||||
<DIV><table><tbody>
|
||||
<p>
|
||||
<span color="#FF0000" size="+2">元旦のイソップ童話</span><br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<img src="http://fakehost/gazou/pc_gazou/aesop/aesop052.jpg" alt="よくばりなイヌ" width="480" height="360"><br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
欲張りなイヌ<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<a href="http://hukumusume.com/douwa/English/aesop/01/01_j.html" target="_blank">ひらがな</a> ←→ <a href="http://hukumusume.com/douwa/English/aesop/01/01_j&E.html" target="_blank">日本語・英語</a> ←→ <a href="http://hukumusume.com/douwa/English/aesop/01/01_E.html" target="_blank">English</a>
|
||||
</p>
|
||||
<DIV>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><img src="http://fakehost/366/logo_bana/corner_1.gif" width="7" height="7"></td>
|
||||
<td><span color="#FF0000"><b>おりがみをつくろう</b></span></td>
|
||||
<td><span size="-1">( <a href="http://www.origami-club.com/index.html" target="_blank">おりがみくらぶ</a> より)</span></td>
|
||||
<td><img src="http://fakehost/366/logo_bana/corner_2.gif" width="7" height="7"></td>
|
||||
<td>
|
||||
<img src="http://fakehost/366/logo_bana/corner_1.gif" width="7" height="7">
|
||||
</td>
|
||||
<td>
|
||||
<span color="#FF0000"><b>おりがみをつくろう</b></span>
|
||||
</td>
|
||||
<td>
|
||||
<span size="-1">( <a href="http://www.origami-club.com/index.html" target="_blank">おりがみくらぶ</a> より)</span>
|
||||
</td>
|
||||
<td>
|
||||
<img src="http://fakehost/366/logo_bana/corner_2.gif" width="7" height="7">
|
||||
</td>
|
||||
</tr>
|
||||
<tr><td colspan="4"><table><tbody><tr><td>
|
||||
<a href="http://www.origami-club.com/easy/dogfase/index.html" target="_blank"><span size="+2"><img src="http://fakehost/gazou/origami_gazou/kantan/dogface.gif" alt="犬の顔の折り紙" width="73" height="51">いぬのかお</span></a><a href="http://www.origami-club.com/easy/dog/index.html" target="_blank"><img src="http://fakehost/gazou/origami_gazou/kantan/dog.gif" alt="犬の顔の紙" width="62" height="43"><span size="+2">いぬ</span></a>
|
||||
</td></tr></tbody></table></td></tr>
|
||||
</tbody></table></DIV>
|
||||
<table><tbody>
|
||||
<tr><td>
|
||||
<tr>
|
||||
<td colspan="4">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="http://www.origami-club.com/easy/dogfase/index.html" target="_blank"><span size="+2"><img src="http://fakehost/gazou/origami_gazou/kantan/dogface.gif" alt="犬の顔の折り紙" width="73" height="51">いぬのかお</span></a> <a href="http://www.origami-club.com/easy/dog/index.html" target="_blank"><img src="http://fakehost/gazou/origami_gazou/kantan/dog.gif" alt="犬の顔の紙" width="62" height="43"><span size="+2">いぬ</span></a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</DIV>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
♪音声配信(html5)
|
||||
</td></tr>
|
||||
<tr><td><audio src="http://ohanashi2.up.seesaa.net/mp3/ae_0101.mp3" controls=""></audio></td></tr>
|
||||
<tr><td><a href="http://www.voiceblog.jp/onokuboaki/" target="_blank"><span size="-1">亜姫の朗読☆ イソップ童話より</span></a></td></tr>
|
||||
</tbody></table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<audio src="http://ohanashi2.up.seesaa.net/mp3/ae_0101.mp3" controls=""></audio>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="http://www.voiceblog.jp/onokuboaki/" target="_blank"><span size="-1">亜姫の朗読☆ イソップ童話より</span></a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>
|
||||
肉をくわえたイヌが、橋を渡っていました。 ふと下を見ると、川の中にも肉をくわえたイヌがいます。 イヌはそれを見て、思いました。(あいつの肉の方が、大きそうだ) イヌは、くやしくてたまりません。 (そうだ、あいつをおどかして、あの肉を取ってやろう) そこでイヌは、川の中のイヌに向かって思いっきり吠えました。 「ウゥー、ワン!!」 そのとたん、くわえていた肉はポチャンと川の中に落ちてしまいました。 「ああー、ぁぁー」 川の中には、がっかりしたイヌの顔がうつっています。 さっきの川の中のイヌは、水にうつった自分の顔だったのです。 同じ物を持っていても、人が持っている物の方が良く見え、また、欲張るとけっきょく損をするというお話しです。
|
||||
</p>
|
||||
<p>
|
||||
おしまい
|
||||
</p>
|
||||
<p><a href="javascript:history.back();" onmouseout="MM_swapImgRestore()" onmouseover="MM_swapImage('Image10','','../../../gazou/pc_gazou/all/top_bana/back_logo_b.gif',1)" target="_blank"><img src="http://fakehost/gazou/pc_gazou/all/top_bana/back_logo_r.gif" alt="前のページへ戻る" name="Image10" width="175" height="32" id="Image10"></a><br><br><br><br></p>
|
||||
<p>
|
||||
<a href="javascript:history.back();" onmouseout="MM_swapImgRestore()" onmouseover="MM_swapImage('Image10','','../../../gazou/pc_gazou/all/top_bana/back_logo_b.gif',1)" target="_blank"><img src="http://fakehost/gazou/pc_gazou/all/top_bana/back_logo_r.gif" alt="前のページへ戻る" name="Image10" width="175" height="32" id="Image10"></a><br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
|
||||
|
||||
</p>
|
||||
</td>
|
||||
<td><img src="file:///C:/Documents%20and%20Settings/%E7%A6%8F%E5%A8%98note/%E3%83%87%E3%82%B9%E3%82%AF%E3%83%88%E3%83%83%E3%83%97/company_website15/image/spacer.gif" width="1" height="1"></td>
|
||||
<td>
|
||||
<table><tbody><tr>
|
||||
<td><img src="http://fakehost/366/logo_bana/corner_1.gif" width="7" height="7"></td>
|
||||
<img src="file:///C:/Documents%20and%20Settings/%E7%A6%8F%E5%A8%98note/%E3%83%87%E3%82%B9%E3%82%AF%E3%83%88%E3%83%83%E3%83%97/company_website15/image/spacer.gif" width="1" height="1">
|
||||
</td>
|
||||
<td>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<img src="http://fakehost/366/logo_bana/corner_1.gif" width="7" height="7">
|
||||
</td>
|
||||
<td></td>
|
||||
<td><img src="http://fakehost/366/logo_bana/corner_2.gif" width="7" height="7"></td>
|
||||
</tr></tbody></table>
|
||||
<table><tbody>
|
||||
<tr><td>
|
||||
<span size="-1"><b>1月 1日の豆知識</b></span><br><br><span size="-2"><u><br><br>
|
||||
<td>
|
||||
<img src="http://fakehost/366/logo_bana/corner_2.gif" width="7" height="7">
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<span size="-1"><b>1月 1日の豆知識</b></span><br>
|
||||
<br>
|
||||
<span size="-2"><u><br>
|
||||
<br>
|
||||
366日への旅</u></span>
|
||||
</td></tr>
|
||||
<tr><td>
|
||||
<img src="file:///C:/Documents%20and%20Settings/%E7%A6%8F%E5%A8%98note/%E3%83%87%E3%82%B9%E3%82%AF%E3%83%88%E3%83%83%E3%83%97" width="1" height="1"><b><span size="-1">きょうの記念日</span></b><br><br><a href="http://fakehost/366/kinenbi/pc/01gatu/1_01.htm" target="_blank"><span size="-1">元旦</span></a>
|
||||
</td></tr>
|
||||
<tr><td>
|
||||
<img src="file:///C:/Documents%20and%20Settings/%E7%A6%8F%E5%A8%98note/%E3%83%87%E3%82%B9%E3%82%AF%E3%83%88%E3%83%83%E3%83%97/company_website15/image/spacer.gif" width="1" height="1"><b><span size="-1">きょうの誕生花</span></b><br><br><a href="http://fakehost/366/hana/pc/01gatu/1_01.htm" target="_blank"><span size="-1">松(まつ)</span></a>
|
||||
</td></tr>
|
||||
<tr><td>
|
||||
<b><span size="-1">きょうの誕生日・出来事</span></b><br><br><a href="http://fakehost/366/birthday/pc/01gatu/1_01.htm" target="_blank"><span size="-1">1949年 Mr.マリック(マジシャン)</span></a>
|
||||
</td></tr>
|
||||
<tr><td>
|
||||
<b><span size="-1">恋の誕生日占い</span></b><br><br><a href="http://fakehost/sakura/uranai/birthday/01/01.html" target="_blank"><span size="-1">自分の考えをしっかりと持った女の子。</span></a>
|
||||
</td></tr>
|
||||
<tr><td>
|
||||
<b><span size="-1">なぞなぞ小学校</span></b><br><br><a href="http://fakehost/nazonazo/new/2012/04/02.html" target="_blank"><span size="-1">○(丸)を取ったらお母さんになってしまう男の人は?</span></a>
|
||||
</td></tr>
|
||||
<tr><td>
|
||||
<b><span size="-1">あこがれの職業紹介</span></b><br><br><a href="http://fakehost/sakura/navi/work/2017/041.html" target="_blank"><span size="-1">歌手</span></a>
|
||||
</td></tr>
|
||||
<tr><td>
|
||||
<b><span size="-1">恋の魔法とおまじない</span></b> 001<br><br><a href="http://fakehost/omajinai/new/2012/00/re01.html" target="_blank"><span size="-1">両思いになれる おまじない</span></a>
|
||||
</td></tr>
|
||||
<tr><td><span size="-1"><b>1月 1日の童話・昔話</b><br><br><u><span size="-2"><br><br>
|
||||
福娘童話集</span></u></span></td></tr>
|
||||
<tr><td>
|
||||
<b><span size="-1">きょうの日本昔話</span></b><br><br><a href="http://fakehost/douwa/pc/jap/01/01.htm" target="_blank"><span size="-1">ネコがネズミを追いかける訳</span></a>
|
||||
</td></tr>
|
||||
<tr><td>
|
||||
<b><span size="-1">きょうの世界昔話<img src="file:///C:/Documents%20and%20Settings/%E7%A6%8F%E5%A8%98note/%E3%83%87%E3%82%B9%E3%82%AF%E3%83%88%E3%83%83%E3%83%97/company_website15/image/spacer.gif" width="1" height="1"></span></b><br><br><a href="http://fakehost/douwa/pc/world/01/01a.htm" target="_blank"><span size="-1">モンゴルの十二支話</span></a>
|
||||
</td></tr>
|
||||
<tr><td>
|
||||
<img src="file:///C:/Documents%20and%20Settings/%E7%A6%8F%E5%A8%98note/%E3%83%87%E3%82%B9%E3%82%AF%E3%83%88%E3%83%83%E3%83%97/company_website15/image/spacer.gif" width="1" height="1"><b><span size="-1">きょうの日本民話</span></b><br><br><a href="http://fakehost/douwa/pc/minwa/01/01c.html" target="_blank"><span size="-1">仕事の取替えっこ</span></a>
|
||||
</td></tr>
|
||||
<tr><td>
|
||||
<b><span size="-1">きょうのイソップ童話</span></b><br><br><a href="http://fakehost/douwa/pc/aesop/01/01.htm" target="_blank"><span size="-1">欲張りなイヌ</span></a>
|
||||
</td></tr>
|
||||
<tr><td>
|
||||
<b><span size="-1">きょうの江戸小話</span></b><br><br><a href="http://fakehost/douwa/pc/kobanashi/01/01.htm" target="_blank"><span size="-1">ぞうきんとお年玉</span></a>
|
||||
</td></tr>
|
||||
<tr><td>
|
||||
<b><span size="-1">きょうの百物語</span></b><br><br><a href="http://fakehost/douwa/pc/kaidan/01/01.htm" target="_blank"><span size="-1">百物語の幽霊</span></a>
|
||||
</td></tr>
|
||||
</tbody></table>
|
||||
<table><tbody>
|
||||
<tr><td><b><span size="-1">福娘のサイト</span></b></td></tr>
|
||||
<tr><td><span size="-1"><b>366日への旅</b><br><br><a href="http://hukumusume.com/366/" target="_blank">毎日の記念日・誕生花 ・有名人の誕生日と性格判断</a></span></td></tr>
|
||||
<tr><td><span size="-1"><b>福娘童話集</b><br><br><a href="http://hukumusume.com/douwa/" target="_blank">世界と日本の童話と昔話</a></span></td></tr>
|
||||
<tr><td><span size="-1"><b>女の子応援サイト -さくら-</b><br><br><a href="http://hukumusume.com/sakura/index.html" target="_blank">誕生日占い、お仕事紹介、おまじない、など</a></span></td></tr>
|
||||
<tr><td><span size="-1"><b>子どもの病気相談所</b><br><br><a href="http://hukumusume.com/my_baby/sick/" target="_blank">病気検索と対応方法、症状から検索するWEB問診</a></span></td></tr>
|
||||
<tr><td><span size="-1"><b>世界60秒巡り</b><br><br><a href="http://hukumusume.com/366/world/" target="_blank">国旗国歌や世界遺産など、世界の国々の豆知識</a></span></td></tr>
|
||||
</tbody></table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<img src="file:///C:/Documents%20and%20Settings/%E7%A6%8F%E5%A8%98note/%E3%83%87%E3%82%B9%E3%82%AF%E3%83%88%E3%83%83%E3%83%97" width="1" height="1"><b><span size="-1">きょうの記念日</span></b><br>
|
||||
<br>
|
||||
<a href="http://fakehost/366/kinenbi/pc/01gatu/1_01.htm" target="_blank"><span size="-1">元旦</span></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<img src="file:///C:/Documents%20and%20Settings/%E7%A6%8F%E5%A8%98note/%E3%83%87%E3%82%B9%E3%82%AF%E3%83%88%E3%83%83%E3%83%97/company_website15/image/spacer.gif" width="1" height="1"><b><span size="-1">きょうの誕生花</span></b><br>
|
||||
<br>
|
||||
<a href="http://fakehost/366/hana/pc/01gatu/1_01.htm" target="_blank"><span size="-1">松(まつ)</span></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<b><span size="-1">きょうの誕生日・出来事</span></b><br>
|
||||
<br>
|
||||
<a href="http://fakehost/366/birthday/pc/01gatu/1_01.htm" target="_blank"><span size="-1">1949年 Mr.マリック(マジシャン)</span></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<b><span size="-1">恋の誕生日占い</span></b><br>
|
||||
<br>
|
||||
<a href="http://fakehost/sakura/uranai/birthday/01/01.html" target="_blank"><span size="-1">自分の考えをしっかりと持った女の子。</span></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<b><span size="-1">なぞなぞ小学校</span></b><br>
|
||||
<br>
|
||||
<a href="http://fakehost/nazonazo/new/2012/04/02.html" target="_blank"><span size="-1">○(丸)を取ったらお母さんになってしまう男の人は?</span></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<b><span size="-1">あこがれの職業紹介</span></b><br>
|
||||
<br>
|
||||
<a href="http://fakehost/sakura/navi/work/2017/041.html" target="_blank"><span size="-1">歌手</span></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<b><span size="-1">恋の魔法とおまじない</span></b> 001<br>
|
||||
<br>
|
||||
<a href="http://fakehost/omajinai/new/2012/00/re01.html" target="_blank"><span size="-1">両思いになれる おまじない</span></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span size="-1"> <b>1月 1日の童話・昔話</b><br>
|
||||
<br>
|
||||
<u><span size="-2"><br>
|
||||
<br>
|
||||
福娘童話集</span></u></span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<b><span size="-1">きょうの日本昔話</span></b><br>
|
||||
<br>
|
||||
<a href="http://fakehost/douwa/pc/jap/01/01.htm" target="_blank"><span size="-1">ネコがネズミを追いかける訳</span></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<b><span size="-1">きょうの世界昔話<img src="file:///C:/Documents%20and%20Settings/%E7%A6%8F%E5%A8%98note/%E3%83%87%E3%82%B9%E3%82%AF%E3%83%88%E3%83%83%E3%83%97/company_website15/image/spacer.gif" width="1" height="1"></span></b><br>
|
||||
<br>
|
||||
<a href="http://fakehost/douwa/pc/world/01/01a.htm" target="_blank"><span size="-1">モンゴルの十二支話</span></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<img src="file:///C:/Documents%20and%20Settings/%E7%A6%8F%E5%A8%98note/%E3%83%87%E3%82%B9%E3%82%AF%E3%83%88%E3%83%83%E3%83%97/company_website15/image/spacer.gif" width="1" height="1"><b><span size="-1">きょうの日本民話</span></b><br>
|
||||
<br>
|
||||
<a href="http://fakehost/douwa/pc/minwa/01/01c.html" target="_blank"><span size="-1">仕事の取替えっこ</span></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<b><span size="-1">きょうのイソップ童話</span></b><br>
|
||||
<br>
|
||||
<a href="http://fakehost/douwa/pc/aesop/01/01.htm" target="_blank"><span size="-1">欲張りなイヌ</span></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<b><span size="-1">きょうの江戸小話</span></b><br>
|
||||
<br>
|
||||
<a href="http://fakehost/douwa/pc/kobanashi/01/01.htm" target="_blank"><span size="-1">ぞうきんとお年玉</span></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<b><span size="-1">きょうの百物語</span></b><br>
|
||||
<br>
|
||||
<a href="http://fakehost/douwa/pc/kaidan/01/01.htm" target="_blank"><span size="-1">百物語の幽霊</span></a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<b><span size="-1">福娘のサイト</span></b>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span size="-1"><b>366日への旅</b><br>
|
||||
<br>
|
||||
<a href="http://hukumusume.com/366/" target="_blank">毎日の記念日・誕生花 ・有名人の誕生日と性格判断</a></span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span size="-1"><b>福娘童話集</b><br>
|
||||
<br>
|
||||
<a href="http://hukumusume.com/douwa/" target="_blank">世界と日本の童話と昔話</a></span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span size="-1"><b>女の子応援サイト -さくら-</b><br>
|
||||
<br>
|
||||
<a href="http://hukumusume.com/sakura/index.html" target="_blank">誕生日占い、お仕事紹介、おまじない、など</a></span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span size="-1"><b>子どもの病気相談所</b><br>
|
||||
<br>
|
||||
<a href="http://hukumusume.com/my_baby/sick/" target="_blank">病気検索と対応方法、症状から検索するWEB問診</a></span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span size="-1"><b>世界60秒巡り</b><br>
|
||||
<br>
|
||||
<a href="http://hukumusume.com/366/world/" target="_blank">国旗国歌や世界遺産など、世界の国々の豆知識</a></span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</DIV></article>
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
<p>The IAB Tech Lab will continue to provide the tools for publishers in the digital supply chain to have a dialogue with users about their choices so that content providers can generate revenue while creating value. Publishers should have the opportunity to provide rich advertising experiences, L.E.A.N. advertising experiences, and subscription services. Or publishers can simply deny their service to users who choose to keep on blocking ads. That is all part of elasticity of consumer tolerance and choice.</p>
|
||||
<p>Finally, we must do this in an increasingly fragmented market, across screens. We must do this in environments where entire sites are blocked, purposefully or not. Yes, it is disappointing that our development efforts will have to manage with multiple frameworks while we work to supply the economic engine to sustain an open internet. However, our goal is still to provide diverse content and voices to as many connected users as possible around the world.</p>
|
||||
<p>That is user experience.</p>
|
||||
|
||||
<P>IAB Tech Lab Members can join the IAB Tech Lab Ad Blocking Working Group, please email <a href="mailto:adblocking@iab.com" target="_blank">adblocking@iab.com</a> for more information.</P>
|
||||
<p>Read <a target="_blank" href="http://www.iab.com/insights/ad-blocking/">more about ad blocking here</a>.</p>
|
||||
</div></article>
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,4 +1,13 @@
|
|||
<article><div id="readability-page-1">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<p>Feb. 23, 2015 -- Life-threatening peanut allergies have mysteriously
|
||||
been
|
||||
on the rise in the past decade, with little hope for a cure.</p>
|
||||
|
@ -52,6 +61,7 @@
|
|||
to
|
||||
eat tiny amounts of peanuts after they wore it for a year.</p>
|
||||
<h3>A Change in Guidelines?</h3>
|
||||
|
||||
<p>Allergies to peanuts and other foods are on the rise. In the U.S.,
|
||||
more
|
||||
than 2% of people react to peanuts, a 400% increase since 1997. And
|
||||
|
|
|
@ -18,8 +18,7 @@ pub static BYLINE: Lazy<Regex> = Lazy::new(|| {
|
|||
.build()
|
||||
.expect("BYLINE regex")
|
||||
});
|
||||
pub static NORMALIZE: Lazy<Regex> =
|
||||
Lazy::new(|| Regex::new(r#"/\s{2,}/g"#).expect("NORMALIZE regex"));
|
||||
pub static NORMALIZE: Lazy<Regex> = Lazy::new(|| Regex::new(r#"\s{2,}"#).expect("NORMALIZE regex"));
|
||||
pub static TOKENIZE: Lazy<Regex> = Lazy::new(|| Regex::new(r#"\W+"#).expect("TOKENIZE regex"));
|
||||
pub static UNLIELY_CANDIDATES: Lazy<Regex> = Lazy::new(|| {
|
||||
RegexBuilder::new(r#"-ad-|ai2html|banner|breadcrumbs|combx|comment|community|cover-wrap|disqus|extra|footer|gdpr|header|legends|menu|related|remark|replies|rss|shoutbox|sidebar|skyscraper|social|sponsor|supplemental|ad-break|agegate|pagination|pager|popup|yom-remote"#).case_insensitive(true).build().expect("UNLIELY_CANDIDATES regex")
|
||||
|
|
|
@ -1001,7 +1001,7 @@ impl FullTextParser {
|
|||
|| Util::has_single_tag_inside_element(&node, "SECTION")
|
||||
{
|
||||
if let Some(mut parent) = node.get_parent() {
|
||||
if let Some(mut child) = node.get_child_nodes().into_iter().next() {
|
||||
if let Some(mut child) = node.get_child_elements().into_iter().next() {
|
||||
for (k, v) in node.get_attributes().into_iter() {
|
||||
child.set_attribute(&k, &v).map_err(|e| {
|
||||
log::error!("{e}");
|
||||
|
|
|
@ -34,7 +34,7 @@ impl Readability {
|
|||
let tag_name = node_ref.get_name().to_uppercase();
|
||||
|
||||
if tag_name == "TEXT" && node_ref.get_content().trim().is_empty() {
|
||||
node = Util::remove_and_next(node_ref);
|
||||
node = Util::next_node(node_ref, true);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -188,18 +188,6 @@ impl Readability {
|
|||
node = Util::next_node(node_ref, false);
|
||||
}
|
||||
|
||||
// let html = document.to_string_with_options(libxml::tree::SaveOptions {
|
||||
// format: true,
|
||||
// no_declaration: false,
|
||||
// no_empty_tags: true,
|
||||
// no_xhtml: false,
|
||||
// xhtml: false,
|
||||
// as_xml: false,
|
||||
// as_html: true,
|
||||
// non_significant_whitespace: false,
|
||||
// });
|
||||
// std::fs::write("debug.html", &html).unwrap();
|
||||
|
||||
let mut candidates = Vec::new();
|
||||
// Loop through all paragraphs, and assign a score to them based on how content-y they look.
|
||||
// Then add their score to their parent node.
|
||||
|
@ -262,6 +250,10 @@ impl Readability {
|
|||
if let Some(score) = Self::get_content_score(&ancestor) {
|
||||
let add_score = content_score / score_divider;
|
||||
let new_score = score + add_score;
|
||||
log::debug!(
|
||||
"{}: {score} + {add_score} = {new_score}",
|
||||
ancestor.get_name()
|
||||
);
|
||||
Self::set_content_score(&mut ancestor, new_score)?;
|
||||
}
|
||||
}
|
||||
|
@ -289,9 +281,14 @@ impl Readability {
|
|||
});
|
||||
|
||||
let top_candidates = candidates.into_iter().take(5).collect::<Vec<_>>();
|
||||
// for candidate in top_candidates.iter() {
|
||||
// println!("candidate: {} {:?}", candidate.get_name(), candidate.get_attributes());
|
||||
// }
|
||||
|
||||
for candidate in top_candidates.iter() {
|
||||
log::debug!(
|
||||
"candidate: {} {:?}",
|
||||
candidate.get_name(),
|
||||
candidate.get_attributes()
|
||||
);
|
||||
}
|
||||
let mut needed_to_create_top_candidate = false;
|
||||
let mut top_candidate = top_candidates.first().cloned().unwrap_or_else(|| {
|
||||
// If we still have no top candidate, just use the body as a last resort.
|
||||
|
@ -302,6 +299,8 @@ impl Readability {
|
|||
rt
|
||||
});
|
||||
|
||||
//Util::serialize_node(&top_candidate, "top_candidate.html");
|
||||
|
||||
let mut alternative_candidate_ancestors = Vec::new();
|
||||
// Find a better top candidate node if it contains (at least three) nodes which belong to `topCandidates` array
|
||||
// and whose scores are quite closed with current `topCandidate` node.
|
||||
|
@ -346,6 +345,8 @@ impl Readability {
|
|||
Self::initialize_node(&mut top_candidate, &state)?;
|
||||
}
|
||||
|
||||
//Util::serialize_node(&top_candidate, "new_top_candidate.html");
|
||||
|
||||
// Because of our bonus system, parents of candidates might have scores
|
||||
// themselves. They get half of the node. There won't be nodes with higher
|
||||
// scores than our topCandidate, but if we see the score going *up* in the first
|
||||
|
@ -433,7 +434,11 @@ impl Readability {
|
|||
let mut append = false;
|
||||
|
||||
let score = Self::get_content_score(&sibling).unwrap_or(0.0);
|
||||
log::debug!("Looking at sibling node: {sibling:?} with score {score}");
|
||||
log::debug!(
|
||||
"Looking at sibling node: {} ({:?}) with score {score}",
|
||||
sibling.get_name(),
|
||||
sibling.get_attribute("class")
|
||||
);
|
||||
|
||||
if top_candidate == sibling {
|
||||
append = true;
|
||||
|
@ -473,14 +478,22 @@ impl Readability {
|
|||
}
|
||||
|
||||
if append {
|
||||
log::debug!("Appending node: {sibling:?}");
|
||||
log::debug!(
|
||||
"Appending node: {} ({:?})",
|
||||
sibling.get_name(),
|
||||
sibling.get_attribute("class")
|
||||
);
|
||||
|
||||
if !constants::ALTER_TO_DIV_EXCEPTIONS
|
||||
.contains(sibling.get_name().to_uppercase().as_str())
|
||||
{
|
||||
// We have a node that isn't a common block level element, like a form or td tag.
|
||||
// Turn it into a div so it doesn't get filtered out later by accident.
|
||||
log::debug!("Altering sibling: {sibling:?} to div.");
|
||||
log::debug!(
|
||||
"Altering sibling: {} ({:?})",
|
||||
sibling.get_name(),
|
||||
sibling.get_attribute("class")
|
||||
);
|
||||
|
||||
sibling.set_name("DIV").map_err(|error| {
|
||||
log::error!("{error}");
|
||||
|
@ -544,6 +557,8 @@ impl Readability {
|
|||
let text = Util::get_inner_text(&article_content, true);
|
||||
let text_length = text.len();
|
||||
|
||||
//Util::serialize_node(&article_content, "debug.html");
|
||||
|
||||
if text_length < constants::DEFAULT_CHAR_THRESHOLD {
|
||||
parse_successful = false;
|
||||
|
||||
|
|
|
@ -8,7 +8,10 @@ use crate::{
|
|||
|
||||
async fn run_test(name: &str) {
|
||||
libxml::tree::node::set_node_rc_guard(10);
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
let _ = env_logger::builder()
|
||||
.filter_level(log::LevelFilter::Debug)
|
||||
.is_test(true)
|
||||
.try_init();
|
||||
|
||||
let empty_config = ConfigEntry::default();
|
||||
|
||||
|
@ -170,7 +173,7 @@ async fn dropbox_blog() {
|
|||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn ebbb_org() {
|
||||
async fn ebb_org() {
|
||||
run_test("ebb-org").await
|
||||
}
|
||||
|
||||
|
|
25
src/util.rs
25
src/util.rs
|
@ -308,7 +308,7 @@ impl Util {
|
|||
pub fn get_inner_text(node: &Node, normalize_spaces: bool) -> String {
|
||||
let content = node.get_content().trim().to_owned();
|
||||
if normalize_spaces {
|
||||
constants::NORMALIZE.replace(&content, " ").into()
|
||||
constants::NORMALIZE.replace_all(&content, " ").into()
|
||||
} else {
|
||||
content
|
||||
}
|
||||
|
@ -427,7 +427,7 @@ impl Util {
|
|||
}
|
||||
|
||||
pub fn get_link_density(node: &Node) -> f64 {
|
||||
let text_length = Util::get_inner_text(node, false).len();
|
||||
let text_length = Util::get_inner_text(node, true).len();
|
||||
if text_length == 0 {
|
||||
return 0.0;
|
||||
}
|
||||
|
@ -443,7 +443,7 @@ impl Util {
|
|||
} else {
|
||||
1.0
|
||||
};
|
||||
link_length += Util::get_inner_text(&link_node, false).len() as f64 * coefficient;
|
||||
link_length += Util::get_inner_text(&link_node, true).len() as f64 * coefficient;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -580,7 +580,7 @@ impl Util {
|
|||
}
|
||||
|
||||
let link_density = Self::get_link_density(node);
|
||||
let content = Self::get_inner_text(node, false);
|
||||
let content = Self::get_inner_text(node, true);
|
||||
let content_length = content.len();
|
||||
|
||||
let have_to_remove = (img > 1
|
||||
|
@ -780,4 +780,21 @@ impl Util {
|
|||
|| ((tag_name == "A" || tag_name == "DEL" || tag_name == "INS")
|
||||
&& node.get_child_nodes().iter().all(Self::is_phrasing_content))
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn serialize_node(node: &Node, filename: &str) {
|
||||
let mut doc = libxml::tree::Document::new().unwrap();
|
||||
doc.set_root_element(node);
|
||||
let html = doc.to_string_with_options(libxml::tree::SaveOptions {
|
||||
format: true,
|
||||
no_declaration: false,
|
||||
no_empty_tags: true,
|
||||
no_xhtml: false,
|
||||
xhtml: false,
|
||||
as_xml: false,
|
||||
as_html: true,
|
||||
non_significant_whitespace: false,
|
||||
});
|
||||
std::fs::write(filename, &html).unwrap();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue