Skip to content

Releases: graniticio/granitic

v2.2.2

11 Sep 11:27
Compare
Choose a tag to compare

v2.2.1

06 Jul 13:43
Compare
Choose a tag to compare

Fixes for CodeQL analysis issues

v2.2.0

24 May 14:14
Compare
Choose a tag to compare

Granitic 2.2 Release Notes

Granitic 2.2 adds features and fixes that are backwards-compatible with code based on Granitic 2.0.x

Logging

JSON structured access and application logging

Application logs and access logs can now configured to output a user-defined JSON structure for each log event.

Refer to the reference manual for application logging and the HTTP server facility for more details.

STDOUT access logging

The HTTP Server access log can now write to STDOUT if you set HTTPServer.AccessLog.LogPath to STDOUT in configuration.

Multiple ContextFilters

Your application can now have as more than one component that implements logging.ContextFilter. If more than one component is found, they will be merged into a logging.PrioritisedContextFilter

You can control the how keys present in more than one ContextFilter are resolved to a single value by having your ContextFilters implement logging.FilterPriority

Application start up

Save merged configuration

Supply the -m flag and a path to a file when starting your application will cause Granitic to write its final, merged view of your application's configuration to that file (as JSON) and then exit.

This is useful when debugging problems introduced by merging configuration files.

Instance IDs

Setting the -u flag when starting your application will cause Granitic to generate a V4 UUID and use that as the ID for that instance of your application.

Your application's instance ID is now available as configuration at the path System.InstanceID

Query Manager

Slices as parameters

When using the query manager (either directly or via the RDBMS interfaces) to construct a parameterised query, you may now provide slices/arrays of some types as parameters. The default behaviour is to format the slice as a comma separated list. Slices may contain any of the types supported as individual parameters - basic int types, booleans, strings and their nilable equivalents.

Web Services

Slices as parameters in query strings and request paths

Request path and query binding now supports binding into a slice.

The parameter value should be expressed as a comma-separated list (e.g. /some/p,a,t,h or /path?a=1,2,3&b=true,false)

Target slices can be a slice of any Go basic type (except uintptr, complex64 and complex128) and any
nilable type.

Bug fixes

Query manager default configuration

Enabling the query manager facility with its default configuration was causing a fatal error on application startup.

2.2 JSON logging preview (v3)

27 Apr 12:02
Compare
Choose a tag to compare
Pre-release
v2.2.0-20200427

ContextFilter initialisation order fix

2.2 JSON logging preview (v2)

24 Apr 10:51
Compare
Choose a tag to compare
Pre-release
v2.2.0-20200424

Log level mapping

2.2 JSON logging preview

20 Apr 16:51
Compare
Choose a tag to compare
Pre-release
v2.2.0-20200420

Support for standard access logging format

v2.1.0

27 Oct 16:12
Compare
Choose a tag to compare

Granitic 2.1 Release Notes

Granitic 2.1 adds features and fixes that are backwards-compatible with code based on Granitic 2.0.x

See the milestone on GitHub
for a complete list of issues resolved in this release.

Access Logging

The access logging feature of the HTTPServer facility has the following changed behaviour.

  • Improved stopping behaviour (silently ignores LogRequest when application is stopping) and closes log line channel correctly
  • Now explicitly switches to synchronous/blocking logging when HTTPServer.AccessLog.LineBufferSize is set to zero or less. Default is 10.
  • Data stored in a context.Context can now be logged in access log lines (using the %{KEY}X verb) as long
    as you have created a component that implements logging.ContextFilter

Application logging

Data stored in a context.Context can now be logged in the prefix of applicaiton log lines (using the %{KEY}X verb) as long
as you have created a component that implements logging.ContextFilter

HTTP Response Status Codes

The default set of HTTP status codes (described here) can now be overridden in
configuration as described here

UUIDs

The function uuid.V4() can now be used to generate version four UUIDs. The implementation is fast and uses Go's
crypto/rand package to create the random numbers on which they are based.

You can now also configure the HTTPSever facility to assign UUID V4 IDs to each request

Request IDs

If request identification has been set up, your code can now find the string
ID for the current request by calling ws.RequestID(context.Context)

v2.0.2

30 Aug 09:30
Compare
Choose a tag to compare

Fixes:

See the v2.0.0 release notes for major changes and v1->v2 migration

v2.0.1

15 Apr 17:07
Compare
Choose a tag to compare

Fixed broken RDBMS client decorator test.

See the release notes for 2.0.0 for major changes

v2.0.0

14 Apr 19:50
Compare
Choose a tag to compare

Granitic 2.0 Release Notes

Granitic 2.0 is a major release of Granitic focusing on YAML support, Go module support, streamlining of web service code, improvements to grnc-bind, code quality and documentation.

This release is not backwards compatible, refer to the migration guide at the bottom of these notes for more information.

YAML

Granitic now supports YAML for configuration and component definition files. This involves the use of a third-party YAML parser and so to preserve Granitic's principle of having no dependencies, you must download the additional granitic-yaml project from GitHub or add it as a Go module dependency (see below).

The default file format for Granitic is currently still JSON and all documentation and examples will continue to use JSON, but YAML versions of the tutorial source code are now available.

Note you will need to change your application's main function to

func main() {
	granitic-yaml.StartGraniticWithYaml(bindings.Components())
}

New default locations for files

The previous default locations for application configuration (resource/config) and component definitions (resource/components) were too verbose and have been deprecated. The new preferred locations are config and comp-def.

grnc-project has been modified to create projects with these new locations. The empty files it creates are now config/base.json and comp-def/common.json and the generated entrypoint file is main.go

The old locations are still respected, but you will see a warning when you use them. Support for the old locations will be removed in a future version of Granitic.

Reference documentation

Granitic now has a reference manual, intended to compliment the information in the Godoc.
You can find this manual in doc/ref/index.md or on the Granitic website.

Go modules

Grantic 2 is compatible with the requirements of Go modules including
semantic import verisioning. As such Granitic
now requires the use of Go 1.11 or later.

Your applications should declare their dependency on Granitic in their go.mod file with:

    require github.com/graniticio/granitic/v2 v2

or (if you are using YAML configuration and component files)

    require github.com/graniticio/granitic-yaml/v2 v2

Wherever your code (or component definition files) imports Granitic types, the import statements should be of
the form:

    import "github.com/graniticio/granitic/v2/packageName"

Tool support

grnc-project and grnc-yaml-project now generate working Granitic projects using modules. A go.mod will automatically
be created for you.

grnc-bind and grnc-yaml-bind have additional support for modules. These features are explained below.

Web service streamlining

Your web service logic component no longer needs to implement handler.WsRequestProcessor or
handler.WsUnmarshallTarget. Instead it just needs
to declare a method with the signature:

  ProcessPayload(context.Context, *ws.Request, *ws.Response, *YourStruct)  

Where *YourStruct is a pointer to any type that you want the HTTP request's payload to be parsed into.

If you do not need any body, path or query parameter data parsed (e.g. a simple GET or HEAD), you should continue to implement
handler.WsRequestProcessor.

If you need more control over the struct that is created as your parsing target (e.g. you need to pre-populate it), you
should continue to implement handler.WsUnmarshallTarget.

Request instrumentation

Granitic now includes integration points for adding instrumentation to a web service request and
supporting for propagating that instrumentation to downstream web service requests. A common
use-case for this is to add timing traces to service calls.

See the instrument package documentation for more details.

Request unique identifiers

Granitic now includes integration points for generating unique IDs for web service requests
and having them injected into that request's context.Context. You need to create a component that implements
IdentifiedRequestContextBuilder

Code quality

Granitic 2 sees significant improvements in file and statement unit test coverage. This release
also see the start of Granitic committing to abiding by all of the advice from the go vet and
golint tools.

This has resulted in changes to the names of a number of exported types and the names of some Granitic
facilities. See the migration guide at the bottom of these notes for information on how this might affect your
application.

RDBMS client is now an interface

To make it easier to provide mock implementations for testing, the struct rdbms.RdbmsClient is now the interface
rdbms.Client

grnc-bind

grnc-bind (and its YAML equivalent grnc-yaml-bind) have gained a number of additional features
and quality of life improvements.

Validation and error handling

Rather than exit as soon as an error is found,grnc-bind attempts to continue parsing your
component definition files for as long as possible. This means that multiple errors are now reported
in a single run.

Additional validation has been applied to increase the number of problems detected during the bind
phase instead of during go build

Logging

You can now provide a -l LOGLEVEL flag to grnc-bind for more detailed output. Valid
values for LOGLEVEL are TRACE, DEBUG, INFO, WARN, ERROR and FATAL (case
insensitive). Default is WARN

New symbols for dependency and configuration promises

In addition to the c:, conf:, r: and ref: prefixes for indicating configuration promises
and component dependencies, you can now also use the symbols $ and + as an alternative.

For example:

"ComponentName": {
  "type": "some.Type",
  "A": "$some.config.path",
  "B": "+someOtherComponent"
}

If strings in your component definition file start with these new symbols, you can escape them with $$ or ++

Nested components

You can now define components in a nested manner under the field of the parent component
that the nested component should be injected into.

For example:

  "artistHandler": {
    "type": "handler.WsHandler",
    "PathPattern": "$paths.getArtist(^/artist)",
    "HTTPMethod": "GET",
    "Logic": {
      "type": "endpoint.ArtistLogic"
    }
}

The only requirement is that you specify a type or a parent template for the nested component.
If you want to be able to refer to the nested component from other components, you need to
provide a name field, e.g.:

   "Logic": {
     "type": "endpoint.ArtistLogic",
     "name": "artistLogic"
   }
       

Default values

You can now provide a default value along with a configuration promise by including the
default in brackets after the config path. This value will be used if no configuration
is provided to your application that overrides that config path.

For example:

"ComponentName": {
  "type": "some.Type",
  "A": "$some.config.path(true)",
  "B": "$some.other.path(1.2"
}

Note that default values will only be type checked against the fields you are trying to
inject them into at application run time (not during the build phase).

Package aliases

If your component definition files import two packages that clash (because the final part of the
package name is the same), you can define an alias for one of the packages, then refer to the
alias when defining types.

For example:

{
  "packages": [
    "github.com/graniticio/granitic/v2/ws/handler"
  ],

  "packageAliases": {
    "mh": "myproject/handler"
  },
  
  "SomeComponent": {
    "type": "mh.SomeType"  
  }
}

Find Granitic installation from go.mod (experimental)

grnc-bind serialises a copy of Granitic's facility configuration files into your application.
As such it needs to know where to find a copy of Granitic on disk. Previously this required
you to set the $GRANITIC_HOME environment variable or check Granitic out to a standard location.

In Granitic 2, the go.mod file can instead be used to automatically work out where to find
Granitic (but you still need to set your $GOPATH environment variable correctly).

This feature has not been fully tested with module proxies so should be considered experimental.

Bug fixes

  • Component definition files containing a slice of float64 could not be bound if the first element was parseable as an int.
  • The ServiceErrorManager was not respecting the value of ErrorCodeUser.ValidateMissing() when complaining about missing error codes.
  • Using ConfigAccessor to try and push configuration into an unsupported type of target field was not returning an error.
  • Some configuration parsing errors were causing Granitic to exit rather than return an error

Granitic 1.x to 2.0 migration

Support for Go modules and implementing th...

Read more