');--input-focus-border-color:Highlight;--input-focus-outline:1px solid Canvas;--input-unfocused-border-color:transparent;--input-disabled-border-color:transparent;--input-hover-border-color:#000}@media (forced-colors:active){:root{--input-focus-border-color:CanvasText;--input-unfocused-border-color:ActiveText;--input-disabled-border-color:GrayText;--input-hover-border-color:Highlight}.annotationLayer .buttonWidgetAnnotation.checkBox input:required,.annotationLayer .buttonWidgetAnnotation.radioButton input:required,.annotationLayer .choiceWidgetAnnotation select:required,.annotationLayer .textWidgetAnnotation input:required,.annotationLayer .textWidgetAnnotation textarea:required{outline:1.5px solid selectedItem}}.annotationLayer{--scale-factor:1;left:0;pointer-events:none;position:absolute;top:0;transform-origin:0 0}.annotationLayer section{box-sizing:border-box;pointer-events:auto;position:absolute;text-align:initial;transform-origin:0 0}.annotationLayer .buttonWidgetAnnotation.pushButton>a,.annotationLayer .linkAnnotation>a{font-size:1em;height:100%;left:0;position:absolute;top:0;width:100%}.annotationLayer .buttonWidgetAnnotation.pushButton>canvas{height:100%;width:100%}.annotationLayer .buttonWidgetAnnotation.pushButton>a:hover,.annotationLayer .linkAnnotation>a:hover{background:#ff0;box-shadow:0 2px 10px #ff0;opacity:.2}.annotationLayer .textAnnotation img{cursor:pointer;height:100%;position:absolute;width:100%}.annotationLayer .buttonWidgetAnnotation.checkBox input,.annotationLayer .buttonWidgetAnnotation.radioButton input,.annotationLayer .choiceWidgetAnnotation select,.annotationLayer .textWidgetAnnotation input,.annotationLayer .textWidgetAnnotation textarea{background-image:var(--annotation-unfocused-field-background);border:2px solid var(--input-unfocused-border-color);box-sizing:border-box;font:calc(9px*var(--scale-factor)) sans-serif;height:100%;margin:0;vertical-align:top;width:100%}.annotationLayer .buttonWidgetAnnotation.checkBox input:required,.annotationLayer .buttonWidgetAnnotation.radioButton input:required,.annotationLayer .choiceWidgetAnnotation select:required,.annotationLayer .textWidgetAnnotation input:required,.annotationLayer .textWidgetAnnotation textarea:required{outline:1.5px solid red}.annotationLayer .choiceWidgetAnnotation select option{padding:0}.annotationLayer .buttonWidgetAnnotation.radioButton input{border-radius:50%}.annotationLayer .textWidgetAnnotation textarea{resize:none}.annotationLayer .buttonWidgetAnnotation.checkBox input[disabled],.annotationLayer .buttonWidgetAnnotation.radioButton input[disabled],.annotationLayer .choiceWidgetAnnotation select[disabled],.annotationLayer .textWidgetAnnotation input[disabled],.annotationLayer .textWidgetAnnotation textarea[disabled]{background:none;border:2px solid var(--input-disabled-border-color);cursor:not-allowed}.annotationLayer .buttonWidgetAnnotation.checkBox input:hover,.annotationLayer .buttonWidgetAnnotation.radioButton input:hover,.annotationLayer .choiceWidgetAnnotation select:hover,.annotationLayer .textWidgetAnnotation input:hover,.annotationLayer .textWidgetAnnotation textarea:hover{border:2px solid var(--input-hover-border-color)}.annotationLayer .buttonWidgetAnnotation.checkBox input:hover,.annotationLayer .choiceWidgetAnnotation select:hover,.annotationLayer .textWidgetAnnotation input:hover,.annotationLayer .textWidgetAnnotation textarea:hover{border-radius:2px}.annotationLayer .choiceWidgetAnnotation select:focus,.annotationLayer .textWidgetAnnotation input:focus,.annotationLayer .textWidgetAnnotation textarea:focus{background:none;border:2px solid var(--input-focus-border-color);border-radius:2px;outline:var(--input-focus-outline)}.annotationLayer .buttonWidgetAnnotation.checkBox :focus,.annotationLayer .buttonWidgetAnnotation.radioButton :focus{background-color:transparent;background-image:none}.annotationLayer .buttonWidgetAnnotation.checkBox :focus{border:2px solid var(--input-focus-border-color);border-radius:2px;outline:var(--input-focus-outline)}.annotationLayer .buttonWidgetAnnotation.radioButton :focus{border:2px solid var(--input-focus-border-color);outline:var(--input-focus-outline)}.annotationLayer .buttonWidgetAnnotation.checkBox input:checked:after,.annotationLayer .buttonWidgetAnnotation.checkBox input:checked:before,.annotationLayer .buttonWidgetAnnotation.radioButton input:checked:before{background-color:CanvasText;content:"";display:block;position:absolute}.annotationLayer .buttonWidgetAnnotation.checkBox input:checked:after,.annotationLayer .buttonWidgetAnnotation.checkBox input:checked:before{height:80%;left:45%;width:1px}.annotationLayer .buttonWidgetAnnotation.checkBox input:checked:before{transform:rotate(45deg)}.annotationLayer .buttonWidgetAnnotation.checkBox input:checked:after{transform:rotate(-45deg)}.annotationLayer .buttonWidgetAnnotation.radioButton input:checked:before{border-radius:50%;height:50%;left:30%;top:20%;width:50%}.annotationLayer .textWidgetAnnotation input.comb{font-family:monospace;padding-left:2px;padding-right:0}.annotationLayer .textWidgetAnnotation input.comb:focus{width:103%}.annotationLayer .buttonWidgetAnnotation.checkBox input,.annotationLayer .buttonWidgetAnnotation.radioButton input{-webkit-appearance:none;appearance:none}.annotationLayer .popupTriggerArea{height:100%;width:100%}.annotationLayer .popupWrapper{font-size:calc(9px*var(--scale-factor));min-width:calc(180px*var(--scale-factor));pointer-events:none;position:absolute;width:100%}.annotationLayer .popup{word-wrap:break-word;background-color:#ff9;border-radius:calc(2px*var(--scale-factor));box-shadow:0 calc(2px*var(--scale-factor)) calc(5px*var(--scale-factor)) #888;cursor:pointer;font:message-box;margin-left:calc(5px*var(--scale-factor));max-width:calc(180px*var(--scale-factor));padding:calc(6px*var(--scale-factor));pointer-events:auto;position:absolute;white-space:normal}.annotationLayer .popup>*{font-size:calc(9px*var(--scale-factor))}.annotationLayer .popup h1{display:inline-block}.annotationLayer .popupDate{display:inline-block;margin-left:calc(5px*var(--scale-factor))}.annotationLayer .popupContent{border-top:1px solid #333;margin-top:calc(2px*var(--scale-factor));padding-top:calc(2px*var(--scale-factor))}.annotationLayer .richText>*{font-size:calc(9px*var(--scale-factor));white-space:pre-wrap}.annotationLayer .caretAnnotation,.annotationLayer .circleAnnotation svg ellipse,.annotationLayer .fileAttachmentAnnotation,.annotationLayer .freeTextAnnotation,.annotationLayer .highlightAnnotation,.annotationLayer .inkAnnotation svg polyline,.annotationLayer .lineAnnotation svg line,.annotationLayer .polygonAnnotation svg polygon,.annotationLayer .polylineAnnotation svg polyline,.annotationLayer .squareAnnotation svg rect,.annotationLayer .squigglyAnnotation,.annotationLayer .stampAnnotation,.annotationLayer .strikeoutAnnotation,.annotationLayer .underlineAnnotation{cursor:pointer}.annotationLayer .annotationTextContent,.annotationLayer section svg{height:100%;position:absolute;width:100%}.annotationLayer .annotationTextContent{color:transparent;opacity:0;pointer-events:none;-webkit-user-select:none;user-select:none}.annotationLayer .annotationTextContent span{display:inline-block;width:100%}code[class*=language-],pre[class*=language-]{word-wrap:normal;background:none;color:#000;font-family:Consolas,Monaco,Andale Mono,Ubuntu Mono,monospace;font-size:1em;-webkit-hyphens:none;hyphens:none;line-height:1.5;tab-size:4;text-align:left;text-shadow:0 1px #fff;white-space:pre;word-break:normal;word-spacing:normal}code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{background:#b3d4fc;text-shadow:none}@media print{code[class*=language-],pre[class*=language-]{text-shadow:none}}pre[class*=language-]{margin:.5em 0;overflow:auto;padding:1em}:not(pre)>code[class*=language-],pre[class*=language-]{background:#f5f2f0}:not(pre)>code[class*=language-]{border-radius:.3em;padding:.1em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#708090}.token.punctuation{color:#999}.token.namespace{opacity:.7}.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color:#905}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#690}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url{background:hsla(0,0%,100%,.5);color:#9a6e3a}.token.atrule,.token.attr-value,.token.keyword{color:#07a}.token.class-name,.token.function{color:#dd4a68}.token.important,.token.regex,.token.variable{color:#e90}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}@font-face{font-display:swap;font-family:Averta Web;font-style:normal;font-weight:400;src:url(/content-platform/static/Averta-Regular-fd1297bf462e95eea6aa118597d8ef9e.otf) format("opentype")}@font-face{font-display:swap;font-family:Averta Web;font-style:italic;font-weight:400;src:url(/content-platform/static/Averta-RegularItalic-a93ae4a14814b0363207932e2c55e7bb.otf) format("opentype")}@font-face{font-display:swap;font-family:Averta Web;font-style:normal;font-weight:600;src:url(/content-platform/static/Averta-Semibold-3cbea55cef956724c095d3faa96ac883.otf) format("opentype")}@font-face{font-display:swap;font-family:Averta Web;font-style:italic;font-weight:600;src:url(/content-platform/static/Averta-SemiboldItalic-7962116f4e3c788c3df34f71cb41f4c1.otf) format("opentype")}@font-face{font-display:swap;font-family:"PT Serif";font-style:normal;font-weight:400;src:url(/content-platform/static/PT_Serif-Web-Regular-a12d02e92a52545c0e252cb52e59a199.ttf) format("truetype")}@font-face{font-display:swap;font-family:"PT Serif";font-style:italic;font-weight:400;src:url(/content-platform/static/PT_Serif-Web-Italic-fbc44e1e589cb892ee02348b2a8a348c.ttf) format("truetype")}@font-face{font-display:swap;font-family:"PT Serif";font-style:normal;font-weight:600;src:url(/content-platform/static/PT_Serif-Web-Bold-f86a6a1831027140ee56a79917cdd50d.ttf) format("truetype")}@font-face{font-display:swap;font-family:"PT Serif";font-style:italic;font-weight:600;src:url(/content-platform/static/PT_Serif-Web-BoldItalic-dc0d330f07cb434d3df2ada512eeb3b3.ttf) format("truetype")}@font-face{font-display:swap;font-family:Simplon Mono;font-style:normal;font-weight:400;src:url(/content-platform/static/SimplonMono-Regular-f7db758b4f03c8b9179c1d8fe0bb44f8.woff2) format("woff2"),url(/content-platform/static/SimplonMono-Regular-4873b89276459e0daae704dc30e2966d.woff) format("woff")}@font-face{font-display:swap;font-family:Haffer;font-style:normal;font-weight:400;src:url(/content-platform/static/HafferXH-Regular-5aabd3cd7105e25df233f608f2d66bc2.otf) format("opentype")}@font-face{font-display:swap;font-family:Haffer;font-style:italic;font-weight:400;src:url(/content-platform/static/HafferXH-RegularItalic-8cc7af3f0d75ba1b610a1b1878ea5eee.otf) format("opentype")}@font-face{font-display:swap;font-family:Haffer;font-style:normal;font-weight:500;src:url(/content-platform/static/HafferXH-Medium-dae5509349255a527ba6223b40257a7c.otf) format("opentype")}@font-face{font-display:swap;font-family:Haffer;font-style:normal;font-weight:600;src:url(/content-platform/static/HafferXH-SemiBold-64a01291b8f7380359bb3642c1b1e00a.otf) format("opentype")}@font-face{font-display:swap;font-family:Haffer;font-style:italic;font-weight:600;src:url(/content-platform/static/HafferXH-SemiBoldItalic-869dd4deb4c6e290c1aaf1e6a8670036.otf) format("opentype")}@font-face{font-display:swap;font-family:Nudge;font-style:normal;font-weight:100;src:url(/content-platform/static/VCNudge-Thin-09f2315fb254f9dc017f0e4983166415.otf) format("opentype")}@font-face{font-display:swap;font-family:Nudge;font-style:normal;font-weight:300;src:url(/content-platform/static/VCNudge-Light-dc44d09f0564da3a5f46801b8bb26cd8.otf) format("opentype")}@font-face{font-display:swap;font-family:Nudge;font-style:normal;font-weight:400;src:url(/content-platform/static/VCNudge-Regular-be0a147c918c6bec670c17f5204784bb.otf) format("opentype")}@font-face{font-display:swap;font-family:Nudge;font-style:normal;font-weight:700;src:url(/content-platform/static/VCNudge-Bold-822d17e33e72d439ad42d99a75ae6df0.otf) format("opentype")}@font-face{font-display:swap;font-family:Nudge;font-style:normal;font-weight:800;src:url(/content-platform/static/VCNudge-ExtraBold-a2d0723b460f32bc659ad1670a00ae22.otf) format("opentype")}@font-face{font-display:swap;font-family:Nudge;font-style:normal;font-weight:900;src:url(/content-platform/static/VCNudge-Black-9e870be920be60c228f9a4affa885f8d.otf) format("opentype")}@font-face{font-display:swap;font-family:Para;font-style:normal;font-weight:300;src:url(/content-platform/static/Para-Central-Light-b0a58901815efc51b2b07b595eca45f7.otf) format("opentype")}@font-face{font-display:swap;font-family:Para;font-style:italic;font-weight:300;src:url(/content-platform/static/Para-Central-Light-Italic-48e4a958a048c612c6a0927f538018b8.otf) format("opentype")}@font-face{font-display:swap;font-family:Para;font-style:normal;font-weight:400;src:url(/content-platform/static/Para-Central-Regular-03a3a49a91a9bbf991dd6263feab3975.otf) format("opentype")}@font-face{font-display:swap;font-family:Para;font-style:normal;font-weight:700;src:url(/content-platform/static/Para-Central-Bold-3107caa8a871d45bb00cb084bcc8ffc1.otf) format("opentype")}@font-face{font-display:swap;font-family:DM Mono;font-style:normal;font-weight:300;src:url(/content-platform/static/DMMono-Light-2cf6d0b2de012ff294ce86eecb4263e5.ttf) format("truetype")}@font-face{font-display:swap;font-family:DM Mono;font-style:italic;font-weight:300;src:url(/content-platform/static/DMMono-LightItalic-0e20bf0432fcf702ef0306184759a593.ttf) format("truetype")}@font-face{font-display:swap;font-family:DM Mono;font-style:normal;font-weight:400;src:url(/content-platform/static/DMMono-Regular-15edd89a6460acfb1a86017399e47a1f.ttf) format("truetype")}@font-face{font-display:swap;font-family:DM Mono;font-style:italic;font-weight:400;src:url(/content-platform/static/DMMono-Italic-6b7b77e96ef2aa8ec8fffe2e28239719.ttf) format("truetype")}@font-face{font-display:swap;font-family:DM Mono;font-style:normal;font-weight:500;src:url(/content-platform/static/DMMono-Medium-50d7af0bb966bc0570a212128d7ab24d.ttf) format("truetype")}@font-face{font-display:swap;font-family:DM Mono;font-style:italic;font-weight:500;src:url(/content-platform/static/DMMono-MediumItalic-85bff8703124566bb1a660afda35365b.ttf) format("truetype")}body,html{box-sizing:border-box;margin:0;padding:0}
Introducing Logjam | GoCardless Skip to content menu Open site navigation sidebar For use case
Our customers
For small business
For enterprise
Collect Payments
Protect revenue
Open Banking
Connect to GoCardless
Help and support
News and resources
Login Sign up Introducing Logjam Last editedJun 2024 — 2 min read
Internally at GoCardless, we are undergoing a top-down restructuring of our server infrastructure. We are planning on moving away from the one-app-per-server model with a mixture of cloud and dedicated hardware, to a more general compute style cluster; powered by Apache Mesos and Docker on top of dedicated hardware.
One of the problems to solve leading up to this change is what we do with logs. Currently we use logstash-forwarder to pick up entries in our application's rails.log
and forward them to our Logstash server. Given that our applications can possibly come and go frequently, be created for the sole purpose of running a one-off or recurring task, and the separation of the container and the host filesystem; we are posed an interesting problem which led us to deem our current solution inadequate.
Possible solutions included:
Mounting an external volume on the docker container, binding to its logs
directory. However this would require a large change to our applications to ensure they write to a unique log file. Additionally we find logstash-fowarder has difficulty with dynamic log collection and traversing a long directory tree.
Moving logstash-forwarder from the host server into each individual container. However this would increase the complexity of the container and has the addition of each container now creating N+1 processes.
Having applications log directly to logstash . This potentially decreases the reliability of the application by introducing potential faults through reliance on a further external service.
After reviewing our options, we decided to design our own log collection agent using a unique combination of existing methods to provide a simple and reliable system for our logging. We called this Logjam .
Logjam is a daemon which listens locally on a UDP socket and accepts a stream of JSON log entries. These entries are then buffered (either in memory or on disk) and forwarded to a remote collection server (in our case logstash) for storage and querying. In our use case, we configure logjam on the host system to listen on the network bridge interface created by docker (called docker0
), by doing this we can ensure that all running containers can communicate with logjam using the network bridges IP address (by default 172.16.42.1
).
Logjam implements a simple processing pipeline consisting of two major subsystems. The first of which, called receiver
, is responsible for listening on a local network interface and receiving incoming log entries. The second, called shipper
, is responsible for taking log entries and reliably submitting them to a remote collection server for storage. Inbetween the two subsystems consists an in-memory buffer (optionally persisted to disk) of configurable size of recent log entries to ship.
Logjam is written in Go and is available from GitHub .
We will be writing throughout this major re-architecting of our infrastructure, documenting our experiences, as we design and implement it.
Over 85,000 businesses use GoCardless to get paid on time. Learn more about how you can improve payment processing at your business today.
Interested in automating the way you get paid? GoCardless can help Contact us
Seen 'GoCardless Ltd' on your bank statement? Learn more
GoCardless Ltd, Sutton Yard, 65 Goswell Road, London, EC1V 7EN, United Kingdom
GoCardless Ltd (company registration number 07495895) is authorised by the Financial Conduct Authority under the Payment Services Regulations 2017, registration number 597190, for the provision of payment services.