3

Suppose there is a system that is run on GCP, but as a backup, can be run locally.

When running on the cloud, stackdriver is pretty straightforward.

However, I need my system to push to stackdriver if on the cloud, and if not on the cloud, use the local python logger.

I also don't want to include any logic to do so, and this should be automatic.

  1. When logging, log straight to Python/local logger.
  2. If on GCP -> push these to stackdriver.

I can write logic that could implement this but that is bad practice. There surely is a direct way of getting this to work.

Example

import google.cloud.logging

client = google.cloud.logging.Client()
client.setup_logging()


import logging
cl = logging.getLogger()
file_handler = logging.FileHandler('file.log')
cl.addHandler(file_handler)
logging.info("INFO!")

This will basically log to python logger, and then 'always' upload to cloud logger. How can I have it so that I don't need to explicitly add import google.cloud.logging and basically if stackdriver is installed, it directly gets the logs? Is that even possible? If not can someone explain how this would be handled from a best practices perspective?

Attempt 1 [works]

Created /etc/google-fluentd/config.d/workflow_log.conf

<source>
    @type tail
    format none
    path /home/daudn/this_log.log
    pos_file /var/lib/google-fluentd/pos/this_log.pos
    read_from_head true
    tag workflow-log
</source>

Created /var/log/this_log.log

pos_file /var/lib/google-fluentd/pos/this_log.pos exists

import logging
cl = logging.getLogger()
file_handler = logging.FileHandler('/var/log/this_log.log')
file_handler.setFormatter(logging.Formatter("%(asctime)s;%(levelname)s;%(message)s"))
cl.addHandler(file_handler)

logging.info("info_log")
logging.error("error_log")

This works! Look for your logs for the specific VM and not global>python

Community
  • 1
  • 1
DUDANF
  • 2,618
  • 1
  • 12
  • 42

2 Answers2

2

Fortunately, this is a story that is handled. Stackdriver Logging is a very versatile framework for logging. However, there are a variety of logging APIs and Google's intent was not that you had to rewrite all your existing applications to leveraging the Stackdriver logging native APIs. Instead, you can use a logging API of your choice (including standard and defacto APIs) and these logging APIs will then map to Stackdriver. If executed outside a GCP environment or you simply wish to switch to an alternate log collector, your applications would not have to be re-coded or recompiled.

A list of the logging APIs available for different languages can be found at Setting Up Language Runtimes and this includes Setting Up Stackdriver Logging for Python.

For Python, at runtime, you have a configuration property (eg an Environment variable) that declares whether or not you wish to use Stackdriver. If set to true, then .. and only then ... would you execute the login that sets up the native Python logging for Stackdriver otherwise that logic would not be called and hence you would have no dependency on Stackdriver.

A possible piece of code might be:

if os.environ.get('USE_STACKDRIVER') == 'true':
  import google.cloud.logging
  client = google.cloud.logging.Client()
  client.setup_logging()
Kolban
  • 13,794
  • 3
  • 38
  • 60
  • I've had a look at these pages, and basically the entire doc. How would I manage this? What is the env variable at runtime? For me the only way is to use `google-cloud-logging` and that is basically tied to stackdriver. – DUDANF Nov 25 '19 at 15:32
  • 1
    Ive added a fragment of code as an example ... be careful as my Python skills are super weak and there may be logic errors ... but hopefully the intent comes across. – Kolban Nov 25 '19 at 15:40
  • 1
    but here we are specifically including that logic. That means I have to make `USE_STACKDRIVER` and set it to true or false. There has to be a way to implement this without coding in such logic. – DUDANF Nov 25 '19 at 15:41
  • You can use Stackdriver outside of actually running on GCP. For example, you can use Stackdriver logging running your code on premises as long as there is network connectivity to the Internet. If you don't want to setup your own flag for whether to use Stackdriver or not ... let's see if there isn't some other indication that you are running on GCP. For example, if you are running on Compute Engines, look at the set of environment variables that are set there implicitly and use one of those. – Kolban Nov 25 '19 at 15:43
0

You do not need to specifically enable or use Stackdriver in your program. You can use the Python logger and write to any file you want. However, Stackdriver only logs specific log files. This means that you would need to manually set up Stackdriver to log "your" log files.

In your example, you are writing to file.log. Modify /etc/google-fluentd/config.d/mylogfile.conf to include the following. You will need to specify the full path for file.log and not just the file name. In this example, I named it /var/log/mylogfile.log. This example also assumes that your logs start each line with a date.

<source>
  @type tail

  # Parse the timestamp, but still collect the entire line as 'message'
  format /^(?<message>(?<time>[^ ]*\s*[^ ]* [^ ]*) .*)$/

  path /var/log/mylogfile.log
  pos_file /var/lib/google-fluentd/pos/mylogfile.log.pos
  read_from_head true
  tag auth
</source>

For more information read the following document:

Stackdriver - Configuring the Agent

Now your program will run outside GCP and when running on a configured instance, log to Stackdriver.

Note: I would do the opposite of what you have asked. I would always use Stackdriver. When not running in GCP I would manually set up Stackdriver on my desktop, local server, etc and continue to log to Stackdriver.

John Hanley
  • 74,467
  • 6
  • 95
  • 159
  • if you can take a look at my edited post, if I simply change `/var/log/syslog` to `/home/daudn/file.log` and restart google-fluentd it should write those logs to stackdriver. However, it does not. What could I be doing incorrectly? – DUDANF Nov 25 '19 at 16:09
  • I feel like there is nothing to 'refresh'/'update' stackdriver now and even if the file is updated, it doesn't really make a diff. – DUDANF Nov 25 '19 at 16:23
  • @daudnadeem - Please do not change question scope. This can invalidate the answers and confuse future readers. Create a new question instead. Did you create the file as specified in my answer and then restart the Stackdriver Agent? – John Hanley Nov 25 '19 at 16:24
  • the scope of the question never changed, just getting closer to finding an appropriate answer. When it works, I'll edit my question to enable easy reading for future readers. I editted my conf, i made the logs write to `file.log` with date. But it doesn't write to stackdriver without `import google.cloud.logging` – DUDANF Nov 25 '19 at 16:26
  • @daudnadeem - If you need to include the import, then you did not configure the agent to log the file correctly. Review my last comment. – John Hanley Nov 25 '19 at 16:29
  • Theres definitely some step that I'm missing. what I did was 1. create `/etc/google-fluentd/config.d/mylogfile.conf`2. create `/var/log/mylogfile.log` 3. Append to logfile. But it didn't work. I'm having a play to see what I could be doing wrong. – DUDANF Nov 26 '19 at 09:40
  • I wrote this article on setting up Stackdriver. There is a section for debugging. https://www.jhanley.com/google-compute-stackdriver-logging-installation-setup-debugging/ – John Hanley Nov 26 '19 at 19:28