ISO standard timestamp variable available to message logging policy? Also Line Breaks?

Not applicable

So i am running some experiments w/ message logging policy. It isnt that hard to use. it seems to support a couple of commercial log consolidation systems out of the box (but not Logstash - interestingly enough). Hooking up custom logs to logstash should not be too much of a problem if i want to use the file system option (the semi insanity of the pathing system is going to be a bit of a configuration disaster - but I will solve that later) Heres where im stuck...

i seem to be able to output a timestamp like this:

1377112607413

or like this:

Wed, 21 Aug 2013 19:16:47 UTC

but not in ISO format (like this):

2015-07-10 21:07:38,935

If there is a way to output this i would love it. I can work around it if i need to - but its become pretty standard around here and i have to ask if its available as output.

Also - Line Breaks... the output im sending right now seems to be .. never mind - I figured out how to add a line break at the end of each message...

Solved Solved
0 16 2,518
1 ACCEPTED SOLUTION

Not applicable

Hi @Benjamin Goldman. You can leverage the following code executed by a JavaScript policy and store it in a context variable, which then can be used by the message logging policy like this:

var isoDate = new Date().toISOString();
context.setVariable("isoDate", isoDate);

Then from the Message logging policy:

<MessageLogging name="LogToSyslog">>   <Syslog>    <Message>[3f509b58 tag="{organization.name}.{apiproxy.name}.{environment.name}"] {isoDate}</Message> <Host>logs-01.loggly.com</Host> <Port>514</Port>     <Protocol>TCP</Protocol>   </Syslog> 
</MessageLogging>

Credits to @Sudheer Gopalam.

Hope it helps!

View solution in original post

16 REPLIES 16

Not applicable

Hi @Benjamin Goldman. You can leverage the following code executed by a JavaScript policy and store it in a context variable, which then can be used by the message logging policy like this:

var isoDate = new Date().toISOString();
context.setVariable("isoDate", isoDate);

Then from the Message logging policy:

<MessageLogging name="LogToSyslog">>   <Syslog>    <Message>[3f509b58 tag="{organization.name}.{apiproxy.name}.{environment.name}"] {isoDate}</Message> <Host>logs-01.loggly.com</Host> <Port>514</Port>     <Protocol>TCP</Protocol>   </Syslog> 
</MessageLogging>

Credits to @Sudheer Gopalam.

Hope it helps!

So i think i should modify my question - because while this will do what i asked above - it doesnt actually do what I want.

I dont want a timestamp. I want THE timestamp from the inbound request.

There are a couple of variables exposed in apigee related to start/end of both request and response. These are very much accurate in terms of when transactions are taking place. Both allow output of one of the two timestamp formats i mentioned above.

I bet i could do exactly the same thing but call that variable inside the javascript. I will experiment with that tomorrow. In the mean time im not going to accept the answer but give you points 🙂

When i test this - if it allows me to do what I need I will accept your answer and post my version of the solution in the comments (it will confuse people a bit - but you can then edit your answer and include my version in the quotes maybe? not sure)

Correct. You should be able to leverage system.timestamp instead then:

var isoDate = new Date(context.getVariable("system.timestamp")).toISOString();
context.setVariable("isoDate", isoDate);

I was hoping to be able to access {client.received.start.timestamp} - this way I could use similar variables later and make my logs a source of truth for troubleshooting.

It looks like it is returning no data. This variable is TRUTH as to when the request to the message processor starts - so it should be used for logging. a general timestamp isnt actually when the request starts, even if you put the javascript policy as the first entry.

No matter how this works out though - it is going to be messy to build enough timestamps to allow really detailed logging like this: i am going to have to not only have multiple log policies but potentially many many javascript policies... which is a shame - because there is a nice variable {client.received.start.timestamp} which i could use but it just doesnt provide me a usable format.

And this doesnt even begin to address the problems im going to have introducing this as a standard policy to all of the proxies on my system... and uf.. one problem at a time.

FYI - this is the best answer there is going to be! Thanks for your help.

Thanks. It's good to report these issues.

@arghya das - Are you aware of this issue?

var isoSystemTimeStamp = new Date(context.getVariable("system.timestamp")).toISOString(); context.setVariable("loggingIsoSystemTimeStamp", isoSystemTimeStamp);

works

var isoSystemTimeStamp = new Date(context.getVariable("client.received.start.timestamp")).toISOString(); context.setVariable("loggingIsoSystemTimeStamp", isoSystemTimeStamp);

does not work - returns nothing.

<figured out that it was a scope problem - misunderstood where this was available>

adas
New Member

@Benjamin Goldman Can you email me your proxy and let me see what you are doing. Here's the bundle that I tried where I tried the exact same javascript as yours, and that's the only policy I have in the no target proxy. It seems to work fine for me.

Not applicable

So i went back and re-typed the entire statement again:

var isoSystemTimeStamp = new Date(context.getVariable("client.received.start.timestamp")).toISOString(); context.setVariable("loggingIsoSystemTimeStamp", isoSystemTimeStamp);

and i am now able to access the variable w/o it being empty.

gave you points because you forced me to fiddle with it more instead of moving on and using something other than what I wanted to.

Not applicable

A quick correction, a timestamp using a space separator between the date and hour is not the official specification, instead, the separator should be a "T". There are some exceptional circumstances where space is allowed, such as compatibility, but it should not be used in general. @Benjamin Goldman

Hi @Benjamin Goldman

how did you manage to obtain this date format "Wed, 21 Aug 2013 19:16:47 UTC" ?

Did you use an extra JavaScript policy for that?

Thanks in advance

Adding a new answer to an old question... you can now do this in AssignMessage.

<AssignMessage name='AM-FormatTime'>
  <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
  <AssignVariable>
    <Name>formatString1</Name>
    <Value>yyyy-MM-dd HH:mm:ss.SSS</Value> <!-- EEEE -->
  </AssignVariable>
  <AssignVariable>
    <Name>formattedTime</Name>
    <Template>{timeFormatUTCMs(formatString1,client.received.end.timestamp)}</Template>
  </AssignVariable>

</AssignMessage>

I know it's old thread but does it work in Raise Fault?Looking for a simple timestamp in ISO format(2021-03-29T04:06:04.223Z) while raising fault.

Tried few combinations but doesn't seems to be working. Any suggestions?

https://docs.apigee.com/api-platform/reference/message-template-intro#spacesnotallowed

You should be able to use AssignVariable within RaiseFault. It looks like this:

<RaiseFault name='RF-1'>
  <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
  <UsePolicyNameAsFaultReason>true</UsePolicyNameAsFaultReason>
  <FaultResponse>
    <AssignVariable>
      <Name>formatString1</Name>
      <Value>yyyy-MM-dd HH:mm:ss.SSS</Value> <!-- EEEE -->
    </AssignVariable>
    <AssignVariable>
      <Name>formattedTime</Name>
      <Template>{timeFormatUTCMs(formatString1,client.received.end.timestamp)}</Template>
    </AssignVariable>
    <Set>
      <Payload contentType='text/plain'>error at {formattedTime}</Payload>
      <StatusCode>400</StatusCode>
      <ReasonPhrase>Bad Request</ReasonPhrase>
    </Set>
  </FaultResponse>
</RaiseFault>