When you have a blog you usually want to let your followers know when
a new article is posted. This blog has an Atom feed
but RSS readers are less common than they used to be and seem a bit old fashioned.
I remembered that I have an account at If This Then That and decided
to try using that. It is already linked to my Twitter account so that part of the process
was ready to go.
I created a new Applet (IFTTT-speak for a set of rules that link services together;
formerly called a Recipe) to check the Atom feed periodically and tweet an announcement.
But IFTTT showed the Applet as never run and did not display any error messages that I
could find.
Invalid Atom feed
IFTTT help pages include a link to the W3C Feed Validation Service.
Using that showed the feed to be invalid because the email address field was empty.
This was solved by adding author.email to _config.yml. (I used a valid
email address that I can get my mail provider to filter if
it starts attracting spam.)
There were other, minor issues, including the link information showing
http://blog.michaelstrasser.com instead of https://blog.michaelstrasser.com. I don’t know
why Jekyll does that, but a solution is to add an explicit url value to the configuration
file:
url:https://blog.michaelstrasser.com
(This value is only used in Jekyll production
mode.
In the default development mode it is overwritten by the actual URL: http://localhost:4000
by default.)
Success
Update: The tweet for this page is:
By default, IFTTT uses its own link shortener, but I turned that off as described
here.
On a recent project we implemented an API service using Spring
Boot with two operations:
initiate a new, asynchronous workflow
report on the status of an existing workflow
Each workflow is identified by a unique ID that is generated by the
service on the first call and returned to the consumer. The consumer then uses
that ID in subsequent status requests to identify the workflow.
Spring Cloud Sleuth
The service is one of a mesh of microservices and we added Spring Cloud
Sleuth to provide tracing across microservice calls.
In Sleuth, a Span is a basic unit of work, and spans are linked together into a Trace
for a single logical transaction.
The Sleuth Reference
provides much more detail, including this useful diagram:
Use the Sleuth trace ID for each workflow
Instead of generating a separate ID (such as a UUID) we decided to take the
trace ID from Sleuth. Sleuth generates a random long integer as a trace
ID at the beginning of the request and passes that as part of
requests to other services.
Part of our rationale for using the trace ID is to reduce log message clutter.
When Sleuth is included, the IDs are inserted into the Spring logs via
the SLF4J MDC. Here is a simple Spring Boot log message with information
added by Sleuth:
2017-07-14 13:32:59.094 INFO [api-service,92e9013d25cca084,92e9013d25cca084,false] [10.242.22.52] 25453 --- [nio-8080-exec-1] c.e.s.WorkflowController : Received request
api-service is the service name
92e9013d25cca084 is the trace ID; here it is also the span ID because this is the first
span in the trace
Span#traceIdString() returns the trace ID
in the same hexadecimal format used in the log messages.
The controller that handles the request to start the workflow injects
this service and calls breadcrumb.getBreadcrumb() to get the current
trace ID string.
Inserting the Sleuth trace ID
When a consumer requests status of a workflow they provide the breadcrumb ID to use, e.g.:
GET /v1/workflow/92e9013d25cca084
We want to set that value as the Sleuth trace ID.
Filter that injects the trace ID
The solution we chose is to create a Spring web filter that addes a Sleuth span as an
attribute of the HTTP request so the Sleuth TraceFilter behaves as if the request
is part of an existing Sleuth trace. Our filter:
is in the filter chain before TraceFilter
reads the breadcrumb ID from the request
constructs an appropriate Span object
adds the span as an attribute of the request with the correct key
When TraceFilter executes it finds the span in the request attribute
and uses it as if the service had been called by another one in the same
trace.
Here is the filter code, abridged for clarity, with explanatory comments:
// Load this filter before TraceFilter@Order(TraceFilter.ORDER-1)publicclassInjectTraceFilterextendsGenericFilterBean{// Only modify requests that match this patternprivatestaticfinalPatternREQUEST_PATTERN=Pattern.compile("^/v1/workflow/(?<crumbId>[0-9a-f]+)$");// Key of the request attribute that TraceFilter searches forprivatestaticfinalStringTRACE_REQUEST_ATTR=TraceFilter.class.getName()+".TRACE";// Used to construct the span nameprivatestaticfinalStringSPAN_NAME_BASE="http:/v1/workflow/";privatefinalRandomrandom=newRandom(System.currentTimeMillis());@OverridepublicvoiddoFilter(finalServletRequestrequest,finalServletResponseresponse,finalFilterChainchain)throwsIOException,ServletException{finalHttpServletRequesthttpRequest=(HttpServletRequest)request;finalStringbreadcrumbId=extractBreadcrumbId(httpRequest);if(breadcrumbId!=null){// Set up a span with this breadcrumb ID as the trace IDhttpRequest.setAttribute(TRACE_REQUEST_ATTR,spanForId(breadcrumbId));chain.doFilter(httpRequest,response);}else{chain.doFilter(request,response);}}/**
* Returns the breadcrumb ID if a GET request matches the pattern, otherwise null.
*/privateStringextractBreadcrumbId(finalHttpServletRequesthttpRequest){if("GET".equals(httpRequest.getMethod())){finalMatchermatcher=REQUEST_PATTERN.matcher(httpRequest.getRequestURI());if(matcher.matches()){returnmatcher.group("crumbId");}}returnnull;}/**
* Constructs a span for the specified trace ID with a random span ID.
*/privateSpanspanForId(finalStringtraceId){returnSpan.builder().traceId(Span.hexToId(traceId)).spanId(random.nextLong()).exportable(false).name(SPAN_NAME_BASE+traceId).build();}}
After adding a
Categories page
I wanted to add tag-handling to the blog. I wanted to display the tags assigned
to each post under the title.
Using the same principles as for categories and adapting some CSS from
Codinfox,
I have achieved that. Each tag name is a link to the relevant section of the
Tags page.
Like categories, tags are specified for a post in the front matter, as for this post:
---layout:posttitle:Showing tags on postscategories:techtags:blog---
Jekyll supports specification of variables category, categories and tags in the front
matter of blog posts but it is left as an Exercise for the Reader™ to do anything with them. The
Lanyon theme does not itself include page with category or tag lists
(but of course is infinitely expandable).
So I created a contents page by adapting this
technique
with my own amateur CSS applied. The page is contents.html in the root directory of the
site and has front matter:
---layout:pagetitle:Categories---
The Lanyon sidebar automatically creates links to any
pages with layout: page in the front matter so the Categories page is easily found.