[B6]heroku postgres-hgmnz
-
Author
naver-d2 -
Category
Technology
-
view
1.890 -
download
0
Embed Size (px)
description
Transcript of [B6]heroku postgres-hgmnz
![Page 1: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/1.jpg)
Heroku PostgresThe Tale of Conceiving and Buildinga Leading Cloud Database Service
1
Harold Gimé[email protected]
Saturday, September 8, 12
![Page 2: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/2.jpg)
2
Heroku Postgres
• Database-as-a-service
• Cloud
• Fully managed
• Over 2 years in production
• From tiny blogs to superbowl commercials
Saturday, September 8, 12
Heroku Postgres is a Database as a Service providerWe provision and run databases in cloud infrastructureIt is fully managed, always on and availableHas been in production for over 2 years, and has powered everything from a personal blog to sites backing superbowl commercial sites.
![Page 3: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/3.jpg)
Heroku origins
3
Saturday, September 8, 12
Heroku is born with a vision of increasing developer productivity and agility.
Anyone remember heroku garden? While that product no longer exists, that vision remains part of our core culture.
We want to enable developers to bring their creations to market as fast and pleasantly as possible.
![Page 4: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/4.jpg)
focus on rails
4
Saturday, September 8, 12
heroku got in the business of running web applications. As with any startup, it focused on doing one thing well, and for heroku that was running rails applications.
The approach empowered developers like never before. As a heroku customer, as I was back then, I was excited to make hobby apps available on the internet on a regular basis. It was so easy.
![Page 5: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/5.jpg)
rails apps need a database
5
Saturday, September 8, 12
Clearly, rails apps need a database. Rails got really good at doing CRUD, after all.
![Page 6: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/6.jpg)
web apps need a database
6
Saturday, September 8, 12
but this is true of any web application
![Page 7: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/7.jpg)
thankfully postgres was chosen
7
Saturday, September 8, 12
The story was something like
“Hey, we need a database. What should we use?”
Heroku was a very small team. The security expert happened to speak up and recommends Postgres, for it’s correctness track record and fine grained user role management
![Page 8: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/8.jpg)
otherwise I wouldn’t be here
8
Saturday, September 8, 12
I’ve been a Postgres user for years and know it is vastly superior to other open source RDBMS projects. If Postgres had not been chosen, I wouldn’t be here.
![Page 9: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/9.jpg)
“let’s make a production grade postgres service”
9
Saturday, September 8, 12
Heroku would give you a free database whenever you create an app.
One database server would hold a bunch of users.
But this is not sufficient for serious production applications that require exclusive access to more resources, and higher availability ops.
![Page 10: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/10.jpg)
10
Saturday, September 8, 12
This is our team’s mascot. It is a slide from IBM used in marketing materials in the 70s.
It’s funny how this vision was not true back then, but we are making it a reality over 30 years later.
![Page 11: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/11.jpg)
(hopefully yours)
11
Saturday, September 8, 12
![Page 12: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/12.jpg)
12
Heroku Postgres v.0.pre.alpha
• A sinatra app implementing the heroku addons API
• create servers
• install postgres service
• create databases for users - a “Resource”
• Sequel talks to postgres
• stem talks to AWS
Saturday, September 8, 12
Let’s talk about the tools used to build the very first version of Heroku Postgres.
It was built in Ruby. Sinatra is used to expose and APIs.Sequel is used to talk to postgres databases as well as as an ORMstem was built for this project - a very minimalistic and pleasant interface to the AWS APIs. stem was made available as open source software.
![Page 13: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/13.jpg)
Two main entities
13
Saturday, September 8, 12
There are two main entities in this application
![Page 14: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/14.jpg)
Resource
14
{ database: ‘d4f9wdf02’, port: 5432, username: ‘uf0wjasdf’, password: ‘pf14fhjas’, created_at: ‘2012-05-02’, state: ‘available’}
Saturday, September 8, 12
A resource encapsulates a database, the actual tangible resource that customers buy. A customer only cares about the database URL, used to connect to it.
![Page 15: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/15.jpg)
Server
15
{ elastic_ip: ‘192.168.0.1’, instance_id: ‘i-2efjoiads’, ami: ‘pg-prod’, availability_zone: ‘us-east-1’, created_at: ‘2012-05-02’, state: ‘booting’}
Saturday, September 8, 12
A server is the physical box where the resource is installed.
Customers don’t have direct access to it. It’s for our own bookkeeping and maintenance.
It includes an IP address, availability zone, and other AWS related attributes.
![Page 16: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/16.jpg)
...and a thin admin web interface
16
erb templates in sinatra endpoint
Saturday, September 8, 12
The early application also had an admin interface, right in the very same codebase as erb templates within some sinatra HTTP endpoints.
![Page 17: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/17.jpg)
We are just an add-on
17
Saturday, September 8, 12
The Heroku Postgres offering is just an heroku addon.
![Page 18: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/18.jpg)
18
Saturday, September 8, 12
There are numerous components to Heroku, one of which is the addons system.
Heroku Postgres is an addon just like any other third party is an addon (such as Papertrail or Sendgrid). We don’t utilize any backdoors of any kind, and instead interface with the rest of Heroku in the same way other addon providers do.
This is a great position to be in, because as consumers of the heroku addons echosystem, we help drive its evolution.
![Page 19: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/19.jpg)
19
we run on
Saturday, September 8, 12
Furthermore, the entire Heroku Postgres infrastructure runs on Heroku itself.
![Page 20: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/20.jpg)
the simplest thing that could possibly work,
but no less
20
Saturday, September 8, 12
Simplicity is key to building any sort of system, and in this case, the initial version of the Heroku Postgres management app was as simple as it could be.
This allows us to modify behavior and evolve as quickly as possible, on a smaller more pleasant code base.
![Page 21: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/21.jpg)
We’ve come a long way since then
21
Saturday, September 8, 12
Fast forward a few years, and we are now managing a very large number of databases, keeping them alive, and creating new ones at a higher rate than ever.
This requires more sophisticated processes and managers.
Let’s dive into how it works today
![Page 22: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/22.jpg)
Monitoring and Workflow
22
Saturday, September 8, 12
Monitoring and Workflow are key to this type of system.
![Page 23: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/23.jpg)
draw inspiration from gaming
23
Saturday, September 8, 12
In programming we often draw inspiration from a number of things.
A good example is OOP itself, which is inspired by the way messages are sent between organisms in a biological ecosystem
The project lead (@pvh) has a background in gaming.
Imagine the bad guy in a Diablo game. He’s just wandering around doing nothing, because there’s nothing to attack around him. At some point, he sees your character and charges toward you. You battle the Diablo. He fights back, and finally you kill him. He dies a slow and painful death.
There are many ways to model these kinds of systems. One can be an events based system, where observers listen on events that are occurring and react to them appropriately. You could also load all objects that need monitoring and process that queue. This either gets too complex easily, or doesn’t scale at all because of memory constraints and size of the workload.
A state machine is another good way to model this. A state machine is, at heart, an entity that is fed some inputs, and in return it takes some action, and then may or may not transition to a different state.
The bad guy is in a `wondering around` state when nothing is around it. But as soon as it saw your character, it entered a `battle` state, and so on.
We model what happens in real life, which is that we observe our environment, register it, and react to it.
![Page 24: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/24.jpg)
24
class Resource def feel observations.create( Feeler.new(self).current_environment ) endend
class Feeler def current_environment { service_available?: service_available?, open_connections: open_connections, row_count: row_count, table_count: table_count, seq_scans: seq_scans, index_scans: index_scans } endend
monitoring
Saturday, September 8, 12
This is what the actual source code looks like.
A Resource has a #feel method, which stores an observation based on what the Feeler sees.
A Feeler is an object that observes the current environment around it. It checks things like is the service available, how many connections are open, and many more health checks.
![Page 25: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/25.jpg)
25
class Resource include Stateful
state :available do unless service_available? transition :unavailable end endend
resource = Resource.newresource.transition :availableresource.feelresource.tickputs resource.state # ‘unavailable’
workflow
Saturday, September 8, 12
![Page 26: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/26.jpg)
26
module Stateful def self.included(base) base.extend ClassMethods end
module ClassMethods def state(name, &block) states[name] = block end def states; @states ||= {}; end end
def tick self.instance_eval( &self.class.states[self.state.to_sym] ) end
def transition(state) # log and assign new state endend
workflow
Saturday, September 8, 12
In terms of workflow, we built an extremely simple state machine system.
It allows you to define states via the `state` method which takes an arbitrary block of code to execute when invoked via the `#tick` method.
![Page 27: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/27.jpg)
27
resource.feelresource.tick
Need to do this all the time
Saturday, September 8, 12
We first call #feel on an object, and then call #tick on it.
Feel stores new observed information, while #tick uses this information to make system decisions, such as transitioning to other states, sending alerts, and much more.
We must run these two methods continuously
![Page 28: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/28.jpg)
28
db1 db2 db3 db4 db5 db6 db7 db8 db9 ... dbn
db1.feeldb1.tick
Saturday, September 8, 12
One way to run it continously is via a work queue.
![Page 29: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/29.jpg)
29
db2 db3 db4 db5 db6 db7 db8 db9 ... dbn db1
db2.feeldb2.tick enqueue(db1)
Saturday, September 8, 12
We create a queue and place all active resources on it. A set or workers pull jobs from the queue, invoke feel and tick, and then enqueue themselves again.
This is in escense a poorly implemented distributed ring buffer, and it’s served us well.
![Page 30: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/30.jpg)
30
QueueClassichttp://github.com/ryandotsmith/queue_classic
Saturday, September 8, 12
Our queue is implemented on top of the QueueClassic gem, which is a queue system built in Ruby on top of Postgres with some interesting characteristics.
![Page 31: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/31.jpg)
31
Saturday, September 8, 12
Let’s look at some of the states on our resource class. A resource can go through these states.
One very important aspect of this system is idempotency. The system must be designed in such a way that each state can be run any number of times and without affecting the end result.
Examples where this is not immediately obvious are the creating and deprovisioning state.
![Page 32: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/32.jpg)
Durability and Availability
32
Saturday, September 8, 12
Let’s talk about how we handle durability and availability of databases.
![Page 33: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/33.jpg)
33
Saturday, September 8, 12
In Postgres, as in other similar systems, when you issue a write transaction, it firsts writes the transaction to what’s called the Write-Ahead Log (WAL), and only then does it write to the data files.
This ensures that all data committed to the system exists first in the WAL stream.
![Page 34: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/34.jpg)
34
Saturday, September 8, 12
Of course, if the WAL stream is on the same physical disks as the data files, there’s a high risk of data loss.
Many opt to place the wal segments on a separate disk than the data files. This is a great first step (and one we also take).
But really, we don’t consider data to be durable until the WAL segments are replicated across many data centers.
We ship WAL segments to multi-datacenter storage every 60 seconds. We use Wal-e, a python WAL archiver written at Heroku and now available as open source.
![Page 35: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/35.jpg)
35
Saturday, September 8, 12
Now that the WAL segments are out of the box, we can do many other tricks.
For example, creating a “follower” is as easy as fetching the WAL segments from the distributed storage, and replaying these logs on a brand new server - once it has caught up, we set up direct streaming replication between primary and follower.
![Page 36: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/36.jpg)
36
Saturday, September 8, 12
Similary, a fork of a database sets pulls down the WAL segments from distributed storage and replays them on a new server.
Once it’s caught up, instead of setting up streaming replication as in the follow case, instead this new server starts producing WAL segments of it’s own (when write transactions occur on it). So now the fork is set up to ship WAL segments to distributed storage, just like its leader.
![Page 37: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/37.jpg)
Continuous Protection
37
• Write-Ahead Log segments shipped to durable storage every 60 seconds
• We can replay these logs on a new server to recover your data
• https://github.com/heroku/WAL-E
Saturday, September 8, 12
This is what we call Continuous Protection.
Having WAL segments always available is a primary concern of ours, as it allows us to easily rebuild a server’s data state, and can be updated continuously as opposed to capturing full backups of the system.
![Page 38: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/38.jpg)
Need a more flexible object model
38
Saturday, September 8, 12
Now, the introduction of all of these functions required us to rethink our object model.
![Page 39: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/39.jpg)
39timeline
Saturday, September 8, 12
We have the concept of a timeline
A timeline at time = zero contains no data, no commits.
![Page 40: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/40.jpg)
40participant
Saturday, September 8, 12
Participants are attached to a timeline. Participants can write data to the timeline.
![Page 41: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/41.jpg)
41
Saturday, September 8, 12
Writing data to the timeline moves the timeline forward in time.
![Page 42: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/42.jpg)
42
Saturday, September 8, 12
![Page 43: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/43.jpg)
43resource
Saturday, September 8, 12
A resource is what our users get. It maps to a URL. A resource is attached to one participant.
![Page 44: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/44.jpg)
44follower
Saturday, September 8, 12
This allows us to model followers easily.
A follower is just a participant on the same timeline as its reader.
The difference is that followers can’t write to the same timeline. Only one participant can write to the timeline, the follower’s leader (or primary).
![Page 45: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/45.jpg)
45fork
Saturday, September 8, 12
When we fork a database, it creates its own timeline. The new timeline now has drifted away from it’s parent, and can be writable. So it will create it’s own path.
![Page 46: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/46.jpg)
46disaster
Saturday, September 8, 12
Finally, this system can be used during the event of catastrophic hardware failure.
When a database’s hardware fails completely, instead of trying to recover the server itself, it’s best to create a new node and “STONITH” (http://en.wikipedia.org/wiki/STONITH)
![Page 47: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/47.jpg)
47
Saturday, September 8, 12
What we do is create a new participant, hidden from the user.
![Page 48: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/48.jpg)
48recovery
Saturday, September 8, 12
And once it is caught up and ready to go, we tie the resource to it.
So, the user only sees a blip in availability, but behind the scenes they are actually sitting on entirely new hardware, like magic.
![Page 49: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/49.jpg)
big project
49
Saturday, September 8, 12
Needless to say, this has become a big project over time.
![Page 50: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/50.jpg)
lots of moving parts
50
Saturday, September 8, 12
![Page 51: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/51.jpg)
long test suite
51
Saturday, September 8, 12
![Page 52: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/52.jpg)
modularize and build APIs
52
Saturday, September 8, 12
So it’s time to spread out responsabilities by modularizing the system and building APIs that are used for them to talk to each other.
![Page 53: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/53.jpg)
53
Saturday, September 8, 12
What we’ve built is a constellation of heroku apps. We may split this even further in the future.
![Page 54: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/54.jpg)
gain in agility
54
Saturday, September 8, 12
This gains un in agility.
The test suites of each individual project is much smaller now, which improves our ability to develop quicker.
It also means that each component can be deployed individually. For example, a deploy to the admin front end UI has no effect on the main system’s APIs.
![Page 55: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/55.jpg)
composable services
55
Saturday, September 8, 12
It also allows us to build better abstractions at the systematic level, which gains us in the ability to compose services better.
For example, a system that provisions and manages servers from our infrastructure provider can be used by many other consumers, not only heroku postgres.
![Page 56: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/56.jpg)
independently scalable
56
Saturday, September 8, 12
They can furthermore be scaled individually. Some parts of the system require different loads and response times than others, so now we are able to easily and clearly tweak our system operations based on clearly decoupled subsystems.
![Page 57: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/57.jpg)
Logging and Metrics
57
Saturday, September 8, 12
Finally, I’d like to talk about visibility into our app.
![Page 58: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/58.jpg)
log generation
58
Saturday, September 8, 12
First, let’s talk about logging.
![Page 59: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/59.jpg)
59
Saturday, September 8, 12
In Heroku, there’s a service called Logplex (it’s open source).
Your application is able to send logs to the logplex service to a specific channel (it uses Capability Based Security).
Then, one or more consumers can “drain” the logs for that channel.
![Page 60: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/60.jpg)
logs are event streams
60
Saturday, September 8, 12
![Page 61: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/61.jpg)
how should you log?
61
Saturday, September 8, 12
Having this logging infrastructure available, let’s talk about how to make best use of it.
![Page 62: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/62.jpg)
62
post “/work” do puts “starting to do work” worker = Worker.new(params) begin worker.lift_things_up worker.put_them_down rescue WorkerError => e puts “Fail :( #{e.message}” status 500 end puts “done doing work” status 200end
Saturday, September 8, 12
This is an example of terrible logging.
![Page 63: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/63.jpg)
63
$ heroku logs --tail
2012-07-28T02:43:35 [web.4] starting to dowork2012-07-28T02:43:35 [web.4] Fail :( invalid worker, nothing to do2012-07-28T02:43:35 heroku[router] POST myapp.com/work dyno=web.4 queue=0 wait=0msservice=14ms status=500 bytes=643
Saturday, September 8, 12
There’s no structure to these logs, so it can’t be easily read and interpreted by a computer.
![Page 64: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/64.jpg)
64
bad logging
• What exactly happened?
• When did it happen?
• How long did it take?
• How many times has it happened?
Saturday, September 8, 12
![Page 65: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/65.jpg)
good logging
• parseable
• consistent
• plentiful
65
Saturday, September 8, 12
![Page 66: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/66.jpg)
66
post “/work” do log(create_work: true, request_id: uuid) do worker = Worker.new(params.merge(uuid: uuid)) begin worker.lift_things_up worker.put_them_down rescue WorkerError => e log_exception(e, create_work: true) end endend
helpers do def uuid @uuid ||= SecureRandom.uuid endend
Saturday, September 8, 12
Instead, let’s do some more structured logging.
Also note how every request gets a UUID. This is critical to tying up all the logs for a given request.
![Page 67: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/67.jpg)
67
require ‘scrolls’module App module Logs extend self
def log(data, &block) Scrolls.log(with_env(data), &block) end
def log_exception(exception, data, &block) Scrolls.log_exception(with_env(data), &block) end
def with_env(hash) { environment: ENV[‘RACK_ENV’] }.merge(data) end endend
Saturday, September 8, 12
On the prior slide, we saw the `log` and `log_exception` methods.
This is a small module that provides those methods. It is a wrapper for the `scrolls` (open source) gem.
Scrolls provides a framework for structured logging.This module merely adds our environment name to the logs, which is useful for parsing later.
![Page 68: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/68.jpg)
68
$ heroku logs --tail2012-07-28T02:43:35 [web.4] create_work request_id=afe2-f0d at=start2012-07-28T02:43:35 [web.4] create_workrequest_id=afe2-f0d at=exceptionmessage=invalid worker, nothing to do2012-07-28T02:43:35 [web.4] create_work request_id=afe2-f0d at=finish elapsed=532012-07-28T02:43:35 heroku[router] POST myapp.com/work dyno=web.4 queue=0 wait=0msservice=14ms status=500 bytes=643
Saturday, September 8, 12Now our logs look like this.
Easy to parse, and still easy to read by a human.
![Page 69: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/69.jpg)
69
log consumption
Saturday, September 8, 12
Let’s talk about consuming those logs, which should make it clear why structured logging is so important.
![Page 70: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/70.jpg)
(this is the fun part)
70
Saturday, September 8, 12
![Page 71: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/71.jpg)
71
Saturday, September 8, 12
As mentioned before, it’s possible to set up multiple log drains.
The heroku toolbelt has a utility to print out logs to your terminal (accessible via heroku logs --tail).But why stop there? You can have as many drains as you want!
We can set up a drain that stores data locally for further analysis and metrics generation. Here, a postgres database is set up and logs stored to it on the key-value data type called hstore.
![Page 72: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/72.jpg)
72
select * from events;
Saturday, September 8, 12
![Page 73: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/73.jpg)
73
Saturday, September 8, 12
Now that we have stored data on a postgres database, we can use SQL to query it and generate some metrics.
We have a process that continuously queries this database and sends aggregated results to a metrics collection service (third party).
![Page 74: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/74.jpg)
74
good logging
metrics
alerts
Saturday, September 8, 12
Visibility into your system starts with good logging
Great logs enable easy metrics collection
Metrics lead to system alerts.
![Page 75: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/75.jpg)
current tooling
75
• still using sequel and sinatra
• fog displaced stem
• backbone.js for web UIs
• fernet for auth tokens, valcro for validations
• python, go and bash in some subsystems
Saturday, September 8, 12
So to wrap up, our current tooling includes these pieces of technology
![Page 76: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/76.jpg)
• managing databases is hard
• start simple
• extract (and share) reusable code
• separate concerns into services
• learn to love your event stream
76
lessons
Saturday, September 8, 12
![Page 77: [B6]heroku postgres-hgmnz](https://reader037.fdocuments.in/reader037/viewer/2022102922/54b54b4f4a795979748b460d/html5/thumbnails/77.jpg)
thanks!
77
@hgmnz
@herokupostgres
Saturday, September 8, 12